优化Ansible速度 ​1. Ansible与SaltStack的对比1.1 VirtualBox虚拟机说明1.2 测试剧本说明2. 优化策略2.1 开启SSH长连接2.2 开启pipelining2.3 开启accelerate模式2.4 设置fact缓存1. Ansible与SaltStack的对比 ​特点AnsibleSaltStack语言使用YAML语法编写Playbooks使用Python语法编写States是否有客户端无有运行方式Push模式,通过SSH远程执行操作Push或Pull模式,通过ZeroMQ进行通信应用范围适用于配置管理、自动化部署、应用发布等适用于配置管理、监控、自动部署扩展性插件丰富,易于扩展功能拥有强大的扩展性,能够定制各种功能管理和监控简单易用,可直接在控制端执行操作开箱即用,自带管理和监控功能社区支持拥有庞大的社区用户群社区规模较小,但质量较高学习曲线相对较低,易上手学习曲线较陡峭,需要一定的技术基础安全可控通过SSH加密传输数据,较为安全通过ZeroMQ传输数据,也较为安全有些人说Ansible的执行效率比SaltStack低,确实,使用默认的SSH方式通信,效率远低于SaltStack的zeromq消息队列。下面来介绍一些优化Ansible执行速度的方法。

1.1 VirtualBox虚拟机说明 ​使用以下环境进行测试。

序号虚拟机主机名IPCPU内存说明1ansible-masteransible192.168.56.1202核4GAnsible控制节点2ansible-node1node1192.168.56.1212核2GAnsible工作节点13ansible-node2node2192.168.56.1222核2GAnsible工作节点24ansible-node3node3192.168.56.1232核2GAnsible工作节点31.2 测试剧本说明 ​你可以参考ansible role角色(4)--include的使用 我们使用该剧本来测试执行时间。

由于我之前多次执行过剧本,相关配置差不多都配置到呼工作节点了。此时执行一遍剧本文件,看看用时多久:

sh# 第一次统计输出时间

[root@ansible ansible_playbooks]# time ansible-playbook -i base_hosts.ini base.yml

PLAY [basehosts] *****************************************************************************************************************************************************************************************************************************************************************************

TASK [Gathering Facts] ***********************************************************************************************************************************************************************************************************************************************************************

ok: [192.168.56.121]

ok: [192.168.56.122]

ok: [192.168.56.123]

TASK [base : Show hostname] ******************************************************************************************************************************************************************************************************************************************************************

ok: [192.168.56.121] => {

"msg": "ansible-node1"

}

ok: [192.168.56.123] => {

"msg": "ansible-node3"

}

ok: [192.168.56.122] => {

"msg": "ansible-node2"

}

TASK [base : Set hostname] *******************************************************************************************************************************************************************************************************************************************************************

ok: [192.168.56.122]

ok: [192.168.56.123]

ok: [192.168.56.121]

TASK [base : Get SELinux value] **************************************************************************************************************************************************************************************************************************************************************

ok: [192.168.56.123]

ok: [192.168.56.122]

ok: [192.168.56.121]

TASK [base : Set SELinux prints warnings instead of enforcing] *******************************************************************************************************************************************************************************************************************************

skipping: [192.168.56.121]

skipping: [192.168.56.122]

skipping: [192.168.56.123]

TASK [base : Ensure SELinux is set to disable mode] ******************************************************************************************************************************************************************************************************************************************

ok: [192.168.56.121]

ok: [192.168.56.122]

ok: [192.168.56.123]

TASK [base : Get SELinux value] **************************************************************************************************************************************************************************************************************************************************************

ok: [192.168.56.121]

ok: [192.168.56.122]

ok: [192.168.56.123]

TASK [base : Create a directory if it does not exist] ****************************************************************************************************************************************************************************************************************************************

ok: [192.168.56.122]

ok: [192.168.56.121]

ok: [192.168.56.123]

TASK [base : Create backup directory] ********************************************************************************************************************************************************************************************************************************************************

ok: [192.168.56.121]

ok: [192.168.56.123]

ok: [192.168.56.122]

TASK [base : Backup old repo config] *********************************************************************************************************************************************************************************************************************************************************

ok: [192.168.56.121] => (item={u'dest': u'/etc/yum.repos.d.bak', u'src': u'/etc/yum.repos.d'})

ok: [192.168.56.122] => (item={u'dest': u'/etc/yum.repos.d.bak', u'src': u'/etc/yum.repos.d'})

ok: [192.168.56.123] => (item={u'dest': u'/etc/yum.repos.d.bak', u'src': u'/etc/yum.repos.d'})

TASK [base : Create backup directory] ********************************************************************************************************************************************************************************************************************************************************

ok: [192.168.56.121]

ok: [192.168.56.122]

ok: [192.168.56.123]

TASK [base : Copy repo and pypi config] ******************************************************************************************************************************************************************************************************************************************************

ok: [192.168.56.121] => (item={u'dest': u'/etc/yum.repos.d/Centos-7.repo', u'src': u'Centos-7.repo'})

ok: [192.168.56.122] => (item={u'dest': u'/etc/yum.repos.d/Centos-7.repo', u'src': u'Centos-7.repo'})

ok: [192.168.56.123] => (item={u'dest': u'/etc/yum.repos.d/Centos-7.repo', u'src': u'Centos-7.repo'})

ok: [192.168.56.121] => (item={u'dest': u'/etc/yum.repos.d/epel-7.repo', u'src': u'epel-7.repo'})

ok: [192.168.56.122] => (item={u'dest': u'/etc/yum.repos.d/epel-7.repo', u'src': u'epel-7.repo'})

ok: [192.168.56.123] => (item={u'dest': u'/etc/yum.repos.d/epel-7.repo', u'src': u'epel-7.repo'})

ok: [192.168.56.121] => (item={u'dest': u'~/.pip/pip.conf', u'src': u'pip.conf'})

ok: [192.168.56.123] => (item={u'dest': u'~/.pip/pip.conf', u'src': u'pip.conf'})

ok: [192.168.56.122] => (item={u'dest': u'~/.pip/pip.conf', u'src': u'pip.conf'})

TASK [base : ensure a list of packages installed] ********************************************************************************************************************************************************************************************************************************************

ok: [192.168.56.121]

ok: [192.168.56.122]

ok: [192.168.56.123]

TASK [create base folder] ********************************************************************************************************************************************************************************************************************************************************************

changed: [192.168.56.121]

changed: [192.168.56.122]

changed: [192.168.56.123]

TASK [base : Extract safe-rm-0.12.tar.gz into /srv/safe-rm] **********************************************************************************************************************************************************************************************************************************

changed: [192.168.56.122]

changed: [192.168.56.121]

changed: [192.168.56.123]

TASK [base : Move safe-rm to /usr/bin] *******************************************************************************************************************************************************************************************************************************************************

ok: [192.168.56.121]

ok: [192.168.56.122]

ok: [192.168.56.123]

TASK [base : Delete temp folder] *************************************************************************************************************************************************************************************************************************************************************

changed: [192.168.56.122]

changed: [192.168.56.121]

changed: [192.168.56.123]

TASK [base : Copy safe-rm config] ************************************************************************************************************************************************************************************************************************************************************

ok: [192.168.56.121]

ok: [192.168.56.123]

ok: [192.168.56.122]

TASK [base : Update pip command] *************************************************************************************************************************************************************************************************************************************************************

changed: [192.168.56.123]

changed: [192.168.56.122]

changed: [192.168.56.121]

TASK [base : Install python package] *********************************************************************************************************************************************************************************************************************************************************

ok: [192.168.56.122]

ok: [192.168.56.123]

ok: [192.168.56.121]

TASK [base : Sync time at every 10 minutes] **************************************************************************************************************************************************************************************************************************************************

ok: [192.168.56.122]

ok: [192.168.56.123]

ok: [192.168.56.121]

TASK [base : Sync time at 2:30 am] ***********************************************************************************************************************************************************************************************************************************************************

ok: [192.168.56.121]

ok: [192.168.56.123]

ok: [192.168.56.122]

TASK [base : Print the IP] *******************************************************************************************************************************************************************************************************************************************************************

ok: [192.168.56.121] => {

"msg": "HOST_IP: 192.168.56.121"

}

ok: [192.168.56.122] => {

"msg": "HOST_IP: 192.168.56.122"

}

ok: [192.168.56.123] => {

"msg": "HOST_IP: 192.168.56.123"

}

TASK [base : Remove sshkey file] *************************************************************************************************************************************************************************************************************************************************************

changed: [192.168.56.121] => (item=/root/.ssh/id_rsa)

changed: [192.168.56.122] => (item=/root/.ssh/id_rsa)

changed: [192.168.56.123] => (item=/root/.ssh/id_rsa)

changed: [192.168.56.121] => (item=/root/.ssh/id_rsa.pub)

changed: [192.168.56.122] => (item=/root/.ssh/id_rsa.pub)

changed: [192.168.56.123] => (item=/root/.ssh/id_rsa.pub)

TASK [base : Generate SSH key pair] **********************************************************************************************************************************************************************************************************************************************************

