docker ubuntu python3.7

FROM ubuntu:18.04

# Set temp work directory

# for package configuration

WORKDIR /usr/src/cache

# Update apt packages RUN apt update RUN apt upgrade -y

# Install vim

RUN apt install vim -y

# Install python 3.7

RUN apt install software-properties-common -y

RUN add-apt-repository ppa:deadsnakes/ppa

RUN apt install python3.7 -y # Make python 3.7 the default

RUN echo "alias python=python3.7" >> ~/.bashrc

RUN export PATH=${PATH}:/usr/bin/python3.7

RUN /bin/bash -c "source ~/.bashrc"

# Install pip

RUN apt install python3-pip -y

RUN python -m pip install --upgrade pip

ubuntu18 nvidia cuda tensorflow2.1 driver install

conda

wget https://mirrors.tuna.tsinghua.edu.cn/anaconda/miniconda/Miniconda3-4.7.10-Linux-x86_64.sh

chmod 777 Miniconda3-4.7.10-Linux-x86_64.sh 

./Miniconda3-4.7.10-Linux-x86_64.sh 

conda create -n tf21 python=3.7

driver

sudo ubuntu-drivers devices

sudo apt install nvidia-driver-430

conda activate tf21

conda install cudatoolkit=10.1

conda install cudnn=7.6

HSTS

最近一直在测试 ingress 的 https 连接, 所以域名和证书频繁更换, 然后… 今天下午快被 HSTS 恶心死了

症状是换了证书或者地址之后, 浏览器认为是网站被劫持了

HSTS 会做什么呢? 在浏览器第一次访问了 www.bestofgit.com 之后, 如果此时连接被跳转到了https, 并且得到了HSTS的头标识, 那么支持HSTS的浏览器 ( 最新版的chrome ) , 会强制你的浏览器在下次访问的时候使用https连接这个网站 , 并且… 如果证书是不安全的 ( 自签名那种, 没有经过第三方认证的 ) , 那么恭喜你, 你会一直看到下面这个页面

一直到… 天荒地老 … 当然不是, 一直到 HSTS 头中定义的时间过去, 如果它定义了 1 年, 那么再次恭喜你, 跟天荒地老也差不多了

如何关闭这个功能呢? 首先我想到的是修改服务器, 但是仍然会看到这个页面, 只能去修改chrome

chrome://net-internals/#hsts

然后看到

在最下面的 delete 那里输入你的 域名 , 然后delete 

Ansible 入门 5 (Ansible管理docker的容器)

YAML格式的playbook的属性包括

必要属性只有下面两个

host : 目标的一组主机

task : 需要执行的任务

可选的属性包括

name 其实是一段注释,用来标注这个play , 内容会被执行这个playbook的时候打印出来

sudo 如果设置为true , 运行task的时候会使用sudo命令切换root

vars 变量与值组成的列表

vars:    server_name : myserver    port : 22
– name : run taskshell : echo “{{server_name}}”

task 是需要执行的任务列表

其中name属性是可选的,例如

– apt : name=nginx update_cache=yes

task支持一些模块, 常用的包括

shell, apt, copy , file , service, template, pip 等

Ansible 入门 4 (Ansible管理docker的容器)

上一章节我给出了一个简单的playbook

这一章节让我们来看看细节

playbook 是 YAML 格式的

YAML是”YAML Ain’t a Markup Language”(YAML不是一种置标语言)的递归缩写。

在开发的这种语言时,YAML 的意思其实是:”Yet Another Markup Language”(仍是一种置标语言)

YAML 文件应该以三个减号 — 开头, 不过你也可以忽略它, 不会带来任何问题

注释是通过 # , 和 shell 脚本一样

字符串文本也不需要使用 引号 括起来, 当然如果括起来可以, 即使中间包含空格也可以不用引号

hello world 这样的字符串完全可以识别正确

对于布尔类型的值十分灵活

如果一个值为”真” 可以使用

true, True , TRUE , yes, Yes, YES, on, On, ON , y ,Y

对应的如果一个值为 “假” 可以使用

