Linux

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-hocPlaybook
形态命令行一次一条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用户名
statepresent 创建(默认)/ 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路径
statetouch 文件 / 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是否启用
statepresent / 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服务名
statestarted / stopped / restarted
enabledyes 开机自启 / 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

在做什么(读剧本的方法)

  1. 组 test01 的机器装 httpd
  2. 启动并开机自启
  3. 建 /webdev,并链到网站目录
  4. 写入首页内容
  5. 修 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
YAMLkey: 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、组名以题面为准;模块用法相同。

小结

  1. Playbook = YAML:空格缩进、冒号后空格、禁止 Tab。
  2. 结构:hosts → tasks → 模块;一个文件可多个 play。
  3. 优先专用模块,理解 幂等(再跑应 ok 而非失败)。
  4. 常用模块:yum user file copy service,参数用 ansible-doc 查。

下一篇:变量、loop、when、block——让剧本按条件变着花样干活。


系列导航:总目录 · 上一篇:Ansible 快速上手 · 下一篇:变量与流程控制

相关阅读

全部文章 →
← 返回列表更多「Linux」