changed: [192.168.56.121]

changed: [192.168.56.122]

changed: [192.168.56.123]

TASK [base : Copy alias config] **************************************************************************************************************************************************************************************************************************************************************

ok: [192.168.56.123]

ok: [192.168.56.121]

ok: [192.168.56.122]

TASK [base : Insert block to .bashrc] ********************************************************************************************************************************************************************************************************************************************************

ok: [192.168.56.121]

ok: [192.168.56.122]

ok: [192.168.56.123]

PLAY RECAP ***********************************************************************************************************************************************************************************************************************************************************************************

192.168.56.121 : ok=26 changed=6 unreachable=0 failed=0 skipped=1 rescued=0 ignored=0

192.168.56.122 : ok=26 changed=6 unreachable=0 failed=0 skipped=1 rescued=0 ignored=0

192.168.56.123 : ok=26 changed=6 unreachable=0 failed=0 skipped=1 rescued=0 ignored=0

real 0m25.265s

user 0m9.161s

sys 0m4.371s

[root@ansible ansible_playbooks]#123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171时间输出结果说明:

real是程序的实际运行时间,从程序开始到程序执行结束时所消耗的时间,包括CPU的用时和所有延迟程序执行的因素的总和。CPU用时被划分为user和sys两块。

user是用户态的时间,表示程序本身,以及它所调用的库中的子例程使用的时间。

sys是内核态的时间,是由程序直接或间接调用的系统调用执行的时间。

单核情况,real远远大于user和sys之和。

real=CPU用时+其他因素时间。

CPU用时=user+sys。

因此,我们在此处主要关注real用时输出。

重复再执行三次,看输出结果:

sh# 第2次执行,统计输出时间

[root@ansible ansible_playbooks]# time ansible-playbook -i base_hosts.ini base.yml

...过程输出省略

real 0m16.135s

user 0m9.308s

sys 0m4.259s

[root@ansible ansible_playbooks]#

# 第3次执行,统计输出时间

[root@ansible ansible_playbooks]# time ansible-playbook -i base_hosts.ini base.yml

...过程输出省略

real 0m15.673s

user 0m9.404s

sys 0m3.874s

[root@ansible ansible_playbooks]#

# 第4次执行,统计输出时间

[root@ansible ansible_playbooks]# time ansible-playbook -i base_hosts.ini base.yml

...过程输出省略

real 0m15.562s

user 0m9.466s

sys 0m3.725s

[root@ansible ansible_playbooks]#123456789101112131415161718192021可以看到,后面3次实际用时差不多都是16秒钟。我们后面测试就来对比这个时间。

2. 优化策略 ​2.1 开启SSH长连接 ​在OpenSSH 5.6版本以后SSH就支持了Multiplexing。如果Ansible控制节点SSH版本高于5.6就可以开启SSH长连接。

我们来检查一下:

sh[root@ansible ~]# ssh -V

OpenSSH_7.4p1, OpenSSL 1.0.2k-fips 26 Jan 2017

[root@ansible ~]#123可以看到,控制节点SSH版本为OpenSSH_7.4p1,满足要求。

直接在ansible.cfg文件中设置SSH长连接即可。设置参数如下:

ssh_args = -C -o ControlMaster=auto -o ControlPersist=5d1ControlPersist=5d这个参数是设置整个长连接保持时间为5天。如果开启该功能,通过SSH连接过的的设备都会在当前~/.ansible/cp目录下生成一个socket文件。

先来看看配置文件中有没有这个参数:

sh[root@ansible ~]# grep sh_args /etc/ansible/ansible.cfg

#ssh_args = -C -o ControlMaster=auto -o ControlPersist=60s

[root@ansible ~]#123可以看到,默认注释掉了该参数。

修改前,先备份一下原来的配置文件:

sh[root@ansible ~]# ll /etc/ansible/ansible.cfg*

-rw-r--r--. 1 root root 19985 Jan 16 2022 /etc/ansible/ansible.cfg

[root@ansible ~]# cp -p /etc/ansible/ansible.cfg /etc/ansible/ansible.cfg.default123然后使用vim编辑/etc/ansible/ansible.cfg配置文件,并增加ssh_args参数,修改后查看配置信息:

sh[root@ansible ~]# grep -C5 sh_args /etc/ansible/ansible.cfg

[ssh_connection]

# ssh arguments to use

# Leaving off ControlPersist will result in poor performance, so use

# paramiko on older platforms rather than removing it, -C controls compression use

#ssh_args = -C -o ControlMaster=auto -o ControlPersist=60s

ssh_args = -C -o ControlMaster=auto -o ControlPersist=5d

# The base directory for the ControlPath sockets.

# This is the "%(directory)s" in the control_path option

#

# Example:

[root@ansible ~]#1234567891011121314为了检查后面会不会连接长连接,先安装net-tools包,然后使用netstat命令查看当前连接信息:

sh[root@ansible ~]# yum install net-tools

Loaded plugins: fastestmirror

Determining fastest mirrors

base | 3.6 kB 00:00:00

epel | 4.7 kB 00:00:00

extras | 2.9 kB 00:00:00

updates | 2.9 kB 00:00:00

(1/5): epel/x86_64/group_gz | 100 kB 00:00:00

(2/5): epel/x86_64/updateinfo | 1.0 MB 00:00:00

(3/5): extras/7/x86_64/primary_db | 250 kB 00:00:00

(4/5): epel/x86_64/primary_db | 7.0 MB 00:00:01

(5/5): updates/7/x86_64/primary_db | 25 MB 00:00:08

Resolving Dependencies

--> Running transaction check

---> Package net-tools.x86_64 0:2.0-0.25.20131004git.el7 will be installed

--> Finished Dependency Resolution

Dependencies Resolved

==============================================================================================================================================================================================================================================================================================

Package Arch Version Repository Size

==============================================================================================================================================================================================================================================================================================

Installing:

net-tools x86_64 2.0-0.25.20131004git.el7 base 306 k

Transaction Summary

==============================================================================================================================================================================================================================================================================================

Install 1 Package

Total download size: 306 k

Installed size: 917 k

Is this ok [y/d/N]: y

Downloading packages:

net-tools-2.0-0.25.20131004git.el7.x86_64.rpm | 306 kB 00:00:00

Running transaction check

Running transaction test

Transaction test succeeded

Running transaction

Installing : net-tools-2.0-0.25.20131004git.el7.x86_64 1/1

Verifying : net-tools-2.0-0.25.20131004git.el7.x86_64 1/1

Installed:

net-tools.x86_64 0:2.0-0.25.20131004git.el7

Complete!

[root@ansible ~]# netstat -ato

Active Internet connections (servers and established)

Proto Recv-Q Send-Q Local Address Foreign Address State Timer

tcp 0 0 0.0.0.0:ssh 0.0.0.0:* LISTEN off (0.00/0/0)

tcp 0 0 localhost:smtp 0.0.0.0:* LISTEN off (0.00/0/0)

tcp 0 0 ansible:37438 101.6.15.130:https TIME_WAIT timewait (41.86/0/0)

tcp 0 0 ansible:37436 101.6.15.130:https TIME_WAIT timewait (57.06/0/0)

tcp 0 0 ansible:37444 101.6.15.130:https TIME_WAIT timewait (49.59/0/0)

tcp 0 0 ansible:37446 101.6.15.130:https TIME_WAIT timewait (57.04/0/0)

tcp 0 48 ansible-master:ssh 192.168.56.1:8421 ESTABLISHED on (0.22/0/0)

tcp 0 0 ansible:37442 101.6.15.130:https TIME_WAIT timewait (43.11/0/0)

tcp 0 0 ansible:37439 101.6.15.130:https TIME_WAIT timewait (49.55/0/0)

tcp 0 0 ansible-master:ssh 192.168.56.1:8423 ESTABLISHED keepalive (4321.38/0/0)

tcp6 0 0 [::]:ssh [::]:* LISTEN off (0.00/0/0)

tcp6 0 0 localhost:smtp [::]:* LISTEN off (0.00/0/0)

[root@ansible ~]#12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061切换到剧本目录,再次执行剧本:

sh[root@ansible ~]# cd ansible_playbooks/

[root@ansible ansible_playbooks]# time ansible-playbook -i base_hosts.ini base.yml

PLAY [basehosts] *****************************************************************************************************************************************************************************************************************************************************************************

TASK [Gathering Facts] ***********************************************************************************************************************************************************************************************************************************************************************

ok: [192.168.56.122]

ok: [192.168.56.121]

ok: [192.168.56.123]

TASK [base : Show hostname] ******************************************************************************************************************************************************************************************************************************************************************

ok: [192.168.56.121] => {

"msg": "ansible-node1"

}

ok: [192.168.56.122] => {

"msg": "ansible-node2"

}

ok: [192.168.56.123] => {

"msg": "ansible-node3"

}

TASK [base : Set hostname] *******************************************************************************************************************************************************************************************************************************************************************

ok: [192.168.56.122]

ok: [192.168.56.121]

ok: [192.168.56.123]

TASK [base : Get SELinux value] **************************************************************************************************************************************************************************************************************************************************************

