1、Playbook 组成
![图片[1]-Ansible Playbook-李佳程的个人主页](http://www.lijiach.com/wp-content/uploads/2022/12/image-10.png)
- 一个 playbook(剧本)文件是一个YAML语言编写的文本文件
- 通常一个playbook只包括一个play
- 一个 play的主要包括两部分:主机和tasks。 即实现在指定一组主机上执行一个tasks定义好的任务列表。
- 一个tasks中可以有一个或多个task任务
- 每一个Task本质上就是调用ansible的一个module
- 在复杂场景中,一个playbook中也可以包括多个play,实现对多组不同的主机执行不同的任务
2、Playbook 与 Ad-Hoc 对比
- Playbook 是对多个 AD-Hoc 的一种编排组合的实现方式
- Playbook 能控制任务执行的先后顺序
- Playbook 可以持久保存到文件中从而方便多次调用运行,而Ad-Hoc只能临时运行。
- Playbook 适合复杂的重复性的任务,而Ad-Hoc适合做快速简单的一次性任务
3、Playbook 核心组件
https://docs.ansible.com/ansible/latest/reference_appendices/playbooks_keywords.
html#playbook-keywords
一个playbook 中由多个组件组成,其中所用到的常见组件类型如下:
- Hosts 执行的远程主机列表
- Tasks 任务集,由多个task的元素组成的列表实现,每个task是一个字典,一个完整的代码块功能需最少元素需包括 name 和 task,一个name只能包括一个task
- Variables 内置变量或自定义变量在playbook中调用
- Templates 模板,可替换模板文件中的变量并实现一些简单逻辑的文件
- Handlers 和 notify 结合使用,由特定条件触发的操作,满足条件方才执行,否则不执行
- tags 标签 指定某条任务执行,用于选择运行playbook中的部分代码。ansible具有幂等性,因此会自动跳过没有变化的部分,即便如此,有些代码为测试其确实没有发生变化的时间依然会非常地长。此时,如果确信其没有变化,就可以通过tags跳过此些代码片断
3.1、hosts 组件
Hosts:playbook中的每一个play的目的都是为了让特定主机以某个指定的用户身份执行任务。hosts用于指定要执行指定任务的主机,须事先定义在主机清单中
one.example.com
one.example.com:two.example.com
192.168.1.50
192.168.1.*
Websrvs:dbsrvs #或者,两个组的并集
Websrvs:&dbsrvs #与,两个组的交集
webservers:!dbsrvs #在websrvs组,但不在dbsrvs组
- hosts: websrvs:appsrvs
- hosts: all
3.2、remote_user 组件
remote_user:可用于Host和task中。也可以通过指定其通过sudo的方式在远程主机上执行任务,其可用于play全局或某任务;此外,甚至可以在sudo时使用sudo_user指定sudo时切换的用户
- hosts: websrvs
remote_user: root
tasks:
- name: test connection
ping:
remote_user: devop
sudo: yes #默认sudo为root
sudo_user: test #sudo为test
3.3、task列表和action组件
play的主体部分是task list,task list中有一个或多个task,各个task 按次序逐个在hosts中指定的所有主机上执行,即在所有主机上完成第一个task后,再开始第二个task
task的目的是使用指定的参数执行模块,而在模块参数中可以使用变量。模块执行是幂等的,这意味着多次执行是安全的,因为其结果均一致
每个task都应该有其name,用于playbook的执行结果输出,建议其内容能清晰地描述任务执行步骤。如果未提供name,则action的结果将用于输出
task两种格式
action: module arguments #示例: action: shell wall hello
module: arguments #建议使用 #示例: shell: wall hello
注意:shell和command模块后面跟命令,而非key=value
# 范例
[root@ansible ansible]# vim hello.yml
---
# 第一个yaml文件
- hosts: webservers
remote_user: root
gather_facts: no # 不收集系统信息,提高执行效率
tasks:
- name: task1
debug: msg="task1 running"
- name: task2
debug: msg="task2 running"
- hosts: appservers
remote_user: root
gather_facts: no
tasks:
- name: task3
debug: msg="task3 running"
- name: task4
debug: msg="task4 running"
# 范例
[root@ansible ansible]#vim hello1.yaml
---
- hosts: websrvs
remote_user: root
gather_facts: no
tasks:
- name: test network connection
ping:
- name: excute command
command: wall "hello world!"
# 范例
---
- hosts: websrvs
remote_user: root
gather_facts: no
tasks:
- name: install httpd
yum: name=httpd
- name: start httpd
service: name=httpd state=started enabled=yes
3.4、其它组件说明
某任务的状态在运行后为changed时,可通过”notify”通知给相应的handlers任务
还可以通过”tags”给task 打标签,可在ansible-playbook命令上使用-t指定进行调用
3.5、ShellScripts VS Playbook 案例
# SHELL脚本实现
#!/bin/bash
# 安装Apache
yum install -y httpd
# 复制配置文件
cp /tmp/httpd.conf /etc/httpd/conf/httpd.conf
cp /tmp/vhosts.conf /etc/httpd/conf.d/
# 启动Apache,并设置开机启动
systemctl enable --now httpd
#Playbook实现
---
- hosts: websrvs
remote_user: root
gather_facts: no
tasks:
- name: "安装Apache"
yum: name=httpd
- name: "复制配置文件"
copy: src=/tmp/httpd.conf dest=/etc/httpd/conf/
- name: "复制配置文件"
copy: src=/tmp/vhosts.conf dest=/etc/httpd/conf.d/
- name: "启动Apache,并设置开机启动"
service: name=httpd state=started enabled=yes
4、playbook 命令
格式
ansible-playbook <filename.yml> ... [options]
常见选项
--syntax,--syntax-check #语法检查,功能相当于bash -n
-C --check #模拟执行dry run ,只检测可能会发生的改变,但不真正执行操作
--list-hosts #列出运行任务的主机
--list-tags #列出tag
--list-tasks #列出task
--limit 主机列表 #只针对主机列表中的特定主机执行
-i INVENTORY, --inventory INVENTORY #指定主机清单文件,通常一个项对应一个主机清单文件
--start-at-task START_AT_TASK #从指定task开始执行,而非从头开始,START_AT_TASK
为任务的
name
-v -vv -vvv #显示过程
# 一个简单的playbook
[root@ansible ansible]# vim hello.yml
---
- hosts: webservers
tasks:
- name: hello
command: echo "Hello World"
[root@ansible ansible]# ansible-playbook hello.yml
PLAY [webservers] *****************************************************************************************************************
TASK [Gathering Facts] ************************************************************************************************************
ok: [192.168.1.12]
ok: [192.168.1.13]
TASK [hello] **********************************************************************************************************************
changed: [192.168.1.12]
changed: [192.168.1.13]
PLAY RECAP ************************************************************************************************************************
192.168.1.12 : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
192.168.1.13 : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
[root@ansible ansible]# ansible-playbook -v hello.yml
Using /etc/ansible/ansible.cfg as config file
PLAY [webservers] *****************************************************************************************************************
TASK [Gathering Facts] ************************************************************************************************************
ok: [192.168.1.13]
ok: [192.168.1.12]
TASK [hello] **********************************************************************************************************************
changed: [192.168.1.13] => {"changed": true, "cmd": ["echo", "Hello World"], "delta": "0:00:00.001742", "end": "2022-12-14 07:21:29.981835", "rc": 0, "start": "2022-12-14 07:21:29.980093", "stderr": "", "stderr_lines": [], "stdout": "Hello World", "stdout_lines": ["Hello World"]}
changed: [192.168.1.12] => {"changed": true, "cmd": ["echo", "Hello World"], "delta": "0:00:00.001698", "end": "2022-12-14 07:21:29.982687", "rc": 0, "start": "2022-12-14 07:21:29.980989", "stderr": "", "stderr_lines": [], "stdout": "Hello World", "stdout_lines": ["Hello World"]}
PLAY RECAP ************************************************************************************************************************
192.168.1.12 : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
192.168.1.13 : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
# 检查和限制主机
ansible-playbook file.yml --check #只检测
ansible-playbook file.yml
ansible-playbook file.yml --limit webservers
# 一个playbook 多个play
[root@ansible ansible]# vim test.yml
---
- hosts: webservers
remote_user: root
gather_facts: no
tasks:
- name: play1
command: echo "hello play1"
- hosts: appservers
remote_user: root
gather_facts: no
tasks:
- name: play2
command: echo "hello play2"
[root@ansible ansible]# ansible-playbook test.yml
PLAY [webservers] *****************************************************************************************************************
TASK [play1] **********************************************************************************************************************
changed: [192.168.1.12]
changed: [192.168.1.13]
PLAY [appservers] *****************************************************************************************************************
TASK [play2] **********************************************************************************************************************
changed: [192.168.1.11]
PLAY RECAP ************************************************************************************************************************
192.168.1.11 : ok=1 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
192.168.1.12 : ok=1 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
192.168.1.13 : ok=1 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
[root@ansible ansible]# ansible-playbook -v test.yml
Using /etc/ansible/ansible.cfg as config file
PLAY [webservers] *****************************************************************************************************************
TASK [play1] **********************************************************************************************************************
changed: [192.168.1.12] => {"ansible_facts": {"discovered_interpreter_python": "/usr/bin/python"}, "changed": true, "cmd": ["echo", "hello play1"], "delta": "0:00:00.001720", "end": "2022-12-14 07:24:56.507854", "rc": 0, "start": "2022-12-14 07:24:56.506134", "stderr": "", "stderr_lines": [], "stdout": "hello play1", "stdout_lines": ["hello play1"]}
changed: [192.168.1.13] => {"ansible_facts": {"discovered_interpreter_python": "/usr/bin/python"}, "changed": true, "cmd": ["echo", "hello play1"], "delta": "0:00:00.001556", "end": "2022-12-14 07:24:56.508019", "rc": 0, "start": "2022-12-14 07:24:56.506463", "stderr": "", "stderr_lines": [], "stdout": "hello play1", "stdout_lines": ["hello play1"]}
PLAY [appservers] *****************************************************************************************************************
TASK [play2] **********************************************************************************************************************
changed: [192.168.1.11] => {"ansible_facts": {"discovered_interpreter_python": "/usr/bin/python"}, "changed": true, "cmd": ["echo", "hello play2"], "delta": "0:00:00.001611", "end": "2022-12-14 07:24:57.018406", "rc": 0, "start": "2022-12-14 07:24:57.016795", "stderr": "", "stderr_lines": [], "stdout": "hello play2", "stdout_lines": ["hello play2"]}
PLAY RECAP ************************************************************************************************************************
192.168.1.11 : ok=1 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
192.168.1.12 : ok=1 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
192.168.1.13 : ok=1 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END