前言

因为工作的缘故接触并积极推动Ansible在企业级生产环境的落地,独立承担并实现了《基于ansible的主机自动化配置管理》项目,此前也先后接触过Puppet和SaltStack,本文不会讨论开源或者自主研发方案的优劣,重点是和大伙儿分享自己在ansible技术领域积累的一些项目实战经验,如果大家遇到任何问题也欢迎通过留言或者其他方式进行互动,我尽力做到有效回复。

Ansible is Simple IT Automation

更新历史

2020年06月21日 - 增加Mitogen for Ansible
2020年06月01日 - 增加基于Ansible的自动化运维开源项目
2020年01月22日 - 增加Ansible参考文章
2018年05月15日 - 初稿

阅读原文 - https://wsgzao.github.io/post/ansible/

扩展阅读

ansible - https://docs.ansible.com/


Ansible 标准化学习路径

Ansible相关的书籍在逐步增多,由于Ansible版本迭代更新频率高但学习成本低,个人建议书为辅,官方文档为主

Ansible is an IT automation tool. It can configure systems, deploy software, and orchestrate more advanced IT tasks such as continuous deployments or zero downtime rolling updates.

Ansible’s main goals are simplicity and ease-of-use. It also has a strong focus on security and reliability, featuring a minimum of moving parts, usage of OpenSSH for transport (with other transports and pull modes as alternatives), and a language that is designed around auditability by humans–even those not familiar with the program.

We believe simplicity is relevant to all sizes of environments, so we design for busy users of all types: developers, sysadmins, release engineers, IT managers, and everyone in between. Ansible is appropriate for managing all environments, from small setups with a handful of instances to enterprise environments with many thousands of instances.

Ansible manages machines in an agent-less manner. There is never a question of how to upgrade remote daemons or the problem of not being able to manage systems because daemons are uninstalled. Because OpenSSH is one of the most peer-reviewed open source components, security exposure is greatly reduced. Ansible is decentralized–it relies on your existing OS credentials to control access to remote machines. If needed, Ansible can easily connect with Kerberos, LDAP, and other centralized authentication management systems.

This documentation covers the current released version of Ansible and also some development version features. For recent features, we note in each section the version of Ansible where the feature was added.

Ansible releases a new major release of Ansible approximately every two months. The core application evolves somewhat conservatively, valuing simplicity in language design and setup. However, the community around new modules and plugins being developed and contributed moves very quickly, adding many new modules in each release.

Ansible Lightbulb 新版本是 Red Hat Ansible Automation Platform Workshops

The Ansible Lightbulb project is an effort to provide a content toolkit and educational reference for effectively communicating and teaching Ansible topics.

Ansible Lightbulb - https://github.com/ansible/lightbulb

Red Hat Ansible Automation Platform Workshops - https://ansible.github.io/workshops/

Ansible Documentation 是 Ansible 官方文档,我的建议还是对英文不要害怕,多动手查多敲命令去理解

Ansible Documentation - http://docs.ansible.com/ansible/latest/index.html

如果大家需要使用Role推荐阅读Ansible Best Practices

Ansible Best Practices

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
inventories/
production/
hosts # inventory file for production servers
group_vars/
group1.yml # here we assign variables to particular groups
group2.yml
host_vars/
hostname1.yml # here we assign variables to particular systems
hostname2.yml

staging/
hosts # inventory file for staging environment
group_vars/
group1.yml # here we assign variables to particular groups
group2.yml
host_vars/
stagehost1.yml # here we assign variables to particular systems
stagehost2.yml

library/ # if any custom modules, put them here (optional)
module_utils/ # if any custom module_utils to support modules, put them here (optional)
filter_plugins/ # if any custom filter plugins, put them here (optional)

site.yml # master playbook
webservers.yml # playbook for webserver tier
dbservers.yml # playbook for dbserver tier

files/ # here we assign files for simple plays
plays/ # here we assign plays as the entrance
tasks/ # here we assign tasks for plays to call

