Playbook 与模块
RHEL 9 用 YAML 写 Ansible Playbook,并掌握 user、file、yum、service、copy 等常用模块与幂等性。
本页目录
上一篇用 ad-hoc 一次敲一条命令。考试里更多是写 Playbook(剧本):把多步操作写进 .yml,一次跑完、可重复执行。本篇先会 YAML 语法,再逐个拆常用模块,最后串成一个完整剧本。
系列:从 RHCSA 到 RHCE · 第 15 / 17 篇 上一篇:Ansible 快速上手 下一篇:变量与流程控制 总目录:系列索引
环境说明
- 系统:RHEL 9
- 节点:control + node1…(见 Ansible 快速上手)
- 工作目录:
/home/alice/ansible(cfg 与 inventory 已配好,ansible all -m ping已通) - 身份:普通用户 + sudo 提权(cfg 里
become=True)
1. ad-hoc 和 Playbook 有什么不同
| ad-hoc | Playbook | |
|---|---|---|
| 形态 | 命令行一次一条 | YAML 文件,多条任务 |
| 重复使用 | 差,靠历史命令 | 好,文件可版本管理 |
| 条件/循环/角色 | 弱 | 强(后面几篇) |
| 考试 | 偶尔 | 主力 |
ad-hoc:
ansible node1 -m user -a "name=tom"
Playbook:写文件 → ansible-playbook 文件.yml。
2. YAML 最小语法(先背这几条)
Playbook 用 YAML 写。新手只需要记牢:
| 规则 | 说明 |
|---|---|
| key: value | 冒号后必须有空格 |
| - 列表项 | 短横线后也要空格 |
| 缩进 | 用空格(推荐 2 个),禁止 Tab |
| 同级对齐 | 同一层级缩进必须一致 |
| --- | 文件开头可写,表示 YAML(非强制) |
| 扩展名 | 常用 .yml / .yaml |
最小例子
---
age: 18
name: tom
列表:
---
fruits:
- apple
- banana
易错:
name:tom(冒号后没空格)会解析失败。 易错:用 Tab 缩进。在 VIM 里可:set expandtab用空格。
用「剧本」类比(帮助理解结构)
把 Playbook 想成舞台剧:
一个剧本文件
└── 可以有多场戏(多个 play)
└── 每场戏:在哪些演员(hosts)身上
└── 按顺序做哪些动作(tasks → 模块)
3. 第一个 Playbook
cd /home/alice/ansible
vim yum.yml
---
- hosts: all
tasks:
- yum:
name: wget
state: present
- name: 安装 unzip
yum:
name: unzip
state: present
逐行读:
| 部分 | 含义 |
|---|---|
| - hosts: all | 一场 play:对清单里所有主机 |
| tasks: | 下面是任务列表 |
| - yum: | 一个任务:使用 yum 模块 |
| name: wget | 装什么包 |
| state: present | 确保「已安装」(不是删除) |
| name: 安装 unzip | 可选:给任务起个显示名(推荐写) |
执行:
ansible-playbook yum.yml
会看到:
PLAY [all] *****
TASK [Gathering Facts] *****
TASK [yum] *****
changed: [node1]
...
PLAY RECAP *****
说明:默认会先跑
Gathering Facts(采集节点信息),下一讲变量篇会用到。
4. 多场 play:一个文件管不同主机组
vim yum2.yml
---
- hosts: node1
tasks:
- yum:
name: tuned
state: present
- hosts: node2,node3
tasks:
- yum:
name: tmux
state: present
| 写法 | 含义 |
|---|---|
| hosts: node1 | 只对 node1 |
| hosts: node2,node3 | 逗号分隔多台 |
| hosts: web | 对 inventory 里的组 |
ansible-playbook yum2.yml
5. 幂等性(Ansible 的灵魂)
幂等:跑一次和跑多次,目标状态一样;已经满足条件时不再改系统。
ansible node1 -m user -a "name=user10"
ansible node1 -m user -a "name=user10"
| 输出 | 含义 |
|---|---|
| CHANGED | 这次真的改了系统 |
| SUCCESS 且再跑一次仍是 SUCCESS、changed=false | 已经是目标状态,什么都没做 |
Playbook 里同理:第二次跑,多数任务应变成 ok 而不是 changed。
没有幂等的例子:shell 模块
ansible node1 -m shell -a "useradd user11"
ansible node1 -m shell -a "useradd user11"
第二次可能:
FAILED! => ... useradd: user 'user11' already exists
考点:能用专用模块(
user、yum)就别用shell乱敲命令;专用模块自带幂等。
6. 常用模块卡片
下面每个模块都按「用途 → 关键参数 → 例子」写。参数没有先后顺序要求。
user:用户
| 参数 | 含义 |
|---|---|
| name | 用户名 |
| state | present 创建(默认)/ absent 删除 |
| password | 密码(须哈希,见下) |
| group | 基本组 |
| groups | 附加组 |
- user:
name: tom
state: present
- user:
name: tom
state: absent
密码不要写明文进 shadow 逻辑,用过滤器哈希:
- user:
name: user2
password: "{{ '123456' | password_hash('sha512') }}"
易错:
password: '123456'未哈希,节点上 shadow 里是明文,且有 WARNING。
file:文件与目录
| 参数 | 含义 |
|---|---|
| path | 路径 |
| state | touch 文件 / directory 目录 / link 链接 / absent 删除 |
| src | 链接的源 |
| dest | 链接的目标(state=link 时) |
| owner / group | 属主 / 属组 |
| mode | 权限 |
- file:
path: /opt/a.txt
state: touch
- file:
path: /opt/qq
state: directory
- file:
src: /opt/a.txt
dest: /opt/link.txt
state: link
yum / dnf:装包
- yum:
name: httpd
state: present
RHEL 9 上 yum 模块名仍常用;也可用 dnf 模块,语义类似。
yum_repository:写软件源
| 参数 | 含义 |
|---|---|
| name | 仓库 ID |
| description | 描述 |
| baseurl | 源地址 |
| gpgcheck / gpgkey | 校验 |
| enabled | 是否启用 |
| state | present / absent |
- yum_repository:
name: base
description: BaseOS
baseurl: http://192.168.56.1/rhel9/BaseOS
gpgcheck: yes
gpgkey: http://192.168.56.1/rhel9/RPM-GPG-KEY-redhat-release
enabled: yes
state: present
service:管服务
| 参数 | 含义 |
|---|---|
| name | 服务名 |
| state | started / stopped / restarted |
| enabled | yes 开机自启 / no 取消 |
- service:
name: crond
state: stopped
enabled: no
copy:拷文件
| 参数 | 含义 |
|---|---|
| src | 控制端源文件 |
| dest | 节点目标路径 |
| content | 直接写内容(不用 src) |
- copy:
src: /home/alice/ansible/rhce.txt
dest: /opt/rhce.cfg
- copy:
content: "RHCSA"
dest: /opt/rhcsa.txt
get_url:下载
- get_url:
url: http://192.168.56.1/materials/hardware.empty
dest: /root/hardware.txt
replace:替换文件内容
- replace:
path: /etc/issue.net
regexp: "Kernel"
replace: "Ansible"
cron:计划任务
- name: 示例计划任务(分 时 日 月 周)
cron:
name: "myjob"
minute: "13"
hour: "12"
user: alice
job: "ls -alh > /dev/null"
debug / fail:显示与制造错误
- debug:
msg: "hello from playbook"
- fail:
msg: "error1"
fail 会让 play 停止——考试里有时用来演示「遇到错误即停」。
firewalld:防火墙
- firewalld:
service: http
state: enabled
permanent: true
immediate: true
| 参数 | 含义 |
|---|---|
| service / port | 按服务名或端口 |
| permanent: true | 写入永久配置 |
| immediate: true | 立刻生效 |
shell:万能但慎用
- shell: chcon -R -t httpd_sys_content_t /webdev/
注意:
shell/command默认没有幂等,重复执行可能失败。能用专用模块就不要用 shell。
7. 综合示例:装 httpd 并发布页面
vim web.yml
---
- hosts: test01
tasks:
- yum:
name: httpd
state: present
- service:
name: httpd
state: started
enabled: yes
- file:
path: /webdev
state: directory
- file:
src: /webdev
dest: /var/www/html/webdev
state: link
- copy:
content: "hello world!"
dest: /webdev/index.html
- shell: chcon -R -t httpd_sys_content_t /webdev/
ansible-playbook web.yml
curl http://node1/webdev/index.html
在做什么(读剧本的方法)
- 组
test01的机器装 httpd - 启动并开机自启
- 建
/webdev,并链到网站目录 - 写入首页内容
- 修 SELinux 标签(见 httpd 与 SELinux)
考点:综合题常见「包 + 服务 + 目录/链接 + 内容 + 防火墙/SELinux」一条龙。
8. 怎么查模块参数
ansible-doc yum
ansible-doc -l | wc -l
ansible-doc cron
在帮助里:
- 空格翻页,
q退出 - 输入
/EXAMPLES搜索官方示例(很有用)
9. 推荐练习(约 40 分钟)
cd /home/alice/ansible
# 1) 最小装包剧本
vim yum.yml
# 内容见本文第 3 节
ansible-playbook yum.yml
# 2) 再跑一遍,观察 changed 变少(幂等)
ansible-playbook yum.yml
# 3) user 模块 + 哈希密码
vim user.yml
---
- hosts: node1
tasks:
- user:
name: myuser
password: "{{ '123456' | password_hash('sha512') }}"
state: present
ansible-playbook user.yml
# 在 node1 上:grep myuser /etc/shadow
# 4) copy + file
vim files.yml
---
- hosts: node1
tasks:
- file:
path: /opt/lab15
state: directory
- copy:
content: "from playbook\n"
dest: /opt/lab15/note.txt
ansible-playbook files.yml
# node1: cat /opt/lab15/note.txt
期望
- 第一次
yum.yml多为changed - 第二次多数
ok - shadow 中密码为
$6$...而非明文 note.txt内容正确
10. 速查表
| 目标 | 写法 |
|---|---|
| 执行剧本 | ansible-playbook xx.yml |
| YAML | key: value;列表 - ;空格缩进 |
| play 结构 | - hosts: + tasks: |
| 装包 | yum: name= state=present |
| 用户 | user: name= password={{ pass | password_hash('sha512') }} |
| 文件/目录 | file: path= state=touch/directory/link |
| 拷贝 | copy: src/content dest= |
| 服务 | service: name= state= enabled= |
| 查模块 | ansible-doc 模块名 |
考点与易错
考点:按题面写出可执行 playbook;模块参数写对;第二次执行幂等。 易错:YAML 用 Tab、冒号后没空格、缩进不对齐。 易错:密码未
password_hash。 易错:用shell堆命令代替user/yum/service,丢掉幂等。 易错:copy的src是控制端路径,dest是节点路径。 易错:file的state=link时src/dest写反。 练习环境:仓库地址、用户alice、组名以题面为准;模块用法相同。
小结
- Playbook = YAML:空格缩进、冒号后空格、禁止 Tab。
- 结构:
hosts→tasks→ 模块;一个文件可多个 play。 - 优先专用模块,理解 幂等(再跑应
ok而非失败)。 - 常用模块:
yumuserfilecopyservice,参数用ansible-doc查。
下一篇:变量、loop、when、block——让剧本按条件变着花样干活。
系列导航:总目录 · 上一篇:Ansible 快速上手 · 下一篇:变量与流程控制