好好学习,天天向上

发生了什么|Ansible之故事的放映室:ansible-playbook

基于Ansible 1.9.6。Github

概述

ansible-playbook是ansible用于执行playbook的命令行工具。而ansible-playbook位于ansible/bin/下。

好戏开始了

主流程:main(args)

  1. 创建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缓存
  2. 一些准备工作
    • 检查权限相关的选项是否冲突:
      • 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选项过滤掉不需要执行的主机,然后再一次判断过滤后的主机列表是否为空
  3. 运行命令行参数指定的所有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,则在前面所有操作都运行完后没有任何错误,则表示语法正常,直接返回。
    • 运行playbookansible.playbook.PlayBook.run()
    • 解析执行结果(此时,前面定义的AggregateStats实例派上用场)
      • 计算failed(失败)或者unreachable(不可达)的主机,根据C.RETRY_FILES_ENABLED参数按需生成retry文件
      • 对每个主机,展示执行结果:ok / changed / unreachable / failed
      • 若failed的主机数大于0,则返回2
      • 若unreachable的主机数大于0,则返回3
      • 中途抛出任意异常,则返回1

边边角角的类及函数说明

  1. 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")
  2. 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)
  3. 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,
      )
    • 几个方法
      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-playbook是个非常强大的工具,你只需写好剧本(playbook),定下剧情(task),挑好主角(host),有时还需要一些变化(var),就可以上演一出大戏。

ansible官网对其python API解释甚少。但是我们可以通过ansible-playbook的实现入手(ansible-playbook比ansible更复杂,更全面),了解ansible内部的python API的作用和使用方法。从而在需要的时候,参考其使用手法,在自己的app中借助ansible内部提供的方法,避免重复造轮子,打造自己的自动化工具。

请言小午吃个甜筒~~