roles/
common/ # this hierarchy represents a "role"
tasks/ #
main.yml # <-- tasks file can include smaller files if warranted
handlers/ #
main.yml # <-- handlers file
templates/ # <-- files for use with the template resource
ntp.conf.j2 # <------- templates end in .j2
files/ #
bar.txt # <-- files for use with the copy resource
foo.sh # <-- script files for use with the script resource
vars/ #
main.yml # <-- variables associated with this role
defaults/ #
main.yml # <-- default lower priority variables for this role
meta/ #
main.yml # <-- role dependencies
library/ # roles can also include custom modules
module_utils/ # roles can also include custom module_utils
lookup_plugins/ # or other types of plugins, like lookup in this case

webtier/ # same kind of structure as "common" was above, done for the webtier role
monitoring/ # ""
fooapp/ # ""

提升 Ansible 执行效率的插件

众所周知,Ansible是基于ssh(当然还有telnet,winrm等连接插件)的自动化配置管理工具,其简单易用,无agent式的工作方式在很多场景中都有不少优势,不过也是由于这种工作方式导致了它没有其他c/s类的工具执行效率高,饱受其他C/S类工具使用者的讥讽,对此,Ansible官方也对Ansible的速度效率做了不少优化手段。

参数名/优化类别 说明
fact cache 将facts信息第一次收集后缓存到memory或者redis或者文件中。
gather_subset 可选择性的收集network,hardware等信息,而不是全部
control_path 开启ssh socket持久化,复用ssh连接
pipelinling 开启ssh pipelining,客户端从管道中读取执行渲染后的脚本,而不是在客户端创建临时文件
fork 提高并行执行主机的数量
serial play_hosts``①中主机再分批执行
strategy 默认linear,每个主机的单个task执行完成会等待其他都完成后再执行下个任务,设置free可不等待其他主机,继续往下执行(看起来会比较乱),还有一个选项host_pinned,我也不知道干嘛的

无意发现了一个Mitogen的Ansible plugin(strategy plugin),当前已迭代到0.29版本,看介绍说能提升1.2x ~ 7x以上的执行效率,着实惊人!

它通过高效的远程过程调用来取代ansible默认的嵌入式与纯python shell调用,它不会优化模块本身的执行效率,只会尽可能快的②去执行模块获取返回(执行模块前也是有一系列连接,发送数据,传输渲染脚本等操作的)来提高整体的效率,特性如下

Expect a 1.25x - 7x speedup and a CPU usage reduction of at least 2x, depending on network conditions, modules executed, and time already spent by targets on useful work. Mitogen cannot improve a module once it is executing, it can only ensure the module executes as quickly as possible.

  • One connection is used per target, in addition to one sudo invocation per user account. This is much better than SSH multiplexing combined with pipelining, as significant state can be maintained in RAM between steps, and system logs aren’t spammed with repeat authentication events.

  • A single network roundtrip is used to execute a step whose code already exists in RAM on the target. Eliminating multiplexed SSH channel creation saves 4 ms runtime per 1 ms of network latency for every playbook step.

  • Processes are aggressively reused, avoiding the cost of invoking Python and recompiling imports, saving 300-800 ms for every playbook step.

  • Code is ephemerally cached in RAM, reducing bandwidth usage by an order of magnitude compared to SSH pipelining, with around 5x fewer frames traversing the network in a typical run.

  • Fewer writes to the target filesystem occur. In typical configurations, Ansible repeatedly rewrites and extracts ZIP files to multiple temporary directories on the target. Security issues relating to temporary files in cross-account scenarios are entirely avoided.

The effect is most potent on playbooks that execute many short-lived actions, where Ansible’s overhead dominates the cost of the operation, for example when executing large with_items loops to run simple commands or write files.

大体就是执行过程中主机使用一个连接(默认每执行一个task或者loop循环都会重新打开一次连接的);渲染的执行代码暂存于内存中;减少多路复用ssh隧道的时间消耗;减少临时文件传输的带宽;代码重用,避免代码的重新编译成本等

实现原理的话,可以去看下官网解释,反正我是没怎么看懂

① . play_hosts为内置参数,指当前正在执行的playbook中的主机列表

②. 尽可能快的 指到运行模块前的阶段

  1. Download and extract mitogen-0.2.9.tar.gz
  2. Modify ansible.cfg
1
2
3
[defaults]
strategy_plugins = /path/to/mitogen-0.2.9/ansible_mitogen/plugins/strategy
strategy = mitogen_linear

The strategy key is optional. If omitted, the ANSIBLE_STRATEGY=mitogen_linear environment variable can be set on a per-run basis. Like mitogen_linear, the mitogen_free and mitogen_host_pinned strategies exists to mimic the free and host_pinned strategies.