ok: [192.168.56.123]

ok: [192.168.56.122]

ok: [192.168.56.121]

TASK [base : Set SELinux prints warnings instead of enforcing] *******************************************************************************************************************************************************************************************************************************

skipping: [192.168.56.121]

skipping: [192.168.56.122]

skipping: [192.168.56.123]

TASK [base : Ensure SELinux is set to disable mode] ******************************************************************************************************************************************************************************************************************************************

ok: [192.168.56.123]

ok: [192.168.56.121]

ok: [192.168.56.122]

TASK [base : Get SELinux value] **************************************************************************************************************************************************************************************************************************************************************

ok: [192.168.56.121]

ok: [192.168.56.122]

ok: [192.168.56.123]

TASK [base : Create a directory if it does not exist] ****************************************************************************************************************************************************************************************************************************************

ok: [192.168.56.123]

ok: [192.168.56.122]

ok: [192.168.56.121]

TASK [base : Create backup directory] ********************************************************************************************************************************************************************************************************************************************************

ok: [192.168.56.121]

ok: [192.168.56.122]

ok: [192.168.56.123]

TASK [base : Backup old repo config] *********************************************************************************************************************************************************************************************************************************************************

ok: [192.168.56.121] => (item={u'dest': u'/etc/yum.repos.d.bak', u'src': u'/etc/yum.repos.d'})

ok: [192.168.56.123] => (item={u'dest': u'/etc/yum.repos.d.bak', u'src': u'/etc/yum.repos.d'})

ok: [192.168.56.122] => (item={u'dest': u'/etc/yum.repos.d.bak', u'src': u'/etc/yum.repos.d'})

TASK [base : Create backup directory] ********************************************************************************************************************************************************************************************************************************************************

ok: [192.168.56.121]

ok: [192.168.56.122]

ok: [192.168.56.123]

TASK [base : Copy repo and pypi config] ******************************************************************************************************************************************************************************************************************************************************

ok: [192.168.56.122] => (item={u'dest': u'/etc/yum.repos.d/Centos-7.repo', u'src': u'Centos-7.repo'})

ok: [192.168.56.121] => (item={u'dest': u'/etc/yum.repos.d/Centos-7.repo', u'src': u'Centos-7.repo'})

ok: [192.168.56.123] => (item={u'dest': u'/etc/yum.repos.d/Centos-7.repo', u'src': u'Centos-7.repo'})

ok: [192.168.56.122] => (item={u'dest': u'/etc/yum.repos.d/epel-7.repo', u'src': u'epel-7.repo'})

ok: [192.168.56.123] => (item={u'dest': u'/etc/yum.repos.d/epel-7.repo', u'src': u'epel-7.repo'})

ok: [192.168.56.121] => (item={u'dest': u'/etc/yum.repos.d/epel-7.repo', u'src': u'epel-7.repo'})

ok: [192.168.56.122] => (item={u'dest': u'~/.pip/pip.conf', u'src': u'pip.conf'})

ok: [192.168.56.123] => (item={u'dest': u'~/.pip/pip.conf', u'src': u'pip.conf'})

ok: [192.168.56.121] => (item={u'dest': u'~/.pip/pip.conf', u'src': u'pip.conf'})

TASK [base : ensure a list of packages installed] ********************************************************************************************************************************************************************************************************************************************

ok: [192.168.56.122]

ok: [192.168.56.121]

ok: [192.168.56.123]

TASK [create base folder] ********************************************************************************************************************************************************************************************************************************************************************

changed: [192.168.56.122]

changed: [192.168.56.121]

changed: [192.168.56.123]

TASK [base : Extract safe-rm-0.12.tar.gz into /srv/safe-rm] **********************************************************************************************************************************************************************************************************************************

changed: [192.168.56.123]

changed: [192.168.56.122]

changed: [192.168.56.121]

TASK [base : Move safe-rm to /usr/bin] *******************************************************************************************************************************************************************************************************************************************************

ok: [192.168.56.122]

ok: [192.168.56.121]

ok: [192.168.56.123]

TASK [base : Delete temp folder] *************************************************************************************************************************************************************************************************************************************************************

changed: [192.168.56.121]

changed: [192.168.56.123]

changed: [192.168.56.122]

TASK [base : Copy safe-rm config] ************************************************************************************************************************************************************************************************************************************************************

ok: [192.168.56.121]

ok: [192.168.56.122]

ok: [192.168.56.123]

TASK [base : Update pip command] *************************************************************************************************************************************************************************************************************************************************************

changed: [192.168.56.123]

changed: [192.168.56.122]

changed: [192.168.56.121]

TASK [base : Install python package] *********************************************************************************************************************************************************************************************************************************************************

ok: [192.168.56.122]

ok: [192.168.56.123]

ok: [192.168.56.121]

TASK [base : Sync time at every 10 minutes] **************************************************************************************************************************************************************************************************************************************************

ok: [192.168.56.121]

ok: [192.168.56.122]

ok: [192.168.56.123]

TASK [base : Sync time at 2:30 am] ***********************************************************************************************************************************************************************************************************************************************************

ok: [192.168.56.121]

ok: [192.168.56.122]

ok: [192.168.56.123]

TASK [base : Print the IP] *******************************************************************************************************************************************************************************************************************************************************************

ok: [192.168.56.121] => {

"msg": "HOST_IP: 192.168.56.121"

}

ok: [192.168.56.122] => {

"msg": "HOST_IP: 192.168.56.122"

}

ok: [192.168.56.123] => {

"msg": "HOST_IP: 192.168.56.123"

}

TASK [base : Remove sshkey file] *************************************************************************************************************************************************************************************************************************************************************

changed: [192.168.56.121] => (item=/root/.ssh/id_rsa)

changed: [192.168.56.122] => (item=/root/.ssh/id_rsa)

changed: [192.168.56.123] => (item=/root/.ssh/id_rsa)

changed: [192.168.56.123] => (item=/root/.ssh/id_rsa.pub)

changed: [192.168.56.121] => (item=/root/.ssh/id_rsa.pub)

changed: [192.168.56.122] => (item=/root/.ssh/id_rsa.pub)

TASK [base : Generate SSH key pair] **********************************************************************************************************************************************************************************************************************************************************

changed: [192.168.56.121]

changed: [192.168.56.123]

changed: [192.168.56.122]

TASK [base : Copy alias config] **************************************************************************************************************************************************************************************************************************************************************

ok: [192.168.56.122]

ok: [192.168.56.121]

ok: [192.168.56.123]

TASK [base : Insert block to .bashrc] ********************************************************************************************************************************************************************************************************************************************************

ok: [192.168.56.121]

ok: [192.168.56.122]

ok: [192.168.56.123]

PLAY RECAP ***********************************************************************************************************************************************************************************************************************************************************************************

192.168.56.121 : ok=26 changed=6 unreachable=0 failed=0 skipped=1 rescued=0 ignored=0

192.168.56.122 : ok=26 changed=6 unreachable=0 failed=0 skipped=1 rescued=0 ignored=0

192.168.56.123 : ok=26 changed=6 unreachable=0 failed=0 skipped=1 rescued=0 ignored=0

real 0m16.704s

user 0m9.431s

sys 0m4.175s

[root@ansible ansible_playbooks]#123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171可以看到,开启长连接后,第一次执行剧本,用时16s,与未开启长连接前用时一致。

检查是否用长连接:

sh[root@ansible ansible_playbooks]# netstat -ato

Active Internet connections (servers and established)

Proto Recv-Q Send-Q Local Address Foreign Address State Timer

tcp 0 0 0.0.0.0:ssh 0.0.0.0:* LISTEN off (0.00/0/0)

tcp 0 0 localhost:smtp 0.0.0.0:* LISTEN off (0.00/0/0)

tcp 0 0 ansible-master:48610 ansible-node3:ssh ESTABLISHED keepalive (7040.48/0/0)

tcp 0 0 ansible-master:36912 ansible-node2:ssh ESTABLISHED keepalive (7040.48/0/0)

tcp 0 0 ansible-master:44752 ansible-node1:ssh ESTABLISHED keepalive (7040.48/0/0)

tcp 0 48 ansible-master:ssh 192.168.56.1:8421 ESTABLISHED on (0.23/0/0)

tcp 0 0 ansible-master:ssh 192.168.56.1:8423 ESTABLISHED keepalive (4025.82/0/0)

tcp6 0 0 [::]:ssh [::]:* LISTEN off (0.00/0/0)

tcp6 0 0 localhost:smtp [::]:* LISTEN off (0.00/0/0)

[root@ansible ansible_playbooks]# ll ~/.ansible/cp/

total 0

srw-------. 1 root root 0 Mar 17 12:18 6e835d9f0e

srw-------. 1 root root 0 Mar 17 12:18 a734bde817

srw-------. 1 root root 0 Mar 17 12:18 f59c3dce9d

[root@ansible ansible_playbooks]#123456789101112131415161718

可以看到,长连接建立了,对应socket文件也生成了。

也可以通过以下命令判断~/.ansible/cp目录下的文件是socket文件:

