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