https://networkgenomics.com/ansible/

https://mitogen.networkgenomics.com/ansible_detailed.html

基于 Ansible 的开源项目

第一个是ansible官方开源项目,其他都是和ansible相关的运维平台开源项目,推荐学习和参考

Ansible - https://github.com/ansible/ansible

Jumpserver - http://www.jumpserver.org/

OpsManage - https://github.com/welliamcao/OpsManage

spug - https://github.com/openspug/spug

BigOps - http://www.bigops.com/

Ansible 项目实践

以下内容来自于《基于ansible的主机自动化配置管理》项目,基于ansible目前可以满足生产环境所有基线要求,相信对大家有一定的参考价值

ansible 部署

因为生产环境为内外网物理隔离,所有的安装部署都是离线进行的

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
# Install Packages
yum install gcc zlib zlib-devel openssl-devel -y

# Install Python
tar xf Python-2.7.14.tgz
cd Python-2.7.14
./configure
make
make install
cd ..

# renew python env
exit

# ImportError: No module named six.moves
tar xf six-1.11.0.tar.gz
cd six-1.11.0
python setup.py install
cd ..

# ImportError: No module named packaging.version
tar xf packaging-17.1.tar.gz
cd packaging-17.1
python setup.py install
cd ..

# ImportError: No module named pyparsing
tar xf pyparsing-2.2.0.tar.gz
cd pyparsing-2.2.0
python setup.py install
cd ..

# ImportError: No module named appdirs
tar xf appdirs-1.4.3.tar.gz
cd appdirs-1.4.3
python setup.py install
cd ..

# Install Setuptools
unzip setuptools-38.5.2.zip
cd setuptools-38.5.2
python setup.py install
cd ..

# Install pip
tar xf pip-9.0.1.tar.gz
cd pip-9.0.1
python setup.py install
cd ..

# pip 离线下载
# pip download -d DIR -r requirements.txt
pip download -d ~/ansible/ ansible

# pip 离线安装
# pip install --no-index --find-links=DIR -r requirements.txt
pip install --no-index --find-links=pip-ansible-2.3.3/ -r requirements.txt
pip install --no-index --find-links=pip-ansible-2.5.0/ -r requirements.txt -U

# pip 离线安装pipenv
pip install --no-index --find-links=pip-pipenv/ pipenv

# 使用pipenv创建虚拟环境
mkdir win_ansible
cd win_ansible
pipenv shell
pip install --no-index --find-links=pip-ansible-2.5.2/ -r requirements.txt

ansible.cfg 配置解析

ansible.cfg不影响执行结果但合理的配置会有效提升效率

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# 配置文件路径(优先级)
./ansible.cfg
/etc/ansible/ansible.cfg

# 配置文件内容
[defaults]
#inventory = /etc/ansible/hosts
#log_path = /var/log/ansible.log
forks = 100 # 设置并发数
host_key_checking = False # 不检查SSH主机登录的密钥
display_skipped_hosts = False # 不显示已跳过的主机
retry_files_enabled = False # 不创建任务失败后的重试文件
# 按照1d设置setup缓存,优化执行效率
gathering = smart
fact_caching_timeout = 86400
fact_caching = jsonfile
fact_caching_connection = cachedir

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
[defaults]
forks = 50
timeout = 120
host_key_checking = False
display_skipped_hosts = False
deprecation_warnings = False
retry_files_enabled = False
# log_path = ansible.log
# retry_files_enabled = True
retry_files_save_path = ansible-retry
# https://mitogen.networkgenomics.com/ansible_detailed.html
strategy_plugins = ./plugin/mitogen-0.2.9/ansible_mitogen/plugins/strategy
strategy = mitogen_linear
callback_whitelist=timer
# gathering = smart
# fact_caching_timeout = 7200
# fact_caching = jsonfile
# fact_caching_connection = cachedir

[ssh_connection]
pipelining = True
ssh_args = -o ControlMaster=auto -o ControlPersist=60s -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -o ForwardAgent=yes


Ansible常见技巧

