Documentation

Intro to Playbooks

关于Playbooks

与ad-hoc任务执行模式相比,Playbooks方式使用ansible是一种完全不同的方式,并且功能特别强大。

简而言之,playbooks是真正简单的配置管理和多机器部署系统的基础,与已有的系统不同,并且非常适合部署复杂的应用程序。

Playbooks可以声明配置,但它们也可以协调任何手动安排流程的步骤,即使不同的步骤必须在特定安排的机器组之间来回跳转。 他们可以同步或异步启动任务。

虽然您可以运行主/usr/bin/ansible程序来执行临时任务,但是Playbook更可能保留在源代码管理中并用于推出配置或确保远程配置系统符合规范。

ansible-examples存储库中还有一些完整的手册说明了很多这些技术。 我们建议您在另一个标签中查看这些内容。

在学习了playbook后,还有许多跳转标签点,所以在完成本节后,请跳回文档索引。

Playbook语言示例

Playbooks以YAML格式表示(参见YAML语法)并且具有最少的语法,有意尝试不是编程语言或脚本,而是配置或进程的模型。

每个playbook由列表中的一个或多个“plays”组成。

playbook的目标是将一组主机映射到一些定义明确的角色,由ansible调用任务表示。 在基本级别,任务只不过是对ansible模块的调用(参见使用模块)。

通过编写多个“plays”的playbook,可以编排多机部署,在Web服务器组中的所有计算机上运行某些步骤,然后在数据库服务器组上执行某些步骤,然后在Web服务器组上执行更多命令,等等。

“plays”或多或少类似体育。 你可以有很多plays影响你的系统做不同的事情。 这并不是说你只是定义了一个特定的状态或模型,而是可以在不同的时间运行不同的playbook。

对于初学者来说,这是一个只包含一个play的playbook:

---
- hosts: webservers
  vars:
    http_port: 80
    max_clients: 200
  remote_user: root
  tasks:
  - name: ensure apache is at the latest version
    yum:
      name: httpd
      state: latest
  - name: write the apache config file
    template:
      src: /srv/httpd.j2
      dest: /etc/httpd.conf
    notify:
    - restart apache
  - name: ensure apache is running (and enable it at boot)
    service:
      name: httpd
      state: started
      enabled: yes
  handlers:
    - name: restart apache
      service:
        name: httpd
        state: restarted

When working with tasks that have really long parameters or modules that take many parameters, you can break tasks items over multiple lines to improve the structure. Below is another version of the above example but using YAML dictionaries to supply the modules with their key=value arguments.:

---
- hosts: webservers
  vars:
    http_port: 80
    max_clients: 200
  remote_user: root
  tasks:
  - name: ensure apache is at the latest version
    yum:
      name: httpd
      state: latest
  - name: write the apache config file
    template:
      src: /srv/httpd.j2
      dest: /etc/httpd.conf
    notify:
    - restart apache
  - name: ensure apache is running
    service:
      name: httpd
      state: started
  handlers:
    - name: restart apache
      service:
        name: httpd
        state: restarted

Playbooks可以包含多个plays。 您可能有一个首先针对Web服务器,然后是数据库服务器的playbook。 例如:

---
- hosts: webservers
  remote_user: root

  tasks:
  - name: ensure apache is at the latest version
    yum:
      name: httpd
      state: latest
  - name: write the apache config file
    template:
      src: /srv/httpd.j2
      dest: /etc/httpd.conf

- hosts: databases
  remote_user: root

  tasks:
  - name: ensure postgresql is at the latest version
    yum:
      name: postgresql
      state: latest
  - name: ensure that postgresql is started
    service:
      name: postgresql
      state: started

您可以使用此方法在您要定位的主机组,登录到远程服务器的用户名,是否为sudo等之间切换。 与任务一样,plays按照playbook中指定的顺序运行:从上到下。

下面,我们将分解playbook语言的各种功能。

基础

主机和用户

对于playbook中的每个play,您可以选择基础架构中的哪些计算机作为目标,以及用什么远程用户完成步骤(称为任务)。

hosts行是一个由冒号分隔的一个或多个组或主机匹配模式的列表,如使用匹配模式文档中所述。 remote_user只是用户帐户的名称:

---
- hosts: webservers
  remote_user: root

Note

remote_user参数以前只称为user 它在Ansible 1.4中重命名,使其与user模块(用于在远程系统上创建用户)更加区分开。

每个任务也可以定义远程用户:

---
- hosts: webservers
  remote_user: root
  tasks:
    - name: test connection
      ping:
      remote_user: yourname

还支持以另一个用户身份运行(请参阅了解权限提升):

---
- hosts: webservers
  remote_user: yourname
  become: yes

您还可以在特定任务而不是整个playbook中使用 become:

---
- hosts: webservers
  remote_user: yourname
  tasks:
    - service:
        name: nginx
        state: started
      become: yes
      become_method: sudo

您也可以像登录一样,然后 become 与root不同的用户:

---
- hosts: webservers
  remote_user: yourname
  become: yes
  become_user: postgres

您还可以使用其他权限提升方法,例如su:

---
- hosts: webservers
  remote_user: yourname
  become: yes
  become_method: su

如果您需要为sudo指定密码,请使用--ask-become-pass运行ansible-playbook或使用旧的sudo语法--ask-sudo-pass-K)。 如果你运行一个 become playbook并且playbook似乎挂起,它可能会停留在权限提升提示下。 只需Control-C即可将其停止并再次运行并添加相应的密码。

重要

become_user用于root以外的用户时,会将模块参数简要写入/ tmp中的随机临时文件中。 执行命令后立即删除它们。 这种情况只发生在将用户从'bob'更改为'timmy'时的权限,而不是从'bob'更改为'root',或直接以'bob'或'root'身份登录时。 如果您担心此数据可以短暂读取(不可写),请避免在设置become_user的情况下传输未加密的密码。 在其他情况下,不使用/tmp,这不起作用。 Ansible还注意不记录密码参数。

版本2.4中的新功能。

您还可以控制运行主机的顺序。 默认设置是遵循主机库存提供的顺序:

- hosts: all
  order: sorted
  gather_facts: False
  tasks:
    - debug:
        var: inventory_hostname

顺序的可能值为:

inventory:
默认值。 顺序由主机库存“提供”
reverse_inventory:
顾名思义,这会反转主机库存“提供”的顺序
sorted:
主机按名称按字母顺序排序
reverse_sorted:
主机按名称按反向字母顺序排序
shuffle:
主机是每次运行随机排序的

任务列表

每个play都包含一系列任务。 在继续执行下一个任务之前,任务将按顺序执行,对应所有与主机模式匹配的计算机。 重要的是要理解,在play中,所有主机都将获得相同的任务指令。 play的目的是将选择的主机映射到任务。

当运行从上到下运行的playbook时,具有失败任务的主机将从整个playbook的轮换中取出。 如果事情失败,只需更正playbook文件并重新运行。

每个任务的目标是执行一个具有非常具体参数的模块。 如上所述,变量可用于模块的参数。

模块应该是幂等的,也就是说,在序列中多次运行模块应该与仅运行一次模块具有相同的效果。 实现幂等性的一种方法是让模块检查是否已经实现了期望的最终状态,并且如果已经实现该状态,则退出而不执行任何动作。 如果playbook使用的所有模块都是幂等的,那么playbbok本身很可能是幂等的,因此重新运行剧本应该是安全的。

commandshell模块通常会再次重新运行相同的命令,如果命令类似于chmodsetsebool 等,则完全可以。 虽然有一个creates标志可用于使这些模块也是幂等的。

每个任务都应该有一个name,它包含在运行playbook的输出中。 这是人类可读的输出,因此提供每个任务步骤的良好描述是有用的。 如果没有提供名称,则输入“action”的字符串将用于输出。

可以使用兼容的方式声明任务 action: module options 格式,但建议您使用更传统的 module: options 格式。 在本文档中完全使用了此推荐格式,但在某些剧本中可能会遇到旧格式。

这是基本任务的样子。 与大多数模块一样,服务模块采用key=value参数:

tasks:
  - name: make sure apache is running
    service:
      name: httpd
      state: started

commandshell模块是获取参数列表且不使用key=value表单的模块。 这使它们像您期望的那样工作:

tasks:
  - name: enable selinux
    command: /sbin/setenforce 1

commandshell模块关心返回码,因此如果您有一个成功退出但状态码不为零的命令,您可能希望这样做:

tasks:
  - name: run this command and ignore the result
    shell: /usr/bin/somecommand || /bin/true

或这样:

tasks:
  - name: run this command and ignore the result
    shell: /usr/bin/somecommand
    ignore_errors: True

如果动作行太长而不舒服,你可以在空格上打破它并缩进任何延续线:

tasks:
  - name: Copy ansible inventory file to client
    copy: src=/etc/ansible/hosts dest=/etc/ansible/hosts
            owner=root group=root mode=0644

变量可用于动作行。 假设您在vars部分中定义了一个名为vhost的变量,您可以这样做:

tasks:
  - name: create a virtual host file for {{ vhost }}
    template:
      src: somefile.j2
      dest: /etc/httpd/conf.d/{{ vhost }}

这些相同的变量可以在模板中使用,我们将在稍后介绍。

现在,在一个非常基本的playbook中,所有任务都将直接列在该play中,尽管按照创建可重复使用的剧本中的描述分解任务通常更有意义。

动作速记

版本0.8中的新功能。

