Playbook与ad-hoc相比,是一种完全不同的运用ansible的方式,类似与saltstack的state状态文件。
ad-hoc无法持久使用,playbook可以持久使用。
playbook是由一个或多个play组成的列表,play的主要功能在于将事先归并为一组的主机装扮成事先通过ansible中的task定义好的角色。从根本上来讲,所谓的task无非是调用ansible的一个module。将多个play组织在一个playbook中,即可以让它们联合起来按事先编排的机制完成某一任务
playbook使用yaml语法格式,后缀可以是yaml,也可以是yml。
playbook
文件中,可以连续三个连子号(---
)区分多个play
。还有选择性的连续三个点好(...
)用来表示play
的结尾,也可省略。playbook
的内容,一般都会写上描述该playbook
的功能。tab
混用。YAML
文件内容和Linux
系统大小写判断方式保持一致,是区分大小写的,k/v
的值均需大小写敏感k/v
的值可同行写也可以换行写。同行使用:分隔。v
可以是个字符串,也可以是一个列表name: task
创建playbook文件
[root@ansible ~]# vim playbook01.yml
--- #固定格式
- hosts: 192.168.1.31 #定义需要执行主机
remote_user: root #远程用户
vars: #定义变量
http_port: 8088 #变量
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: config httpd
template: src=./httpd.conf dest=/etc/httpd/conf/httpd.conf
notify: #定义执行一个动作(action)让handlers来引用执行,与handlers配合使用
- restart apache #notify要执行的动作,这里必须与handlers中的name定义内容一致
- 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
handlers: #处理器:更加tasks中notify定义的action触发执行相应的处理动作
- name: restart apache #要与notify定义的内容相同
service: name=httpd state=restarted #触发要执行的动作
测试页面准备
[root@ansible ~]# echo "playbook test file
" >>/var/www/html/index.html
配置文件准备
[root@ansible ~]# cat httpd.conf |grep ^Listen
Listen {{ http_port }}
#执行playbook, 第一次执行可以加-C选项,检查写的playbook是否ok
[root@ansible ~]# ansible-playbook playbook01.yml
PLAY [192.168.1.31] *********************************************************************************************
TASK [Gathering Facts] ******************************************************************************************
ok: [192.168.1.31]
TASK [create new file] ******************************************************************************************
changed: [192.168.1.31]
TASK [create new user] ******************************************************************************************
changed: [192.168.1.31]
TASK [install package] ******************************************************************************************
changed: [192.168.1.31]
TASK [config httpd] *********************************************************************************************
changed: [192.168.1.31]
TASK [copy index.html] ******************************************************************************************
changed: [192.168.1.31]
TASK [start httpd] **********************************************************************************************
changed: [192.168.1.31]
PLAY RECAP ******************************************************************************************************
192.168.1.31 : ok=7 changed=6 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
验证上面playbook执行的结果
[root@ansible ~]# ansible 192.168.1.31 -m shell -a 'ls /tmp/playtest.txt && id test02'
192.168.1.31 | CHANGED | rc=0 >>
/tmp/playtest.txt
uid=990(test02) gid=985(test02) 组=985(test02)
[root@ansible ~]# curl 192.168.1.31:8088
<h1>playbook test file</h1>
通过ansible-playbook命令运行,格式:
ansible-playbook <filename.yml> ... [options]
[root@ansible PlayBook]# ansible-playbook -h
ansible-playbook常用选项:
在一个playbook开始时,最先定义的是要操作的主机和用户
---
- hosts: 192.168.1.31
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
每一个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
很多时候当我们某一个配置发生改变,我们需要重启服务,(比如httpd配置文件文件发生改变了)这时候就可以用到handlers
和notify
了;
(当发生改动时)notify actions
会在playbook
的每一个task结束时被触发,而且即使有多个不同task通知改动的发生,notify actions
知会被触发一次;比如多个resources
指出因为一个配置文件被改动,所以apache
需要重启,但是重新启动的操作知会被执行一次。
[root@ansible ~]# cat httpd.yml
#用于安装httpd并配置启动
---
- hosts: 192.168.1.31
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。
环境说明:这里配置了两个组,一个apache组和一个nginx组
[root@ansible PlayBook]# cat /etc/ansible/hosts
[apache]
192.168.1.36
192.168.1.33
[nginx]
192.168.1.3[1:2]
执行playbook
时候通过参数-e
传入变量,这样传入的变量在整个playbook中都可以被调用,属于全局变量。
[root@ansible PlayBook]# cat variables.yml
---
- hosts: all
remote_user: root
tasks:
- name: install pkg
yum: name={{ pkg }}
#执行playbook 指定pkg
[root@ansible PlayBook]# ansible-playbook -e "pkg=httpd" variables.yml
在/etc/ansible/hosts
文件中定义变量,可以针对每个主机定义不同的变量,也可以定义一个组的变量,然后直接在playbook中直接调用。注意,组中定义的变量没有单个主机中的优先级高。
# 编辑hosts文件定义变量
[root@ansible PlayBook]# vim /etc/ansible/hosts
[apache]
192.168.1.36 webdir=/opt/test #定义单个主机的变量
192.168.1.33
[apache:vars] #定义整个组的统一变量
webdir=/web/test
[nginx]
192.168.1.3[1:2]
[nginx:vars]
webdir=/opt/web
# 编辑playbook文件
[root@ansible PlayBook]# cat variables.yml
---
- hosts: all
remote_user: root
tasks:
- name: create webdir
file: name={{ webdir }} state=directory #引用变量
# 执行playbook
[root@ansible PlayBook]# ansible-playbook variables.yml
编写playbook
时,直接在里面定义变量,然后直接引用,可以定义多个变量;注意:如果在执行playbook
时,又通过-e
参数指定变量的值,那么会以-e
参数指定的为准。
# 编辑playbook
[root@ansible PlayBook]# cat variables.yml
---
- hosts: all
remote_user: root
vars: #定义变量
pkg: nginx #变量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@ansible PlayBook]# ansible-playbook variables.yml
# 如果执行时候又重新指定了变量的值,那么会已重新指定的为准
[root@ansible PlayBook]# ansible-playbook -e "dir=/tmp/test2" variables.yml
setup
模块默认是获取主机信息的,有时候在playbook
中需要用到,所以可以直接调用。常用的参数
# 编辑playbook文件
[root@ansible PlayBook]# cat variables.yml
---
- hosts: all
remote_user: root
tasks:
- name: create file
file: name={{ ansible_fqdn }}.log state=touch #引用setup中的ansible_fqdn
# 执行playbook
[root@ansible PlayBook]# ansible-playbook variables.yml
为了方便管理将所有的变量统一放在一个独立的变量YAML
文件中,laybook
文件直接引用文件调用变量即可。
# 定义存放变量的文件
[root@ansible PlayBook]# cat var.yml
var1: vsftpd
var2: httpd
# 编写playbook
[root@ansible PlayBook]# 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@ansible PlayBook]# ansible-playbook variables.yml