https://docs.ansible.com/ansible/latest/inventory_guide/index.html
https://docs.ansible.com/ansible/latest/inventory_guide/intro_inventory.html

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
参数								描述
ansible_host 将要连接的远程主机名.与你想要设定的主机的别名不同的话,可通过此变量设置.
ansible_port 连接端口号,如果是ssh的话,默认是22
ansible_user 用于连接认证的用户名
ansible_password 用于连接认证的用户名密码
ansible_ssh_private_key_file ssh 使用的私钥文件.适用于有多个密钥,而你不想使用 SSH 代理的情况.

ansible_become 开启提权,等同于ansible_sudo,ansible_su
ansible_become_method 提权方式
ansible_become_user 提权用户,等同于ansible_sudo_user,ansible_su_user
ansible_become_password 提权密码,等同于ansible_sudo_password,ansible_su_password
ansible_become_flags 提权命令的参数,等同于ansible_sudo_flags,ansible_su_flags

-e EXTRA_VARS, --extra-vars EXTRA_VARS 添加附加变量,比如key=value,yaml,json格式。使用@指定文件
-f FORKS, --forks FORKS 指定定要使用的并行进程数,默认为5个。
-i INVENTORY, --inventory INVENTORY, --inventory-file INVENTORY 指定主机清单文件或逗号分隔的主机,默认为/etc/ansible/hosts。
-l SUBSET, --limit SUBSET 进一步限制所选主机/组模式,只执行-l后的主机和组。
-t TAGS, --tags TAGS 运行指定的带有tags任务
--skip-tags=SKIP_TAGS 跳过运行标记此标签的任务
-v, --verbose 输出执行的详细信息,使用-vvv获得更多,-vvvv 启用连接调试

--become-method=BECOME_METHOD 权限升级方法使用 ,默认为sudo,有效选择:[sudo | su | pbrun | pfexec | runas | doas | dzdo]
--become-user=BECOME_USER 使用哪个用户运行,默认为root
-K, --ask-become-pass 提供权限提升密码
-b, --become 运行权限提升

become 指令
become 设置yes即开启提升权限
become_user 指定提升权限的用户
become_method 指定提升权限的方式,有sudo,su,runas等。
become_flags 传给可执行文件的参数

- name: Run a command as nobody
command: somecommand
become: yes
become_method: su
become_user: nobody
become_flags: '-s /bin/sh'

以下是一些重要的注册变量的组件
changed: 显示是否已更改
cmd: 执行的命令
rc: 命令的返回码
stdout:命令的输出
stdout_lines: 逐行输出
stderr: 如果有错误,则输出错误的信息
stderr_lines: 逐行输出错误信息

默认情况下,Ansible会并行地管理一个剧本中引用的所有机器。对于滚动更新用例,可以使用serial关键字定义Ansible并行执行多少台主机
---
- name: test play
hosts: webservers
serial: 3
gather_facts: False

tasks:
- name: task one
command: hostname
- name: task two
command: hostname

在任务上使用delegate_to关键字,可以将任务委托给指定主机去执行。delegate_to: 127.0.0.1 是将任务委派到ansible本地去执行,你可以使用简写的local_action 去执行
---
- hosts: webservers
serial: 5

tasks:
- name: take out of load balancer pool
command: /usr/bin/take_out_of_pool {{ inventory_hostname }}
delegate_to: 127.0.0.1

为运行程序指定环境变量,需指定environment关键字
- tasks:
- apt: name=cobbler state=installed
environment:
http_proxy: http://proxy.example.com:8080
PATH: /var/local/nvm/versions/node/v4.2.1/bin:{{ ansible_env.PATH }}

ignore_errors 模块可以在任务执行错误时,忽略错误并继续执行任务。
- tasks:
- command: /bin/false
ignore_errors: true

- debug: msg="false"

多行字符串可以使用|保留换行符,也可以使用>折叠换行。
this: |
Foo
Bar

that: >
Foo
Bar

+表示保留文字块末尾的换行,-表示删除字符串末尾的换行。
s1: |
Foo


s2: |+
Foo


s3: |-
Foo



Linux

  • 服务端操作系统:RHEL 6/7(Windows不可作为控制端)
  • 服务端Python版本:2.7.14(实测安装完成无需额外调整)
  • Ansible版本:2.3.3.0(实测2.4以上版本已不支持rhel5.5,客户端需simplejson)
  • 管理对象:目前主要针对RHEL 5/6/7(Windows使用高版本Ansible)
  • 基线标准:参考《主机岗配置基线 v1.1.xlsx》

