优化ansible速度
简单介绍和说明下,优化ansible执行速度的方法,具体如下~
常规优化方法
ansible的-t选项妙用
ansible的"-t"或"--tree"选项是将ansible的执行结果按主机名保存在指定目录下的文件中。
ansible test -m ping -o -f 6 -t /tmp/tree
至于保存的内容为何?实际上仅仅只是保存了普通的输出内容而已。
# pwd
/tmp/tree
# cat 192.168.246.187
{"ansible_facts": {"discovered_interpreter_python": "/usr/bin/python"}, "changed": false, "ping": "pong"}
设置ansible开启ssh长连接
如要开启ssh长连接,要求ansible端的openssh版本高于或等于5.6。使用ssh -V
可以查看版本号。然后设置ansible 使用ssh连接被控端的连接参数,此处修改/et c/ans ible/ansible.cfg
,在此文件中启动下面的连接选项,其中ControlPersist=5d
是控制ssh连接会话保持时长为5天。
ssh_args = -C -o ControlMaster=auto -o ControlPersist=5d
除此之外直接设置/etc/ssh/ssh_config
(不是sshd_config
,因为ssh命令是客户端命令)中对应的长连接项也是可以的。
开启长连接后,在会话过期前会一直建立连接,在netstat
的结果中会看到ssh连接是一直established
状态,且会在当前用户家目录的.ans ible/cp
目录下生成一些 socket 文件,每个会话一个文件。
例如:执行一次ad-hoc
操作:
ansible test -m ping
查看netstat ,发现ssh进程的会话一直是established状态。
netstat -lnpta
且家目录下~/.ansible/cp/
下会生成对应的socket文件。
⚠️关于 ssh 保持长连接的方法:
(1)修改server端的etc/ssh/sshd_config
ClientAliveInterval 60 #server每隔60秒发送一次请求给client,然后client响应,从而保持连接
ClientAliveCountMax 3 #server发出请求后,客户端没有响应得次数达到3,就自动断开连接,正常情况下,client不会不响应
systemctl reload sshd
(2)修改client端的etc/ssh/ssh_config添加以下:(在没有权限改server配置的情形下)
ServerAliveInterval 60 #client每隔60秒发送一次请求给server,然后server响应,从而保持连接
ServerAliveCountMax 3 #client发出请求后,服务器端没有响应得次数达到3,就自动断开连接,正常情况下,server不会不响应
(3)命令行临时修改
在命令参数里ssh -o ServerAliveInterval=60
这样子只会在需要的连接中保持持久连接, 毕竟不是所有连接都要保持持久的。
开启pipelining
pipeline也是openssh的一个特性。在ansible执行每个任务的流程中,有一个过程是将临时任务文件put到一个 ansible 端的一个临时文件中,然后sftp传输到远端,然后通过ssh连接过去远程执行这个任务。
如果开启了pipelining
,一个任务的所有动作都在一个ssh会话中完成,也会省去sftp到远端的过程,它会直接将要执行的任务在ssh会话中进行。
开启pipelining的方式是配置文件(如ansible.cf g)中设置pipelining=true
,默认是false。
但是要注意,如果在ansible中使用sudo命令的话(ssh user@host sudo cmd),需要在被控节点的/etc/sudoers
中 禁用"requiretty"。
之所以要设置/etc/sudoers中的requiretty,是因为ssh远程执行命令时,它的环境是非登录式非交互式shell,默认不会分配tty,没有tty,ssh的sudo就无法关闭密码回显(使用"-tt"选项强制SSH分配tty)。
所以出于安全考虑,/etc/sudoers中默认是开启requiretty的,它要求只有拥有tty的用户才能使用sudo,也就是说ssh连接过去不允许执行sudo 。可以通过 visudo/vim 编辑配置文件,注释该选项来禁用它。
grep requiretty /etc/sudoers
# Defaults requiretty
修改设置/etc/sudoers是在被控节点上进行的(或者ansible连接过去修改),其实在ansible端也可以解决sudo的问题,只需在ansible的ssh参数上加上"- tt "选项即可。
ssh_args = -C -o ControlMaster=auto -o ControlPersist=5d -tt
开启pipelining后,每次执行任务时都大量减少了ssh连接次数(只需要一次ssh连接),且省去了sftp传输任务文件的过程,因此在管理大量节点时能极大提升执行效率。
修改ansible执行策略
默认ansible在远程执行任务是按批并行执行的,一批控制多少台主机由命令行的"-f"或"--forks"选项控制。例如,默认的并行进程数是5,如果有20台被控主机,那么只有在每5台全部执行完一个任务才继续下一批的5台执行该任务,即使中间某台机器性能较好,完成速度较快,它也会空闲地等待在那,直到所有20台主机都执行完该任务才会以同样的方式继续下一个任务。如下所示:
h1 h2 h3 h4 h5(T1)-->h6 h7 h8 h9 h10(T1)...-->h16 h17 h18 h19 h20(T1)-->h1 h2 h3 h4 h5(T2)-->.....
在ansible 2.0中,添加了一个策略控制选项strategy,默认值为"linear",即上面按批并行处理的方式。还可以设置 strategy的值为"free"。
在free模式下,ansible会尽可能快的切入到下一个主机。同样是上面的例子,首先每5台并行执行一个任务,当其中某一台机器由于性能较好提前完成了该任务,它不会等待其他4台完成,而是会跳出该任务让ansible切入到下一台机器来执行该任务。也就是说,这种模式下,一台主机完成一个任务后,另一台主机会立即执行任务,它是"前赴后继"的方式。如下所示:
h1 h2 h3 h4 h5(T1)-->h1 h2 h3 h4 h6(T1)-->h1 h3 h4 h6 h7(T1)-->......-->h17 h18 h19 h20(T1) h1(T2)-->h18 h19 h20(T1) h1 h2(T2)-->...
设置的方式如下:
- hosts: all
strategy: free
tasks:
...
设置facts缓存
ansible或ansible-playbook默认总是先收集facts信息。在被控主机较少的情况下,收集信息还可以容忍,如果被控主机数量非常大,收集 facts 信息会消耗掉非常多时间。
可以设置gather_facts: no
来禁止ansible收集facts信息,但是有时候又需要使用facts中的内容,这时候可以设置facts的缓存。例如,在空闲的时候收集facts ,缓存下来,在需要的时候直接读取缓存进行引用。
ansible的配置文件中可以修改'gathering'的值为smart
、implicit
或者explicit
。
(1)smart 表示默认收集facts,但facts已有的情况下不会收集,即使用缓存facts;
(2)implicit 表示默认收集facts ,要禁止收集,必须使用gather_facts: False
;
(3)explicit 则表示默认不收集,要显式收集,必须使用gather_facts: Ture
;
在使用facts缓存时(即设置为smart),ansible支持两种f acts缓存:redis
和jsonfile
。
例如,以下是/etc/ansible/ansible.cfg
中jsonfile格式的缓存配置方法。
[defaults]
gathering = smart
fact_caching_timeout = 86400 ## 这里设置的缓存过期时间为86400秒,即缓存一天。
fact_caching = jsonfile fact_caching_connection = /path/to/cachedir ## 缓存的json文件放在/path/to/cachedir目录下,各主机的缓存 文件以主机名命名。
缓存文件是一个json文件,要查看缓存文件,如/path/to/cachedir/192.168.100.59中的内容, 使用如下语句即可:
cat /path/to/cachedir/192.168.100.59 | python -m json.tool