文档首页 > > 用户指南> Playbook编写指导> Playbook详解

Playbook详解

分享
更新时间: 2020/03/12 GMT+08:00

背景信息

Playbook部署模板主要包括部署动作、执行用户、Tasks、Handles、Roles、变量、Template、条件、循环等内容,详细介绍分别如下:

部署动作

部署服务支持的部署动作有:安装(install)、卸载(uninstall)、升级(upgrade)、回滚(rollback)。“Deploy.json”文件配置如下:

{ 
"options":[ 
{"enable":"1","name":"install"}, 
{"enable":"1","name":"uninstall"}, 
{"enable":"1","name":"upgrade"}, 
{"enable":"1","name":"rollback"} 
] 
}     

Playbook目录中,每个部署动作需要创建对应的“yml”文件,来配置具体的任务,如:

playbook 
install.yml 
unstall.yml 
upgrade.yml 
rollback.yml     

执行用户

“yml”文件中,可以定义自己的远程用户:

- remote_user: yourname

也可以从 sudo 执行命令:

- remote_user: yourname 
  sudo: yes     

Tasks

每个playbook都包含一个task列表(任务列表)。一个task在其所对应的所有主机上执行完毕之后,下一个task才会执行。在同一个playbook之中,所有主机会获取相同的任务指令。

在运行playbook时(从上到下执行),如果一个主机执行task失败,这个主机将会从整个playbook中移除。如果发生执行失败的情况,请修正playbook中的错误,然后重新执行即可。

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

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

以下是一种基本的task的定义,service moudle使用“key=value”格式的参数,这也是大多数module使用的参数格式:

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

command和shell两个特殊moudle,不使用“key=value”格式的参数,格式如下:

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

如果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 }}     

Handlers

module具有幂等性,所以当远端系统被改动时,可以重放playbooks达到恢复的目的。playbooks本身可以识别这种改动,并且有一个基本的事件系统,可以响应这种改动。

当发生改动时,‘notify’actions会在playbook的每一个task结束时被触发,当多个不同的task发生通知改动,‘notify’actions也只会被触发一次。

如多个resources指出因为一个配置文件被改动,apache需要重新启动,但是重新启动的操作只会被执行一次。

示例:当一个文件的内容被改动时,重启两个services。

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

“notify”下列出的即是handlers。“Handlers”是一些task的列表,通过名字来引用,和一般的task并没有什么区别。

“Handlers”是由通知者进行notify,如果没有被notify,handlers不会执行,不管有多少个通知者进行了notify,等到play中的所有task执行完成之后,handlers也只会被执行一次。

示例如下:

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

“Handlers”常用的应用场景是用来重启服务或者触发系统重启操作,其他地方很少用到。

Roles

了解了tasks和handlers,那怎样组织playbook才是最好的方式呢?简单的回答就是:使用roles。“Roles”基于一个已知的文件结构,自动加载某些tasks和handlers。基于roles对内容进行分组,从而可以容易地组合、重构Playbook。

项目结构如下:

roles/ 
   common/ 
     files/ 
     templates/ 
     tasks/ 
     handlers/ 
   webservers/ 
     files/ 
     templates/ 
     tasks/ 
     handlers/     

playbook如下:

--- 
- roles: 
     - common 
     - webservers     

playbook为角色x指定的行为如下:

  • 如果“roles/x/tasks/main.yml”存在, 其中列出的tasks将被添加到play中。
  • 如果“roles/x/handlers/main.yml”存在, 其中列出的handlers将被添加到play中。
  • 所有copy tasks可以引用“roles/x/files/”中的文件,不需要指明文件的路径。
  • 所有script tasks可以引用“roles/x/files/”中的脚本,不需要指明文件的路径。
  • 所有template tasks可以引用“roles/x/templates/”中的文件,不需要指明文件的路径。
  • 所有include tasks可以引用“roles/x/tasks/”中的文件,不需要指明文件的路径。

如果某些任务不需要频繁去执行,可以为roles设置触发条件,如:

--- 
- roles: 
    - { role: some_role, when: "ansible_os_family == 'RedHat'" }     

