Ansible Playbook使用

Playbook

介绍

前面简单介绍了下Ansible的安装和基本使用,这篇就说下Playbook吧,这篇与那篇一样,都是从我总结的文档中摘取出来的,整篇太长,大部分也都从官方文档整理过来的,也就不放全了。

Playbooks 的格式是YAML(详见:下面),语法做到最小化,意在避免 playbooks 成为一种编程语言或是脚本,但它也并不是一个配置模型或过程的模型.

playbook 由一个或多个 ‘plays’ 组成.它的内容是一个以 ‘plays’ 为元素的列表.

在 play 之中,一组机器被映射为定义好的角色.在 ansible 中,play 的内容,被称为 tasks,即任务.在基本层次的应用中,一个任务是一个对 ansible 模块的调用,这在前面章节学习过.

YAML语法

YAML语法格式是Ansible playbooks的配置管理语言。使用YAML是因为与XML或JSON等其他常见数据格式相比,人类读取和写入更容易。

对于Ansible,几乎每个YAML文件都以一个列表开始。 列表中的每个项目都是键/值对列表,通常称为“散列”或“字典”。 所以,我们需要知道如何在YAML中编写列表和字典。

YAML还有一个小小的怪癖。 所有YAML文件(不管它们是否与Ansible相关联)都选择以— 开始并以 … 结尾。这是YAML格式的一部分,它指示文档的开始和结束。

列表中的所有以相同的缩进级别开头的行成员,以“ – ”开头(短划线和空格):

---
# A list of tasty fruits
fruits:
    - Apple
    - Orange
    - Strawberry
    - Mango
...

字典用一个简单的 key: value 表示(冒号后必须跟一个空格):

# An employee record
martin:
    name: Martin D'vloper
    job: Developer
    skill: Elite

也可以组成更复杂的数据结构,例如字典列表,字典值列表或者混合两者:

# Employee records
-  martin:
    name: Martin D'vloper
    job: Developer
    skills:
      - python
      - perl
      - pascal
-  tabitha:
    name: Tabitha Bitumen
    job: Developer
    skills:
      - lisp
      - fortran
      - erlang

如果你真的想用,字典和列表也可以用缩写形式来表示:

---
martin: {name: Martin D'vloper, job: Developer, skill: Elite}
fruits: ['Apple', 'Orange', 'Strawberry', 'Mango']

Ansible并没有真正使用它们,你可以用多种形式指定一个布尔值(true / false):

create_key: yes
needs_agent: no
knows_oop: True
likes_emacs: TRUE
uses_cvs: false

值可以使用 | 或 > 跨越多行。使用“文字块标量”| 跨越多行将包括换行符和任何尾随空格。 使用“折叠块标量”> 将折线换行为空格; 它用于制作更容易阅读和编辑的内容。 在任何一种情况下,缩进都将被忽略。 例如:

include_newlines: |
            exactly as you see
            will appear these three
            lines of poetry

fold_newlines: >
            this is really a
            single line of text
            despite appearances

在上面的例子中,所有换行符都被折叠为空格,但有两种方法可以强制执行换行符:

fold_some_newlines: >
    a
    b

    c
    d
      e
    f
same_as: "a b\nc d\n  e\nf\n"

让我们结合我们上面在YAML示例中学到的内容。 这与Ansible毫无关系,但会给你一种格式的感觉:

---
# An employee record
name: Martin D'vloper
job: Developer
skill: Elite
employed: True
foods:
    - Apple
    - Orange
    - Strawberry
    - Mango
languages:
    perl: Elite
    python: Elite
    pascal: Lame
education: |
    4 GCSEs
    3 A-Levels
    BSc in the Internet of Things

 

Playbook介绍

Playbook基础

主机与用户

你可以为 playbook 中的每一个 play,选择操作的目标机器是哪些,以哪个用户身份去完成要执行的步骤(called tasks).

hosts 行的内容是一个或多个组或主机的 patterns,以逗号为分隔符,remote_user就是用户名:

---
- hosts: webservers
  remote_user: root

远程用户也可以在每个任务中单独指定:

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

同样支持切换root用户身份运行任务:

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

你也可以在特定的一个任务中进行become,而不是整个playbook:

---
- 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或使用旧的sudo语法–ask-sudo-pass(-K)运行命令 ansible-playbook。

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

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

顺序的可能值有:

  • inventory:默认值,顺序由inventory库文件提供。
  • reverse_inventory:按库文件的倒序提供。
  • sorted:主机按名称字母排序。
  • reverse_sorted:主机按名称字母倒序。
  • shuffle:每次主机都会随机排列。

 

任务列表

每个剧本Play包含一个任务列表。在进入下一个任务之前,针对主机模式匹配的所有机器按顺序执行任务。 重要的是要明白,在一个剧本中,所有主机都将获得相同的任务指令。 剧本的目的是将选择的主机映射到任务。

在运行从上到下的剧本时,具有失败任务的主机将被移出整个剧本的轮换。 如果事务失败,只需更正剧本文件并重新运行。

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

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

command和shell模块通常会重新运行相同的命令,如果该命令类似于chmod或setsebool等,则完全可以。尽管可用create标志使这些模块也具有幂等性。

每一个任务都有一个 name,它会显示在运行剧本的输出中。这是人性化可读的输出,因此提供每个任务详细描述是很有用的。如果没有提供name,则输入 ‘action’ 的字符串将被用于输出。

可以使用传统的 action: module options 格式来声明任务,但建议使用更常规的module: options格式。这个建议的格式在整个文档中都会使用。

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

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

command和shell模块是仅有不的使用key=value格式的模块。这使得它们的工作方式与你所期望的一样简单:

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

command和shell模块会在意执行后的返回码(return codes),所以,如果你有命令执行成功后的返回码不为0,你需要这样做:

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

变量可以在动作行内使用。假如你在var部分定义了一个名为vhost的变量,你可以这样做:

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

这些相同的变量将会在模板中可用。

处理程序

模块应该是幂等的,并且在远程系统上有更改时可以中继。Playbooks认识到这一点,并有一个可用于响应变化的基本事件系统。

‘notify’动作在剧本中的每个任务块(block of tasks)结束时被触发,并且即使被多个不同任务通知也只会被触发一次。

例如,多个资源可能表示需要重新启动Apache,因为配置文件已经更新,但Apache只会受理一次以避免不必要的重启。

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

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

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

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

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

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"

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

注意:

  • 通知处理程序始终按照它们定义的相同顺序运行,而不按通知语句中列出的顺序运行。处理程序使用listen的情况也是如此。
  • 处理程序名称和侦听话题位于全局名称空间中。
  • 如果两个处理程序任务具有相同的名称,则只有一个会运行。
  • 你无法通知一个在包含内定义的处理程序。从1开始,这确实起作用,但包含必须是静态的。

值得指出的是:

  • 在pre_tasks,tasks和post_tasks部分中通知的处理程序会在通知的部分末尾自动刷新flush;
  • 在roles部分中通知的处理程序会在tasks部分结束时自动刷新,但在任何tasks处理程序之前。

如果你想要立即刷新所有的处理程序命令,你可以这样做:

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

上面的例子中,任何排队的处理程序会在meta语句到达时处理。这是一个小示例,但有时会派上用场。

Tips and Tricks

要检查一个playbook的语法,可以使用 ansible-playbook –syntax-check。它将检查playbook文件是否有语法错误。

如果您想要查看成功模块的详细输出以及不成功的模块,请使用–verbose标志。

要查看哪些主机会受到playbook的影响,你可以这样:

ansible-playbook playbook.yml --list-hosts

 

发表评论

error: Content is protected !!