如何Ansible编写一个Playbook

2019-11-12 18:05:42 浏览数 (1)

1、playbooks介绍

playbooks是 一个不同于使用Ansible命令行执行方式的模式,其功能更强大灵活。简单来说,playbook是一个非常简单的配置管理和多主机部署系统,不同于任何已经存在的模式,可作为一个适合部署复杂应用程序的基础。Playbook可以定制配置,可以按照指定的操作步骤有序执行,支持同步和异步方式。值得注意的是playbook是通过YAML格式来进行描述定义的。

2、playbook基础组件

1.Hosts:运行执行任务(task)的目标主机

2.remote_user:在远程主机上执行任务的用户

3.tasks:任务列表

4.handlers:任务,与tasks不同的是只有在接受到通知时才会被触发

5.templates:使用模板语言的文本文件

6.variables:变量,变量替换

3、playbook和临时命令的比较

1.临时命令不适合复杂配置管理或编配场景。

2.临时命令一次只能调用一个模块或一组参数。当需要多个操作时,必须使用多个临时命令来执行。

3.playbook是描述要在受管理主机上实施的必要配置或程序性步骤的文件。playbook为配置管理和部署提供了强大而灵活的解决方案。playbook可以将冗长而复杂的管理任务变为可轻松重复的历程,并且预测成果。

4、命令到playbook的演化

为了便于理解playbook,我们使用user模块在指定节点docker-03上创建一个用户名为newbie,uid为4000的用户。

代码语言:javascript复制
 [root@docker-01 ~]# ansible -m user -a "name=newbie uid=4000 state=present" docker-03
 docker-03 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
   }, 
    "changed": true, 
    "comment": "", 
    "create_home": true, 
    "group": 4000, 
    "home": "/home/newbie", 
    "name": "newbie", 
    "shell": "/bin/bash", 
    "state": "present", 
    "system": false, 
    "uid": 4000
 }

如果写成playbook

代码语言:javascript复制
 [root@docker-01 ~]# cat user.yml 
 ---
 -name: Configure important user consistently
 hosts: docker-03
 tasks:                       
    -name: newbie exists with UID 4000     
     user: 
       name: newbie
       uid: 4000
       state: present
 
 [root@docker-01 ~]# ansible-playbook user.yml 
 
 PLAY [Configure important user consistently] ***********************************
 
 TASK [Gathering Facts] *********************************************************
 ok: [docker-03]
 
 TASK [newbie exists with UID 4000] *********************************************
 changed: [docker-03]
 
 PLAY RECAP *********************************************************************
 docker-03                 : ok=2   changed=1   unreachable=0   failed=0   skipped=0   rescued=0   ignored=0 

paly的第一行以破折号和空格(指示play是列表的第一项)开始,然后是第一个key:name

name key描述paly的目的。name key是可选的,但推荐使用。

代码语言:javascript复制
 -name: Configure important user consistently

play中的第二个key是hosts属性,指定运行play任务的主机。

代码语言:javascript复制
 hosts: docker-03

play中最后一个key是tasks属性,为这个play运行的任务列表。

代码语言:javascript复制
 tasks:                       
    -name: newbie exists with UID 4000     
     user: 
       name: newbie
       uid: 4000
       state: present

playbook是YAML格式的文本文件,扩展名通常为yml。

playbook使用带空格字符的缩进来表示数据结构。YAML对缩进使用了多少空格没有严格的要求,但是有两个基本规则:

1、层次机构中相同级别的数据元素(例如相同列表中的项)必须具有相同的缩进。

2、子项必须比其父项缩进的更多。

可以添加空行增加可读性。

5、Tab键的使用

yml文件只能使用空格缩进,不能使用Tab,如果vim编辑器,可以通过编辑$HOME/.vimrc将Tab转化为2个空格。文件如果不存在,则自己创建。

代码语言:javascript复制
 [root@docker-03 ~]# vim ~/.vimrc
 autocmd FileType yaml setlocal ai ts=2sw=2et

6、playbook的格式

playbook以三个破折号(---)作为文档开始标记。以三个点(...)作为文档结尾标记,尽管在实践中经常被省略。

在这些标记之间,playbook由一组paly构成。YAML列表中的item以一个破折号开始,后跟空格。例如:

代码语言:javascript复制
 -name: Configure important user consistently
 -apple: This is an apple
 -orange: This is an orange

paly本身是key-value对的集合。同一个paly中keys应该有相同的缩进。下面的示例显示了一个带有三个keys的YAML代码片段。前两个keys的值很简单。第三个key的列表中有三个items作为值。

代码语言:javascript复制
 name: Configure important user consistently
 hosts: docker-03
 tasks:
    -first
    -second
    -third

tasks属性列出要在主机上运行的任务,列表中的每个任务本身都是键值对的集合。

以下是另一个多tasks的演示

代码语言:javascript复制
 tasks:
    -name: web server is enabled
      service:
       name: httpd
       enabled: true
 
    -name: NTP server is enabled
      service:
       name: chronyd
       enabled: true
 
    -name: Postfix is enabled
      service:
       name: postfix
       enables: true

7、执行一个简单的playbook

