在执行 ad-hoc 或者 playbook 的时候,在后面加上 -vvv
参数,就可以看到 Ansible 的详细执行过程,便于排错。
[[email protected] ~]# ansible dbservers -i hosts -m ping -vvv
[[email protected] ~]# ansible-playbook -i hosts checkhost.yml -vvv
openssh5.6 版本后支持 Multiplexing
[[email protected] ~]# ssh -V
OpenSSH_7.4p1, OpenSSL 1.0.2k-fips 26 Jan 2017
[[email protected] ~]# grep sh_args /etc/ansible/ansible.cfg
ssh_args = -C -o ControlMaster=auto -o ControlPersist=10d
# ControlPersist=10d 表示保持长连接 10 天。
# 60s 是 60 秒
设置好后,重新连接一次被控主机,即可让控制主机和被控主机之间建立长连接
[[email protected] ~]# ansible webservers -i hosts -m ping
172.18.0.4 | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": false,
"ping": "pong"
}
验证长连接
[[email protected] ~]# ss -nta |grep ESTAB
tcp ESTAB 0 0 172.18.0.2:51864 172.18.0.4:2222
输出中 有 ESTAB
状态的就代表是长连接
同时会在主控机当前用户的家目录下的 .ansibl/cp/ 目录下生成对应的 socket 文件
[[email protected] ~]# ls -l .ansible/cp/13fe34a1c4
srw------- 1 root root 0 Apr 17 03:36 .ansible/cp/13fe34a1c4
我们知道默认情况下 Ansible 执行过程中会把生成好的本地 python 脚本文件 PUT 到 远端机器。如果我们开启了 ssh 的 pipelining 特性,这个过程就会在 SSH 的会话中进行。
在不通过实际文件传输的情况下执行ansible模块来使用管道特性, 可以减少执行远程服务器上的模块所需的网络操作数量。比如 PUT sftp 等操作都需要建立网络连接。
下面是关闭 Pipeline 的情况下的三步操作。
<172.18.0.3> PUT /root/.ansible/tmp/ansible-local-10883q1xq1u/tmpNbePyo TO /root/.ansible/tmp/ansible-tmp-1587214813.33-212837305246708/AnsiballZ_ping.py
<172.18.0.3> SSH: EXEC sftp -b - -C -o ControlMaster=auto -o ControlPersist=600s -o KbdInteractiveAuthentication=no -o PreferredAuthentications=gssapi-with-mic,gssapi-keyex,hostbased,publickey -o PasswordAuthentication=no -o ConnectTimeout=10 -o ControlPath=/root/.ansible/cp/553ad38749 '[172.18.0.3]'
<172.18.0.3> (0, 'sftp> put /root/.ansible/tmp/ansible-local-10883q1xq1u/tmpNbePyo /root/.ansible/tmp/ansible-tmp-1587214813.33-212837305246708/AnsiballZ_ping.py\n', '')
如果开启这个设置,将显著提高性能.。
下面的步骤是实现这个特性的步骤
在 ansible.cfg 配置文件中设置 pipelining 为 True
[[email protected] ~]# grep pipelining /etc/ansible/ansible.cfg
# Enabling pipelining reduces the number of SSH operations required to
pipelining = True
默认情况下,Ansible 每次执行 playbook 时的第一个 Task 就是 获取每台主机的 facts 信息。假如不需要可以设置 gather_facts = no
进行关闭,以提高执行 playbook 的效率。
假如想获取 facts 信息,同时又想加速这个 task 的效率,就需要设置 facts 缓存。
缓存 facts 信息可以存档 JSON 文件中,也可以方式 redis 和 memcached 中。
grep gathering /etc/ansible/ansible.cfg
gathering = smart
gathering 的值可以设置为其中的一个: smart
、implicit
或者 explicit
。
smart
--> 表示默认收集facts,但facts信息已经存在的情况下不会收集,也就是会使用缓存facts;
implicit
--> 表示默认收集facts,但要禁止收集,可以在 playbook中设置gather_facts: no
;
explicit
--> 则表示默认不收集,但要收集,可以在 playbook中设置 gather_facts: yes
例如:在playbook 中设置
---
- hosts: all
gather_facts: yes # 收集
gather_facts: no # 不收集
在 ansible.cfg 文件中配置缓存到一个普通文件中,保存的数据是 JSON 格式
要保证配置到 [defaults]
配置块内
[root@5e4b448b73e5 ~]# grep -P -v '^#|^$' /etc/ansible/ansible.cfg
[defaults]
gathering = smart
fact_caching = jsonfile # 缓存到 json 文件
fact_caching_connection = /dev/shm/ansible_fact_cache/ # 保存的文件
fact_caching_timeout = 86400 # 缓存数据时间是一天
fact_caching_connection
值是一个本地可写的目录路径,如果目录不存在,ansible会试图创建最后一级目录,文件名是在 Inventory 中保存的 IP 或者 hostname .
验证
[[email protected] ~]# ls /dev/shm/ansible_fact_cache/
172.18.0.3 172.18.0.5
[[email protected] ~]# head -n 3 /dev/shm/ansible_fact_cache/*
==> /dev/shm/ansible_fact_cache/172.18.0.3 <==
{
"_ansible_facts_gathered": true,
"ansible_all_ipv4_addresses": [
==> /dev/shm/ansible_fact_cache/172.18.0.5 <==
{
"_ansible_facts_gathered": true,
"ansible_all_ipv4_addresses": [
[[email protected] ~]#
[[email protected] ~]# yum install redis
~ # grep '^bind' /etc/redis.conf
bind 0.0.0.0
[[email protected] ~]# pip install redis
在 ansible.cfg 文件中配置缓存到 redis
192.168.1.37 是 redis 服务器地址
[root@5e4b448b73e5 ~]# grep -P -v '^#|^$' /etc/ansible/ansible.cfg
[defaults]
gathering = smart
fact_caching = redis # 缓存到 redis
fact_caching_connection = 192.168.1.37:6379:0
fact_caching_timeout = 86400 # 缓存数据时间是一天
127.0.0.1:6379> keys *
1) "ansible_facts172.18.0.3"
2) "ansible_facts172.18.0.4"
3) "ansible_cache_keys"
127.0.0.1:6379> get ansible_facts172.18.0.3
通过从命令行提供多个清单参数或通过配置多个清单参数,可以同时定位多个清单源(目录,动态清单脚本或清单插件支持的文件)
这对于具有多环境的状态下非常有帮助,比如生产环境和开发环境。
ansible-playbook get_logs.yml -i development -i production
可以通过组合目录下的多个清单来源和来源类型来创建清单。
这对于组合静态和动态主机并将它们作为一个清单进行管理很有用。
以下清单结合了清单插件源,动态清单脚本和具有静态主机的文件
inventory/
aliyun.ini # 获取阿里云的主机和组
static-inventory # 静态主机和组
group_vars/ # 存放变量的目录,目录名必须是这个
all.yml # 给所有的主机指定变量
ansible-playbook test.yml -i inventory
假设这个清单目录的绝对路径是: /etc/ansible/inventory
应该这样配置:
[defaults]
inventory = /etc/ansible/inventory/
之后在 /etc/ansible/inventory/
目录下创建相应的文件已经文件内容
aliyun.yml
[webservers]
172.16.2.30
static-inventory
[dbservers]
172.16.2.20
如果多个主机清单之间存在变量的冲突或组依赖关系,则需要通过控制主机清单的合并顺序来控制变量能按照我们所期望的值进行生效。
可以通过在文件前添加数字前缀来控制合并的顺序:
inventory/
01-aliyun.ini # 获取阿里云的主机
02-static-inventory # 添加静态主机和组
group_vars/
all.yml # 给所有的主机指定变量
重复定义变量导致变量被覆盖,是应该避免的,也可以避免的。
目录结构
[[email protected] ~]# tree inventory
inventory
|-- 01-aliyun.ini
`-- 02-static-inventory
0 directories, 2 files
文件内容
# inventory/01-aliyun.ini
[webservers]
172.16.2.30
webservers:
vars:
- name: xiguatian
# inventory/02-static-inventory
[dbservers]
172.16.2.20
[allservers:children]
dbservers
webservers
[allservers:vars]
name = shark
验证变量的值
[[email protected] ~]# ansible all -m debug -a "var=name"