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: False"
或者 "gather_facts: No"
即可(False和No都为小写也可以)。
$ cat test.yml - hosts: test_server remote_user: root tasks: - name: this is a test shell: echo "haha" # 执行这个paly,会发现第一个执行的是gather facts,因为默认是打开gather facts功能的!!!! $ ansible-playbook test.yml PLAY [test_server] ****************************************************************************************************** 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功能
$ cat test.yml - hosts: test_server remote_user: root gather_facts: False tasks: - name: this is a test shell: echo "haha" # 再执行这个play,就会发现没有了gathering facts执行过程,整个执行速度也快了! $ ansible-playbook test.yml PLAY [test_server] ****************************************************************************************************** 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 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编辑配置文件,注释该选项来禁用它。
$ 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-release CentOS Linux release 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: False"
来提高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功能 $ cat test.yml --- - hosts: 10.4.7.101 remote_user: root vars: - list: [1,2,3] tasks: - name: this is loop debug: msg="{{ item }}" with_items: '{{list}}' 查看这个playbook过程,用时6.699s(第一次可能稍微慢点,缓存之后,后面执行就很快了) $ time ansible-playbook test.yml 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 user 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-release $ 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-ser 26593 redis 4u IPv4 125427 0t0 TCP localhost:6379 (LISTEN) $ time ansible-playbook test.yml 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 user 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 .......... self._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 = False # 打开注释即可 # 取消ssh的yes和no的交互: $ vim /root/.ssh/config UserKnownHostsFile /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_server -m command -a "hostname" $ time ansible test_server -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执行效率会有所提升。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律