服务端

  • 操作系统版本:RHEL 6/7
  • Python版本:2.7.14
  • 安装方式:pip离线安装依赖包

客户端

  • 操作系统版本:RHEL 5/6/7
  • 非最小模式安装无需做调整
  • RHEL5.5需要安装simplejson

核心用法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 检测ansible是否可以正常访问主机
ansible-playbook -i hosts playbooks/ping.yml -v
# 配置好inventory,执行以下命令创建用户并建立信任关系
ansible-playbook -i hosts playbooks/user/default.yml -v
# 配置时间同步/进程服务/基线文件
ansible-playbook -i hosts playbooks/baseline/cfgset.yml -v
ansible-playbook -i hosts playbooks/baseline/cfgset.yml -v --tags="repo"
ansible-playbook -i hosts playbooks/baseline/cfgset.yml -v --skip-tags="ntp,repo"
# 更新系统软件包和补丁包
ansible-playbook -i hosts playbooks/baseline/pakset.yml -v
# 修改用户密码
ansible-playbook -i hosts_changepw playbooks/user/changepw.yml -v -e "@userpass.json"
# 备份配置,支持自定义日期命名,默认为"%Y%m%d"
ansible-playbook -i hosts backup/backup.yml -v
# 恢复配置,支持按日期目录全局或者局部主机恢复
ansible-playbook -i hosts backup/restore.yml -v -e "var_backup_date=20180305"

Windows

  • 服务端操作系统:RHEL 6/7(Windows不可作为控制端)
  • 服务端Python版本:2.7.14(实测安装完成无需额外调整)
  • Ansible版本:2.5.0(Windows原生模块支持需要持续更新Ansible新版本)
  • 管理对象:目前主要针对Windows 7/2008/2012(不支持xp/2003)
  • 基线标准:参考《Windows 安全基线》

服务端

  • 操作系统版本:RHEL 6/7
  • Python版本:2.7.14
  • 安装方式:pip离线安装依赖包(目前使用pipenv切换管理Linux和Windows)

客户端

  • 操作系统版本:Window 7/2008/2012
  • WinRM(Windows 7/2008 需要升级至 Powershell v3.0)

核心用法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 检测ansible是否可以正常访问主机
ansible-playbook -i hosts win_playbooks/ping.yml -v
# 配置好inventory,执行以下命令创建用户并建立信任关系
ansible-playbook -i hosts win_playbooks/user/default.yml -v
# 配置时间同步/进程服务/基线文件
ansible-playbook -i hosts win_playbooks/baseline/cfgset.yml -v
ansible-playbook -i hosts win_playbooks/baseline/cfgset.yml -v --tags="wsus"
ansible-playbook -i hosts win_playbooks/baseline/cfgset.yml -v --skip-tags="ntp,wsus"
# 更新系统软件包和补丁包
ansible-playbook -i hosts win_playbooks/baseline/pakset.yml -v
# 修改用户密码
ansible-playbook -i win_hosts_changepw win_playbooks/user/changepw.yml -v -e "@userpass.json"
# 备份配置,支持自定义日期命名,默认为"%Y%m%d"
ansible-playbook -i win_hosts win_backup/backup.yml -v
# 恢复配置,支持按日期目录全局或者局部主机恢复
ansible-playbook -i win_hosts win_backup/restore.yml -v -e "var_backup_date=20180305"

Where X=ansible

https://learnxinyminutes.com/docs/ansible/

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
---
"{{ Ansible }}" is an orchestration tool written in Python.
...

---
- hosts: apache

vars:
apache2_log_level: "warn"

handlers:
- name: restart apache
service:
name: apache2
state: restarted
enabled: True
notify:
- Wait for instances to listen on port 80
become: True

- name: reload apache
service:
name: apache2
state: reloaded
notify:
- Wait for instances to listen on port 80
become: True

- name: Wait for instances to listen on port 80
wait_for:
state: started
host: localhost
port: 80
timeout: 15
delay: 5

tasks:
- name: Update cache
apt:
update_cache: yes
cache_valid_time: 7200
become: True

- name: Install packages
apt:
name={{ item }}
with_items:
- apache2
- logrotate
notify:
- restart apache
become: True

