编程 · 27 2 月, 2025 0

Ansible Playbook速成实战:稍微复杂一些的例子

不废话,让我们直接开始!

什么需求?

  • 操作对象是1台服务器SRV01,都有Python环境
  • 需要在每台服务器上跑一些收集服务信息的命令
  • 要把每个命令的输出分门别类保存在用户文件夹

本例中涉及到的知识点

  • group_vars的使用
  • 循环的使用
  • 字典、列表的使用

开始整活

1. 创建工作目录

带“!”的目录,目录名请与下述保持一致。Ansible会自动从中读取所需内容。

pj/ (主目录)
 |- site.yml
 |- group_vars (!)/
    |- all.yml
 |- inventory (!)/
    |- servers.ini
 |- roles (!)
    |- run_commands
       |- tasks (!)/
          |- main.yml

2. 编辑inventory

参考《简单的例子》,保留SRV01。这里不再赘述。

3. 编辑site.yml

说明见《简单的例子》,这里不再赘述。

---
- name: ANSIBLE TEST
  hosts: my_servers
  gather_facts: no
  tasks:

  roles:
    - role: run_commands

4. 编辑group_vars

将以下内容写入pj/group_vars/all.yml

cmd_list:
  uname: "uname -a"
  date: "date"

其中字典键值unamedate将作为命令的索引。

5. 编辑Role

将以下内容写入pj/roles/run_commands/tasks/main.yml

- name: 执行命令
  command: "{{ cmd_list[item] }}"
  with_items: "{{ cmd_list.keys() }}"
  register: cmd_return

- name: 保存文件
  connection: local
  # 不写connection的话文件会被存储到远程主机上
  copy:
    content: "{{ item.stdout }}"
    dest: "{{ lookup('env', 'HOME') }}/{{ item.item }}.txt"
  loop:
    "{{ cmd_return.results }}"

这里说明几件事:

  • 推荐用loop,它和with_items功能相同。而且据说后者快要被淘汰了。。
  • 你可能看不懂loop循环的语法,但你应该看得懂Python。下面的Python语句和Playbook是一个意思:
# Python
for item in ['A', 'B', 'C']:
    print(item)
# Playbook
debug:
  msg: {{ item }}
loop:
  - "A"
  - "B"
  - "C"
  • 字典索引可以用dict.key形式,也可以用Python的dict[key]形式。
  • 如果你用msg打印了命令执行结果cmd_return就会明白,cmd_return是一个类似于下面这个结构的字典。这也就是使用cmd_return.results作为循环项目的原因。
{
  "changed": true,
  "msg": "All items completed",
  "results": [{...}, {...}, ...]
  // 其中{...}保存着每个命令的执行结果以及相关信息
}

6. 执行脚本🎉

至此,实现需求所需要的条件都已具备。现在切回主目录pj/中,执行以下命令执行Ansible Playbook。

ansible-playbook -i ./inventory/servers.ini ./site.yml

你会看到在~/中创建了date.txtuname.txt两个文件,内容为dateuname -a在远程主机上的执行结果。