false, False, FALSE, no, No, NO, off, Off, OFF, n, N

列表格式

如果你使用过json, json的列表格式是这样的

[    “hello”,    “world”]

YAML中列表使用 减号 “-” 分割列表

– hello- world

第三节中我们使用了 – name: install 这样的描述

YAML中的 冒号 是用来表示 “字典” 的, 但是这个字典更像是 json中的对象, python中的字典

我们以一个python字典为例  

{key1 : value1, key2 : value2 }

对应的YAML是

key1: value1key2: value2

对于较长的内容,   大于号 > 标记 折行 , 而所有的换行符反而会被替换成空格

通过观察,你现在可以看出一个yaml文件的内容, 实际上就是 由字典元素组成的列表

– 列表

  字典key1:字典value1

  字典key2:字典value2

  字典key3:

    -key3的列表

     key3列表里的key1:value1

每个play必需包含下面两项

  • host
  • task

host用于标示一组主机

task用于标示需要执行的任务

free命令的available

3.14内核新增了一个内存信息MemAvailable , 当调用free命令时可以显示为available

之前没留意过

[root@VM_167_46_centos etc]# free -h
                         total         used             free      shared     buff/cache      available
Mem:           993M        253M        334M         39M               405M             556M
Swap:           2.0G          82M             1.9G

我们知道used + free + buff 基本等于 total

used是被使用的

free是完全没有被使用的

shared是被程序之间可以(已经被)共享使用的

buffers是指用来给块设备做的缓冲大小,它只记录文件系统的metadata以及 tracking in-flight pages

cached是用来给文件做缓冲

也就是 buffers是用来存储目录里面有什么内容,权限等等。而cached直接用来缓存我们打开的文件

available到底是什么

Many load balancing and workload placing programs check /proc/meminfo to estimate how much free memory is available. They generally do this by adding up “free” and “cached”, which was fine ten years ago, but is pretty much guaranteed to be wrong today.
It is wrong because Cached includes memory that is not freeable as page cache, for example shared memory segments, tmpfs, and ramfs, and it does not include reclaimable slab memory, which can take up a large fraction of system memory on mostly idle systems with lots of files.Currently, the amount of memory that is available for a new workload,without pushing the system into swap, can be estimated from MemFree, Active(file), Inactive(file), and SReclaimable, as well as the “low”watermarks from /proc/zoneinfo.However, this may change in the future, and user space really should not be expected to know kernel internals to come up with an estimate for the amount of free memory.It is more convenient to provide such an estimate in /proc/meminfo. If things change in the future, we only have to change it in one place.

也就是说available才是你的”可用内存” , 而不是像过去那样简单的把free和buffer加起来

available 小于 free+buffer 是一定的了

Ansible 入门 3 (Ansible管理docker的容器)

playbook 指的是用于配置管理的脚本, 实际上playbook才是ansible的重头戏

我将尝试使用一个playbook同时控制之前创建的3个虚拟机(docker 容器)

先看一个简单脚本

[root@vagrant playbooks]# vi hostname.yml 
- name: call hostname
  hosts: dockers
  sudo: False
  tasks:
    - name: install
      shell: hostname > /hostname.txt

直接调用

[root@vagrant playbooks]# ansible-playbook hostname.yml 

PLAY [call hostname] ********************************************************** 

GATHERING FACTS *************************************************************** 
ok: [172.17.0.4]
ok: [172.17.0.3]
ok: [172.17.0.2]

TASK: [install] *************************************************************** 
changed: [172.17.0.3]
changed: [172.17.0.4]
changed: [172.17.0.2]

PLAY RECAP ******************************************************************** 
172.17.0.2                 : ok=2    changed=1    unreachable=0    failed=0   
172.17.0.3                 : ok=2    changed=1    unreachable=0    failed=0   
172.17.0.4                 : ok=2    changed=1    unreachable=0    failed=0 

检查一下结果

下面是一个安装httpd的脚本

[root@vagrant playbooks]# vi httpd.yml
- name: install httpd from yum
  hosts: dockers
  sudo: False
  tasks:
    - name: install
      shell: yum install httpd
    - name: start httpd
      shell: /usr/sbin/httpd

