自动化管理利器Ansible-最佳实战
文章目录
一、调试
在执行 ad-hoc 或者 playbook 的时候,在后面加上 -vvv
参数,就可以看到 Ansible 的详细执行过程,便于排错。
[root@qfedu.com ~]# ansible dbservers -i hosts -m ping -vvv
[root@qfedu.com ~]# ansible-playbook -i hosts checkhost.yml -vvv
二、优化 Ansible 执行速度
1. 设置 SSH 为长连接
openssh5.6 版本后支持 Multiplexing
1.1 检查控制机器的 ssh 版本
[root@qfedu.com ~]# ssh -V
OpenSSH_7.4p1, OpenSSL 1.0.2k-fips 26 Jan 2017
1.2 设置 ansible 配置文件
[root@qfedu.com ~]# grep sh_args /etc/ansible/ansible.cfg
ssh_args = -C -o ControlMaster=auto -o ControlPersist=10d
# ControlPersist=10d 表示保持长连接 10 天。
# 60s 是 60 秒
1.3 建立长连接并测试
设置好后,重新连接一次被控主机,即可让控制主机和被控主机之间建立长连接
[root@qfedu.com ~]# ansible webservers -i hosts -m ping
172.18.0.4 | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": false,
"ping": "pong"
}
验证长连接
[root@qfedu.com ~]# ss -nta |grep ESTAB
tcp ESTAB 0 0 172.18.0.2:51864 172.18.0.4:2222
输出中 有 ESTAB
状态的就代表是长连接
同时会在主控机当前用户的家目录下的 .ansibl/cp/ 目录下生成对应的 socket 文件
[root@qfedu.com ~]# ls -l .ansible/cp/13fe34a1c4
srw------- 1 root root 0 Apr 17 03:36 .ansible/cp/13fe34a1c4
2. 开启 pipelining
我们知道默认情况下 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
[root@qfedu.com ~]# grep pipelining /etc/ansible/ansible.cfg
# Enabling pipelining reduces the number of SSH operations required to
pipelining = True
三、设置 facts 缓存
默认情况下,Ansible 每次执行 playbook 时的第一个 Task 就是 获取每台主机的 facts 信息。假如不需要可以设置 gather_facts = no
进行关闭,以提高执行 playbook 的效率。
假如想获取 facts 信息,同时又想加速这个 task 的效率,就需要设置 facts 缓存。
缓存 facts 信息可以存档 JSON 文件中,也可以方式 redis 和 memcached 中。
1. 首先是可以在 ansible.cfg 文件中设置
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 # 不收集
2 配置缓存的目标
2.1 缓存到文件(JSON格式的数据)
在 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 .
验证
[root@qfedu.com ~]# ls /dev/shm/ansible_fact_cache/
172.18.0.3 172.18.0.5
[root@qfedu.com ~]# 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": [
[root@qfedu.com ~]#
2.2 缓存到 redis
- 在任一机器或者ansible 控制主机上部署 Redis 服务
[root@qfedu.com ~]# yum install redis
- 假如 Redis 服务不在 ansible 控制主机上,还应该设置 redis 监听地址
~ # grep '^bind' /etc/redis.conf
bind 0.0.0.0
- 在控制主机 python 的 redis 库
[root@qfedu.com ~]# 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
四、使用多个 Inventory 文件
通过从命令行提供多个清单参数或通过配置多个清单参数,可以同时定位多个清单源(目录,动态清单脚本或清单插件支持的文件)
这对于具有多环境的状态下非常有帮助,比如生产环境和开发环境。
1 从命令行定位两个源,如下所示:
ansible-playbook get_logs.yml -i development -i production
2 使用目录汇总清单源
可以通过组合目录下的多个清单来源和来源类型来创建清单。
这对于组合静态和动态主机并将它们作为一个清单进行管理很有用。
以下清单结合了清单插件源,动态清单脚本和具有静态主机的文件
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
3 要注意变量的覆盖
如果多个主机清单之间存在变量的冲突或组依赖关系,则需要通过控制主机清单的合并顺序来控制变量能按照我们所期望的值进行生效。
可以通过在文件前添加数字前缀来控制合并的顺序:
inventory/
01-aliyun.ini # 获取阿里云的主机
02-static-inventory # 添加静态主机和组
group_vars/
all.yml # 给所有的主机指定变量
重复定义变量导致变量被覆盖,是应该避免的,也可以避免的。
- 测试:
目录结构
[root@qfedu.com ~]# 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
验证变量的值
[root@qfedu.com ~]# ansible all -m debug -a "var=name"