Skip to content

03. playbooks

一个 playbooks 可以包含多个 play:

---
- 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

1. 基础

1.1 Hosts and Users

---
- hosts: webservers
  remote_user: root
  • hosts 的语法,以冒号分隔多个主机。

  • remote_user 指定登录到远程主机的账户(同时是默认的执行任务的账户)。

还支持指定其他帐户执行 (Understanding privilege escalation: become)(在 play 或 task 级别):

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

1.1.1 order

在 2.4 及之后,还可以指定主机的执行顺序。

- hosts: all
  order: sorted

可选的值有以下几种:

  • inventory:默认值,按照 inventory 提供的顺序执行
  • reverse_inventory
  • sorted:主机按名称的字母顺序排列
  • reverse_sorted
  • shuffle

1.2 Tasks list

任务是按序执行的。当执行 playbook 的时候,任务失败的主机将从整个 playbook 的轮换中删除。

任务都是通过模块来执行的。并且模块应该是幂等的,即在一个序列中多次运行一个模块应该与仅运行一次具有相同的效果。

大部分模块的参数都是通过 key=value 的方式指定的:

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

commandshell 是唯一使用参数列表的模块:

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

并且它们关心退出码,若命令成功执行的退出码非零,那么可以这样写:

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

2. Handlers

当 task 执行的执行结果是 changed 时, notify 动作会触发其他的 tasks,这些 tasks 就是 handler。

这些 notify 动作是在 play 中每个任务块的结尾处触发的,即使被多个不同的任务通知,也只会触发一次(因为模块的幂等性)。

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

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

注意:因为 handler 的 name 是模板化的,不要在 handler 的名字中使用变量!

从 Ansible 2.2 开始, handler 还可以 listen 通用 topic,task 可以像下面这样通知这些 topics:

  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"

仔细看,"restart web services" 并没有指向任何一个 handler ,它只是被 handler 监听,在通知时触发这些 handler。

Note

  • handler 的执行顺序是定义时的顺序,而不是被通知的顺序;
  • handler 的 name 与 listen topics 的作用域是全局的;
  • handler 的 name 是模板化的,listen topics 不是;
  • 为每个 handler 定义唯一的 name,否则只会执行最后一个被定义的 handler ;
  • 在 Ansible 2.2 以前,不能通知被引入(include)的 handler;从 Ansible 2.2 开始, 可以这样使用,但必须是静态引入。