- name: Configure apache2 log level
lineinfile:
dest: /etc/apache2/apache2.conf
line: "LogLevel {{ apache2_log_level }}"
regexp: "^LogLevel"
notify:
- reload apache
become: True
...

# Universal way
$ pip install ansible

# Debian, Ubuntu
$ apt-get install ansible

# Command pings localhost (defined in default inventory: /etc/ansible/hosts)
$ ansible -m ping localhost
# You should see this output
localhost | SUCCESS => {
"changed": false,
"ping": "pong"
}

$ ansible -m ping all
$ ansible -m shell -a 'date; whoami' localhost #hostname_or_a_group_name

$ ansible -m command -a 'date; whoami' # FAILURE
$ ansible -m command -a 'date' all
$ ansible -m command -a 'whoami' all

- hosts: all

tasks:
- name: "ping all"
ping:

- name: "execute a shell command"
shell: "date; whoami; df -h;"

$ ansible-playbook path/name_of_the_playbook.yml

localhost

[some_group]
hostA.mydomain.com
hostB.localdomain
1.2.3.4

[a_group_of_a_groups:children]
some_group
some_other_group

- hosts: all

tasks:
- name: "ping all"
ping:
- name: "execute a shell command"
shell: "date; whoami; df -h;"

roles:
- some_role
- { role: another_role, some_variable: 'learnxiny', tags: ['my_tag'] }

pre_tasks:
- name: some pre-task
shell: echo 'this task is the last, but would be executed before roles, and before tasks'

$ # The following example contains a shell-prompt to indicate the venv and relative path
$ git clone git@github.com:sirkubax/ansible-for-learnXinYminutes.git
user@host:~/$ cd ansible-for-learnXinYminutes
user@host:~/ansible-for-learnXinYminutes$ source environment.sh
$
$ # First lets execute the simple_playbook.yml
(venv) user@host:~/ansible-for-learnXinYminutes$ ansible-playbook playbooks/simple_playbook.yml

$ source environment.sh
$ # Now we would run the above playbook with roles
(venv) user@host:~/ansible-for-learnXinYminutes$ ansible-playbook playbooks/simple_role.yml

roles/
some_role/
defaults/ # contains default variables
files/ # for static files
templates/ # for jinja templates
tasks/ # tasks
handlers/ # handlers
vars/ # more variables (higher priority)
meta/ # meta - package (role) info

playbooks/roles/simple_apache_role/
├── tasks
│ └── main.yml
└── templates
└── main.yml

# read playbooks/lookup.yml
# then run
(venv) user@host:~/ansible-for-learnXinYminutes$ ansible-playbook playbooks/lookup.yml

ansible -m shell -a 'echo "{{ my_variable }}"' -e 'my_variable="{{ lookup("pipe", "date") }}"' localhost
ansible -m shell -a 'echo "{{ my_variable }}"' -e 'my_variable="{{ lookup("pipe", "hostname") }}"' all

# Or use in playbook

(venv) user@host:~/ansible-for-learnXinYminutes$ ansible-playbook playbooks/lookup.yml

(venv) user@host:~/ansible-for-learnXinYminutes$ ansible-playbook playbooks/register_and_when.yml

---
- hosts: localhost
tasks:
- name: check the system capacity
shell: df -h /
register: root_size

- name: debug root_size
debug:
msg: "{{ root_size }}"

- name: debug root_size return code
debug:
msg: "{{ root_size.rc }}"

# when: example

- name: Print this message when return code of 'check the system capacity' was ok
debug:
msg: "{{ root_size.rc }}"
when: root_size.rc == 0
...

---
- hosts: localhost
tasks:
- name: check the system capacity
shell: df -h /
when: some_variable in 'a string'
roles:
- { role: mid_nagios_probe, when: allow_nagios_probes }
...

ansible-playbook playbooks/simple_playbook.yml --tags=tagA,tag_other
ansible-playbook playbooks/simple_playbook.yml -t tagA,tag_other

There are special tags:
always

--skip-tags can be used to exclude a block of code
--list-tags to list available tags

ansible-playbook playbooks/simple_playbook.yml --limit localhost

--limit my_hostname
--limit groupname
--limit some_prefix*
--limit hostname:group #JM

Some static content

{{ a_variable }}

{% for item in loop_items %}
this line item is {{ item }}
{% endfor %}

