Ansible性能优化——提升ansible执⾏效率
⽬录
最初,ansible的执⾏效率和saltstack(基于zeromq消息队列的⽅式)相⽐要慢的多的多,特别是被控节点量很⼤的时候。但是ansible发展到现在,它的效率得到了极⼤的改善。在被控节点不太多的时候,默认的设置已经够快。即使被控节点数量巨⼤的时候,也可以通过⼀些优化去极⼤的提⾼ansible的执⾏效率。所以在使⽤ Ansible 的过程中,当管理的服务器数量增加时,不得不⾯对⼀个⽆法避免的问题执⾏效率慢,这⾥列出⼀些解决办法。
⼀、关闭gathering facts功能
如果观察过ansible-playbook的执⾏过程,就会发现ansible-playbook的第1个步骤总是执⾏gather facts,不论你有没有在playbook设定这个tasks。
如果你不需要获取被控机器的fact数据的话,就可以关闭获取fact数据功能。关闭之后,可以加快ansible-playbook的执⾏效率,尤其是你管理很⼤量的机器时,这⾮常明显。
关闭获取facts很简单,只需要在playbook⽂件中加上"gather_facts: Fal"或者"gather_facts: No"即可(Fal和No都为⼩写也可以)。
$ l
- hosts: test_rver
remote_ur: root
tasks:
- name: this is a test
shell: echo "haha"
# 执⾏这个paly,会发现第⼀个执⾏的是gather facts,因为默认是打开gather facts功能的
$ l
PLAY [test_rver] ******************************************************************************************************
TASK [Gathering Facts] **************************************************************************************************
ok: [10.4.7.102]
ok: [10.4.7.101]
TASK [this is a test] ***************************************************************************************************
changed: [10.4.7.102]
changed: [10.4.7.101]
PLAY RECAP **************************************************************************************************************
10.4.7.101 : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
10.4.7.102 : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
现在关闭gathering facts功能
$ l
- hosts: test_rver
remote_ur: root
gather_facts: Fal
tasks:
- name: this is a test
shell: echo "haha"
# 再执⾏这个play,就会发现没有了gathering facts执⾏过程,整个执⾏速度也快了!
$ l
PLAY [test_rver] ******************************************************************************************************
TASK [this is a test] ***************************************************************************************************
changed: [10.4.7.102]
changed: [10.4.7.101]
PLAY RECAP **************************************************************************************************************火上浇油的近义词
10.4.7.101 : ok=1 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
10.4.7.102 : ok=1 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
⼆、开启SSH pipelining
pipeline是openssh的⼀个特性,ssh pipelining是⼀个加速Ansible执⾏速度的简单⽅法。
在ansible执⾏每个任务的整个流程中,有⼀个过程是将临时任务⽂件put到远程的ansible客户机上,然后通过ssh连接过去远程执⾏这个任务。
如果开启了pipelining,⼀个任务的所有动作都在⼀个ssh会话中完成,也会省去sftp到远端的过程,它会直接将要执⾏的任务在ssh会话中进⾏。
ssh pipelining 默认是关闭之所以默认关闭是为了兼容不同的sudo配置,主要是 requiretty 选项。如果不使⽤sudo,建议开启
打开此选项可以减少ansible执⾏没有传输时ssh在被控机器上执⾏任务的连接数。
不过,如果使⽤sudo,必须关闭requiretty选项。修改/etc/ansible/ansible.cfg⽂件可以开启pipelining
$ vim /etc/ansible/ansible.cfg
........
pipelining = True
这样开启了pipelining之后, ansible执⾏的整个流程就少了⼀个PUT脚本去远程服务端的流程,然后就可以批量对机器执⾏命令试下,可以明显感受到速度的提升。
但是要注意的是:
如果在ansible中使⽤sudo命令的话(ssh ur@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编辑配置⽂件,注释该选项来禁⽤它。
$ grep requiretty /etc/sudoers
# Defaults requiretty
三、开启SSH长连接
ansible天然⽀持openssh,默认连接⽅式下,它对ssh的依赖性⾮常强。所以优化ssh连接,在⼀定程度上也在优化ansible。其中⼀点是开
启ssh的长连接,即长时间保持连接状态。
Ansible模式是使⽤SSH和远程主机进⾏通信, 所以Ansible对SSH的依赖性⾮常强, 在OpenSSH 5.6版本以后SSH就⽀持了Multiplexing(多路复⽤)。
所以如果Ansible中控机的SSH -V版本⾼于5.6时, 就可以使⽤ControlPersist来提⾼ssh连接速度,从⽽提⾼ansible执⾏效率。
$ cat /etc/redhat-relea
CentOS Linux relea 7.6.1810 (Core)
$ ssh -V
OpenSSH_7.4p1, OpenSSL 1.0.2k-fips 26 Jan 2017
$ vim /etc/ansible/ansible.cfg
..........
ssh_args = -C -o ControlMaster=auto -o ControlPersist=5d
金农系统# 注意:ConrolPersist=5d, 这个参数是设置整个长连接保持时间为5天。
开启此参数的ssh长连接功能后,在会话过期前会⼀直建⽴连接,在netstat的结果中会看到ssh连接是⼀直established状态,且通过SSH连接过的设备都会在当前⽤户家⽬录的
".ansible/cp"⽬录下⽣成⼀个socket⽂件,每个会话对应⽣成⼀个socket⽂件。也可以通过netstat命令查看, 会发现有⼀个ESTABLISHED状态的连接⼀直与远程设备进⾏着TCP连接。
$ ps -ef|grep ssh|grep ansible
root 26064 1 0 17:32 ? 00:00:00 ssh: /root/.ansible/cp/cb9972d2a5 [mux]
root 26067 1 0 17:32 ? 00:00:00 ssh: /root/.ansible/cp/baefa88ac8 [mux]
$ ps -ef|grep ssh|grep /root
root 26064 1 0 17:32 ? 00:00:00 ssh: /root/.ansible/cp/cb9972d2a5 [mux]
一年级美术画
root 26067 1 0 17:32 ? 00:00:00 ssh: /root/.ansible/cp/baefa88ac8 [mux]
$ ls /root/.ansible/cp/
baefa88ac8 cb9972d2a5
需要注意:
ControlPersist 特性需要⾼版本的SSH才⽀持,CentOS 6默认是不⽀持的,如果需要使⽤,需要⾃⾏升级openssh(确保SSH -V版本⾼于5.6)。
ControlPersist即持久化socket,⼀次验证,多次通信。并且只需要修改ssh客户端就⾏,也就是 Ansible 机器即可。
三、设置facts缓存
如果细⼼的话, 就会发现执⾏playbook的时候, 默认第⼀个task都是GATHERING FACTS, 这个过程就是Ansible在收集每台主机的facts信息。
⽅便我们在playbook中直接饮⽤facts⾥的信息,当然如果你的playbook中不需要facts信息, 可以在playbook中设置"gather_facts: Fal"来提⾼playbook效率.
但是如果我们既想在每次执⾏playbook的时候都能收集facts, ⼜想加速这个收集过程, 那么就需要配置facts缓存了。
3.1 使⽤json⽂件缓存
$ vim /etc/ansible/ansible.cfg
.........
gathering = smart
fact_caching_timeout = 86400
fact_caching = jsonfile
fact_caching_connection = /dev/shm/ansible_fact_cache
# 正常配置palybook,不需要关闭gathering facts功能
$ l
---
- hosts: 10.4.7.101
remote_ur: root
vars:
- list: [1,2,3]
tasks:
- name: this is loop
debug: msg="{{ item }}"
with_items: '{{list}}'
查看这个playbook过程,⽤时6.699s(第⼀次可能稍微慢点,缓存之后,后⾯执⾏就很快了)
$ time l
PLAY [10.4.7.101] *******************************************************************************************************************************
TASK [Gathering Facts] **************************************************************************************************************************
ok: [10.4.7.101]
TASK [this is loop] *****************************************************************************************************************************
ok: [10.4.7.101] => (item=1) => {
"msg": 1
}
ok: [10.4.7.101] => (item=2) => {
"msg": 2
}
ok: [10.4.7.101] => (item=3) => {
"msg": 3
}
PLAY RECAP **************************************************************************************************************************************
10.4.7.101 : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
real 0m6.699s
ur 0m1.301s
sys 0m0.250s
# 如果去掉上⾯的facts缓存的四⾏配置,再次执⾏上⾯的playbok,发现⽤时10s左右
# 查看缓存⽂件
$ ls /dev/shm/ansible_fact_cache/
10.4.7.101
3.2 使⽤redis存储facts⽂件需安装redis,还需要安装python库
$ yum install redis
$ yum -y install epel-relea
$ yum install python-pip
$ pip install redis
$ vim /etc/ansible/ansible.cfg
........
太阳新天地
gathering = smart
facts_caching_timeout = 86400 #设置缓存过期时间86400秒
facts_caching = redis # 使⽤redis或者 (或者使⽤memcached,即"facts_caching = memcached")
fact_caching_connection = 127.0.0.1:6379
#若redis设置了密码,⽐如密码为"admin",则配置修改如下:
# fact_caching_connection = localhost:6379:0:admin
$ systemctl start redis
$ lsof -i:6379
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
redis-r 26593 redis 4u IPv4 125427 0t0 TCP localhost:6379 (LISTEN)
$ time l
PLAY [10.4.7.101] *******************************************************************************************************************************
TASK [Gathering Facts] **************************************************************************************************************************
ok: [10.4.7.101]
TASK [this is loop] *****************************************************************************************************************************
ok: [10.4.7.101] => (item=1) => {
"msg": 1
}
ok: [10.4.7.101] => (item=2) => {
"msg": 2
种间关系
竞争上岗演讲稿
}
ok: [10.4.7.101] => (item=3) => {
"msg": 3
}
PLAY RECAP **************************************************************************************************************************************
10.4.7.101 : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
real 0m6.720s
ur 0m1.219s
sys 0m0.338s
需要注意:
在使⽤redis缓存后,如果出现异常(若未出现,请忽略):TypeError: the JSON object must be str, not 'bytes'。
解决办法:
$ find / -name ansible
$ vim /usr/lib/python2.7/site-packages/ansible/plugins/cache/redis.py
..........
lf._cache[key] = json.loads(value.decode('utf-8')) # 修改为这个
查看redis存储情况
$ redis-cli
127.0.0.1:6379> keys *
1) "ansible_facts10.4.7.101"
2) "ansible_cache_keys"
总之:不同⽹络环境下的耗时肯定是不同的,但是设置缓存是肯定可以加快 Ansible 运⾏速度的,特别是 playbook 的运⾏。
四、Ansible取消交互
物流工作总结
$ vim /etc/ansible/ansible.cfg
........
host_key_checking = Fal # 打开注释即可
# 取消ssh的yes和no的交互:
$ vim /root/.ssh/config
UrKnownHostsFile /dev/null
ConnectTimeout 15
StrictHostKeyChecking no
或者直接ssh时增加⼀个参数
$ ssh -o StrictHostKeyChecking=no -p22 root@10.4.7.101
五、Ansible的-t选项,提⾼ansible执⾏效率
ansible的"-t"或"--tree"选项是将ansible的执⾏结果按主机名保存在指定⽬录下的⽂件中。
有些时候,ansible执⾏起来的速度会⾮常慢,这种慢体现在即使执⾏的是⼀个⽴即返回的简单命令(如ping模块),也会耗时很久,且不是因为ssh连接慢导致的。
如果使⽤-t选项,将第⼀次执⾏得到的结果按inventory中定义的主机名保存在⽂件中,下次执⾏到同⼀台主机时速度将会变快很多,即使之后不再加上-t选项,
也可以在⼀定时间内保持迅速执⾏。即使执⾏速度正常(如执⾏⼀个Ping命令0.7秒左右),使⽤-t选项也可以在此基础上变得更快。
安全施工组织设计
除了使⽤-t选项,使⽤重定向将结果重定向到某个⽂件中也是⼀样的效果。
这也算是⼀种ansible提速⽅式,但在centos6上使⽤低版本ansible时,有时会出现执⾏很慢的现象,但不是每次都这样,且centos7执⾏速度正常
所以这也是⼀种"bug"式问题,故这种⽅式没有通⽤性。
$ time ansible test_rver -m command -a "hostname"
$ time ansible test_rver -m command -a "hostname" -t /tmp/test
$ ll /tmp/test/
总⽤量 8
-rw-r--r--. 1 root root 236 2⽉ 7 17:59 10.4.7.101
-rw-r--r--. 1 root root 307 2⽉ 7 17:59 10.4.7.102
上⾯做了对⽐,发现使⽤-t或重定向⽅式,将ansible的执⾏结果按主机名保存在指定⽬录下的⽂件中,ansible执⾏效率会有所提升。