Ansible更喜欢这样列出模块:

template:
    src: templates/foo.j2
    dest: /etc/foo.conf

早期版本的Ansible使用以下格式,它仍然有效:

action: template src=templates/foo.j2 dest=/etc/foo.conf

处理程序:在变更时触发的运行操作

正如我们所提到的,模块应该是幂等的,并且可以在他们对远程系统进行更改时进行中继。 Playbooks认识到这一点,并拥有一个可用于响应变化的基本事件系统。

这些“notify”操作在play中的每个任务块结束时触发,即使由多个不同任务通知也只会触发一次。

例如,多个资源可能表示需要重新启动apache,因为他们已经更改了配置文件,但是apache只会被重启一次以避免不必要的重启。

以下是在文件内容发生更改时重新启动两个服务的示例,但仅在文件更改时:

- name: template configuration file
  template:
    src: template.j2
    dest: /etc/foo.conf
  notify:
     - restart memcached
     - restart apache

任务的notify部分中列出的内容称为处理程序。

处理程序是由全局唯一名称引用并由通知程序通知的任务列表,与常规任务实际上没有任何不同。 如果没有通知处理程序,它将不会运行。 无论通知处理程序的任务有多少,在特定playbook中完成所有任务后,它只会运行一次。

这是一个示例处理程序部分:

handlers:
    - name: restart memcached
      service:
        name: memcached
        state: restarted
    - name: restart apache
      service:
        name: apache
        state: restarted

从Ansible 2.2开始,处理程序也可以“listen”通用主题,任务可以通知如下主题:

handlers:
    - name: restart memcached
      service:
        name: memcached
        state: restarted
      listen: "restart web services"
    - name: restart apache
      service:
        name: apache
        state:restarted
      listen: "restart web services"

tasks:
    - name: restart everything
      command: echo "this task will restart the web services"
      notify: "restart web services"

这种使用使得触发多个处理程序变得更加容易。 它还将处理程序与其名称分离,从而更容易在playbooks和角色之间共享处理程序(尤其是在使用Galaxy等共享源中的第三方角色时)。

Note

  • 通知处理程序始终按照定义的顺序运行,按通知语句中列出的顺序运行。 使用listen的处理程序也是如此。
  • 处理程序名称和listen主题位于全局命名空间中。
  • 如果两个处理程序任务具有相同的名称,则只运行一个。 *
  • 您无法通知在include内定义的处理程序。 从Ansible 2.1开始,这确实有效,但include必须是static

角色将在后面描述,但值得指出的是:

  • pre_taskstaskspost_tasks部分中通知的处理程序将在通知它们的部分末尾自动刷新;
  • roles部分中通知的处理程序将在tasks部分的末尾自动刷新,但在任何tasks处理程序之前。

如果您想立即刷新所有处理程序命令,可以执行以下操作:

tasks:
   - shell: some tasks go here
   - meta: flush_handlers
   - shell: some other tasks

在上面的示例中,当到达meta语句时,将尽早处理任何排队的处理程序。 这是一个小巧的案例,但可以不时派上用场。

执行Playbook

既然你已经学会了playbook语法,你如何运行剧本? 这很简单。 让我们使用10的并行度级别运行一个剧本:

ansible-playbook playbook.yml -f 10

Ansible-Pull:Ansible拉取

如果您想要反转Ansible的体系结构,以便节点检入中心位置,而不是将配置推送到它们,您可以使用 ansible-pull。

ansible-pull是一个小脚本,它将从git中检出配置指令的repo,然后针对该内容运行ansible-playbook

假设您对节点位置进行负载均衡,ansible-pull基本上可以无限扩展。

有关详细信息,请运行ansible-pull --help

还有一个聪明的playbook可以通过crontab从推送模式配置成ansible-pull模式。

技巧和窍门

要检查剧本的语法,请使用带有--syntax-check标志的ansible-playbook 这将通过解析器运行playbook文件,以确保其包含的文件,角色等没有语法问题。

查看playbook执行的输出结果,了解目标节点及其执行方式的摘要。 一般失败和致命的“无法到达”的通信尝试在计数中保持分开。

如果您想查看成功模块以及不成功模块的详细输出,请使用--verbose标志。 这在Ansible 0.5及更高版本中可用。

要在运行之前查看哪个主机会受到剧本的影响,您可以执行以下操作:

ansible-playbook playbook.yml --list-hosts

参考

YAML语法
了解YAML语法
最佳实践
关于在实际工作中管理playbook的各种提示
所有模块
了解可用的模块
开发模块
了解如何通过编写自己的模块来扩展Ansible
使用匹配模式
了解如何选择主机
Github示例目录
完整的端到端playbook示例
邮件列表
有问题吗? 帮帮我? 想法? 止于Google网上论坛列表中