调用 ansible-playbook ./playbooks/httpd.yml

可以看到log中

[root@vagrant log]# tail -500f ansible.log 
2017-06-06 14:55:23,353 p=19632 u=root |  
2017-06-06 14:55:23,354 p=19632 u=root |  /usr/bin/ansible dockers -a hostname
2017-06-06 14:55:23,354 p=19632 u=root |  
2017-06-06 14:55:25,190 p=19632 u=root |  172.17.0.3 | success | rc=0 >>
fd62f7fed827

2017-06-06 14:55:25,195 p=19632 u=root |  172.17.0.2 | success | rc=0 >>
86b87edef2cd

2017-06-06 14:55:25,195 p=19632 u=root |  172.17.0.4 | success | rc=0 >>
7c6125cedfd3

2017-06-06 15:43:02,383 p=21343 u=root |   
2017-06-06 15:43:02,384 p=21343 u=root |  /usr/bin/ansible-playbook ./playbooks/httpd.yml
2017-06-06 15:43:02,384 p=21343 u=root |   
2017-06-06 15:43:02,387 p=21343 u=root |  ERROR: Syntax Error while loading YAML script, ./playbooks/httpd.yml
Note: The error may actually appear before this position: line 6, column 5

    - name: install
    shell: yum install httpd
    ^
2017-06-06 15:45:22,766 p=21408 u=root |   
2017-06-06 15:45:22,766 p=21408 u=root |  /usr/bin/ansible-playbook ./playbooks/httpd.yml
2017-06-06 15:45:22,766 p=21408 u=root |   
2017-06-06 15:45:22,795 p=21408 u=root |  PLAY [install httpd from yum] ************************************************* 
2017-06-06 15:45:22,795 p=21408 u=root |  GATHERING FACTS *************************************************************** 
2017-06-06 15:45:24,231 p=21408 u=root |  failed: [172.17.0.4] => {"failed": true, "parsed": false}
2017-06-06 15:45:24,232 p=21408 u=root |  /bin/sh: sudo: command not found
OpenSSH_6.6.1, OpenSSL 1.0.1e-fips 11 Feb 2013
debug1: Reading configuration data /etc/ssh/ssh_config
debug1: /etc/ssh/ssh_config line 56: Applying options for *
debug1: auto-mux: Trying existing master
debug1: mux_client_request_session: master session id: 2
Shared connection to 172.17.0.4 closed.

2017-06-06 15:45:24,235 p=21408 u=root |  failed: [172.17.0.3] => {"failed": true, "parsed": false}
2017-06-06 15:45:24,235 p=21408 u=root |  /bin/sh: sudo: command not found
OpenSSH_6.6.1, OpenSSL 1.0.1e-fips 11 Feb 2013
debug1: Reading configuration data /etc/ssh/ssh_config
debug1: /etc/ssh/ssh_config line 56: Applying options for *
debug1: auto-mux: Trying existing master
debug1: mux_client_request_session: master session id: 2
Shared connection to 172.17.0.3 closed.

2017-06-06 15:45:24,240 p=21408 u=root |  failed: [172.17.0.2] => {"failed": true, "parsed": false}
2017-06-06 15:45:24,240 p=21408 u=root |  /bin/sh: sudo: command not found
OpenSSH_6.6.1, OpenSSL 1.0.1e-fips 11 Feb 2013
debug1: Reading configuration data /etc/ssh/ssh_config
debug1: /etc/ssh/ssh_config line 56: Applying options for *
debug1: auto-mux: Trying existing master
debug1: mux_client_request_session: master session id: 2
Shared connection to 172.17.0.2 closed.

2017-06-06 15:45:24,249 p=21408 u=root |  TASK: [install] *************************************************************** 
2017-06-06 15:45:24,255 p=21408 u=root |  FATAL: no hosts matched or all hosts have already failed -- aborting

2017-06-06 15:45:24,255 p=21408 u=root |  PLAY RECAP ******************************************************************** 
2017-06-06 15:45:24,256 p=21408 u=root |             to retry, use: --limit @/root/httpd.retry