sh[root@ansible ansible_playbooks]# file ~/.ansible/cp/6e835d9f0e

/root/.ansible/cp/6e835d9f0e: socket

[root@ansible ansible_playbooks]# file ~/.ansible/cp/a734bde817

/root/.ansible/cp/a734bde817: socket

[root@ansible ansible_playbooks]# file ~/.ansible/cp/f59c3dce9d

/root/.ansible/cp/f59c3dce9d: socket

[root@ansible ansible_playbooks]#1234567在工作节点上面检查一下:

sh# 在节点1上检查连接

[root@ansible-node1 ~]# netstat -ato|head -n 2 && netstat -ato|grep ansible

Active Internet connections (servers and established)

Proto Recv-Q Send-Q Local Address Foreign Address State Timer

tcp 0 0 ansible-node1:ssh 192.168.56.1:9859 ESTABLISHED keepalive (7084.41/0/0)

tcp 0 0 ansible-node1:ssh 192.168.56.120:44752 ESTABLISHED keepalive (6789.50/0/0)

tcp 0 0 ansible-node1:ssh 192.168.56.1:9861 ESTABLISHED keepalive (7084.41/0/0)

[root@ansible-node1 ~]#

# 在节点2上检查连接

[root@ansible-node2 ~]# netstat -ato|head -n 2 && netstat -ato|grep ansible

Active Internet connections (servers and established)

Proto Recv-Q Send-Q Local Address Foreign Address State Timer

tcp 0 0 ansible-node2:ssh 192.168.56.1:9899 ESTABLISHED keepalive (7215.16/0/0)

tcp 0 0 ansible-node2:ssh 192.168.56.120:36912 ESTABLISHED keepalive (6723.64/0/0)

tcp 0 0 ansible-node2:ssh 192.168.56.1:9897 ESTABLISHED keepalive (7215.16/0/0)

[root@ansible-node2 ~]#

# 在节点3上检查连接

[root@ansible-node3 ~]# netstat -ato|head -n 2 && netstat -ato|grep ansible

Active Internet connections (servers and established)

Proto Recv-Q Send-Q Local Address Foreign Address State Timer

tcp 0 160 ansible-node3:ssh 192.168.56.1:iua ESTABLISHED on (0.22/0/0)

tcp 0 0 ansible-node3:ssh 192.168.56.120:48610 ESTABLISHED keepalive (6732.82/0/0)

tcp 0 0 ansible-node3:ssh 192.168.:multicast-ping ESTABLISHED keepalive (7207.95/0/0)

[root@ansible-node3 ~]#1234567891011121314151617181920212223242526可以看到,工作节点上面也正常显示了与Ansible控制节点的连接。

建立连接后,再次执行一下剧本,看看是否会降低用时:

sh[root@ansible ansible_playbooks]# time ansible-playbook -i base_hosts.ini base.yml

PLAY [basehosts] *****************************************************************************************************************************************************************************************************************************************************************************

TASK [Gathering Facts] ***********************************************************************************************************************************************************************************************************************************************************************

ok: [192.168.56.122]

ok: [192.168.56.121]

ok: [192.168.56.123]

TASK [base : Show hostname] ******************************************************************************************************************************************************************************************************************************************************************

ok: [192.168.56.121] => {

"msg": "ansible-node1"

}

ok: [192.168.56.122] => {

"msg": "ansible-node2"

}

ok: [192.168.56.123] => {

"msg": "ansible-node3"

}

TASK [base : Set hostname] *******************************************************************************************************************************************************************************************************************************************************************

ok: [192.168.56.121]

ok: [192.168.56.123]

ok: [192.168.56.122]

TASK [base : Get SELinux value] **************************************************************************************************************************************************************************************************************************************************************

ok: [192.168.56.123]

ok: [192.168.56.122]

ok: [192.168.56.121]

TASK [base : Set SELinux prints warnings instead of enforcing] *******************************************************************************************************************************************************************************************************************************

skipping: [192.168.56.121]

skipping: [192.168.56.122]

skipping: [192.168.56.123]

TASK [base : Ensure SELinux is set to disable mode] ******************************************************************************************************************************************************************************************************************************************

ok: [192.168.56.122]

ok: [192.168.56.121]

ok: [192.168.56.123]

TASK [base : Get SELinux value] **************************************************************************************************************************************************************************************************************************************************************

ok: [192.168.56.121]

ok: [192.168.56.122]

ok: [192.168.56.123]

TASK [base : Create a directory if it does not exist] ****************************************************************************************************************************************************************************************************************************************

ok: [192.168.56.121]

ok: [192.168.56.122]

ok: [192.168.56.123]

TASK [base : Create backup directory] ********************************************************************************************************************************************************************************************************************************************************

ok: [192.168.56.122]

ok: [192.168.56.121]

ok: [192.168.56.123]

TASK [base : Backup old repo config] *********************************************************************************************************************************************************************************************************************************************************

ok: [192.168.56.122] => (item={u'dest': u'/etc/yum.repos.d.bak', u'src': u'/etc/yum.repos.d'})

ok: [192.168.56.123] => (item={u'dest': u'/etc/yum.repos.d.bak', u'src': u'/etc/yum.repos.d'})

ok: [192.168.56.121] => (item={u'dest': u'/etc/yum.repos.d.bak', u'src': u'/etc/yum.repos.d'})

TASK [base : Create backup directory] ********************************************************************************************************************************************************************************************************************************************************

ok: [192.168.56.121]

ok: [192.168.56.122]

ok: [192.168.56.123]

TASK [base : Copy repo and pypi config] ******************************************************************************************************************************************************************************************************************************************************

ok: [192.168.56.122] => (item={u'dest': u'/etc/yum.repos.d/Centos-7.repo', u'src': u'Centos-7.repo'})

ok: [192.168.56.121] => (item={u'dest': u'/etc/yum.repos.d/Centos-7.repo', u'src': u'Centos-7.repo'})

ok: [192.168.56.123] => (item={u'dest': u'/etc/yum.repos.d/Centos-7.repo', u'src': u'Centos-7.repo'})

ok: [192.168.56.122] => (item={u'dest': u'/etc/yum.repos.d/epel-7.repo', u'src': u'epel-7.repo'})

ok: [192.168.56.121] => (item={u'dest': u'/etc/yum.repos.d/epel-7.repo', u'src': u'epel-7.repo'})

ok: [192.168.56.123] => (item={u'dest': u'/etc/yum.repos.d/epel-7.repo', u'src': u'epel-7.repo'})

ok: [192.168.56.122] => (item={u'dest': u'~/.pip/pip.conf', u'src': u'pip.conf'})

ok: [192.168.56.121] => (item={u'dest': u'~/.pip/pip.conf', u'src': u'pip.conf'})

ok: [192.168.56.123] => (item={u'dest': u'~/.pip/pip.conf', u'src': u'pip.conf'})

TASK [base : ensure a list of packages installed] ********************************************************************************************************************************************************************************************************************************************

ok: [192.168.56.121]

ok: [192.168.56.123]

ok: [192.168.56.122]

TASK [create base folder] ********************************************************************************************************************************************************************************************************************************************************************

changed: [192.168.56.121]

changed: [192.168.56.123]

changed: [192.168.56.122]

TASK [base : Extract safe-rm-0.12.tar.gz into /srv/safe-rm] **********************************************************************************************************************************************************************************************************************************

changed: [192.168.56.122]

changed: [192.168.56.123]

changed: [192.168.56.121]

TASK [base : Move safe-rm to /usr/bin] *******************************************************************************************************************************************************************************************************************************************************

ok: [192.168.56.122]

ok: [192.168.56.121]

ok: [192.168.56.123]

TASK [base : Delete temp folder] *************************************************************************************************************************************************************************************************************************************************************

changed: [192.168.56.121]

changed: [192.168.56.122]

changed: [192.168.56.123]

TASK [base : Copy safe-rm config] ************************************************************************************************************************************************************************************************************************************************************

ok: [192.168.56.123]

ok: [192.168.56.121]

ok: [192.168.56.122]

TASK [base : Update pip command] *************************************************************************************************************************************************************************************************************************************************************

changed: [192.168.56.123]

changed: [192.168.56.121]

changed: [192.168.56.122]

TASK [base : Install python package] *********************************************************************************************************************************************************************************************************************************************************

ok: [192.168.56.122]

ok: [192.168.56.123]

ok: [192.168.56.121]

TASK [base : Sync time at every 10 minutes] **************************************************************************************************************************************************************************************************************************************************

ok: [192.168.56.121]

ok: [192.168.56.122]

ok: [192.168.56.123]

TASK [base : Sync time at 2:30 am] ***********************************************************************************************************************************************************************************************************************************************************

ok: [192.168.56.121]

ok: [192.168.56.123]

ok: [192.168.56.122]

TASK [base : Print the IP] *******************************************************************************************************************************************************************************************************************************************************************

ok: [192.168.56.121] => {

"msg": "HOST_IP: 192.168.56.121"

}

ok: [192.168.56.122] => {

"msg": "HOST_IP: 192.168.56.122"

}

ok: [192.168.56.123] => {

"msg": "HOST_IP: 192.168.56.123"

}

