Playbook介绍
Playbook
与ad-hoc
相比,是一种完全不同的运用ansible的方式,类似与saltstack
的state
状态文件。ad-hoc
无法持久使用,playbook
可以持久使用。playbook
是由一个或多个play
组成的列表,play
的主要功能在于将事先归并为一组的主机装扮成事先通过ansible
中的task
定义好的角色。从根本上来讲,所谓的task
无非是调用ansible
的一个module
。将多个play
组织在一个playbook
中,即可以让它们联合起来按事先编排的机制完成某一任务
Playbook核心元素
- Hosts 执行的远程主机列表
- Tasks 任务集
- Variables 内置变量或自定义变量在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
1.简单的示例
由于这不是是基础章,里面的写法我就大概进行一个介绍了
hosts是指定哪些主机执行
remote_user是远程主机执行的用户
tasks下面就是一个任务列表,里面包含了一些任务模块
name就是一个类似声明的一个操作
name下面的就是各个模块加上他的参数
---
- hosts : all
remote_user : root
tasks :
- name : 写入开机自动挂载镜像
mount : src=/dev/cdrom path=/mnt fstype=iso9660 state=present
- name : 挂载镜像
mount : src=/dev/cdrom path=/mnt fstype=iso9660 state=mounted
- name : 搭建yum仓库
yum_repository : name=local description="local" baseurl=file:///mnt enabled=1 gpgcheck=no file=tarro
- name : 下载httpd
yum : name=httpd state=installed
- name : 启动httpd
service : name=httpd state=started
- name : 修改index
copy : content="KALItarro" dest=/var/www/html/index.html
...
2.主机与用户
可以看到我们一开始写了在被管理机上执行的用户,我们除了在开头写还可以在下面写,如图
除了在里面可以指定某条模块执行的角色以外还可以使用sudo进行一个授权执行
3.触发器与动作
Handlers(动作)与Notify(触发)
这俩非常好理解,触发器就是我们在某处触发,触发我们指定下面的某个动作
动作就是一般写在文件最下面,我们在上面通过动作名称去触发,触发了就执行指定的动作
很多时候当我们某一个配置发生改变,我们需要重启服务,(比如httpd配置文件文件发生改变了)这时候就可以用到handlers和notify了;(当发生改动时)notify actions会在playbook的每一个task结束时被触发,而且即使有多个不同task通知改动的发生,notify actions知会被触发一次;比如多个resources指出因为一个配置文件被改动,所以apache需要重启,但是重新启动的操作知会被执行一次
---
- hosts : all
remote_user : root
tasks:
- name : "先对http的端口进行修改后,再通过触发器去执行动作"
shell : sed -i 's/Listen 80/Listen 8080/g' /etc/httpd/conf/httpd.conf
notify :
- restart httpd
handlers :
- name : restart httpd
service : name=httpd state=restarted
...
通过在上面的触发,直接触发了下面的对应名称的动作
4.playbook中的变量
命令行指定变量
执行playbook时候通过参数-e传入变量,这样传入的变量在整个playbook中都可以被调用,属于全局变量
---
- hosts: all
remote_user: root
tasks:
- name : "安装指定的变量名的软件"
yum : name={{ a }} state=installed
...
ansible-playbook -e "a=httpd" ins.yaml
使用这条命令的时候使用了-e传入变量
hosts文件中定义变量
/etc/ansible/hosts
---
- hosts: 192.168.6.2
remote_user: root
tasks:
- name: "b=lrzsz变量"
yum: name={{ b }} state=installed
...
---
- hosts: all
remote_user: root
tasks:
- name: "a=httpd"
yum: name={{ a }} state=installed
...
playbook文件中定义变量
---
- hosts: all
remote_user: root
vars:
a: httpd
b: lrzsz
tasks:
- name: "a=httpd"
yum: name={{ a }} state=installed
- name: "b=lrzsz"
yum: name={{ b }} state=installed
...
重新定义原有变量
我这里有个名为pkg的变量,默认是安装gcc的一个变量,我只需在执行时候去通过命令重新定义变量即可完成替换
ansible-playbook -e "pkg=httpd" 1.yaml
这样就被定义成为新变量了
在其他文件中定义变量
我创建了一个名为var.yaml的文件并写入了
这两个内容
我再去修改一下playbook文件导入一下变量
模块自带变量
playbook同样可以调用内部的一些自带变量,如setup模块里的一些
标签
一个playbook文件中,执行时如果想执行某一个任务,那么可以给每个任务集进行打标签,这样在执行的时候可以通过-t选择指定标签执行,还可以通过--skip-tags选择除了某个标签外全部执行等。
tags下面的就是标签,并且可以搭配变量如in{{ na }} 就是inhttpd ,还可以打多个标签
当我们想正常依次执行playbook直接执行就行了
ansible-playbook 3.yaml
我这个playbook中包含了安装,开启,重启,假设我就像执行这个剧本里的开启,我可以通过标签这样操作
ansible-playbook -t sthttpd 3.yaml
这样就 只执行了一个
如果我们现在不想执行开启httpd
ansible-playbook --skip-tags sthttpd 3.yaml
那么现在就只执行安装和重启
如果现在不想执行开启和重启
ansible-playbook --skip-tags sthttpd,rehttpd 3.yaml
可以通过 “,” 去隔开
Playbook中模板的使用
template模板为我们提供了动态配置服务,使用jinja2语言,里面支持多种条件判断、循环、逻辑运算、比较操作等。其实说白了也就是一个文件,和之前配置文件使用copy一样,只是使用copy,不能根据服务器配置不一样进行不同动态的配置。这样就不利于管理。说明:1、多数情况下都将template文件放在和playbook文件同级的templates目录下(手动创建),这样playbook文件中可以直接引用,会自动去找这个文件。如果放在别的地方,也可以通过绝对路径去指定。2、模板文件后缀名为.j2。
实例:
4.yaml里的内容是使用123.j2模板 将模板传输到被管机上的/opt目录下名为321
123.j2里面的内容如下
执行一下playbook ,到被管理机器上看一下
template之when
条件测试:如果需要根据变量、facts或此前任务的执行结果来做为某task执行与否的前提时要用到条件测试,通过when语句执行,在task中使用jinja2的语法格式、when语句:在task后添加when子句即可使用条件测试;when语句支持jinja2表达式语法。
---
- hosts: testA
tasks:
- name: 我要输出dgf
shell: echo -n "dgf"
register: xingming
ignore_errors: True
- name: 我要判断
file: name=/alex state=directory
when: xingming is success
修改playbook
文件,通过setup模块获取系统版本去判断
---
- hosts: all
remote_user: root
vars:
- listen_port: 88
tasks:
- name: Install Httpd
yum: name=httpd state=installed
- name: Config System6 Httpd
template: src=httpd6.conf.j2 dest=/etc/httpd/conf/httpd.conf
when: ansible_distribution_major_version == "6" #判断系统版本,为6便执行上面的template配置6的配置文件
notify: Restart Httpd
- name: Config System7 Httpd
template: src=httpd7.conf.j2 dest=/etc/httpd/conf/httpd.conf
when: ansible_distribution_major_version == "7" #判断系统版本,为7便执行上面的template配置7的配置文件
notify: Restart Httpd
- name: Start Httpd
service: name=httpd state=started
handlers:
- name: Restart Httpd
service: name=httpd state=restarted
template之with_items
上面的意思就是依次安装httpd vsftpd nginx
---
- 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={{ }} group={{ item.group }} state=present
with_items:
- { name: 'user1', group: 'group1' }
- { name: 'user2', group: 'group2' }
- { name: 'user3', group: 'group3' }
这个案例是把用户加入不同的用户组
template之for if
实例:
---
- hosts: all
remote_user: root
vars:
nginx_vhosts:
- web1:
listen: 8081
server_name: ""
root: "/var/www/nginx/web1"
- web2:
listen: 8082
server_name: ""
root: "/var/www/nginx/web2"
- web3:
listen: 8083
server_name: ""
root: "/var/www/nginx/web3"
tasks:
- name: Templage Nginx Config
template: src=nginx.conf.j2 dest=/tmp/nginx_vhost.conf
模板文件编写
{% for vhost in nginx_vhosts %}
server{
listen: {{ vhost.listen }};
server_name: {{ vhost.server_name }};
root: {{ vhost.root }};
}
{% endfor %}