$ source environment.sh
$ # Now we would run the above playbook with roles
(venv) user@host:~/ansible-for-learnXinYminutes$ ansible-playbook playbooks/simple_role.yml --tags apache2

ansible -m shell -a 'echo {{ my_variable }}' -e 'my_variable=something, playbook_parameter=twentytwo' localhost

# check part of this playbook: playbooks/roles/sys_debug/tasks/debug_time.yml
- local_action: shell date +'%F %T'
register: ts
become: False
changed_when: False

- name: Timestamp
debug: msg="{{ ts.stdout }}"
when: ts is defined and ts.stdout is defined
become: False

# get first item of the list
{{ some_list | first() }}
# if variable is undefined - use default value
{{ some_variable | default('default_value') }}

# Try (this would fail)
$ ansible-playbook playbooks/vault_example.yml

$ echo some_very_very_long_secret > ~/.ssh/secure_located_file

# in ansible.cfg set the path to your secret file
$ vi ansible.cfg
ansible_vault_password_file = ~/.ssh/secure_located_file

#or use env
$ export ANSIBLE_VAULT_PASSWORD_FILE=~/.ssh/secure_located_file

$ ansible-playbook playbooks/vault_example.yml

# encrypt the file
$ ansible-vault encrypt path/somefile

# view the file
$ ansible-vault view path/somefile

# check the file content:
$ cat path/somefile

# decrypt the file
$ ansible-vault decrypt path/somefile

$ etc/inv/ec2.py --refresh
$ ansible -m ping all -i etc/inv/ec2.py

vi ansible.cfg
# set this to:
callback_whitelist = profile_tasks

vi ansible.cfg

# if set to a persistent type (not 'memory', for example 'redis') fact values
# from previous runs in Ansible will be stored. This may be useful when
# wanting to use, for example, IP information from one group of servers
# without having to talk to them in the same playbook run to get their
# current IP information.
fact_caching = jsonfile
fact_caching_connection = ~/facts_cache
fact_caching_timeout = 86400

# recreate ansible 2.x venv
$ rm -rf venv2
$ source environment2.sh

# execute playbook
(venv2)$ ansible-playbook playbooks/ansible1.9_playbook.yml # would fail - deprecated syntax

# now lets install ansible 1.9.x next to ansible 2.x
(venv2)$ deactivate
$ source environment.1.9.sh

# execute playbook
(venv1.9)$ ansible-playbook playbooks/ansible1.9_playbook.yml # works!

# please note that you have both venv1.9 and venv2 present - you need to (de)activate one - that is all

- name: Ensure the httpd service is running
service:
name: httpd
state: started
become: true

ansible -m ping web*

ansible -m ping web*:!backend:monitoring:&allow_change

结语

很抱歉我暂时不能分享全部信息,但是这并不妨碍技术上的交流,我会逐步分享有价值的可公开代码

  1. 遵循what/why/how思路,要理解ansible能解决什么问题,为什么选择ansible,怎么使用ansible去解决
  2. Ansible学习成本低但不等同于没有难度,学习路径推荐参考官方文档并积极实践,官网没有答案要善用Google搜索
  3. Ansible纯后台模式只解决了部分问题,还有更多需求要通过基于Ansible的自动化运维平台来实现,拥抱开源技术不能固步自封

参考文章

Ansible Documentation

ansible-workshops

Ansible 入门指南 - 学习总结

这样理解Ansible更容易

前世今生:1 小时学会 Ansible

Ansible 专题文章总揽

朱双印-ansible 系列

骏马金龙-ansible

B站视频-ansible教程-马哥2019全新ansible入门到精通

Ansible 日常使用技巧 - 运维总结

Ansible–奇淫技巧

Ansible入门

Ansible Wiki

文章目录
  1. 1. 前言
  2. 2. 更新历史
  3. 3. Ansible 标准化学习路径
  4. 4. 提升 Ansible 执行效率的插件
  5. 5. 基于 Ansible 的开源项目
  6. 6. Ansible 项目实践
    1. 6.1. ansible 部署
    2. 6.2. ansible.cfg 配置解析
    3. 6.3. Ansible常见技巧
    4. 6.4. Linux
    5. 6.5. Windows
  7. 7. Where X=ansible
  8. 8. 结语
  9. 9. 参考文章