TASK [base : Remove sshkey file] *************************************************************************************************************************************************************************************************************************************************************

changed: [192.168.56.121] => (item=/root/.ssh/id_rsa)

changed: [192.168.56.122] => (item=/root/.ssh/id_rsa)

changed: [192.168.56.123] => (item=/root/.ssh/id_rsa)

changed: [192.168.56.122] => (item=/root/.ssh/id_rsa.pub)

changed: [192.168.56.121] => (item=/root/.ssh/id_rsa.pub)

changed: [192.168.56.123] => (item=/root/.ssh/id_rsa.pub)

TASK [base : Generate SSH key pair] **********************************************************************************************************************************************************************************************************************************************************

changed: [192.168.56.123]

changed: [192.168.56.122]

changed: [192.168.56.121]

TASK [base : Copy alias config] **************************************************************************************************************************************************************************************************************************************************************

ok: [192.168.56.121]

ok: [192.168.56.122]

ok: [192.168.56.123]

TASK [base : Insert block to .bashrc] ********************************************************************************************************************************************************************************************************************************************************

ok: [192.168.56.123]

ok: [192.168.56.122]

ok: [192.168.56.121]

PLAY RECAP ***********************************************************************************************************************************************************************************************************************************************************************************

192.168.56.121 : ok=26 changed=6 unreachable=0 failed=0 skipped=1 rescued=0 ignored=0

192.168.56.122 : ok=26 changed=6 unreachable=0 failed=0 skipped=1 rescued=0 ignored=0

192.168.56.123 : ok=26 changed=6 unreachable=0 failed=0 skipped=1 rescued=0 ignored=0

real 0m20.642s

user 0m9.591s

sys 0m4.031s

[root@ansible ansible_playbooks]#123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170

奇怪了,用时还超了,变成了20.6秒!!

再执行一次,用时还是变多了:

sh[root@ansible ansible_playbooks]# time ansible-playbook -i base_hosts.ini base.yml

...过程输出省略

real 0m21.651s

user 0m9.436s

sys 0m4.177s

[root@ansible ansible_playbooks]#123456通过以上实验可以看到:

开启长连接后,Ansible会保持和目标主机的持续连接,减少了连接的建立和断开时间,但是在执行剧本时,由于要维持这种长连接,可能会增加一些额外的网络开销和系统资源的消耗,导致执行剧本的时间变长。此外,可能还会受到网络延迟等因素的影响,进一步增加执行剧本的时间。因此,尽管长连接可以提高效率,但在某些情况下也可能导致执行时间变长。2.2 开启pipelining ​pipelining也是OpenSSH的一个特性。如果开启了pipelining功能,Ansible会改变默认的执行过程,默认情况下,Ansible有一个流程是把生成好的本地Python脚本PUT到远程服务器,开启pipelining功能后,这个过程将会在SSH的会话中进行,这样可以大大提高整个执行效率。但开启pipelining,需要被控主机/etc/sudoers文件编辑当前Ansible SSH用户为requiretty,否则在执行时会报异常。修改/etc/ansible/ansible.cfg后,查看配置情况:

sh[root@ansible ansible_playbooks]# grep pipelining /etc/ansible/ansible.cfg

# Enabling pipelining reduces the number of SSH operations required to

#pipelining = False

pipelining = True

# The -tt argument is passed to ssh when pipelining is not enabled because sudo

[root@ansible ansible_playbooks]#123456此时执行剧本:

sh[root@ansible ansible_playbooks]# time ansible-playbook -i base_hosts.ini base.yml

...过程输出省略

real 0m12.928s

user 0m7.716s

sys 0m2.435s

[root@ansible ansible_playbooks]#123456可以看到,用时减少了,再执行一次:

sh[root@ansible ansible_playbooks]# time ansible-playbook -i base_hosts.ini base.yml

...过程输出省略

real 0m12.877s

user 0m7.510s

sys 0m2.749s

[root@ansible ansible_playbooks]#123456可以看到,开启了pipelining功能后,总用时约为13秒,相当于默认情况下约快了3秒钟。

如果开启-vvvv详细日志参数,可以看到日志中会出现很多Pipelining is enabled的信息:

我们将配置文件中新增加的pipelining = True删除掉:

sh# 关闭pipelining功能

[root@ansible ansible_playbooks]# grep pipelining /etc/ansible/ansible.cfg

# Enabling pipelining reduces the number of SSH operations required to

#pipelining = False

# The -tt argument is passed to ssh when pipelining is not enabled because sudo

[root@ansible ansible_playbooks]#123456再执行剧本:

日志中没有出现Pipelining is enabled的信息。

注意,开启-vvvv详细日志参数时,剧本执行时间会增加。

按我们测试的剧本来算,默认情况下用时是16秒,开启pipelining功能后用时13秒,速度优化3秒,优化百分比为3/16*100%=18.75%,提升还是不错的。

2.3 开启accelerate模式 ​Ansible还有一个accelerate加速模式,这与前面SSH的Multiplexing有点类似,因为都依赖Ansible中控机跟远程机器有一个长连接。

但是accelerate是使用Python程序在远程主机上运行一个守护进程,然后Ansible会通过这个守护进程监控的端口进行通信,开启accelerate模式很简单,只需要在Ansible playbook中配置accelerate: true即可。

需要注意的是,如果开启accelerate加速模式,则需要在Ansible中控机和远端机器都安装python-keyczar软件包。

下面是在/etc/ansible/ansible.cfg中配置的accelerate加速模式相关的参数:

sh[root@ansible ansible_playbooks]# grep -n -C2 accelerate /etc/ansible/ansible.cfg

444-#command_timeout = 30

445-

446:[accelerate]

447:#accelerate_port = 5099

448:#accelerate_timeout = 30

449:#accelerate_connect_timeout = 5.0

450-

451-# The daemon timeout is measured in minutes. This time is measured

452:# from the last activity to the accelerate daemon.

453:#accelerate_daemon_timeout = 30

454-

455:# If set to yes, accelerate_multi_key will allow multiple

456-# private keys to be uploaded to it, though each user must

457-# have access to the system via SSH to add a new key. The default

458-# is "no".

459:#accelerate_multi_key = yes

460-

461-[selinux]

[root@ansible ansible_playbooks]#1234567891011121314151617181920我们先不安装包,直接修改剧本文件base.yml,增加accelerate: true配置,修改后,查看base.yml内容:

sh[root@ansible ansible_playbooks]# cat base.yml

---

- hosts: basehosts

accelerate: true

roles:

- base123456然后执行剧本,直接报错了:

sh[root@ansible ansible_playbooks]# time ansible-playbook -i base_hosts.ini base.yml

ERROR! 'accelerate' is not a valid attribute for a Play

The error appears to be in '/root/ansible_playbooks/base.yml': line 2, column 3, but may

be elsewhere in the file depending on the exact syntax problem.

The offending line appears to be:

---

- hosts: basehosts

^ here

real 0m0.499s

user 0m0.420s

sys 0m0.079s

[root@ansible ansible_playbooks]#12345678910111213141516提示'accelerate' is not a valid attribute for a Play,即accelerate不是剧本的有效属性。

这里可以找到10年前accelerate.py的源码:accelerate.py

我用Python 3.6.8版本,pip安装ansible 4.10.0也报相同的异常,因此暂时忽略此加速方案。

2.4 设置fact缓存 ​Ansible在执行剧本时,默认第一个task是TASK [Gathering Facts] ,这个任务就是Ansible收集每台主机的facts信息。方便我们在剧本中直接引用facts里面的信息。如果你的剧本里面不需要facts信息,可以在playbook中设置gather_facts: False来提高playbook效率。如果我们既要在每次执行playbook时都能收集facts,又想加速这个收集过程,那么就需要配置facts缓存了。为了测试是否能够正常缓存facts事实变量,我们增加一个自定义的fact配置,详细可参考setup事实变量模块。

在三个节点上面创建目录/etc/ansible/facts.d,并创建文件/etc/ansible/facts.d/myself.fact,创建完成后查看配置内容:

sh[root@ansible-node1 ~]# mkdir -p /etc/ansible/facts.d

[root@ansible-node1 ~]# echo -e "[myfacts]\nmyself_fact=1" > /etc/ansible/facts.d/myself.fact

[root@ansible-node1 ~]# cat /etc/ansible/facts.d/myself.fact

[myfacts]

myself_fact=1

[root@ansible-node1 ~]#123456然后在Ansible控制节点查看自定义fact信息:

sh[root@ansible ansible_playbooks]# ansible -i base_hosts.ini all -m ansible.builtin.setup -a "filter=ansible_local" -o

192.168.56.123 | SUCCESS => {"ansible_facts": {"ansible_local": {"myself": {"myfacts": {"myself_fact": "1"}}}, "discovered_interpreter_python": "/usr/bin/python"}, "changed": false}

192.168.56.121 | SUCCESS => {"ansible_facts": {"ansible_local": {"myself": {"myfacts": {"myself_fact": "1"}}}, "discovered_interpreter_python": "/usr/bin/python"}, "changed": false}

