1.Playbook介绍
.2.Playbook核心元素
3.Playbook 语法
4.Playbook 的运行方式5.Playbook中元素属性
6. Playbook中变量的使用.
7.Playbook中标签的使用
8. Playbook 中模板的使用
如果把ansible的模块比喻成linux命令,那么咱的playbook就好比是shell脚本
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吧
---
- hosts: all ###可以替换成其他的,例如IP地址,或者hostst指定的组
remote_user: root ###使用哪个用户进行操作
tasks: ###任务列表
- name: "创建一个yum源"
yum_repository: name=local description=local baseurl=file:///mnt enabled=1 gpgcheck=0 file=Chengzhang
- name: "挂载镜像"
mount: src=/dev/cdrom path=/mnt fstype=iso9660 state=mounted
- name: "安装web服务"
yum: name=httpd state=installed
- name: "自定义页面"
copy: content="Hello,World" dest=/var/www/html/index.html
- name: "启动服务"
systemd: name=httpd state=started enabled=yes
测试:保证文件没有问题(去掉-C后就可以运行了)
ansible-playbook 文件名.yml -C
---
- hosts: all
remote_user: root
vars: ###自己定义的变量
http_port: 8080
tasks:
- name: "拷贝配置文件"
template: src=httpd.conf.j2 dest=/etc/httpd/conf/httpd.conf
- name: "重启web服务"
systemd: name=httpd state=restarted
然后从其他地方拷贝一个conf文件进行修改
#Listen 12.34.56.78:80
#Listen 80 ####将Listen 80替换为咱们定义的变量然后保存
Listen {{ httpd_port }}
然后进行测试:
成功将80端口改为8080
通过ansible-playbook命令运行
格式: ansible-playbook... [options]
[root@ansible PlayBook]# ansible-playbook -h
#ansible-playbook常用选项:
--check or -C #只检测可能会发生的改变,但不真正执行操作
--list-hosts #列出运行任务的主机
--list-tags #列出playbook文件中定义所有的 tags(列出标签)
--list-tasks #列出playbook 文件中定义的所以任务集
--limit #主机列表只针对主机列表中的某个主机或者某个组执行
-f #指定并发数,默认为5个(最多同时进行5台,如果有100台就用-f指定100)
-t #指定tags运行,运行某一个或者多个tags。(前提playbook中有定义tags)
一V #显示过程-vv-vvv更详细
在一个playbook开始时,最先定义的是要操作的主机和用户
除了上面的定义外,还可以在某一个tasks 中定义要执行该任务的远程用户
还可以定义使用sudo授权用户执行该任务
很多时候当我们某一个配置发生改变,我们需要重启服务,(比如 httpd配置文件文件发生改变了)这时候就可以用到handlers和notify 了;
(当发生改动时)notify actions会在playbook 的每一个task结束时被触发,而且即使有多个不同task通知改动的发生,notify actions 知会被触发一次;比如多个resources指出因为一个配置文件被改动,所以apache需要重启,
是重新启动的操作知会被执行一次。
---
- hosts: all
remote_user: root
tasks:
- name: "拷贝配置文件"
template: src=httpd.conf.j2 dest=/etc/httpd/conf/httpd.conf
- name: "重启web服务" ###到了这步之后就会跳到handlers上找restart_http
shell: ls /root
notify:
- restart_http
- name: "创建一个名为Chengzhang的文件" ###然后此项就会被跳过,但是下一项还是继续执行
file: path=/root/Chengzhang state=touch
- name: "写入文字"
copy: content= "Hello Chengzhang" dest=/root/Chengzhang
handlers:
- name: restart_http ###这个name要与notify相同,不然匹配不到
systemd: name=httpd state=restarted
测试查看:
环境说明:这里配置了两个组,一个webA组和一个webB组
[root@ansible PlayBook]# cat /etc/ansible/hosts
[webA]
192.168.100.203
[webB]
192.168.100.204
[web:children]
webA
webB
执行playbook时候通过参数-e传入变量,这样传入的变量在整个playbook中都可以被调用属于全局变量
(当发生改动时)notify actions会在playbook 的每一个task结束时被触发,而且即使有多个不同task通知改动的发生,notify actions 知会被触发一次;比如多个resources指出因为一个配置文件被改动,所以apache需要重启,
是重新启动的操作知会被执行一次。
写一个变量文件:
---
- hosts: all
remote_user: root
tasks:
- name: "安装变量上的服务"
yum: name={{ gpg }} state=installed
使用-e配置变量
在/etc/ansible/hosts文件中定义变量,可以针对每个主机定义不同的变量,也可以定义一个组的变量,然后直接在playbook中直接调用。注意,组中定义的变量没有单个主机中的优先级高。
编辑playbook剧本
---
- hosts: all
remote_user: root
tasks:
- name: "安装变量上的服务"
file: name={{ webdir }} state=touch
验证:
所以可以证明,局部变量与全局变量相同时,有先使用局部变量
编写playbook时,直接在里面定义变量,然后直接引用,可以定义多个变量;注意:如果在执行playbook时,又通过-e参数指定变量的值,那么会以-e参数指定的为准。
创建playbook文件
---
- hosts: webA
remote_user: root
vars: #自定义变量
pkg: nginx #变量1
dir: /tmp/test1 #变量2
tasks:
- name: "install pkg"
file: name={{ pkg }} state=directory #引用变量
- name: "create new dir"
file: name= {{ dir }} state=touch #引用变量
执行之后就会安装nginx和创建一个/tmp/test1文件
---
- hosts: webA
remote_user: root
tasks:
- name: "create file"
file: name= {{ ansible_fqdn }}.log state=touch #引用setup变量
为了方便管理将所有的变量统一放在一个独立的变量YAML文件中,playbook文件直接引用文件调用变量即可。
单独创建一个yml文件
创建palybook文件
---
- hosts: webA
remote_user: root
vars_files: #引用变量文件
- ./var.yml #指定变量文件是本目录下的
var.yml
tasks:
- name: "install package"
yum: name= {{ var1 }} #引用变量
- name: "create file"
file: name=/tmp/{{ var2 }}.log state=touch
1、主机清单
2、Yaml文件中定义vars:
3、运行ansible-playbook时用-e参数指定
4、编写变量yaml文件,在playbook 中用vars_files:调用5、用setup模块自带的变量
一个playbook 文件中,执行时如果想执行某一个任务,那么可以给每个任务集进行打标签,这样在执行的时候可以通过-t选择指定标签执行,还可以通过--skip-tags选择除了某个标签外全部执行等。
---
- hosts: webA
remote_user: root
tasks:
- name: "拷贝配置文件"
template: src=httpd.conf.j2 dest=/etc/httpd/conf/httpd.conf
tags: httpd.conf ###移动配置文件的标签
- name: "重启web服务"
shell: mkdir /opp
tags: mkdir ###创建文件的标签
- name: restart_http
systemd: name=httpd state=restarted
只执行指定标签的模块
ansible-playbook -t httpd.conf qq.yml
只执行不是标签的模块
ansible-playbook --skip-tage httpd.conf,make qq.yml
when 语句参考
条件测试:如果需要根据变量、facts或此前任务的执行结果来做为某task 执行与否的前提时要用到条件测试,通过when语句执行,在 lask中使用jinja2的语法格式、
when 语句:
在 task后添加when子句即可使用条件测试: when语句支持jinja2.表达式语法。
创建案例
---
- hosts: webA
tasks:
- name: 输出Chengzhang
shell: echo -n "Chengzhang"
register: xingming ##"如果上一条命令执行成功,就创建一个xingming"
ignore_errors: True
- name: 我要判断
shell: rm -rf /opp
when: xingming is success ##判断xingming是不是被成功创建,成功创建就删除根下的/opp
执行之前
执行之后
修改playbook文件,通过setup模块获取系统版本去判断。setup常用模块
[root@ansible PlayBook]# cat qq.yml
# when示例
---
- 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
with_items迭代,当有需要重复性执行的任务时,可以使用迭代机制。
对迭代项的引用,固定变量名为“item”,要在task中使用with_items给定要迭代的元素列表。
列表格式:
字符串
字典
[root@ansible PlayBook]# cat qq.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
与下方案例同等效果
---
- 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
[root@ansible PlayBook]# cat qq.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@ansible PlayBook]# ansible-playbook qq.yml
# 验证是否成功创建用户及组
[root@ansible PlayBook]# ansible all -m shell -a 'tail -3 /etc/passwd'
192.168.100.102 | 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.100.105 | 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.100.101 | 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.100.103 | 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
通过使用for,if可以更加灵活的生成配置文件等需求,还可以在里面根据各种条件进行判断,然后生成不同的配置文件、或者服务器配置相关等。
1)编写playbook
[root@ansible PlayBook]# cat qq.yml
# template for 示例
---
- hosts: all
remote_user: root
vars:
nginx_vhost_port:
- 81
- 82
- 83
tasks:
- name: Templage Nginx Config
template: src=nginx.conf.j2 dest=/tmp/nginx_test.conf
2)模板文件编写
# 循环playbook文件中定义的变量,依次赋值给port
[root@ansible PlayBook]# cat nginx.conf.j2
{% for port in nginx_vhost_port %} ###使用for循环定义变量prot,从nginx_vhost_port中取值,进行循环
server{
listen: {{ port }};
server_name: localhost;
}
{% endfor %}
playbook的验证
[root@localhost ~]# cat /tmp/nginx_test.conf
server{
listen: 81;
server_name: localhost;
}
server{
listen: 82;
server_name: localhost;
}
server{
listen: 83;
server_name: localhost;
}
1)编写playbook
[root@ansible PlayBook]# cat testfor02.yml
# template for 示例
---
- hosts: all
remote_user: root
vars:
nginx_vhosts:
- web1:
listen: 8081
server_name: "web1.example.com"
root: "/var/www/nginx/web1"
- web2:
listen: 8082
server_name: "web2.example.com"
root: "/var/www/nginx/web2"
- web3:
listen: 8083
server_name: "web3.example.com"
root: "/var/www/nginx/web3"
tasks:
- name: Templage Nginx Config
template: src=nginx.conf.j2 dest=/tmp/nginx_vhost.conf
2)模板文件编写
[root@ansible PlayBook]# cat nginx.conf.j2
{% for vhost in nginx_vhosts %}
server{
listen: {{ vhost.listen }};
server_name: {{ vhost.server_name }};
root: {{ vhost.root }};
}
{% endfor %}
3)执行playbook并查看生成结果
[root@ansible PlayBook]# ansible-playbook testfor02.yml
# 去到一个节点看下生成的结果发现自动生成了三个虚拟主机
[root@linux ~]# cat /tmp/nginx_vhost.conf
server{
listen: 8081;
server_name: web1.example.com;
root: /var/www/nginx/web1;
}
server{
listen: 8082;
server_name: web2.example.com;
root: /var/www/nginx/web2;
}
server{
listen: 8083;
server_name: web3.example.com;
root: /var/www/nginx/web3;
}
在for循环中再嵌套if判断,让生成的配置文件更加灵活
1)编写playbook
[root@ansible PlayBook]# cat qq.yml
# template for 示例
---
- hosts: all
remote_user: root
vars:
nginx_vhosts:
- web1:
listen: 8081
root: "/var/www/nginx/web1"
- web2:
server_name: "web2.example.com"
root: "/var/www/nginx/web2"
- web3:
listen: 8083
server_name: "web3.example.com"
root: "/var/www/nginx/web3"
tasks:
- name: Templage Nginx Config
template: src=nginx.conf.j2 dest=/tmp/nginx_vhost.conf
2)模板文件编写
# 说明:这里添加了判断,如果listen没有定义的话,默认端口使用8888,如果server_name有定义,那么生成的配置文件中才有这一项。
[root@ansible PlayBook]# cat nginx.conf.j2
{% for vhost in nginx_vhosts %}
server{
{% if vhost.listen is defined %}
listen: {{ vhost.listen }};
{% else %}
listen: 8888;
{% endif %}
{% if vhost.server_name is defined %}
server_name: {{ vhost.server_name }};
{% endif %}
root: {{ vhost.root }};
}
{% endfor %}
生成结果:
[root@ansible PlayBook]# ansible-playbook qq.yml
# 去到一个节点看下生成的结果发现自动生成了三个虚拟主机
[root@linux ~]# cat /tmp/nginx_vhost.conf
server{
listen: 8081;
root: /var/www/nginx/web1;
}
server{
listen: 8888; ###如果此项在剧本被定义了,那就使用被定义的项,如果没有被定义,默认选择8888
server_name: web2.example.com;
root: /var/www/nginx/web2;
}
server{
listen: 8083;
server_name: web3.example.com;
root: /var/www/nginx/web3;
}