2017-06-06 15:45:24,256 p=21408 u=root |  172.17.0.2                 : ok=0    changed=0    unreachable=0    failed=1   
2017-06-06 15:45:24,256 p=21408 u=root |  172.17.0.3                 : ok=0    changed=0    unreachable=0    failed=1   
2017-06-06 15:45:24,256 p=21408 u=root |  172.17.0.4                 : ok=0    changed=0    unreachable=0    failed=1   
2017-06-06 15:45:53,254 p=21584 u=root |   
2017-06-06 15:45:53,254 p=21584 u=root |  /usr/bin/ansible-playbook ./playbooks/httpd.yml
2017-06-06 15:45:53,254 p=21584 u=root |   
2017-06-06 15:45:53,269 p=21584 u=root |  PLAY [install httpd from yum] ************************************************* 
2017-06-06 15:45:53,270 p=21584 u=root |  GATHERING FACTS *************************************************************** 
2017-06-06 15:45:55,102 p=21584 u=root |  ok: [172.17.0.2]
2017-06-06 15:45:55,107 p=21584 u=root |  ok: [172.17.0.4]
2017-06-06 15:45:55,134 p=21584 u=root |  ok: [172.17.0.3]
2017-06-06 15:45:55,144 p=21584 u=root |  TASK: [install] *************************************************************** 

由于网络问题这里我等待的时间太长了,所以直接中断了 🙁

Ansible 入门 2 (Ansible管理docker的容器)

对于上一章节中我们提到的 /etc/ansible/hosts 配置文件可以通过 -i 参数指定, 如果不指定默认查找/etc/ansible/hosts 路径

ansible dockers -a “hostname”

等价于

ansible -i /etc/ansible/hosts dockers -a “hostname”

在这个hosts文件中还可以通过 ansible_ssh_host和ansible_ssh_port 单独指定目标机器的ip和端口

下面是这次的重点, 如果你需要多个hosts文件的话,你需要使用ansible.cfg文件

这个文件可以用来配置一些默认值

Ansible 按照如下 位置和顺序 来查找 ansible.cfg

1. ANSIBLE_CONFIG 环境变量指定的文件

2. ./ansible.cfg 当前工作目录下的文件

3. ~/.ansible.cfg 用户home路径下的文件

4. /etc/ansible/ansible.cfg 目录下的文件

这里我创建一个/ansible目录作为工作目录

[defaults]
inventory=/ansible/config/hosts
log_path=/ansible/log/ansible.log

然后在/ansible/config/hosts创建一个hosts文件

直接调用出现了错误

[root@vagrant ansible]# ansible dockers -a "hostname" 
Traceback (most recent call last):
  File "/usr/bin/ansible", line 36, in <module>
    from ansible.runner import Runner
  File "/usr/lib/python2.7/site-packages/ansible/runner/__init__.py", line 37, in <module>
    import ansible.inventory
  File "/usr/lib/python2.7/site-packages/ansible/inventory/__init__.py", line 26, in <module>
    from ansible.inventory.ini import InventoryParser
  File "/usr/lib/python2.7/site-packages/ansible/inventory/ini.py", line 21, in <module>
    from ansible.inventory.host import Host
  File "/usr/lib/python2.7/site-packages/ansible/inventory/host.py", line 19, in <module>
    from ansible import utils
  File "/usr/lib/python2.7/site-packages/ansible/utils/__init__.py", line 29, in <module>
    from ansible.utils.display_functions import *
  File "/usr/lib/python2.7/site-packages/ansible/utils/display_functions.py", line 22, in <module>
    from ansible.callbacks import display
  File "/usr/lib/python2.7/site-packages/ansible/callbacks.py", line 42, in <module>
    logging.basicConfig(filename=path, level=logging.DEBUG, format='%(asctime)s %(name)s %(message)s')
  File "/usr/lib64/python2.7/logging/__init__.py", line 1529, in basicConfig
    hdlr = FileHandler(filename, mode)
  File "/usr/lib64/python2.7/logging/__init__.py", line 902, in __init__
    StreamHandler.__init__(self, self._open())
  File "/usr/lib64/python2.7/logging/__init__.py", line 925, in _open
    stream = open(self.baseFilename, self.mode)
