ansible之playbook入门

playbook适合复杂的环境部署。其实用的语法是yaml。

playbook由一个或多个plays组成,它的内容是以plays为元素的列表。在play中,主机被定义为角色,play的内容被称为task,一个task是对ansible模块的一次调用。

举栗子

---
- hosts: webservers
  vars:
    http_port: 80
    max_clients: 200
  remote_user: root
  tasks:
  - name: ensure apache is at the latest version
    yum: pkg=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

这是一个playbook,只包含一个play。

主机与用户

每个play都可以指定主机,执行者身份,和操作内容。

  • hosts 行的内容是一个或多个组或主机的 patterns,以逗号为分隔符,详见 Patterns 章节:
---
- hosts: webservers
  remote_user: root
  • 再者,在每一个 task 中,可以定义自己的远程用户:
---
- hosts: webservers
  remote_user: root
  tasks:
    - name: test connection
      ping:
      remote_user: yourname
  • 也支持用su身份执行命令:
---
- hosts: webservers
  remote_user: yourname
  become:yes
  become_method: su
  • 同样的,你可以仅在一个 task 中,使用 sudo 执行命令,而不是在整个 play 中使用 sudo:
---
- hosts: webservers
  remote_user: yourname
  tasks:
    - service: name=nginx state=started
      become: yes
      become_method: sudo
  • 你也可以登陆后,sudo 到不同的用户身份,而不是使用 root:
---
- hosts: webservers
  remote_user: yourname
  become: yes
  become_user: username

如果需要指定sudo的密码,请使用–ask-become-pass运行ansible-playbook,或者使用旧的sudo语法–ask-sudo-pass(-K)。如果程序卡死,可能是在权限切换部分卡住,执行Ctrl+C打断,检查身份认证的语法再执行。

task list

每个play包含一个task的列表,task按照与主机匹配的模式顺序执行,然后进行下一个task。重要的是要明白,在一个play中,所有的主机都获得了相同的,play的目的是把主机映射到task上。

格式

如果要声明一个 task,以前有一种格式: “action: module options” (可能在一些老的 playbooks 中还能见到).现在推荐使用更常见的格式:”module: options”

  • 下面是一种基本的 task 的定义,service moudle 使用 key=value 格式的参数,这也是大多数 module 使用的参数格式:
tasks:
  - name: make sure apache is running
    service: name=httpd state=running
  • 比较特别的两个 modudle 是 command 和 shell ,它们不使用 key=value 格式的参数,而是这样:
tasks:
  - name: disable selinux
    command: /sbin/setenforce 0
  • 使用 command module 和 shell module 时,我们需要关心返回码信息,如果有一条命令,它的成功执行的返回码不是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
  • 如果 action 行看起来太长,你可以使用 space(空格) 或者 indent(缩进) 隔开连续的一行:
tasks:
  - name: Copy ansible inventory file to client
    copy: src=/etc/ansible/hosts dest=/etc/ansible/hosts
            owner=root group=root mode=0644
  • 在 action 行中可以使用变量.假设在 ‘vars’ 那里定义了一个变量 ‘vhost’ ,可以这样使用它:
tasks:
  - name: create a virtual host file for {{ vhost }}
    template: src=somefile.j2 dest=/etc/httpd/conf.d/{{ vhost }}

这些变量在 tempates 中也是可用的,稍后会讲到.

在一个基础的 playbook 中,所有的 task 都是在一个 play 中列出,稍后将介绍一种更合理的安排 task 的方式:使用 ‘include:’ 指令.

一些知识

  • playbook从上到下执行,如果某个host执行task失败,则会把其从playbook的rotation中去除;如果发生执行失败的情况,则修改playbooks,重新执行。

  • 每个 task 的目标在于执行一个 moudle, 通常是带有特定的参数来执行.在参数中可以使用变量(variables)。

  • modules 具有”幂等”性,意思是如果你再一次地执行 moudle,moudle 只会执行必要的改动,只会改变需要改变的地方.所以重复多次执行 playbook 也很安全。

  • 对于 command module 和 shell module,重复执行 playbook,实际上是重复运行同样的命令.如果执行的命令类似于 ‘chmod’ 或者 ‘setsebool’ 这种命令,这没有任何问题.也可以使用一个叫做 ‘creates’ 的 flag 使得这两个 module 变得具有”幂等”特性 (不是必要的)。

  • 每一个 task 必须有一个名称 name,这样在运行 playbook 时,从其输出的任务执行信息中可以很好的辨别出是属于哪一个 task 的. 如果没有定义 name,‘action’ 的值将会用作输出信息中标记特定的 task.

Handlers: 在发生改变时执行的操作

模块具有幂等性,当远端发生改变时,重复执行playbook可以恢复改动,因为playbook本身识别这种改动,并且有一个系统来响应这种改动。

notify这个动作在每个task末尾被触发,而且就算被多个task触发,也只生效一次。比如说,多个resources表示配置文件改动而需要重启Apache,但是最终Apache只会重启一次。

下面是重启两个服务的例子,但是只有文件更改了才会生效:

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

noitfy下面的列出来的即是handlers

handlers是由全局唯一名称引用的task列表,与常规task完全没有任何区别,并由notifier进行notify,如果没有被notify,handlers将不会执行。在所有task运行完一遍之后,不管有多少个notify,handles只会运行一次。

handlers示例:

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

从ansible2.2开始,处理程序也可以“listen”通用topic,task可以notify该topic:

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"

这将很容易调用多个handlers,也使其名称和handlers分离,从而容易在playbook和roles之间共享handlers。

在介绍role之前,要注意几点:
- 在pre_tasks, tasks, post_tasks 中调用handlers之后,在notify之后就自动刷新handlers。
- 在roles中notify handlers,则在这个task末尾,下一个task之前刷新handlers。

还可以手动刷新handles:

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

在上述例子中,任何在等待的handlers将会在meta时提早执行。

你可能感兴趣的:(ansible笔记)