Ansible剧本编写
# Ansible剧本
# 介绍
- Ansible剧本用于将多个Ansible命令整合成一个剧本文件,来实现类似于脚本式的批量操作。
- Ansible剧本的文件格式是yaml格式,所以Ansible剧本的编写规范需要符合yaml格式。
# 剧本文件规范
合理的信息缩进
- 不能使用真正的tab制表缩进,一般用2个空格缩进即可。
冒号的使用
- 每个冒号后面一定要有一个空格,以冒号结尾不需要空格。
- 例如:
hosts: [信息]
、hosts:
短横线的使用
使用短横线实际上就表示要书写列表中的一个元素。
# YAML格式: - 大项: 小项: - 小小项1 - 小小项2 # 对应到JSON格式实际就是: [ { "大项": { "小项": [ "小小项1", "小小项2" ], } }, ]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
剧本文件使用扩展名.yaml
- 方便识别文件是一个剧本文件。
创建存放剧本的目录
mkdir ./ansible-playbook
,方便进行管理。
分角色创建剧本文件
- 比如服务端就创建一个服务端的剧本文件,客户端就创建一个客户端的剧本文件。
- 另外如果服务端和客户端存在比较多相同的步骤,还可以重新定义在一个通用任务中。
# 剧本文件格式
- hosts: [主机],[主机]...
tasks:
-name: 任务注释名(显示于执行剧本时)
[模块名]: [模块执行的参数]
-name: 任务注释名
[模块名]: [模块执行的参数]
... ...
2
3
4
5
6
7
# 剧本文件语法检查
ansible-playbook --syntax-check [脚本文件路径]
- 会对剧本文件使用语法检测,然后我们可以利用注释找到出错的任务进行排错。
# 模拟执行剧本
ansible-playbook -C [脚本文件路径]
- 用于模拟检测模块参数等是否配置正确,不会真正的进行执行。
- ansible执行剧本时,如果前面的任务执行出错,后面将不会执行。
# 执行剧本文件
ansible-playbook [参数] [脚本文件路径]
# 参数
-v
- 显示详细信息,最多4个v,比如-vvvv。
# 剧本编写流程
# 创建存放文件的目录
- 在剧本文件的目录下以服务名命名创建一个目录,并在其中创建server和client目录用于存放文件。
# 编写主机清单文件
# 编写剧本文件
- 规划服务端、客户端要执行的操作
- 思考要使用变量的地方
- 将共同要执行的任务写在一个角色任务列表中
- 编写服务端、客户端各自任务
- 查看是否有使用扩展功能完善的余地
# 测试执行剧本
- 检查语法 -
ansible-playbook --syntax-check [脚本]
- 测试剧本,不实际执行 -
ansible-playbook -C [脚本]
- 测试彩排可能有一些可以理解的错误可以忽视。
- 执行剧本 -
ansible-playbook [脚本]
- 检查语法 -
# 多个剧本进行整合
与其他剧本同目录下,创建一个新的剧本文件,整合剧本文件格式如下
- import_playbook: [剧本文件名] - import_playbook: [剧本文件名] ... ...
1
2
3然后直接执行整合剧本文件即可
# 实际例子
比如要批量部署Rsync,对应的Ansible命令有以下:
## 服务端 # 批量安装软件 ansible [Rsync服务端主机] -m yum -a "name=rsync state=installed" # 批量分发配置文件,先在本地管理端上编写好配置文件再进行分发 ansibe -m copy -a "src=/root/rsyncd.conf dest=/etc/ backup=yes" # 创建虚拟用户 ansible -m user -a "name=rsync create_home=no shell=/sbin/nologin" # 创建密码文件 ansible -m copy -a "content=rsync_backup:qwe123123 dest=/etc/rsync.passwd mode=600" # 创建备份目录 ansible -m file -a "dest=/backup state=directory owner=rsync group=rsync" # 启动rsync服务 ansible -m service -a "name=rsyncd state=started enabled=yes" ## 客户端 # 批量分发密码文件 ansible [Rsync客户端主机] -m copy -a "content=qwe123123 dest=/etc/rsync.passwd mode=600"
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22将其转化为剧本就是:
# Rsync服务端文件: rsync_server.yaml - hosts: rsync_server tasks: - name: install rsync yum: name=rsync state=installed - name: distribute rsyncd.conf copy: src=/root/rsyncd.conf dest=/etc/ backup=yes - name: create rsync user user: name=rsync create_home=no shell=/sbin/nologin - name: make password file copy: content=rsync_backup:qwe123123 dest=/etc/rsync.passwd mode=600 - name: mkdir backup dir file: dest=/backup state=directory owner=rsync group=rsync - name: start rsync service service: name=rsyncd state=started enabled=yes # Rsync服务端文件: rsync_client.yaml - hosts: rsync_client tasks: - name: make password file copy: content=qwe123123 dest=/etc/rsync.passwd mode=600
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# 剧本错误排错
- 找到剧本中出现问题的关键点(任务)。
- 将出错的任务转换成命令行进行测试。
- 将ansible命令转换成Linux命令进行测试
# 剧本扩展配置功能
# 变量的配置
我们可以在剧本文件中的各模块中调用变量,另外Ansible提供多种配置变量方式,变量使用的优先级:命令行 > 剧本文件 > 主机清单。
# 剧本文件中调用变量
-name: test yum: name={{ 变量名 }} state=installed
1
2# 命令行中设置变量
ansible-playbook -e [变量名]=[变量值] [剧本路径]
- 一个-e参数,只能对应一个变量,但我们可多次使用-e。
# 剧本文件中设置变量
设置的变量只对当前角色任务有效,另外的角色任务需要另外配置。
- hosts: [主机] vars: [变量名]: [变量值] [变量名]: [变量值] ... ... tasks: ... ...
1
2
3
4
5
6
7
# 主机清单中设置变量
设置的变量会应用到对应组的主机,设置的变量只对变量的指定组有效。
[组名:vars] 如: ansible_port=... 其他变量...
1
2
3
# 在剧本中注册变量
在Ansible剧本中我们还可以将命令执行的输出信息,注册给指定变量。register会将命令输出的结果,传递给指定变量。
- hosts: [主机] tasks: - name: test shell: netstat -lntup 873 #将执行shell输出的信息作为值给get_port变量 register: get_port - name: print info #将变量值打印输出 debug: msg={{ get_port }}
1
2
3
4
5
6
7
8
9
10
# 剧本中设置条件判断
- 判断格式:
when: (判断条件)
- Ansible剧本中,我们可以在任务中设置判断条件,当判断条件满足时才会执行该任务。
- 但需要注意的是判断条件只能指定setup模块中有的信息。
- 例如:
when:(ansible_hostname == "web01")
,判断主机名是否是"web01"。
# 剧本中设置循环
在剧本中我们还能将模块相同且参数差不多的任务进行循环。
# saltstack方式(推荐)
- name: circulate test yum: name: ['rsync', 'tree', 'wget'] state: present
1
2
3
4# 字典方式
- name: circulate test fetch: src={{ item.变量名1 }} {{ item.变量名2 }} with_items: - { 变量名1: '/etc/hosts', 变量名2: '/tmp' } - { 变量名1: '/etc/hostname', 变量名2: '/tmp' }
1
2
3
4
5# 列表方式
- name: circulate test fetch: src={{ item }} state=restarted with_items: - [变量1] - [变量2]
1
2
3
4
5
# 剧本中忽略某任务错误
任务出错时忽略该错误,报错但剧本继续执行。可以在测试的时候暂时忽略,看看后面的有没有其他错误。
- name: xxxx xxxx: xxxx ignore_errors: yes
1
2
3
# 在剧本中设置标签信息
我们可以个剧本中的任务进行打标,打标后我们就可以只执行或跳过某些指定动作。一般用于测试修改后的任务是否还会报错。
配置方法
- name: ignore error copy: src=error dest=error tags: [标签名]
1
2
3仅执行指定标签的任务执行
ansible-playbook --tags=[标签名] [剧本路径]
跳过指定标签的任务
ansible-playbook --skip-tags=[标签名] [剧本路径]
# 在剧本中设置触发信息
他是一种
如果修改成功... 则...
的功能,可以实现如果执行任务changed成功(黄色)则触发执行对应任务。配置方法
tasks: - name: execute notify task if changed successfully [模块]: [参数] notify: [通知的任务名] # 触发的任务 handlers: - name: [等待通知的任务名] # 等待触发的任务 [模块]: [参数]
1
2
3
4
5
6
7
8
# Ansible剧本优化
- Ansible作为一个管理工具,能够优化的余地实际很少,但还是有一些。
# 关闭主机信息搜集
不用时建议关闭,可加快剧本执行速度。
- hosts: [主机] gather_facts: no
1
2
# 剧本Roles编写方法
- 剧本角色是用于标准化完善剧本的过程。
# 目录结构规范
剧本角色的目录结构都是固定的,用于将剧本拆分提高阅读性。
# 目录结构
tasks
- 保存要执行的动作文件vars
- 保存变量信息的文件handlers
- 保存触发器的配置文件templates
- 保存需要分发的模板文件files
- 保存需要分发的文件
# 创建角色目录
- 例如需要创建NFS服务的角色目录。
mkdir /etc/ansible/roles/nfs
- 角色目录下建立一个NFS目录便于管理cd /etc/ansible/roles/nfs
- 切换到Roles目录下NFS目录mkdir {nfs-server,nfs-client}
- 创建相应的角色目录,一个主机角色对应一个目录mkdir {nfs-server,nfs-client}/{vars,tasks,templates,handlers,files}
- 在相应的角色目录下创建子目录
# 编写相关文件
# 编写主剧本文件
vim ./roles/[角色父目录]/[主剧本名].yml
- 在roles目录中,创建调用roles相关文件的主剧本。名字可以任意,但最好使用相应角色名例如,例如:
nfs.yml
,执行剧本命令时,指定该文件即可。主剧本文件格式如下:
- hosts: [主机],[主机],... roles: - [调用的roles角色名] - hosts: [主机] roles: - [调用的roles角色名] ......
1
2
3
4
5
6
7
8
# tasks
vim ./tasks/main.yml
- 在tasks目录中创建main.yml文件。并将任务信息编写至该文件,不用写tasks字段,直接写任务信息即可。
- name: xxx [modename]: [parameter] - name: xxx [modename]: [parameter] ... ...
1
2
3
4
5还可以将任务再拆分
vim ./tasks/[任务名].yml
,这时main.yml文件可用于整合调用。- include_tasks: [任务名].yml ... ...
1
2
# vars
vim ./vars/main.yml
- 在vars目录中创建main.yml文件。并将变量信息编写至该文件,可以全局应用到所有角色任务列表中。
[变量名]: [值] Data_dir: /data ... ...
1
2
3
# handlers
vim ./handlers/main.yml
- 在handlers目录中创建main.yml文件。并将handlers信息编写至该文件,不用写handlers字段,直接写等待通知触发的任务即可。
- name: xxx [modename]: [parameter] ......
1
2
3
# templates
./templates
目录用来存放通过templates模块传输的文件。- 模板目录下的文件,其内容可以调用变量,比如:
port =
。 - tasks调用时要使用template模块,使用copy模块不会替换变量且需要指定路径。
- 例如:
template: src=test.txt dest=/root/
# files
- 将需分发的文件,存放到file目录中,然后tasks文件中直接写文件名称即可,不用写文件路径,Ansible会自动的去file目录中寻找文件。
- 例如:比如
copy: src=test.txt dest=/root/