前言
Playbook与ad-hoc相比,是一种完全不同的运用ansible的方式,类似与saltstack的state状态文件。ad-hoc无法持久使用,playbook可以持久使用。
playbook是由一个或多个play组成的列表,play的主要功能在于将事先归并为一组的主机装扮成事先通过ansible中的task定义好的角色。从根本上来讲,所谓的task无非是调用ansible的一个module。将多个play组织在一个playbook中,即可以让它们联合起来按事先编排的机制完成某一任务
Playbook核心元素
Hosts
执行的远程主机列表Tasks
任务集Varniables
内置变量或自定义变量在playbook中调用Templates
模板,即使用模板语法的文件,比如配置文件等Handlers 和 notity
结合使用,由特定条件触发的操作,满足条件方才执行,否则不执行tags
标签,指定某条任务执行,用于选择运行playbook中的部分代码
一、Playbook 语法
playbook使用yaml
语法格式,后缀可以是yaml
,也可以是yml
- 在单一一个playbook文件中,可以
连续三个连子号(---)区分多个play
。还有选择性的连续三个点好(...)用来表示play的结尾
,也可省略 - 次行开始正常写playbook的内容,一般都会
写上描述该playbook的功能
- 使用
#号注释代码
缩进必须统一
,不能空格和tab混用- 缩进的级别也必须是一致的,
同样的缩进代表同样的级别
,程序判别配置的级别是通过缩进结合换行实现的 - YAML文件内容和Linux系统大小写判断方式保持一致,是
区分大小写的
,k/v的值均需大小写敏感 k/v的值可同行写也可以换行写。同行使用:分隔
- v可以是个字符串,也可以是一个列表
- 一个完整的代码块功能需要
最少元素包括 name: task
二、Playbook 运行方式
通过:ansible-playbook
命令运行
格式:ansible-playbook <filename.yml> ... [options]
[root@ansible PlayBook]# ansible-playbook -h
#ansible-playbook常用选项:
--check or -C #只检测可能会发生的改变,但不真正执行操作
--list-hosts #列出运行任务的主机
--list-tags #列出playbook文件中定义所有的tags
--list-tasks #列出playbook文件中定义的所以任务集
--limit #主机列表 只针对主机列表中的某个主机或者某个组执行
-f #指定并发数,默认为5个
-t #指定tags运行,运行某一个或者多个tags。(前提playbook中有定义tags)
-v #显示过程 -vv -vvv更详细
三、示例 安装httpd服务
- 创建 playbook 剧本
[root@localhost ~]# vim playbook.yaml
--- #固定格式
- hosts: 192.168.182.11 #定义需要执行主机
remote_user: root #远程用户
tasks: #定义一个任务的开始
- name: create new file #定义任务的名称
file: name=/tmp/playtest.txt state=touch #调用模块,具体要做的事情
- name: create new user
user: name=test02 system=yes shell=/sbin/nologin
- name: install package
yum: name=httpd
- name: copy index.html
copy: src=/var/www/html/index.html dest=/var/www/html/index.html
- name: start httpd
service: name=httpd state=started
- 测试页面准备(控制端)
[root@localhost ~]# echo "<h1>playbook test file</h1>" >>/var/www/html/index.html
- 配置文件准备(控制端)
[root@localhost ~]# ll /
-rw-r--r--. 1 root root 11753 2月 1 14:12 httpd.conf
- 第一次使用playbook剧本,可以使用
-C
检查是否OK可用
[root@localhost ~]# ansible-playbook villian.yaml -C
- playbook剧本无误,执行yaml剧本
[root@localhost ~]# ansible-playbook playbook.yml
PLAY [192.168.182.11] *********************************************************************************************
TASK [Gathering Facts] ******************************************************************************************
ok: [192.168.182.11]
TASK [create new file] ******************************************************************************************
changed: [192.168.182.11]
TASK [create new user] ******************************************************************************************
changed: [192.168.182.11]
TASK [install package] ******************************************************************************************
changed: [192.168.182.11]
TASK [copy index.html] ******************************************************************************************
changed: [192.168.182.11]
TASK [start httpd] **********************************************************************************************
changed: [192.168.182.11]
PLAY RECAP ***********************************************************************************
192.168.182.11 : ok=7 changed=6 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
- 验证上面playbook执行的结果
[root@localhost ~]# ansible 192.168.182.11 -m shell -a 'ls /tmp/playtest.txt && id test02'
192.168.182.11 | CHANGED | rc=0 >>
/tmp/playtest.txt
uid=988(test02) gid=982(test02) 组=982(test02)
- 验证httpd测试界面
[root@localhost ~]# curl 192.168.182.11:80
<h1>play test file</h1>
四、Playbook中元素属性
1、主机与用户
- 在一个playbook开始时,最先定义的是要操作的主机和用户
---
- hosts: 192.168.182.11
remote_user: root
- 除了上面的定义外,还可以在某一个tasks中定义要执行该任务的远程用户
tasks:
- name: run df -h
remote_user: test
shell: name=df -h
- 还可以定义使用sudo授权用户执行该任务
tasks:
- name: run df -h
sudo_user: test
sudo: yes
shell: name=df -h
2、tasks任务列表
每一个task必须有一个名称name
,这样在运行playbook时,从其输出的任务执行信息中可以很清楚的辨别是属于哪一个task的,如果没有定义 name,action的值将会用作输出信息中标记特定的task。
每一个playbook中可以包含一个或者多个tasks任务列表
,每一个tasks完成具体的一件事,(任务模块)比如创建一个用户或者安装一个软件等,在hosts中定义的主机或者主机组都将会执行这个被定义的tasks。
tasks:
- name: create new file
file: path=/tmp/test01.txt state=touch
- name: create new user
user: name=test001 state=present
3、Handlers与Notify
很多时候当我们某一个 配置发生改变,我们需要重启服务
,(比如httpd配置文件文件发生改变了)这时候就可以用到handlers和notify了;
(当发生改动时)notify actions会在playbook的每一个task结束时被触发,而且即使有多个不同task通知改动的发生,notify actions知会被触发一次;比如多个resources指出因为一个配置文件被改动,所以apache需要重启,但是重新启动的操作知会被执行一次。
[root@localhost ~]# cat httpd.yml
#用于安装httpd并配置启动
---
- hosts: 192.168.182.11
remote_user: root
tasks:
- name: install httpd
yum: name=httpd state=installed
- name: config httpd
template: src=/root/httpd.conf dest=/etc/httpd/conf/httpd.conf
notify:
- restart httpd
- name: start httpd
service: name=httpd state=started
handlers:
- name: restart httpd
service: name=httpd state=restarted
#这里只要对httpd.conf配置文件作出了修改,修改后需要重启生效,在tasks中定义了restart httpd这个action,然后在handlers中引用上面tasks中定义的notify。
五、Playbook中变量的使用
环境说明:这里配置了两个组,一个apache组和一个nginx组
[root@localhost ~]# vim /etc/ansible/hosts
[apache]
192.168.182.11:22
[nginx]
192.168.182.12:22
1、命令行指定变量(安装部署软件
)
- 执行playbook时候通过参数
-e
传入变量,这样传入的变量在整个playbook中都可以被调用,属于全局变量
[root@localhost ~]# cat variables.yml
---
- hosts: all
remote_user: root
tasks:
- name: install pkg
yum: name={{ pkg }}
- 执行 playbook 指定pkg (
用pkg安装httpd服务
)
[root@localhost ~]# ansible-playbook -e "pkg=httpd" variables.yml
PLAY [all] ****************************************************************************
TASK [Gathering Facts] ****************************************************************
ok: [192.168.182.12]
ok: [192.168.182.11]
TASK [install pkg] ********************************************************************
ok: [192.168.182.11]
ok: [192.168.182.12]
PLAY RECAP ****************************************************************************
192.168.182.11 : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
192.168.182.12 : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
2、hosts文件中定义变量(创建文件
)
在/etc/ansible/hosts
文件中定义变量,可以针对每个主机定义不同的变量,也可以定义一个组的变量,然后直接在playbook中直接调用。注意,组中定义的变量没有单个主机中的优先级高
- 编辑hosts文件定义变量
[root@localhost ~]# vim /etc/ansible/hosts
[apache]
192.168.182.11 webdir=/opt/test #定义单个主机的变量
192.168.182.11
[apache:vars] #定义整个组的统一变量
webdir=/web/test
[nginx]
192.168.182.11[1:2]
[nginx:vars]
webdir=/opt/web
- 编辑playbook文件
[root@localhost ~]# cat variables.yml
---
- hosts: all
remote_user: root
tasks:
- name: create webdir
file: name={{ webdir }} state=directory #引用变量
- 执行playbook
[root@localhost ~]# ansible-playbook variables.yml -C ///执行前可通过-C 验证剧本是否可用
[root@localhost ~]# ansible-playbook variables.yml
- 执行结果
在192.168.182.11主机 /opt目录下创建test文件; 在192.168.182.12主机 /web目录创建 test文件;
3、playbook文件中定义变量
编写playbook时,直接在里面定义变量,然后直接引用,可以定义多个变量;注意:如果在执行playbook时,又通过-e参数指定变量的值,那么会以-e参数指定的为准。
- 编辑playbook(
安装httpd
)
[root@localhost ~]# cat variables.yml
---
- hosts: all
remote_user: root
vars: #定义变量
pkg: httpd #变量1
dir: /tmp/test1 #变量2
tasks:
- name: install pkg
yum: name={{ pkg }} state=installed #引用变量
- name: create new dir
file: name={{ dir }} state=directory #引用变量
- 执行playbook
[root@localhost ~]# ansible-playbook variables.yml -C ///执行前可通过-C 验证剧本是否可用
[root@localhost ~]# ansible-playbook variables.yml
- 如果执行时候又
重新指定了其他变量的值
,那么会以重新指定的为准
[root@localhost ~]# ansible-playbook -e "dir=/tmp/test2" variables.yml
4、调用setup模块获取变量
- 编辑playbook文件
[root@ansible PlayBook]# cat variables.yml
---
- hosts: all
remote_user: root
tasks:
- name: create file
file: name=/tmp/{{ ansible_fqdn }}.log state=touch #引用setup中的ansible_fqdn
- 执行playbook
[root@localhost ~]# ansible-playbook variables.yml -C ///执行前可通过-C 验证剧本是否可用
[root@localhost ~]# ansible-playbook variables.yml
5、独立的变量YAML文件中定义
为了方便管理将所有的变量统一放在一个独立的变量YAML文件中,laybook文件直接引用文件调用变量即可
- 定义存放变量
[root@localhost ~]# cat var.yml
var1: vsftpd
var2: httpd
- 编写playbook剧本
[root@localhost ~]# cat variables.yml
---
- hosts: all
remote_user: root
vars_files: #引用变量文件
- ./var.yml #指定变量文件的path(这里可以是绝对路径,也可以是相对路径)
tasks:
- name: install package
yum: name={{ var1 }} #引用变量
- name: create file
file: name=/tmp/{{ var2 }}.log state=touch #引用变量
- 执行playbook
[root@localhost ~]# ansible-playbook variables.yml -C ///执行前可通过-C 验证剧本是否可用
[root@localhost ~]# ansible-playbook variables.yml
- 执行结果
在被管理主机里安装
vsftpd服务;并且在
/tmp目录中创建
httpd文件夹
六、Playbook中标签的使用
一个playbook文件中,执行时如果想执行某一个任务,那么可以给每个任务集进行打标签,这样在执行的时候可以通过-t
选择指定标签执行,还可以通过--skip-tags
选择除了某个标签外全部执行等
- 编辑playbook
[root@localhost ~]# cat httpd.yml
---
- hosts: 192.168.182.11
remote_user: root
tasks:
- name: install httpd
yum: name=httpd state=installed
tags: inhttpd
- name: start httpd
service: name=httpd state=started
tags: sthttpd
- name: restart httpd
service: name=httpd state=restarted
tags: rshttpd
- 正常执行剧本的结果:安装httpd、启动httpd、重启httpd
[root@localhost ~]# ansible-playbook httpd.yml
1、通过-t
选项指定 tags 进行执行
通过-t
指定tags名称,多个tags用逗号隔开
[root@localhost ~]# ansible-playbook -t rshttpd httpd.yml
结果:只执行[restart httpd]
这一步;
2、通过--skip-tags
选项排除不执行的tags
[root@localhost ~]# ansible-playbook --skip-tags inhttpd httpd.yml
结果:执行除了[inhttpd httpd]
这一步的所有tags;
七、Playbook中模板的使用
1、template之with_items
with_items迭代,当有需要重复性执行的任务时,可以使用迭代机制。
对迭代项的引用,固定变量名为“item”,要在task中使用with_items给定要迭代的元素列表。
列表格式:
字符串
字典
示例1:通过with_items安装多个不同软件
[root@localhost ~]# cat testwith.yml
# 示例with_items
---
- hosts: all
remote_user: root
tasks:
- name: Install Package
yum: name={{ item }} state=installed #引用item获取值
with_items: #定义with_items
- httpd
- vsftpd
- nginx
上面tasks写法等同于:
---
- hosts: all
remote_user: root
tasks:
- name: Install Httpd
yum: name=httpd state=installed
- name: Install Vsftpd
yum: name=vsftpd state=installed
- name: Install Nginx
yum: name=nginx state=installed
示例2:通过嵌套子变量创建用户并加入不同的组
- 编写playbook
[root@localhost ~]# cat testwith01.yml
# 示例with_items嵌套子变量
---
- hosts: all
remote_user: root
tasks:
- name: Create New Group
group: name={{ item }} state=present
with_items:
- group1
- group2
- group3
- name: Create New User
user: name={{ item.name }} group={{ item.group }} state=present
with_items:
- { name: 'user1', group: 'group1' }
- { name: 'user2', group: 'group2' }
- { name: 'user3', group: 'group3' }
- 执行playbook并验证
# 执行playbook
[root@localhost ~]# ansible-playbook testwith01.yml
# 验证是否成功创建用户及组
[root@localhost ~]# ansible all -m shell -a 'tail -3 /etc/passwd'
192.168.1.36 | CHANGED | rc=0 >>
user1:x:500:500::/home/user1:/bin/bash
user2:x:501:501::/home/user2:/bin/bash
user3:x:502:502::/home/user3:/bin/bash
192.168.1.32 | CHANGED | rc=0 >>
user1:x:1001:1001::/home/user1:/bin/bash
user2:x:1002:1002::/home/user2:/bin/bash
user3:x:1003:1003::/home/user3:/bin/bash
192.168.1.31 | CHANGED | rc=0 >>
user1:x:1002:1003::/home/user1:/bin/bash
user2:x:1003:1004::/home/user2:/bin/bash
user3:x:1004:1005::/home/user3:/bin/bash
192.168.1.33 | CHANGED | rc=0 >>
user1:x:1001:1001::/home/user1:/bin/bash
user2:x:1002:1002::/home/user2:/bin/bash
user3:x:1003:1003::/home/user3:/bin/bash
翻译至:https://www.cnblogs.com/yanjieli/p/10969299.html#autoid-1-7-0