192.168.56.122 | SUCCESS => {"ansible_facts": {"ansible_local": {"myself": {"myfacts": {"myself_fact": "1"}}}, "discovered_interpreter_python": "/usr/bin/python"}, "changed": false}

[root@ansible ansible_playbooks]#12345可以看到,正常获取到了我自定义的fact事实变量。

在测试前,再次执行两次剧本:

sh[root@ansible ansible_playbooks]# time ansible-playbook -i base_hosts.ini base.yml

...过程输出省略

real 0m15.347s

user 0m9.214s

sys 0m3.838s

[root@ansible ansible_playbooks]#

[root@ansible ansible_playbooks]# time ansible-playbook -i base_hosts.ini base.yml

...过程输出省略

real 0m15.472s

user 0m8.931s

sys 0m4.202s

[root@ansible ansible_playbooks]#12345678910111213执行剧本用时差不多还是16秒钟。

查看现有配置:

sh[root@ansible ~]# grep -nE -C5 'fact_cach|gathering' /etc/ansible/ansible.cfg

31-# the remote system.

32-#

33-# smart - gather by default, but don't regather if already gathered

34-# implicit - gather by default, turn off with gather_facts: False

35-# explicit - do not gather by default, must say gather_facts: True

36:#gathering = implicit

37-

38:# This only affects the gathering done by a play's gather_facts directive,

39:# by default gathering retrieves all facts subsets

40-# all - gather all subsets

41-# network - gather min and network facts

42-# hardware - gather hardware facts (longest facts to retrieve)

43-# virtual - gather min and virtual facts

44-# facter - import facts from facter

--

238-# if set to a persistent type (not 'memory', for example 'redis') fact values

239-# from previous runs in Ansible will be stored. This may be useful when

240-# wanting to use, for example, IP information from one group of servers

241-# without having to talk to them in the same playbook run to get their

242-# current IP information.

243:#fact_caching = memory

244-

245-#This option tells Ansible where to cache facts. The value is plugin dependent.

246-#For the jsonfile plugin, it should be a path to a local directory.

247:#For the redis plugin, the value is a host:port:database triplet: fact_caching_connection = localhost:6379:0

248-

249:#fact_caching_connection=/tmp

250-

251-

252-

253-# retry files

254-# When a playbook fails a .retry file can be created that will be placed in ~/

[root@ansible ~]#123456789101112131415161718192021222324252627282930313233342.4.1 使用json文件进行缓存 ​修改/etc/ansible/ansible.cfg配置文件中以下三个参数:

inigathering = smart

fact_caching = jsonfile

fact_caching_connection = /tmp123修改配置,使用json文件缓存:

sh[root@ansible ~]# grep -nE -C5 'fact_cach|gathering' /etc/ansible/ansible.cfg

31-# the remote system.

32-#

33-# smart - gather by default, but don't regather if already gathered

34-# implicit - gather by default, turn off with gather_facts: False

35-# explicit - do not gather by default, must say gather_facts: True

36:#gathering = implicit

37:gathering = smart

38-

39:# This only affects the gathering done by a play's gather_facts directive,

40:# by default gathering retrieves all facts subsets

41-# all - gather all subsets

42-# network - gather min and network facts

43-# hardware - gather hardware facts (longest facts to retrieve)

44-# virtual - gather min and virtual facts

45-# facter - import facts from facter

--

239-# if set to a persistent type (not 'memory', for example 'redis') fact values

240-# from previous runs in Ansible will be stored. This may be useful when

241-# wanting to use, for example, IP information from one group of servers

242-# without having to talk to them in the same playbook run to get their

243-# current IP information.

244:#fact_caching = memory

245:fact_caching = jsonfile

246-

247-#This option tells Ansible where to cache facts. The value is plugin dependent.

248-#For the jsonfile plugin, it should be a path to a local directory.

249:#For the redis plugin, the value is a host:port:database triplet: fact_caching_connection = localhost:6379:0

250-

251:fact_caching_connection=/tmp

252-

253-

254-

255-# retry files

256-# When a playbook fails a .retry file can be created that will be placed in ~/

[root@ansible ~]#123456789101112131415161718192021222324252627282930313233343536注意,fact_caching_connection=/tmp这个配置一定要打开,要不然后执行剧本时会报以下警告:

sh[root@ansible ansible_playbooks]# time ansible-playbook -i base_hosts.ini base.yml -v

Using /etc/ansible/ansible.cfg as config file

[WARNING]: No setting was provided for required configuration plugin_type: cache plugin: jsonfile setting: _uri

PLAY [basehosts] *****************************************************************************************************************************************************************************************************************************************************************************

TASK [Gathering Facts] ***********************************************************************************************************************************************************************************************************************************************************************

ok: [192.168.56.123]

ok: [192.168.56.121]

ok: [192.168.56.122]

...过程输出省略

[root@ansible ansible_playbooks]#123456789101112此时不会生成缓存文件。

为了验证是否正常收集fact,开启-v参数:

sh[root@ansible ansible_playbooks]# time ansible-playbook -i base_hosts.ini base.yml -v

Using /etc/ansible/ansible.cfg as config file

PLAY [basehosts] *****************************************************************************************************************************************************************************************************************************************************************************

TASK [Gathering Facts] ***********************************************************************************************************************************************************************************************************************************************************************

ok: [192.168.56.121]

ok: [192.168.56.122]

ok: [192.168.56.123]

TASK [base : Show hostname] ******************************************************************************************************************************************************************************************************************************************************************

ok: [192.168.56.121] => {

"msg": "ansible-node1"

}

ok: [192.168.56.122] => {

"msg": "ansible-node2"

}

ok: [192.168.56.123] => {

"msg": "ansible-node3"

}

...过程输出省略

PLAY RECAP ***********************************************************************************************************************************************************************************************************************************************************************************

192.168.56.121 : ok=26 changed=6 unreachable=0 failed=0 skipped=1 rescued=0 ignored=0

192.168.56.122 : ok=26 changed=6 unreachable=0 failed=0 skipped=1 rescued=0 ignored=0

192.168.56.123 : ok=26 changed=6 unreachable=0 failed=0 skipped=1 rescued=0 ignored=0

real 0m15.348s

user 0m9.233s

sys 0m3.940s

[root@ansible ansible_playbooks]#1234567891011121314151617181920212223242526272829303132此时,查看/tmp目录下文件:

sh[root@ansible ansible_playbooks]# cat /tmp/192.168.56.121|jq '.ansible_local'

{

"myself": {

"myfacts": {

"myself_fact": "1"

}

}

}

[root@ansible ansible_playbooks]# cat /tmp/192.168.56.122|jq '.ansible_local'

{

"myself": {

"myfacts": {

"myself_fact": "1"

}

}

}

[root@ansible ansible_playbooks]# cat /tmp/192.168.56.123|jq '.ansible_local'

{

"myself": {

"myfacts": {

"myself_fact": "1"

}

}

}

[root@ansible ansible_playbooks]#12345678910111213141516171819202122232425可以看到,生成的缓存文件。再次执行一次剧本:

sh[root@ansible ansible_playbooks]# time ansible-playbook -i base_hosts.ini base.yml -v

Using /etc/ansible/ansible.cfg as config file

PLAY [basehosts] *****************************************************************************************************************************************************************************************************************************************************************************

TASK [base : Show hostname] ******************************************************************************************************************************************************************************************************************************************************************

ok: [192.168.56.121] => {

"msg": "ansible-node1"

}

ok: [192.168.56.122] => {

"msg": "ansible-node2"

}

ok: [192.168.56.123] => {

"msg": "ansible-node3"

}

TASK [base : Set hostname] **************

...过程输出省略

PLAY RECAP ***********************************************************************************************************************************************************************************************************************************************************************************

192.168.56.121 : ok=25 changed=6 unreachable=0 failed=0 skipped=1 rescued=0 ignored=0

192.168.56.122 : ok=25 changed=6 unreachable=0 failed=0 skipped=1 rescued=0 ignored=0

192.168.56.123 : ok=25 changed=6 unreachable=0 failed=0 skipped=1 rescued=0 ignored=0

real 0m16.801s

user 0m9.292s

sys 0m4.170s

[root@ansible ansible_playbooks]#12345678910111213141516171819202122232425262728此时,可以看到,此时已经没有TASK [Gathering Facts] 这一步任务了,但最后执行任务用时16.8秒,用时还变多了。

再执行一次剧本,用时15.889秒。可以看到,并没有节省多少时间。

如果我们此时更新三个节点上面的自定义变量:

sh[root@ansible-node1 ~]# echo -e "[myfacts]\nmyself_fact=2" > /etc/ansible/facts.d/myself.fact

[root@ansible-node1 ~]# cat /etc/ansible/facts.d/myself.fact

[myfacts]

myself_fact=2

[root@ansible-node1 ~]#12345然后再执行剧本:

shUsing /etc/ansible/ansible.cfg as config file

PLAY [basehosts] *****************************************************************************************************************************************************************************************************************************************************************************

TASK [base : Show hostname] ******************************************************************************************************************************************************************************************************************************************************************

