基于Ansible 1.9.6。Github
概述
ansible-playbook是ansible用于执行playbook的命令行工具。而ansible-playbook位于ansible/bin/下。
好戏开始了
主流程:main(args)
- 创建CLI选项的解析器,对选项进行解析
- ansible-playbook比ansible少的几个选项
-o
/--one-line
:精简输出-t
/--tree
:将输出保存到该目录中,默认值:None-P
/--poll
:如果使用-B选项,则用该选项设置poll间隔,默认值:由constants.DEFAULT_POLL_INTERVAL指定-B
/--background
:异步运行,在X秒后失败,默认值:0
- ansible-playbook比ansible多的几个选项
-D
/--diff
:当修改(小)文件和模板时,显示这些文件的不同;与--check
选项一起服用更佳。默认值:False-t
/--tags
:只运行那些带有该选项指定值的标签的play和task。 默认值:'all'--skip-tags
:只运行那些不带有该选项指定值的标签的play和task。--syntax-check
:对该playbook进行语法检查,并且不对其进行执行。--list-tasks
:列出所有要执行的task--list-tags
:列出所有可用标签--step
:一次执行一个步骤,在每个步骤运行之前进行确认--start-at-task
:在匹配该选项指定的名字的那个task开始该playbook--force-handlers
:即使task失败了,也要运行handler。默认值:由C.DEFAULT_FORCE_HANDLERS
指定--flush-cache
:清除fact缓存
- ansible-playbook比ansible少的几个选项
- 一些准备工作
- 检查权限相关的选项是否冲突:
- sudo相关选项、su相关选项和become相关选项相互排斥
--ask-vault-pass
和--vault-password-file
相互排斥
- 询问密码
- 如果是
--list-hosts
/--syntax-check
/--list-tags
,则按需询问vault password - 否则,在不是本地操作的情况下,按需询问ssh password / become passowrd / vault password
- 在未指定
--ask-vault-pass
,并且指定了vault password file的情况下,读取文件中的vault password
- 如果是
- 判断playbook是否存在,是否是一个文件
- 根据指定的inventory,初始化
ansible.inventory.Inventory
实例- 判断提供的主机列表是否为空
- 根据
--limit
选项过滤掉不需要执行的主机,然后再一次判断过滤后的主机列表是否为空
- 检查权限相关的选项是否冲突:
- 运行命令行参数指定的所有playbook。对每个playbook,有
- 创建一个
ansible.callbacks.AggregateStats
实例,用来对playbook的运行结果进行整理统计 - 创建一个
ansible.callbacks.PlaybookCallbacks
实例 - 创建一个
ansible.callbacks.PlaybookRunnerCallbacks
实例 - 用playbook初始化一个
ansible.playbook.PlayBook
实例 - 除了实际做点什么……
- 设置了
--list-hosts
,则列出该playbook对应的主机列表 - 设置了
--list-tags
/--list-tasks
,则列出该playbook中所有的tag/task - 设置了
--syntax-check
,则在前面所有操作都运行完后没有任何错误,则表示语法正常,直接返回。
- 设置了
- 运行playbook:
ansible.playbook.PlayBook.run()
- 解析执行结果(此时,前面定义的AggregateStats实例派上用场)
- 计算failed(失败)或者unreachable(不可达)的主机,根据
C.RETRY_FILES_ENABLED
参数按需生成retry文件 - 对每个主机,展示执行结果:ok / changed / unreachable / failed
- 若failed的主机数大于0,则返回2
- 若unreachable的主机数大于0,则返回3
- 中途抛出任意异常,则返回1
- 计算failed(失败)或者unreachable(不可达)的主机,根据
- 创建一个
边边角角的类及函数说明
ansible.inventory.Inventory
ansible中用于解析inventory的类- 初始化
1
2
3# host_list:默认值由ansible.constants.DEFAULT_HOST_LIST指定,可以是一个主机文件路径(字符串)、主机脚本路径(字符串)、host列表(列表)、由逗号分隔的主机列表(字符串)
# vault_password:vault password
__init__(self, host_list=C.DEFAULT_HOST_LIST, vault_password=None) - 几个方法
1
2
3
4
5
6# 返回所有主机名匹配参数pattern指定的值的主机,并且考虑所有的inventory限制或者应用的子集。
# pattern:可以是一个列表,或者由";"/","/":"分隔的字符串
get_hosts(self, pattern="all")
# 返回主机名匹配参数pattern指定值的主机名。若pattern取值为"localhost"/"127.0.0.1",则返回值包含pattern
# pattern:同get_hosts
list_hosts(self, pattern="all")
- 初始化
ansible.callbacks.AggregateStats
用以保存playbook运行期间的每一个主机活动。- 几个属性
1
2
3
4
5
6
7
8
9
10
11
12
13# 以下属性的类型皆为dict
# 保存每个主机处理过的操作数
self.processed
# 保存每个主机执行失败的操作数
self.failures
# 保存每个主机正常执行的操作数
self.ok
# 保存每个主机不可达的操作数
self.dark
# 保存每个主机有做修改的操作数
self.changed
# 保存每个主机跳过的操作数
self.skipped - 几个方法
1
2
3
4
5# 对执行结果进行计算,刷新统计信息
# runner_results为ansible.Runner.runner.run()方法的返回结果
compute(self, runner_results, setup=False, poll=False, ignore_errors=False)
# 返回由参数host指定的主机的统计信息
summarize(self, host)
- 几个属性
ansible.playbook.PlayBook
ansible中用于解析playbook的类- 初始化
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# 以下的C指的是ansible.constants
__init__(self,
playbook = None, # 一个playbook文件的路径
host_list = C.DEFAULT_HOST_LIST, # 主机文件的路径,例如/etc/ansible/hosts
module_path = None, # ansible模块的路径,例如/usr/share/ansible/
forks = C.DEFAULT_FORKS, # 所需的并行级别
timeout = C.DEFAULT_TIMEOUT, # 连接超时时间
remote_user = C.DEFAULT_REMOTE_USER, # 如果一个play中没有指定运行用户的话,则用这个用户运行
remote_pass = C.DEFAULT_REMOTE_PASS,
remote_port = None,
transport = C.DEFAULT_TRANSPORT,# 如何连接到一个未指定传输的主机,(local, paramiko等等)
private_key_file = C.DEFAULT_PRIVATE_KEY_FILE,
callbacks = None, # 该playbook的输出回调
runner_callbacks = None, # 用于runner API的回调
stats = None, # 保存每个主机运行事件的聚集信息,为ansible.callbacks.AggregateStats实例
extra_vars = None,
only_tags = None,
skip_tags = None,
subset = C.DEFAULT_SUBSET,
inventory = None, # 可以指定该参数以取代host_list,使用一个预先存在的ansible.inventory.Inventory实例
check = False, # 不进行任何实际操作,用来检测一些潜在的修改操作
diff = False,
any_errors_fatal = False, # 当其中一个主机执行失败的时候,立即结束整个执行过程
vault_password = False,
force_handlers = False, # 即使一个task失败,也会继续通知并运行handler
# privelege escalation
become = C.DEFAULT_BECOME,
become_method = C.DEFAULT_BECOME_METHOD,
become_user = C.DEFAULT_BECOME_USER,
become_pass = None,
) - 几个方法 # 观影心得 ansible-playbook是个非常强大的工具,你只需写好剧本(playbook),定下剧情(task),挑好主角(host),有时还需要一些变化(var),就可以上演一出大戏。
1
2
3
4
5
6
7# 运行playbook
# 实际上会为playbook中的每个play创建ansible.playbook.play实例,然后调用类方法_run_play()运行每个play
run()
# 实际的play运行方法。过程:获取过滤运行该play的主机列表 -> 调用类的_do_setup_step方法获取主机的facts(作为变量用在play中) -> 处理serial标签 -> 进一步过滤运行的主机 -> 运行该play中的每个task/handler -> 对结果进行处理
_run_play()
# 用以获取远程主机的facts。实际上是调用了setup模块
_do_setup_step(play)
- 初始化
ansible官网对其python API解释甚少。但是我们可以通过ansible-playbook的实现入手(ansible-playbook比ansible更复杂,更全面),了解ansible内部的python API的作用和使用方法。从而在需要的时候,参考其使用手法,在自己的app中借助ansible内部提供的方法,避免重复造轮子,打造自己的自动化工具。