Playbook剧本
1、Playbook剧本简介
前面我们都是通过ansible命令形式管理被控节点:
- 此方式适合执行一些临时性的简单任务
Playbook剧本:
- 将需要执行的任务写入剧本文件,看起来简洁清晰
- 剧本文件中可以包含多个任务
- 剧本能够实现流程控制,比如:判断、循环、变量、标签
- 剧本写好后,随时调用剧本,执行相关的任务
- 适用于经常执行的复杂任务
- 剧本提供语法检查以及模拟执行功能
Playbook剧本意义
电影剧本:
电影名
场景
演员
事件
事件1
事件2
事件3
Ansible剧本:
剧本名
被控节点
管理被控节点时使用的用户
任务(事件)
任务1
任务2
任务3
2、剧本书写格式
Playbook剧本要求按照YAML格式编写。
2.1 YAML简介
YAML是一个可读性高、用来表达数据序列的格式语言;YAML以数据为中心,重点描述数据的关系和结构。
2.2 YAML格式特点
YAML语法官方文档:https://docs.ansible.com/ansible/latest/reference_appendices/YAMLSyntax.html
1."#"代表注释,第一行一般为三个横杠表示开头
2.严格的缩进表示层级关系,缩进一般为2个空格
3.缩进必须使用空格,不能使用tab键
4.字符串通常不需要放在引号里,即使字符串中包含空格
5.支持字典,字典以简单的形式表示 key: value;字典也可以使用{}括起来
6.支持列表,列表的内容使用"-"表示;列表也可用[]括起来
7.":"和"-"后面必须要有一个空格
8.跨行数据可以使用">"来换行
9.剧本文件后缀名必须为yaml或yml
3、剧本编写格式
Playbook剧本必不可少的三个部分:name,hosts,tasks。
name 剧本名称
hosts 被控节点,主机或主机组
tasks 要执行的任务
--- #第一行一般为三个横杠,可以省略
- name: Update web servers #剧本名称
hosts: webservers #被控节点,主机或主机组
remote_user: root #管理被控节点时使用哪个用户
tasks: #要执行的任务
- name: apache_install #第一个任务的名称
tags: t1 #该任务的标签
yum: #该任务使用的模块,也就是该任务要做的事情
name: httpd #yum模块的参数,表示httpd包
state: latest #yum模块的参数,表示安装最新版
- name: apache_config_file #第二个任务的名称
tags: t2 #该任务的标签
template: #该任务使用的模块,也就是该任务要做的事情
src: /srv/httpd.j2 #模块参数
dest: /etc/httpd.conf #模块参数
- name: Update db servers #第二个剧本名称,第二种格式
hosts: databases
remote_user: root
tasks:
- name: Ensure postgresql is at the latest version
yum: name=postgresql state=latest
- name: Ensure that postgresql is started
service: name=postgresql state=started
剧本编写案例:编写Rsync服务模式剧本
#环境准备,准备好rsync配置文件和密码文件
[root@manager-18 ~/projects/Rsync_configure_project]# ls
rsyncd.conf rsync.passwd
#编辑剧本文件,将rsync配置流程写入剧本
[root@manager-18 ~/projects/Rsync_configure_project]# vim Rsync_configure_project.yaml
- name: Rsync_configure
hosts: backup
tasks:
- name: 01_install_rsync
tags: t1
yum:
name: rsync
state: latest
- name: 02_copy_config_file
tags: t2
copy:
src: ./rsyncd.conf
dest: /etc/rsyncd.conf
- name: 03_rsync_groupadd
tags: t3
group:
name: rsync
system: yes
- name: 04_rsync_useradd
tags: t4
user:
name: rsync
system: yes
group: rsync
- name: 05_make_backup_directory
tags: t5
file:
path: /backup
owner: rsync
group: rsync
state: directory
- name: 06_copy_password_file
tags: t6
copy:
src: ./rsync.passwd
dest: /etc/rsync.passwd
mode: 600
- name: 07_stop_firewalld_service
tags: t7
service:
name: firewalld
enabled: no
state: stopped
- name: 08_close_the_selinux
tags: t8
selinux:
state: disabled
- name: 09_start_rsyncd_service
tags: t9
service:
name: rsyncd
state: started
4、剧本执行命令
#命令格式
ansible-playbook [选项] 剧本文件
#选项
-C #模拟执行
-i #指定主机清单hosts文件路径,默认是/etc/ansible/hosts
-v #显示过程,-vv、-vvv更详细
--list-hosts #查看哪些主机会执行该剧本
--list-tasks #列出剧本中所有任务
--start-at-task #指定从剧本中某个任务开始运行
--list-tags #列出剧本文件中任务中定义的所有tags
-t #只运行剧本文件中定义的某些tags任务,多个标签用逗号隔开
--skip-tags #跳过剧本中某些标签的任务
#示例
#执行某剧本
[root@manager-18 ~/projects/Rsync_configure_project]# ansible-playbook Rsync_configure_project.yaml
#模拟执行某剧本
[root@manager-18 ~/projects/Rsync_configure_project]# ansible-playbook -C Rsync_configure_project.yaml
#查看哪些主机会执行该剧本
[root@manager-18 ~/projects/Rsync_configure_project]# ansible-playbook --list-hosts Rsync_configure_project.yaml
playbook: Rsync_configure_project.yaml
play #1 (backup): Rsync configure TAGS: []
pattern: [u'backup']
hosts (1):
10.0.0.16
#列出剧本中所有任务
[root@manager-18 ~/projects/Rsync_configure_project]# ansible-playbook --list-tasks Rsync_configure_project.yaml
playbook: Rsync_configure_project.yaml
play #1 (backup): Rsync configure TAGS: []
tasks:
01 install rsync TAGS: [t1]
02 copy config file TAGS: [t2]
03 rsync groupadd TAGS: [t3]
04 rsync useradd TAGS: [t4]
05 make backup directory TAGS: [t5]
06 copy password file TAGS: [t6]
07 stop firewalld service TAGS: [t7]
08 close the selinux TAGS: [t8]
09 start rsyncd service TAGS: [t9]
#指定从剧本中第7个任务开始运行
[root@manager-18 ~/projects/Rsync_configure_project]# ansible-playbook --start-at-task "07 stop firewalld service" Rsync_configure_project.yaml
#列出剧本文件中任务中定义的所有tags
[root@manager-18 ~/projects/Rsync_configure_project]# ansible-playbook --list-tags Rsync_configure_project.yaml
playbook: Rsync_configure_project.yaml
play #1 (backup): Rsync configure TAGS: []
TASK TAGS: [t1, t2, t3, t4, t5, t6, t7, t8, t9]
#只运行剧本文件中定义的tags为t2,t6,t9的任务
[root@manager-18 ~/projects/Rsync_configure_project]# ansible-playbook -t t2,t6,t9 Rsync_configure_project.yaml
#跳过剧本中标签为t3,t4,t5的任务
[root@manager-18 ~/projects/Rsync_configure_project]# ansible-playbook --skip-tags t3,t4,t5 Rsync_configure_project.yaml
5、Ansible变量应用
Ansible支持很多种定义变量的方式;在此简单列举几种,根据优先级排序:
1.Inventory变量
2.Host Facts变量
3.Register变量
4.Playbook变量
5.变量文件
除了以上变量之外还有"命令行定义的变量"和ansible内置的"magic魔法变量"
变量的调用方式:
通过 {{ variable_name }} 调用变量,且变量名前后建议加空格,有时使用 "{{ variable_name }}" 才能生效
5.1 Inventory变量
#Inventory变量就是主机清单配置文件中定义的变量,该变量可以在剧本中被引用
#示例:之前我们在主机清单中定义了ssh远程登录的用户名,我们可以进行调用
[root@manager-18 ~]# vim inventory_variable_test.yml
---
- name: inventory variable test
hosts: backup
tasks:
- name: print
debug:
msg: "the ansible_user value is {{ ansible_user }}"
#var: ansible_user
# debug 模块用于在调试中输出信息
# 参数
msg #输出指定消息,消息用引号引起来,可调用变量,ansible中调用变量方法为 {{ 变量名 }}
var #输出指定变量的值,调用变量不需要使用{{ 变量名 }}
[root@manager-18 ~]# ansible-playbook inventory_variable_test.yml
PLAY [inventory variable test] ******************************************************************************************************
TASK [Gathering Facts] **************************************************************************************************************
ok: [10.0.0.16]
TASK [test01] ***********************************************************************************************************************
ok: [10.0.0.16] => {
"msg": "the ansible_user value is 172.16.1.16"
}
PLAY RECAP **************************************************************************************************************************
10.0.0.16 : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
5.2 Host Facts变量
#事实变量就是setup模块获取到的被控节点的主机信息
#示例一
[root@manager-18 ~]# vim facts_variable_test.yml
---
- name: facts variable test
hosts: backup
tasks:
- name: print
debug:
msg: "the backup host ip address is {{ ansible_ens33.ipv4.address }}"
[root@manager-18 ~]# ansible-playbook facts_variable_test.yml
PLAY [facts variable test] **********************************************************************************************************
TASK [Gathering Facts] **************************************************************************************************************
ok: [10.0.0.16]
TASK [test01] ***********************************************************************************************************************
ok: [10.0.0.16] => {
"msg": "the backup host ip address is 172.16.1.16"
}
PLAY RECAP **************************************************************************************************************************
10.0.0.16 : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
#示例二
[root@manager-18 ~]# vim facts_variable_test.yml
---
- name: facts variable test
hosts: backup
tasks:
- name: test01
shell: echo "{{ ansible_ens33.ipv4.address }}" > /tmp/{{ ansible_ens33.ipv4.address }}
[root@manager-18 ~]# ansible-playbook facts_variable_test.yml
PLAY [facts variable test] **********************************************************************************************************
TASK [Gathering Facts] **************************************************************************************************************
ok: [10.0.0.16]
TASK [test01] ***********************************************************************************************************************
changed: [10.0.0.16]
PLAY RECAP **************************************************************************************************************************
10.0.0.16 : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
[root@backup-16 ~]# cat /tmp/172.16.1.16
172.16.1.16
#注意:若使用不到事实变量,可以关闭获取被控主机的事实变量
# 配置如下:
---
- name: facts variable test
hosts: backup
gather_facts: false
5.3 Register变量
#register语句可以将某个命令的执行结果保存至某变量中,该变量就是注册变量
#示例
[root@manager-18 ~]# vim register_variable_test.yml
---
- name: register variable test
hosts: backup
tasks:
- name: test01
shell: echo "hello world"
register: hi #将此任务的结果保存到一个名为"hi"的变量中
- name: print
debug:
var: hi #在此使用debug模块,输出hi变量内容
#var: hi.stdout #输出hi变量中stdout该部分内容
[root@manager-18 ~]# ansible-playbook register_variable_test.yml
PLAY [register variable test] *******************************************************************************************************
TASK [Gathering Facts] **************************************************************************************************************
ok: [10.0.0.16]
TASK [test01] ***********************************************************************************************************************
changed: [10.0.0.16]
TASK [debug] ************************************************************************************************************************
ok: [10.0.0.16] => {
"hi": {
"changed": true,
"cmd": "echo \"hello world\"",
"delta": "0:00:00.002149",
"end": "2021-12-03 11:12:50.385688",
"failed": false,
"rc": 0,
"start": "2021-12-03 11:12:50.383539",
"stderr": "",
"stderr_lines": [],
"stdout": "hello world",
"stdout_lines": [
"hello world"
]
}
}
PLAY RECAP **************************************************************************************************************************
10.0.0.16 : ok=3 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
5.4 Playbook变量
#在剧本中可以使用vars关键词进行自定义变量
#示例
[root@manager-18 ~]# vim playbook_variable_test.yml
---
- name: playbook variable test
hosts: backup
vars: #在playbook中定义变量
firstname: han #第一个变量和值
lastname: zhuang #第二个变量和值
tasks:
- name: print
debug:
msg: "my name is {{ firstname }} {{ lastname }}"
[root@manager-18 ~]# ansible-playbook playbook_variable_test.yml
PLAY [playbook variable test] *******************************************************************************************************
TASK [Gathering Facts] **************************************************************************************************************
ok: [10.0.0.16]
TASK [print] ************************************************************************************************************************
ok: [10.0.0.16] => {
"msg": "my name is han zhuang"
}
PLAY RECAP **************************************************************************************************************************
10.0.0.16 : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
#vars_prompt语句可以定义变量的值在剧本运行时手动输入
#示例
[root@manager-18 ~]# vim playbook_vars_prompt_test.yml
---
- name: vars prompt test
hosts: backup
gather_facts: false #关闭事实变量获取
vars_prompt: #定义提示变量
- name: login_username #变量名称
prompt: "please input login username: " #变量输入提示语
private: no #不隐藏输入值
- name: login_passwd #第二个变量的名称
prompt: "please input user password: " #变量输入提示语
private: yes #隐藏输入值
tasks:
- name: print
debug:
msg: "username is {{ login_username }} , password is {{ login_passwd }}"
[root@manager-18 ~]# ansible-playbook playbook_vars_prompt_test.yml
please input login username: : hzz #提示输入变量的值
please input user password: : #提示输入变量的值,输入的值不显示
PLAY [vars prompt test] *************************************************************************************************************
TASK [print] ************************************************************************************************************************
ok: [10.0.0.16] => {
"msg": "username is hzz , password is 123456"
}
PLAY RECAP **************************************************************************************************************************
10.0.0.16 : ok=1 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
5.5 变量文件
#单独定义一个变量文件,在playbook中用vars_files调用该文件
#示例,创建变量文件,在剧本中引入变量文件
[root@manager-18 ~]# vim /etc/ansible/vartables.yml
---
login_username: hzz
login_passwd: 123456
[root@manager-18 ~]# vim varsfile_variable_test.yml
---
- name: vars prompt test
hosts: backup
gather_facts: false
vars_files: /etc/ansible/vartables.yml #引入变量文件
tasks:
- name: print
debug:
msg: "username is {{ login_username }} , password is {{ login_passwd }}"
[root@manager-18 ~]# ansible-playbook varsfile_variable_test.yml
PLAY [vars prompt test] *************************************************************************************************************
TASK [print] ************************************************************************************************************************
ok: [10.0.0.16] => {
"msg": "username is hzz , password is 123456"
}
PLAY RECAP **************************************************************************************************************************
10.0.0.16 : ok=1 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
5.6 magic魔法变量
Ansible默认会提供一些内置的变量以实现一些特定的功能,我们称之为魔法变量。
变量名称 | 含义 |
---|---|
hostvars | 用于获取某台指定的主机的相关变量 |
inventory_hostname | 当前正在运行task的主机的IP或主机名 |
groups | inventory中所有主机组的列表 |
group_names | 当前正在执行task的目标主机位于的主机组 |
play_hosts | 当前playbook会在哪些hosts上运行 |
inventory_dir | 主机清单所在目录 |
inventory_file | 主机清单文件 |
… | … |
6、剧本高级特性
6.1 触发器语句
notify和handlers语句用于流程控制;notify语句在任务结束时,会根据条件触发,若任务执行后结果有变化则会触发notify。handlers语句中的定义的任务在notify被触发后会被执行;在书写时handlers与tasks同级。
notify和handlers官方文档:https://docs.ansible.com/ansible/latest/user_guide/playbooks_handlers.html
#示例一,Rsync服务模式剧本优化
#剧本执行时,若配置文件已经存在且内容一致,则rsyncd服务则不会重启,若配置文件被更改,则会重启rsyncd服务
[root@manager-18 ~/projects/Rsync_configure_project]# ls
Rsync_configure_project.yaml rsyncd.conf rsync.passwd
[root@manager-18 ~/projects/Rsync_configure_project]# vim Rsync_configure_project.yaml
- name: Rsync configure
hosts: backup
tasks:
- name: 01_install_rsync
tags: t1
yum:
name: rsync
state: latest
- name: 02_copy_config_file
tags: t2
copy:
src: ./rsyncd.conf
dest: /etc/rsyncd.conf
notify: restart_rsyncd #若该任务执行后结果有变化,则触发notify,转而执行handlers中定义的任务
- name: 03_rsync_groupadd
tags: t3
group:
name: rsync
system: yes
- name: 04_rsync_useradd
tags: t4
user:
name: rsync
system: yes
group: rsync
- name: 05_make_backup_directory
tags: t5
file:
path: /backup
owner: rsync
group: rsync
state: directory
- name: 06_copy_password_file
tags: t6
copy:
src: ./rsync.passwd
dest: /etc/rsync.passwd
mode: 600
notify: restart_rsyncd #若该任务执行后结果有变化,则触发notify,转而执行handlers中定义的任务
- name: 07_stop_firewalld_service
tags: t7
service:
name: firewalld
enabled: no
state: stopped
- name: 08_close_the_selinux
tags: t8
selinux:
state: disabled
handlers:
- name: restart_rsyncd
service:
name: rsyncd
state: restarted
#示例二
#触发notify,执行多个handlers中定义的任务
- name: Template configuration file
template:
src: template.j2
dest: /etc/foo.conf
notify:
- Restart memcached
- Restart apache
handlers:
- name: Restart memcached
service:
name: memcached
state: restarted
- name: Restart apache
service:
name: apache
state: restarted
#handlers中定义的任务会在所有任务执行完毕后再执行,避免handlers中定义的任务被重复执行;handlers中的任务也可以自己监听notify的触发
handlers:
- name: Restart memcached
service:
name: memcached
state: restarted
listen: "restart web services"
- name: Restart apache
service:
name: apache
state: restarted
listen: "restart web services"
tasks:
- name: Restart everything
command: echo "this task will restart the web services"
notify: "restart web services"
6.2 剧本文件复用
剧本中可以导入其他剧本,若有一些基础的任务,可以单独写一个剧本,然后在其他剧本中导入调用。
剧本文件复用官方文档:https://docs.ansible.com/ansible/latest/user_guide/playbooks_reuse.html
导入方式 |
特点 |
---|---|
include_* | 动态导入,包括角色、任务或变量,将它们动态添加到剧本中。导入的任务可能会受到顶级剧本中较早任务结果的影响。官方说已弃用 |
import_* | 静态导入,导入角色、任务或剧本会将它们静态添加到剧本中;在运行剧本中的任何任务之前对导入的文件和角色进行预处理,因此导入的内容永远不会受到顶级剧本中其他任务的影响。预处理导入时变量必须可用,变量需要提前定义。 |
#示例,Rsync服务模式剧本再次优化
[root@manager-18 ~/projects/Rsync_configure_project]# vim Firewalld_selinux_stop.yaml
- name: Firewalld_selinux_stop
hosts: all
tasks:
- name: 01_stop_firewalld_service
tags: t1
service:
name: firewalld
enabled: no
state: stopped
- name: 02_close_the_selinux
tags: t2
selinux:
state: disabled
[root@manager-18 ~/projects/Rsync_configure_project]# vim Rsync_configure_project.yaml
- import_playbook: Firewalld_selinux_stop.yaml #引入前面的关闭防火墙和selinux剧本
- name: Rsync_configure
hosts: backup
tasks:
- name: 01_install_rsync
tags: t1
yum:
name: rsync
state: latest
- name: 02_copy_config_file
tags: t2
copy:
src: ./rsyncd.conf
dest: /etc/rsyncd.conf
notify: restart_rsyncd
- name: 03_rsync_groupadd
tags: t3
group:
name: rsync
system: yes
- name: 04_rsync_useradd
tags: t4
user:
name: rsync
system: yes
group: rsync
- name: 05_make_backup_directory
tags: t5
file:
path: /backup
owner: rsync
group: rsync
state: directory
- name: 06_copy_password_file
tags: t6
copy:
src: ./rsync.passwd
dest: /etc/rsync.passwd
mode: 600
notify: restart_rsyncd
handlers:
- name: restart_rsyncd
service:
name: rsyncd
state: restarted
#示例二,如果要在剧本中多次运行导入的剧本,若导入的剧本中存在变量,则必须定义好变量
tasks:
- import_tasks: wordpress.yml
vars:
wp_user: timmy
- import_tasks: wordpress.yml
vars:
wp_user: alice
- import_tasks: wordpress.yml
vars:
wp_user: bob
6.3 剧本循环语句
循环语句用于多次执行任务,当某些任务需要多次执行时使用循环语句,例如:创建多个用户。
循环语句官方文档:https://docs.ansible.com/ansible/latest/user_guide/playbooks_loops.html
#示例一:Loop循环列表内容,创建多个用户
[root@manager-18 ~]# vim useradd_test.yml
---
- name: create user
hosts: dev
tasks:
- name: create user
user:
name: "{{ item }}"
state: present
loop:
- user01
- user02
- user03
- name: set password
shell: echo '12345678' | passwd --stdin "{{ item }}"
loop:
- user01
- user02
- user03
#示例二:vars变量传递列表内容给Loop循环
[root@manager-18 ~]# vim useradd_test_v2.yml
---
- name: create user
hosts: dev
vars:
users:
- user01
- user02
- user03
tasks:
- name: create user
user:
name: "{{ item }}"
state: present
loop: "{{ users }}"
- name: set password
shell: echo '12345678' | passwd --stdin "{{ item }}"
loop: "{{ users }}"
#示例三:哈希列表Loop循环
[root@manager-18 ~]# vim useradd_test_v3.yml
---
- name: create user
hosts: dev
tasks:
- name: create user and group
user:
name: "{{ item.name }}"
group: "{{ item.groups }}"
loop:
- {name: 'user01', groups: 'wheel'}
- {name: 'user02', groups: 'root'}
#示例四:vars变量传递哈希列表给Loop循环
[root@manager-18 ~]# vim useradd_test_v4.yml
---
- name: loop test
hosts: dev
vars:
users:
- user: 'user01'
group: 'wheel'
- user: 'user02'
group: 'root'
tasks:
- name: debug
user:
name: "{{ item.user }}"
group: "{{ item.group }}"
loop: "{{ users }}"
#示例五:vars变量传递字典给Loop循环,并使用dict filter(字典过滤器)
[root@manager-18 ~]# vim useradd_test_v5.yml
---
- name: loop test
hosts: dev
vars:
users:
user: 'user01'
groups: 'root'
tasks:
- name: debug
debug:
msg: "{{ item.key }} {{ item.value }}"
loop: "{{ users|dict2items }}" # |表示过滤器,|dict2items字典过滤器;users变量中的值传递给字典过滤器,字典过滤器将内容过滤为key,value的格式
#转换之前的格式
vars:
users:
user: 'user01'
groups: 'root'
#转换之后的格式
- key: user
value: user01
- key: groups
value: root
6.4 条件判断语句
when语句用于条件判断,当任务需要在某些特定情况下执行的话,我们就需要进行判断,当判断结果为真时执行此任务,当判断结果为假则不执行此任务。
when语句官方文档:https://docs.ansible.com/ansible/latest/user_guide/playbooks_conditionals.html
比较符、逻辑运算符、其他符号 | 含义 |
---|---|
== | 比较两个对象是否相等 |
!= | 比较两个对象是否不等 |
> | 比较左侧对象是否大于右侧 |
>= | 比较左侧对象是否大于等于右侧 |
< | 比较左侧对象是否小于右侧 |
<= | 比较左侧对象是否小于等于右侧 |
and | 如果前后条件都为为真,则返回真 |
or | 如果前后条件有一个为真,则返回真 |
not | 取反 |
() | 括号对判断条件进行分组 |
变量 is defined | 某变量已经定义 |
变量 is not defined | 某变量未定义 |
注册变量 is succeeded | 注册变量结果为真 |
注册变量 is failed | 注册变量结果为假 |
注册变量 is skipped | 注册变量结果为跳过 |
变量 in 列表/字典 | 某变量在某字典或列表中存储 |
#示例一
[root@manager-18 ~]# vim test.yml
---
- name: test
hosts: web
tasks:
- name: test01
debug:
msg: "this is centos"
when: ansible_distribution == "CentOS"
- name: test02
debug:
msg: "this is redhat"
when: ansible_distribution == "RedHat"
#示例二,当有多个判断条件时使用()将条件进行分组,分组后使用逻辑运算符
[root@manager-18 ~]# vim test.yml
---
- name: test
hosts: web
tasks:
- name: test01
debug:
msg: "this is centos7"
when: (ansible_distribution == "CentOS") and
(ansible_distribution_major_version == "7")
#示例三,当有多个判断条件并且逻辑运算符为 and 时,可写为列表格式
[root@manager-18 ~]# vim test.yml
---
- name: test
hosts: web
tasks:
- name: test01
debug:
msg: "this is centos7"
when:
- ansible_distribution == "CentOS"
- ansible_distribution_major_version == "7"
#示例四,在循环中使用条件判断语句
[root@manager-18 ~]# vim test.yml
---
- name: test
hosts: web
tasks:
- name: Run with items greater than 5
command: echo {{ item }}
loop: [ 0, 2, 4, 6, 8, 10 ]
when: item > 5
#示例五,在循环中使用条件判断语句
[root@manager-18 ~]# vim test.yml
- name: install mariadb-server if enough space
yum:
name: mariadb-server
state: latest
loop: "{{ ansible_mounts }}" #循环事实变量,ansible_mounts表示磁盘挂载信息
when: item.mount == "/" and item.size_available > 300000000 #判断"/"挂载点大小大于300M
#示例六,判断变量是否定义
[root@manager-18 ~]# vim test.yml
- name: test
hosts: backup
vars:
hzz: 123
tasks:
- name: test01
debug:
msg: The variable is defined
when: hzz is defined
- name: test02
debug:
msg: The variable is undefined
when: hzz is undefined
#示例七,判断注册变量结果
[root@manager-18 ~]# vim test.yml
- name: test
hosts: backup
ignore_errors: true
tasks:
- name: test01
shell: echo1 "123"
register: hzz
- name: test02
debug:
msg: The result is succeeded
when: hzz is succeeded
- name: test03
debug:
msg: The result is failed
when: hzz is failed
#示例八,
[root@manager-18 ~]# vim test.yml
- name: test
hosts: backup
ignore_errors: True
tasks:
- name: Statistical process
shell: ps -ef | grep httpd | wc -l
register: check_value
- name: Print information
debug:
msg: echo "Process already exists"
when: check_value.stdout|int > 0 #剧本中使用|过滤器,将注册变量输出的值转换为int类型再进行判断是否大于0
6.5 失败任务处理
ignore_errors语句用于忽略剧本任务中错误的命令。
ignore_errors语句官方文档:https://docs.ansible.com/ansible/latest/user_guide/playbooks_error_handling.html
#示例一
#编写一个测试剧本,故意写错剧本任务
[root@manager-18 ~]# vim error.yml
---
- name: error test
hosts: backup
tasks:
- name: 01 test
service:
name: test #没有此服务,运行该剧本会报错,后面的任务将不会执行
state: started
- name: 02 test
file:
path: /tmp/testfile
state: touch
#忽略剧本中某任务的报错,使剧本继续运行
[root@manager-18 ~]# vim error.yml
---
- name: error test
hosts: backup
tasks:
- name: 01 test
service:
name: test
state: started
ignore_errors: true #在此任务中加入ignore_errors,忽略该任务的错误
- name: 02 test
file:
path: /tmp/testfile
state: touch
#示例二
#忽略剧本中所有报错,使剧本继续运行
[root@manager-18 ~]# vim error.yml
---
- name: error test
hosts: backup
ignore_errors: true #将ignore_errors中加入剧本全局配置,忽略剧本中所有错误
tasks:
- name: 01 test
service:
name: test
state: started
- name: 02 test
file:
path: /tmp/testfile
state: touch
6.6 template模板
template模板是一个文本文件主要作为生成所需文件的模板,模板文件中可以调用变量、嵌套jinja语法;ansible中template模块专门用于传输模板文件;模板文件后缀名为.j2。
jinja2语言:
jinja2是Python的全功能模板引擎。
jinja语言官方文档:https://jinja.palletsprojects.com/en/2.11.x/templates/
jinja2语言支持的特性:
字符串:使用单引号或双引号
数字:整数,浮点数
列表:[item1, item2, ...]
元组:(item1, item2, ...)
字典:{key1:value1, key2:value2,...}
布尔型:true/false
算术运算符:+,-,*,/,//,%,**
比较符:==,!=,>,>=,<,<=
逻辑运算符:and,or,not
其他运算符:in,is,|
表达式:for,if,when
():括号中的内容为一组表达式
{{}}:两对花括号用于调用变量
template模块:
template模块用法与copy模块用法类似,但template模块传输的文件中可写入jinja语法,写入的jinja语法会被template模块识别处理。
#template模块参数
src #控制节点源文件
dest #传输至被控节点后文件存放位置
owner #指定属主
group #指定属组
mode #指定权限
backup #是否备份
template模板应用示例:
#示例一
#先创建好nginx配置文件模板,模板中使用变量替换配置文件内容;内容如下
[root@manager-18 ~]# vim nginx.conf.j2
user nginx;
worker_processes {{ ansible_processor_vcpus }}; #此处在模板文件中使用事实变量,配置文件更加灵活
error_log /var/log/nginx/error.log notice;
pid /var/run/nginx.pid;
.....
.....
#编写nginx服务部署剧本,使用模板文件
[root@manager-18 ~]# vim nginx_config.yml
---
- name: nginx_config
hosts: web
vars:
nginx_vhosts:
- listen: 80
- listen: 8080
tasks:
- name: check_nginx_repo_exists
stat:
path: /etc/yum.repos.d/nginx.repo
ignore_errors: true
register: nginx_repo_file_status
- name: yum_config
copy:
src: ./nginx.repo
dest: /etc/yum.repos.d/nginx.repo
when: nginx_repo_file_status.stat.exists == false
- name: yum_install_nginx
yum:
name: nginx
state: latest
- name: copy_nginx_config
template:
src: ./nginx.conf.j2
dest: /etc/nginx/nginx.conf
backup: yes
notify: restart_nginx
handlers:
- name: restart_nginx
service:
name: nginx
state: restarted
enabled: yes
#改:nginx配置文件模板中也可使用算数运算
[root@manager-18 ~]# vim nginx.conf.j2
user nginx;
worker_processes {{ ansible_processor_vcpus*3 }}; #此处在模板文件中使用事实变量和运算符
error_log /var/log/nginx/error.log notice;
pid /var/run/nginx.pid;
.....
.....
#示例二
#nginx配置文件模板中使用for循环
[root@manager-18 ~]# vim nginx.conf.j2
.....
.....
server {
{% for vhost_port in nginx_vhosts %}
listen {{ vhost_port.listen }};
{% endfor %}
server_name localhost;
.....
.....
#示例三
#nginx配置文件模板中使用if判断
[root@manager-18 ~]# vim nginx.conf.j2
.....
.....
server {
{% for vhost_port in nginx_vhosts %}
listen {{ vhost_port.listen }};
{% endfor %}
{% if ansible_default_ipv4.address=="10.0.0.12" %}
server_name web12.hzz.com;
{% endif %}
{% if ansible_default_ipv4.address=="10.0.0.13" %}
server_name web13.hzz.com;
{% endif %}
{% if ansible_default_ipv4.address=="10.0.0.14" %}
server_name web14.hzz.com;
{% endif %}
.....
.....
#示例四
[root@manager-18 ~]# vim nginx.conf.j2
.....
.....
server {
{% for vhost_port in nginx_vhosts %}
listen {{ vhost_port.listen }};
{% endfor %}
{% if ansible_default_ipv4.address is defined %} #判断变量是否被定义
{% if ansible_default_ipv4.address=="10.0.0.12" %}
server_name web12.hzz.com;
{% endif %}
{% if ansible_default_ipv4.address=="10.0.0.13" %}
server_name web13.hzz.com;
{% endif %}
{% if ansible_default_ipv4.address=="10.0.0.14" %}
server_name web14.hzz.com;
{% endif %}
{% endif %}
.....
.....