什么是Playbook?

playbook是由一个或者多个模块组成的, 使用多个不同的模块, 完成一件事。

playbook通过yaml语法来识别描述的状态文件, 扩展名为yaml

Playbook的三个语法特点

缩进

YAML使用一个固定的缩进风格表示层级结构, 每个缩进由两个空格组成, 不能使用Tab

冒号

除了以冒号为结尾的以外, 其他所有的冒号后面必须要有空格。

短横线

  • 表示列表项, 使用一个短横线加一个空格。
  • 多个项使用同样的缩进级别作为同一列表。

一个安装Httpd的简单实例:

# ansible install httpd

- hosts:    # 这里是需要安装的机器列表, 也可以是ansible配置好的组名
  - 192.168.199.110
  - 192.168.199.180
  tasks:    # 任务块
    - name: install httpd server   # 描述信息
      yum:    # ansible 模块
        name: httpd,lrzsz  # 需要安装的软件名称 
        state: installed   # 执行动作
    - name: start httpd server
      service:
        name: httpd
        state: started
        enabled: yes

Playbook 常用到的关键字

hosts

hosts这一块的内容一个或者多个组或主机, 以逗号为分隔符, 或者也可换行写。

例子如下:

两种写法, 都可:

- hosts: web
  remote_user: root   # 远程执行的用户
  sudo: yes   # 是否使用sudo
  sudo_user: lanyulei   # 登陆到远程机器后sudo到其他用户

或者

- hosts:
  - 192.168.1.1
  - 192.168.1.2

如果你需要在使用sudo时指定密码, 可在运行ansible-playbook命令时加上选项--ask-sudo-pass(-K)

如果使用sudo时, playbook疑似被挂起, 可能是在sudo提示处被卡住, 这时可执行Control-C杀死卡住的任务, 再重新运行一次。

tasks

每一个play包含了一个任务列表。

一个task在其所对应的所有主机上通过hosts匹配的所有主机执行完毕之后, 下一个task才会执行。

有一点需要明白的是(很重要), 在一个play之中, 所有hosts会获取相同的任务指令,这是play的一个目的所在, 也就是将一组选出的hosts映射到task

每一个task必须有一个名称name, 这样在运行playbook时, 从其输出的任务执行信息中可以很好的辨别出是属于哪一个task的。

如果没有定义name, action的值将会用作输出信息中标记特定的task

例子如下:

两种写法, 都可:

tasks:
  - name: make sure apache is running  # 描述
    service:
      name: httpd
      state: started
      enabled: yes

或者

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

比较特别的两个ansible模块, command和shell是无法使用key=value的形式来书写的。

只能写成以下方式:

tasks:
  - name: disable selinux
    command: /sbin/setenforce 0  # shell: /sbin/setenforce 0

当你不需要关心command或者shell的命令执行成功与否的时候, 但是仍需执行后续的动作, 可忽略错误。

例子如下:

tasks:
  - name: run this command and ignore the result
    shell: /usr/bin/somecommand || /bin/true  # 总是返回True

或者

tasks:
  - name: run this command and ignore the result
    shell: /usr/bin/somecommand
    ignore_errors: True    # 忽略错误

action行中, 可以使用变量, 假设在vars哪里定义了一个变量vhost, 则可这样使用:

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

或者

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

handlers

在发生改变时执行的操作。

action发送改动的时候, notify actions会在playbook的指定task 结束时被触发,而且即使有多个不同的task通知改动的发生, notify actions只会被触发一次.

以下例子, 当推送配置文件与远程主机上的不相同, 要修改远程主机上的配置文件的时候, 则触发handlers重启两个服务:

tasks:
  - name: update httpd config
    copy:
      src: ./conf/httpd.conf
      dest: /etc/htppd/conf/httpd.conf
    notify:
      restart httpd   # 对应handlers中的name

  - name: update my.ini
    copy:
      src: ./conf/my.ini
      dest: /etc/my.ini
    notify:
      restart mysql

handlers:
  - name: restart httpd
    service:
      name: httpd
      state: restarted

  - name: restart mysql
    service:
      name: mysqld
      state: restarted

如果你想立即执行所有的handlers命令, 在1.2及以后的版本, 可以这样做:

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

任何在排队等候的handlers会在执行到meta部分时, 优先执行。

这个技巧在有些时候也能派上用场。

handlers最佳的应用场景是用来重启服务, 或者触发系统重启操作, 除此以外很少用到了。