代码语言:javascript复制
 [root@docker-02 ~]# cat webserver.yml 
 ---
 -name: play to setup web server
 hosts: docker-03
 tasks:
  -name: latest httpd version installed
   yum:
     name: httpd
     state: latest
 
 [root@docker-02 ~]# ansible-playbook webserver.yml 
 
 PLAY [play to setup web server] ************************************************
 
 TASK [Gathering Facts] *********************************************************
 ok: [docker-03]
 
 TASK [latest httpd version installed] ******************************************
 changed: [docker-03]
 
 PLAY RECAP *********************************************************************
 docker-03                 : ok=2   changed=1   unreachable=0   failed=0   skipped=0   rescued=0   ignored=0  

上面的输出说明了为何有必要在playbook中将name属性用于play和任务,即便此属性是可选的。playbook执行时显示name属性的值。对于具有多个play和tasks的palybook,使用name属性会给监控playbook的执行提供非常大的帮助。

一般来说,Ansible playbook中的任务是幂等(idempotent)的,可以安全的多次执行playbook。如果目标托管机已经处于正确的状态,则不应进行任何修改。例如,假设前一个例子的剧本再次执行。

代码语言:javascript复制
 [root@docker-02 ~]# ansible-playbook webserver.yml 
 
 PLAY [play to setup web server] ************************************************
 
 TASK [Gathering Facts] *********************************************************
 ok: [docker-03]
 
 TASK [latest httpd version installed] ******************************************
 ok: [docker-03]
 
 PLAY RECAP *********************************************************************
 docker-03                 : ok=2   changed=0   unreachable=0   failed=0   skipped=0   rescued=0   ignored=0 

所有任务状态ok,且没有发生任何change

8、语法验证

在执行playbook前,最好进行验证,确保其内容的语法正确无误。ansible-playbook命令提供--syntax-check选项,可用于验证playbook文件的语法。下例演示了一个playbook成功通过语法验证。

代码语言:javascript复制
 [root@docker-02 ~]# ansible-playbook --syntax-check webserver.yml 
 playbook: webserver.yml

语言验证失败时,将报语法错误。输出中包含语法问题在playbook中的大致位置。下例演示了一个playbook语法验证失败,其中play的name属性后缺少了空格分隔符。

代码语言:javascript复制
 [root@docker-02 ~]# ansible-playbook --syntax-check webserver.yml 
 ERROR! Syntax Error whileloading YAML.
 mapping values are not allowed inthis context
 
 The error appears to be in'/root/webserver.yml': line 3, column 8, but may
 be elsewhere inthe file depending on the exact syntax problem.
 
 The offending line appears to be:
 
 -name: play to setup web server
 hosts: docker-03
       ^ here

9、执行空运算

另一个有用的选项-C选项。这会使Ansible报告在执行该playbook时将会发生什么更改,但不会对受管主机进行任何实际的更改。

下面演示了一个playbook的空运行,它在受管主机上安装了最新版本的httpd软件包。

代码语言:javascript复制
 [root@docker-02 ~]# ansible-playbook -C webserver.yml 
 
 PLAY [play to setup web server] ************************************************
 
 TASK [Gathering Facts] *********************************************************
 ok: [docker-03]
 
 TASK [latest httpd version installed] ******************************************
 changed: [docker-03]
 
 PLAY RECAP *********************************************************************
 docker-03                 : ok=2   changed=1   unreachable=0   failed=0   skipped=0   rescued=0   ignored=0  

10、实战2个plays,针对两台主机分别操作

代码语言:javascript复制
 [root@docker-03 ~]# vim /etc/ansible/hosts 
 [test1]
 172.17.120.50
 [test2]
 172.17.120.51
 
 [root@docker-03 ~]# vim test.yml
 ---
 #This is a simple playbook with two plays
 -name: first play
 hosts: 172.17.120.50
 tasks:
 
  -name: first task
   yum:
     name: httpd
     state: present
 
  -name: second task
    service:
     name: httpd
     enabled: true
 
 -name: second play
 hosts: 172.17.120.51
 tasks:
 
  -name: first task
    service:
     name: mariadb
     enabled: true
      
 [root@docker-03 ~]# ansible-playbook test.yml 
 PLAY [first play] ******************************************************************************************************************************************************************************************
 
 TASK [Gathering Facts] *************************************************************************************************************************************************************************************
 ok: [172.17.120.50]
 
 TASK [first task] ******************************************************************************************************************************************************************************************
 ok: [172.17.120.50]
 
 TASK [second task] *****************************************************************************************************************************************************************************************
 changed: [172.17.120.50]
 
 PLAY [second play] *****************************************************************************************************************************************************************************************
 
 TASK [Gathering Facts] *************************************************************************************************************************************************************************************
 ok: [172.17.120.51]
 
 TASK [first task] ******************************************************************************************************************************************************************************************
 changed: [172.17.120.51]
 
 PLAY RECAP *************************************************************************************************************************************************************************************************
 172.17.120.50             : ok=3   changed=1   unreachable=0   failed=0   skipped=0   rescued=0   ignored=0  
 172.17.120.51             : ok=2   changed=1   unreachable=0   failed=0   skipped=0   rescued=0   ignored=0 

0 人点赞