IOError: [Errno 2] No such file or directory: '/ansible/log/ansible.log'

原来这家伙笨到不会自己创建文件夹

mkdir /ansible/log 之后工作正常

Ansible 入门 1 (Ansible管理docker的容器)

安装 yum -y install ansible 或者 pip install ansible 

需要把托管机的ip加入到hosts文件里

/etc/ansible/hosts

这里我只做个单机测试,使用用户名密码登录,我使用root用户, 尝试让ansible使用vagrant用户

使用用户名密码的话还需要安装 yum install sshpass

[web]
172.28.128.4 ansible_ssh_user=vagrant ansible_ssh_pass=vagrant

运行

[root@vagrant ansible]# ansible web -a “hostname”
172.28.128.4 | success | rc=0 >>
vagrant
 

秘钥登录的话直接去掉ansible_ssh_pass参数就可以了,当然你需要先提供免密码登录

可以参考http://lizhe.name.csdn.net/node/24里的免密码登录

如果是机器A登录到机器B, 在A上生成秘钥对 ssh-keygen -t rsa -P ” 

将机器A上的 公钥 复制到机器B , 内容直接cat给 .ssh/authorzied_keys

记得确认/etc/ssh/sshd_config 中的key文件位置和文件名

/root/.ssh/id_rsa

/root/.ssh/id_rsa.pub

ansible默认使用5个线程执行, 如果需要指定线程数需要使用 -f 参数

[root@vagrant ansible]# ansible web -a “hostname” -f 1
172.28.128.4 | success | rc=0 >>
vagrant
 

上面的例子实际上使用了 command 模块,这个模块是默认提供的,它接收 -a 参数提供的命令,所以下面两行命令实际上是等价的

ansible web -a “hostname”

ansible web -m command -a “hostname”

这里我决定还是请出我们的老朋友, docker和它的容器们

docker run -t -i –name ansible_vm_1 docker.io/centos /bin/bash

docker run -t -i –name ansible_vm_2 docker.io/centos /bin/bash

docker run -t -i –name ansible_vm_3 docker.io/centos /bin/bash

创建了3个容器

虽然docker不鼓励使用ssh登录进容器,也不鼓励修改容器用户的密码, 但是这里实在不想做一遍免密登录了,所以打算直接用用户名密码登录容器, 因为ansible是基于ssh的,所以还是要去给容器安装一下sshd服务

yum -y install openssh-server openssh-clients

/etc/ssh/sshd_config 文件中打开root用户远程登录 PermitRootLogin yes

修改完之后手动启动sshd服务 /usr/sbin/sshd

如果出现找不到key的错误

[root@7c6125cedfd3 /]# /usr/sbin/sshd                                                                                                                                                                               
Could not load host key: /etc/ssh/ssh_host_rsa_key
Could not load host key: /etc/ssh/ssh_host_dsa_key
Could not load host key: /etc/ssh/ssh_host_ecdsa_key
Could not load host key: /etc/ssh/ssh_host_ed25519_key
 

把其他的key注释掉,保留一个rsa_key 然后使用ssh-keygen -t rsa -b 2048 -f /etc/ssh/ssh_host_rsa_key 重新生成一个就行了

passwd root改个密码

把三个容器都配置完成以后在宿主机上尝试添加这3个容器

查看一下容器ip 

docker inspect -f ‘{{.NetworkSettings.IPAddress}}’ ansible_vm_1

把ip加进ansible的配置文件里 /etc/ansible/hosts

[dockers]
172.17.0.2 ansible_ssh_user=root ansible_ssh_pass=root
172.17.0.3 ansible_ssh_user=root ansible_ssh_pass=root
172.17.0.4 ansible_ssh_user=root ansible_ssh_pass=root
 

要屏蔽第一次连接出现yes/no的情况

/etc/ansible/ansible.cfg

# uncomment this to disable SSH key host checking
host_key_checking = False