变量

  • 变量的命名。

    变量名可以为字母、数字和下划线,且始终应该以字母开头。如:“foo_port”“foo5”是合法的变量名。“”、“foo port”“foo.port”“12”则不是合法的变量名。

  • 变量的定义。

    Playbook的变量在“group_vars/all”文件中定义,每一行定义一个变量,格式为:变量名:[空格]变量值 。如下:

    tomcat_url: http://mirror.olnevhost.net/pub/apache/tomcat/tomcat-7/v7.0.78/bin/apache-tomcat-7.0.78.tar.gz 
    war_url: http://xxx.com/xxx.war     
  • 变量的使用。

    “yml”文件中使用变量时,使用{{变量名}}的形式引用变量,如下:

    - name: Download Tomcat 
      get_url: url={{tomcat_url}} dest=/usr/local/     

Template

如果用户需要修改环境中的某些配置文件,将参数写入到配置文件中。Playbook提供了一个非常高效的module可以很方便实现。

Template模块下的文本文件只支持utf-8编码。

以部署tomcat时,修改“server.xml”文件中的端口号为例:

  1. 首先在group_vars中定义变量。如:
    http_port: 8080
  2. 然后在Playbook中对应的role下面的template目录下,创建需要配置的文件“server.xml”,在“server.xml”中配置端口号的地方引用上面定义的变量。如:
    <Connector port="{{ http_port }}" protocol="HTTP/1.1" 
                   connectionTimeout="20000" 
                   redirectPort="8443" />     
  3. 最后,在yml中一个task。如下:
    - name: Configure Tomcat server 
      template: src=server.xml dest=/usr/share/tomcat/conf/     

执行时,会自动去templates目录下寻找src指定的文件,将其复制到被部署主机的dest指定的目录,在复制的过程中,会将group_vars里定义的变量替换到文件中相应位置。

条件

如果用户需要在某个特定的条件下执行某个task,或者越过某个task,这时就需要使用条件语句when。如下:

tasks: 
  - name: "shutdown Debian flavored systems" 
    command: /sbin/shutdown -t now 
when: ansible_os_family == "Debian"     

常见示例如下:

  • 基于true/false值来决定一个任务是否被执行:
    vars: 
      epic: true     
  • 条件语句:
    tasks: 
        - shell: echo "This certainly is epic!" 
          when: epic     

    也可以这样写:

    tasks: 
        - shell: echo "This certainly isn't epic!" 
          when: not epic     
  • 如果变量不存在,可以使用defined命令跳过:
    tasks: 
        - shell: echo "I've got '{{ foo }}' and am not afraid to use it!" 
          when: foo is defined 
     
        - fail: msg="Bailing out. this play requires 'bar'" 
          when: bar is not defined     
  • 在playbook中,用变量存储某个命令的结果,用于以后访问。可以使用register关键词把该命令的结果存储在某个变量中,结果参数可以用在以后的task中,或者when语句。如:
    tasks: 
     
          - shell: cat /etc/motd 
            register: motd_contents 
     
          - shell: echo "motd contains the word hi" 
            when: motd_contents.stdout.find('hi') != -1     

循环

为了保持简洁,重复的任务可以使用以下简写的方式:

- name: add several users 
  user: name={{ item }} state=present groups=wheel 
  with_items: 
     - testuser1 
     - testuser2     

或者:

- name: add user testuser1 
  user: name=testuser1 state=present groups=wheel 
- name: add user testuser2 
  user: name=testuser2 state=present groups=wheel     

“with_items””用于迭代的条目类型不仅仅支持简单的字符串列表。如果有哈希列表,可以用以下方式来引用子项:

- name: add several users 
  user: name={{ item.name }} state=present groups={{ item.groups }} 
  with_items: 
    - { name: 'testuser1', groups: 'wheel' } 
    - { name: 'testuser2', groups: 'root' }     
分享:

    相关文档

    相关产品

文档是否有解决您的问题?

提交成功!

非常感谢您的反馈,我们会继续努力做到更好!

反馈提交失败,请稍后再试!

*必选

请至少选择或填写一项反馈信息

字符长度不能超过200

提交反馈 取消

如您有其它疑问,您也可以通过华为云社区问答频道来与我们联系探讨

智能客服提问云社区提问