ok: [192.168.56.121] => {

"msg": "ansible-node1"

}

ok: [192.168.56.122] => {

"msg": "ansible-node2"

}

ok: [192.168.56.123] => {

"msg": "ansible-node3"

}

TASK [base : Set hostname] *****

...过程输出省略

PLAY RECAP ***********************************************************************************************************************************************************************************************************************************************************************************

192.168.56.121 : ok=25 changed=6 unreachable=0 failed=0 skipped=1 rescued=0 ignored=0

192.168.56.122 : ok=25 changed=6 unreachable=0 failed=0 skipped=1 rescued=0 ignored=0

192.168.56.123 : ok=25 changed=6 unreachable=0 failed=0 skipped=1 rescued=0 ignored=0

real 0m14.830s

user 0m8.939s

sys 0m3.983s

[root@ansible ansible_playbooks]#123456789101112131415161718192021222324252627此时,执行时间降低了!

查看自定义事实缓存文件和配置文件:

sh[root@ansible ansible_playbooks]# ll /tmp

total 84

-rw-r--r--. 1 root root 27350 Mar 18 19:59 192.168.56.121

-rw-r--r--. 1 root root 27685 Mar 18 19:59 192.168.56.122

-rw-r--r--. 1 root root 27727 Mar 18 19:59 192.168.56.123

[root@ansible ansible_playbooks]# cat /tmp/192.168.56.121|jq '.ansible_local'

{

"myself": {

"myfacts": {

"myself_fact": "1"

}

}

}

[root@ansible ansible_playbooks]# cat /tmp/192.168.56.122|jq '.ansible_local'

{

"myself": {

"myfacts": {

"myself_fact": "1"

}

}

}

[root@ansible ansible_playbooks]# cat /tmp/192.168.56.123|jq '.ansible_local'

{

"myself": {

"myfacts": {

"myself_fact": "1"

}

}

}

[root@ansible ansible_playbooks]#123456789101112131415161718192021222324252627282930可以看到,缓存后,当远程主机上面自定义的变量更新后,在缓存文件中并不会马上更新。

手动执行一次获取事实变量:

sh# 手动获取事实变量,可以看到已经获取到远程事实变量myself_fact新值2

[root@ansible ansible_playbooks]# ansible -i base_hosts.ini all -m ansible.builtin.setup -a "filter=ansible_local" -o

192.168.56.123 | SUCCESS => {"ansible_facts": {"ansible_local": {"myself": {"myfacts": {"myself_fact": "2"}}}}, "changed": false}

192.168.56.121 | SUCCESS => {"ansible_facts": {"ansible_local": {"myself": {"myfacts": {"myself_fact": "2"}}}}, "changed": false}

192.168.56.122 | SUCCESS => {"ansible_facts": {"ansible_local": {"myself": {"myfacts": {"myself_fact": "2"}}}}, "changed": false}

# 缓存文件也更新了

[root@ansible ansible_playbooks]# cat /tmp/192.168.56.123|jq '.ansible_local'

{

"myself": {

"myfacts": {

"myself_fact": "2"

}

}

}

[root@ansible ansible_playbooks]# cat /tmp/192.168.56.122|jq '.ansible_local'

{

"myself": {

"myfacts": {

"myself_fact": "2"

}

}

}

[root@ansible ansible_playbooks]# cat /tmp/192.168.56.121|jq '.ansible_local'

{

"myself": {

"myfacts": {

"myself_fact": "2"

}

}

}

[root@ansible ansible_playbooks]# ll /tmp

total 84

-rw-r--r--. 1 root root 27350 Mar 18 20:05 192.168.56.121

-rw-r--r--. 1 root root 27685 Mar 18 20:05 192.168.56.122

-rw-r--r--. 1 root root 27727 Mar 18 20:05 192.168.56.123

[root@ansible ansible_playbooks]#123456789101112131415161718192021222324252627282930313233343536372.4.2 使用redis进行缓存 ​首先在Ansible控制节点安装redis服务并修改配置文件,设置redis密码,并后台启动:

sh# 安装redis

[root@ansible ~]# yum install redis -y

# 安装后,修改配置文件,设置后台启动并设置密码

[root@ansible ~]# grep -E '^requirepass|^daemon' /etc/redis.conf

daemonize yes

requirepass foobared

[root@ansible ~]#

# 启动redis服务

[root@ansible ~]# systemctl status redis

# 测试redis命令行

[root@ansible ~]# /usr/bin/redis-cli -h 127.0.0.1 -p 6379 -a foobared

127.0.0.1:6379> ping

PONG

127.0.0.1:6379> keys *

(empty list or set)

127.0.0.1:6379> exit

[root@ansible ~]#1234567891011121314151617可以看到redis缓存能够正常使用,并且此时没有缓存任何键值。

修改/etc/ansible/ansible.cfg配置文件中以下几个参数:

inigathering = smart

fact_caching = redis

# 缓存时间300秒

fact_caching_timeout = 300

# 带密码的redis配置方式,不带密码时,直接配置成localhost:6379:0

fact_caching_connection = localhost:6379:0:foobared123456修改后查看配置:

sh[root@ansible ansible_playbooks]# grep -nE -C5 'fact_cach|gathering' /etc/ansible/ansible.cfg

31-# the remote system.

32-#

33-# smart - gather by default, but don't regather if already gathered

34-# implicit - gather by default, turn off with gather_facts: False

35-# explicit - do not gather by default, must say gather_facts: True

36:#gathering = implicit

37:gathering = smart

38-

39:# This only affects the gathering done by a play's gather_facts directive,

40:# by default gathering retrieves all facts subsets

41-# all - gather all subsets

42-# network - gather min and network facts

43-# hardware - gather hardware facts (longest facts to retrieve)

44-# virtual - gather min and virtual facts

45-# facter - import facts from facter

--

239-# if set to a persistent type (not 'memory', for example 'redis') fact values

240-# from previous runs in Ansible will be stored. This may be useful when

241-# wanting to use, for example, IP information from one group of servers

242-# without having to talk to them in the same playbook run to get their

243-# current IP information.

244:#fact_caching = memory

245:fact_caching = redis

246-

247-#This option tells Ansible where to cache facts. The value is plugin dependent.

248-#For the jsonfile plugin, it should be a path to a local directory.

249:#For the redis plugin, the value is a host:port:database triplet: fact_caching_connection = localhost:6379:0

250-

251:fact_caching_connection = localhost:6379:0:foobared

252:fact_caching_timeout = 300

253-

254-

255-# retry files

256-# When a playbook fails a .retry file can be created that will be placed in ~/

257-# You can enable this feature by setting retry_files_enabled to True

[root@ansible ansible_playbooks]#12345678910111213141516171819202122232425262728293031323334353637执行剧本:

sh[root@ansible ansible_playbooks]# time ansible-playbook -i base_hosts.ini base.yml -v

Using /etc/ansible/ansible.cfg as config file

[WARNING]: The 'redis' python module (version 2.4.5 or newer) is required for the redis fact cache, 'pip install redis'

...过程输出省略1234可以看到,redis fact缓存需要安装python redis依赖包。

sh# 查看ansible版本

[root@ansible ansible_playbooks]# ansible --version

ansible 2.9.27

config file = /etc/ansible/ansible.cfg

configured module search path = [u'/root/.ansible/plugins/modules', u'/usr/share/ansible/plugins/modules']

ansible python module location = /usr/lib/python2.7/site-packages/ansible

executable location = /usr/bin/ansible

python version = 2.7.5 (default, Oct 14 2020, 14:45:30) [GCC 4.8.5 20150623 (Red Hat 4.8.5-44)]

[root@ansible ansible_playbooks]#123456789对应用的Python是2.7.5。

由于python版本较低,由没有pip命令,在pip-20.2.4.tar.gz下载安装文件pip-20.2.4.tar.gz,并解压安装:

我们安装对应的依赖包:

sh[root@ansible softs]# cd pip-20.2.4

[root@ansible pip-20.2.4]# python setup.py build

[root@ansible pip-20.2.4]# python setup.py install

[root@ansible pip-20.2.4]# pip install redis

[root@ansible pip-20.2.4]# pip list|grep redis

DEPRECATION: Python 2.7 reached the end of its life on January 1st, 2020. Please upgrade your Python as Python 2.7 is no longer maintained. pip 21.0 will drop support for Python 2.7 in January 2021. More details about Python 2 support in pip can be found at https://pip.pypa.io/en/latest/development/release-process/#python-2-support pip 21.0 will remove support for this functionality.

redis 3.5.3

[root@ansible cd]#

[root@ansible ~]# python

Python 2.7.5 (default, Oct 14 2020, 14:45:30)

[GCC 4.8.5 20150623 (Red Hat 4.8.5-44)] on linux2

Type "help", "copyright", "credits" or "license" for more information.

>>> import redis

>>> r = redis.Redis(host='localhost', port=6379, db=0, password='foobared')

>>> r.set('foo', 'bar')

True

>>> r.get('foo')

'bar'

>>> exit()

[root@ansible redis-2.4.5]#1234567891011121314151617181920检查redis缓存:

sh[root@ansible ansible_playbooks]# /usr/bin/redis-cli -h localhost -p 6379 -a foobared

localhost:6379> keys *

1) "foo"

localhost:6379> get foo

"bar"

localhost:6379> exit

[root@ansible ansible_playbooks]#1234567可以看到能正常查询到键foo的值是bar。

此时再执行剧本:

sh[root@ansible ~]# cd ansible_playbooks/

[root@ansible ansible_playbooks]# time ansible-playbook -i base_hosts.ini base.yml -v

Using /etc/ansible/ansible.cfg as config file

PLAY [basehosts] *****************************************************************************************************************************************************************************************************************************************************************************

TASK [Gathering Facts] ***********************************************************************************************************************************************************************************************************************************************************************

ok: [192.168.56.123]

ok: [192.168.56.121]

ok: [192.168.56.122]

TASK [base : Show hostname] ******************************************************************************************************************************************************************************************************************************************************************

ok: [192.168.56.121] => {

"msg": "ansible-node1"

}

ok: [192.168.56.123] => {

"msg": "ansible-node3"

}

ok: [192.168.56.122] => {

"msg": "ansible-node2"

}

...过程输出省略

PLAY RECAP ***********************************************************************************************************************************************************************************************************************************************************************************

192.168.56.121 : ok=26 changed=6 unreachable=0 failed=0 skipped=1 rescued=0 ignored=0

192.168.56.122 : ok=26 changed=6 unreachable=0 failed=0 skipped=1 rescued=0 ignored=0

192.168.56.123 : ok=26 changed=6 unreachable=0 failed=0 skipped=1 rescued=0 ignored=0

real 0m24.150s

user 0m10.202s

sys 0m3.894s

[root@ansible ansible_playbooks]#1234567891011121314151617181920212223242526272829303132此时登陆redis命令行查看缓存信息:

sh[root@ansible ansible_playbooks]# /usr/bin/redis-cli -h localhost -p 6379 -a foobared

localhost:6379> keys *

1) "foo"

2) "ansible_facts192.168.56.121"

3) "ansible_facts192.168.56.123"

4) "ansible_facts192.168.56.122"

5) "ansible_cache_keys"

localhost:6379>12345678再次执行剧本:

sh[root@ansible ansible_playbooks]# time ansible-playbook -i base_hosts.ini base.yml -v

Using /etc/ansible/ansible.cfg as config file

PLAY [basehosts] *****************************************************************************************************************************************************************************************************************************************************************************

TASK [base : Show hostname] ******************************************************************************************************************************************************************************************************************************************************************

ok: [192.168.56.121] => {

"msg": "ansible-node1"

}

ok: [192.168.56.122] => {

"msg": "ansible-node2"

}

ok: [192.168.56.123] => {

"msg": "ansible-node3"

}

...过程输出省略

PLAY RECAP ***********************************************************************************************************************************************************************************************************************************************************************************

PLAY RECAP ***********************************************************************************************************************************************************************************************************************************************************************************

192.168.56.121 : ok=25 changed=6 unreachable=0 failed=0 skipped=1 rescued=0 ignored=0

192.168.56.122 : ok=25 changed=6 unreachable=0 failed=0 skipped=1 rescued=0 ignored=0

192.168.56.123 : ok=25 changed=6 unreachable=0 failed=0 skipped=1 rescued=0 ignored=0

real 0m14.807s

user 0m9.492s

sys 0m3.406s

[root@ansible ansible_playbooks]#123456789101112131415161718192021222324252627可以看到,此时使用了缓存!没有执行TASK [Gathering Facts]任务。此时执行任务快了1秒钟。

2.4.3 使用memcached进行缓存 ​使用memcached配置缓存,与redis类似。

安装memcached服务并启动:

sh[root@ansible ~]# yum install memcached -y

[root@ansible ~]# systemctl start memcached

[root@ansible ~]# ps -ef|grep memcached

memcach+ 16596 1 0 22:19 ? 00:00:00 /usr/bin/memcached -u memcached -p 11211 -m 64 -c 1024

root 16603 1525 0 22:19 pts/0 00:00:00 grep --color=auto memcached

[root@ansible ~]#123456连接memcached:

sh[root@ansible ~]# telnet 127.0.0.1 11211

Trying 127.0.0.1...

Connected to 127.0.0.1.

Escape character is '^]'.

set foo 0 0 3

bar

STORED

get foo

VALUE foo 0 3

bar

END

quit

Connection closed by foreign host.

[root@ansible ~]#1234567891011121314可以看到memcached服务可以使用。

再安装python-memcached包:

sh[root@ansible ~]# pip install python-memcached

DEPRECATION: Python 2.7 reached the end of its life on January 1st, 2020. Please upgrade your Python as Python 2.7 is no longer maintained. pip 21.0 will drop support for Python 2.7 in January 2021. More details about Python 2 support in pip can be found at https://pip.pypa.io/en/latest/development/release-process/#python-2-support pip 21.0 will remove support for this functionality.

Looking in indexes: http://mirrors.aliyun.com/pypi/simple/

Collecting python-memcached

Downloading http://mirrors.aliyun.com/pypi/packages/8f/1b/3b15a37831ae34a264d7d5b71f3ae9fe74a81251453a3ec2135e76888ef1/python_memcached-1.62-py2.py3-none-any.whl (15 kB)

Installing collected packages: python-memcached

Successfully installed python-memcached-1.62

[root@ansible ~]# pip list|grep memcached

DEPRECATION: Python 2.7 reached the end of its life on January 1st, 2020. Please upgrade your Python as Python 2.7 is no longer maintained. pip 21.0 will drop support for Python 2.7 in January 2021. More details about Python 2 support in pip can be found at https://pip.pypa.io/en/latest/development/release-process/#python-2-support pip 21.0 will remove support for this functionality.

python-memcached 1.62

[root@ansible ~]#1234567891011修改/etc/ansible/ansible.cfg配置文件中以下几个参数:

inigathering = smart

fact_caching = memcached

fact_caching_timeout = 300

fact_caching_connection = 127.0.0.1:112111234由于python 2.7的一些语法限制,执行剧本时会报错:

sh[root@ansible ansible_playbooks]# time ansible-playbook -i base_hosts.ini base.yml -vvv

ansible-playbook 2.9.27

config file = /etc/ansible/ansible.cfg

configured module search path = [u'/root/.ansible/plugins/modules', u'/usr/share/ansible/plugins/modules']

ansible python module location = /usr/lib/python2.7/site-packages/ansible

executable location = /usr/bin/ansible-playbook

python version = 2.7.5 (default, Oct 14 2020, 14:45:30) [GCC 4.8.5 20150623 (Red Hat 4.8.5-44)]

Using /etc/ansible/ansible.cfg as config file

host_list declined parsing /root/ansible_playbooks/base_hosts.ini as it did not pass its verify_file() method

script declined parsing /root/ansible_playbooks/base_hosts.ini as it did not pass its verify_file() method

auto declined parsing /root/ansible_playbooks/base_hosts.ini as it did not pass its verify_file() method

yaml declined parsing /root/ansible_playbooks/base_hosts.ini as it did not pass its verify_file() method

Parsed /root/ansible_playbooks/base_hosts.ini inventory source with ini plugin

ERROR! Unexpected Exception, this is probably a bug: invalid syntax (memcache.py, line 374)

the full traceback was:

Traceback (most recent call last):

File "/usr/bin/ansible-playbook", line 123, in

exit_code = cli.run()

File "/usr/lib/python2.7/site-packages/ansible/cli/playbook.py", line 109, in run

loader, inventory, variable_manager = self._play_prereqs()

File "/usr/lib/python2.7/site-packages/ansible/cli/__init__.py", line 473, in _play_prereqs

variable_manager = VariableManager(loader=loader, inventory=inventory, version_info=CLI.version_info(gitinfo=False))

File "/usr/lib/python2.7/site-packages/ansible/vars/manager.py", line 102, in __init__

self._fact_cache = FactCache()

File "/usr/lib/python2.7/site-packages/ansible/vars/fact_cache.py", line 24, in __init__

self._plugin = cache_loader.get(C.CACHE_PLUGIN)

File "/usr/lib/python2.7/site-packages/ansible/plugins/loader.py", line 552, in get

self._module_cache[path] = self._load_module_source(name, path)

File "/usr/lib/python2.7/site-packages/ansible/plugins/loader.py", line 530, in _load_module_source

module = imp.load_source(to_native(full_name), to_native(path), module_file)

File "/usr/lib/python2.7/site-packages/ansible/plugins/cache/memcached.py", line 59, in

import memcache

File "/usr/lib/python2.7/site-packages/memcache.py", line 374

def quit_all(self) -> None:

^

SyntaxError: invalid syntax

real 0m0.344s

user 0m0.298s

sys 0m0.046s

[root@ansible ansible_playbooks]#123456789101112131415161718192021222324252627282930313233343536373839404142在Python 2.7中,quit_all函数的定义可能出现了一些问题。Python 2.7不支持类型注释,即-> None部分。这是导致错误的直接原因。

建议升级Python版本和Ansible版本后再进行测试。