3_【自动化引擎Ansible Runner】深入功能模块 - 不止于 Playbook

课程三:深入功能模块 - 不止于 Playbook

欢迎来到第三课!在前两课中,我们掌握了 Ansible Runner 的核心概念和基本执行方式。你已经知道如何使用私有数据目录,以及如何用 runstart 等命令管理 Playbook 的执行。

但是,Ansible Runner 的能力远不止执行 Playbook。它还可以运行 Ad-Hoc 命令、直接调用角色、灵活管理清单,并为我们提供结构化的输出工件。本课我们将一一探索这些功能,让你能够用 Runner 完成更多类型的自动化任务。

3.1 运行 Ad-Hoc 命令

Ad-Hoc 命令是指直接使用 Ansible 模块执行临时任务,而不需要编写 Playbook。例如,你想快速检查所有主机的存活状态,或者批量重启服务。

ansible-runner 中,使用 -m 指定模块,-a 指定模块参数,--hosts 指定目标主机。

3.1.1 基本语法

css 复制代码
ansible-runner run /path/to/private_data_dir -m <模块名> -a "<模块参数>" --hosts <主机模式>
  • -m:模块名称,如 ansible.builtin.pingansible.builtin.shell
  • -a:模块参数,通常是字符串形式,例如 "uptime""echo hello"
  • --hosts:指定要执行的主机模式,可以是 allwebservers(组名)或具体主机名。

3.1.2 实操案例:执行 Ad-Hoc 命令

假设我们有一个私有数据目录 runner_adhoc,里面有一个简单的清单文件 inventory/hosts

ini 复制代码
[webservers]
web1 ansible_host=192.168.1.10
web2 ansible_host=192.168.1.11
​
[databases]
db1 ansible_host=192.168.1.20

我们想对所有 webservers 执行 uptime 命令。可以这样:

arduino 复制代码
ansible-runner run runner_adhoc -m ansible.builtin.shell -a "uptime" --hosts webservers

Runner 会在每个目标主机上执行命令,并将结果记录在 artifacts 中。你同样可以通过 stdout 或 JSON 事件查看输出。

arduino 复制代码
ansible-runner run . -m ansible.builtin.ping --hosts localhost

注意:这里私有数据目录是当前目录 .,其中可以没有清单文件 ,Runner 默认会包含 localhost

3.1.3 使用场景

  • 快速故障排查:执行 df -hfree -m 等命令。
  • 批量操作:在所有主机上安装某个包(如 yum install -y tree)。
  • 测试连通性:ping 模块。

Ad-Hoc 命令非常适合集成到自动化平台的"一键执行"功能中。

3.2 运行 Ansible 角色

如果你已经将常用的自动化任务封装成了 Ansible 角色,可以直接通过 ansible-runner 运行角色,而无需编写 Playbook 来调用它。

3.2.1 基本语法

css 复制代码
ansible-runner run /path/to/private_data_dir --role <角色名> --role-vars "<变量>"
  • --role:指定要运行的角色的名称。Runner 会在 project/roles/ 目录下查找该角色。
  • --role-vars:以 YAML/JSON 格式传递变量给角色,例如 '{"package": "httpd", "state": "present"}'

3.2.2 准备角色

我们需要在私有数据目录的 project/roles/ 下存放角色。假设我们有一个简单的角色 nginx,目录结构如下:

bash 复制代码
runner_role_demo/
├── inventory/
│   └── hosts # 配置localhost
├── project/
│   └── roles/
│       └── nginx/
│           ├── tasks/
│           │   └── main.yml
│           └── vars/
│               └── main.yml
└── env/

tasks/main.yml 内容:

yaml 复制代码
---
- name: 安装 nginx
  ansible.builtin.package:
    name: "{{ nginx_package }}"
    state: present
​
- name: 启动 nginx
  ansible.builtin.service:
    name: "{{ nginx_service }}"
    state: started
    enabled: yes

vars/main.yml 可以定义默认变量,如 nginx_package: nginxnginx_service: nginx

3.2.3 实操案例:运行角色

runner_role_demo 目录下执行:

arduino 复制代码
ansible-runner run . --role nginx --role-vars "nginx_package=nginx nginx_service=nginx" 

Runner 会使用该角色对清单中的主机执行安装和启动任务。

3.2.4 注意事项

  • 角色必须存放在 project/roles/ 下。
  • 可以通过 --role-vars 覆盖角色默认变量。
  • 如果角色需要额外的文件(如 files/templates/),也应放在角色目录下。

3.3 灵活的清单管理

Ansible Runner 支持多种方式指定清单:

  1. 通过私有数据目录中的 inventory/ 目录 :这是最常用的方式。可以在 inventory/ 下放置静态文件、动态脚本或 hosts 文件。
  2. 通过命令行参数 --inventory:可以指定额外的清单文件或目录,这些清单会与私有数据目录中的清单合并。
  3. 通过环境变量 :在 env/envvars 中设置 ANSIBLE_INVENTORY

3.3.1 实操案例:使用额外清单

假设我们有一个中央清单文件 /etc/ansible/hosts,里面定义了生产环境的所有主机。现在我们想针对其中的 test 组执行一个 Playbook,但不想复制整个清单到私有数据目录。可以使用 --inventory

css 复制代码
 ansible-runner run . --role nginx --role-vars "nginx_package=nginx nginx_service=nginx" 
 --inventory /etc/ansible/hosts --hosts test

注意:--hosts 用于限制执行范围,可以与清单配合使用。

3.3.2 清单的动态脚本

如果使用动态清单脚本(如 AWS EC2、OpenStack 等),只需将脚本放在 inventory/ 目录下并赋予执行权限,Runner 会自动调用它。

3.4 深入理解输出工件

在第二课中,我们初步接触了 artifacts 目录。现在,让我们更深入地了解它的结构,以及如何利用这些数据。

一次执行的 artifacts/<uuid>/ 目录下通常包含:

  • job_events/ :所有事件按顺序编号的 JSON 文件,例如 1-<uuid>.json2-<uuid>.json......
  • stdout:可读的文本输出。
  • status :最终状态,如 successfulfailedtimeout
  • rc:返回码(0 成功,非 0 失败)。
  • facts (可选):如果 Playbook 开启了 gather_facts,facts 会被存储在这里,可供后续执行复用。

3.4.1 事件类型

每个事件文件包含一个 JSON 对象,其中 event 字段标识事件类型,常见的有:

  • playbook_on_start:Playbook 开始。
  • playbook_on_play_start:Play 开始。
  • playbook_on_task_start:任务开始。
  • runner_on_ok:任务在某主机上成功。
  • runner_on_failed:任务在某主机上失败。
  • playbook_on_stats:执行结束时的统计信

3.4.2 实操案例:解析事件数据

假设我们执行了一个 Playbook,想要找出所有失败的任务及其错误信息。可以编写一个简单的 Python 脚本,遍历 job_events 目录下的文件,筛选 eventrunner_on_failed 的事件。

例如:

python 复制代码
import os
import json

events_dir = "artifacts/<uuid>/job_events/"
for filename in os.listdir(events_dir):
    with open(os.path.join(events_dir, filename)) as f:
        event = json.load(f)
        if event.get('event') == 'runner_on_failed':
            print(f"Task failed on {event['host']}: {event['event_data']['res']['msg']}")

这种能力使得我们可以将 Ansible Runner 与监控系统、日志分析平台无缝集成。

3.4.3 使用 -j 参数

在命令行中,可以通过 -j 让 Runner 在终端输出 JSON 格式的摘要信息,便于脚本解析。例如:

arduino 复制代码
my_third_runner# ansible-runner run . --role nginx -j | jq

输出会是一个 JSON,包含状态、事件数量等。

3.5 综合实操:构建一个多功能 Runner 调用脚本

为了巩固本课内容,我们来编写一个 Python 脚本,它能够根据用户输入,灵活地执行 Ad-Hoc 命令、Playbook 或角色,并解析输出。

脚本示例:runner_cli.py

python 复制代码
import argparse
import ansible_runner
import json

def main():
    parser = argparse.ArgumentParser(description='Ansible Runner 多功能调用')
    parser.add_argument('--private-data-dir', required=True, help='私有数据目录路径')
    parser.add_argument('--playbook', help='要执行的 Playbook 文件名')
    parser.add_argument('--module', help='要执行的模块名')
    parser.add_argument('--module-args', help='模块参数')
    parser.add_argument('--hosts', default='all', help='目标主机模式')
    parser.add_argument('--role', help='要执行的角色名')
    parser.add_argument('--role-vars', help='角色变量 JSON 字符串')

    args = parser.parse_args()

    kwargs = {
        'private_data_dir': args.private_data_dir,
        'host_pattern': args.hosts,
    }

    if args.playbook:
        kwargs['playbook'] = args.playbook
    elif args.module:
        kwargs['module'] = args.module
        kwargs['module_args'] = args.module_args
    elif args.role:
        kwargs['role'] = args.role
        if args.role_vars:
            kwargs['role_vars'] = json.loads(args.role_vars)
    else:
        print("请指定 --playbook、--module 或 --role")
        return

    r = ansible_runner.run(**kwargs)

    print(f"状态: {r.status}")
    print(f"返回码: {r.rc}")
    if r.status == 'successful':
        print("执行成功!")
    else:
        print("执行失败,请查看工件目录获取详细信息。")

if __name__ == '__main__':
    main()

注意:private-data-dir使用绝对路径

css 复制代码
python runner_cli.py --private-data-dir /usr/local/src/py_projects/automatic/ansible-runner/tip3-深入功能模块/my_third_runner --role nginx --hosts localhost

可以编写playbook,并指定playbook执行:

my_third_runner/project/ 下创建 site.yml

yaml 复制代码
---
- name: 应用 nginx 角色
  hosts: all
  roles:
    - nginx
css 复制代码
python runner_cli.py --private-data-dir my_third_runner --playbook site.yml --hosts localhost

否则,会提示:

makefile 复制代码
ERROR! the playbook: my_third_runner/project/main.json could not be found
状态: failed
返回码: 1
执行失败,请查看工件目录获取详细信息。

为什么会出现 main.json 错误?

错误信息中的 main.json 是 Runner 尝试查找默认 playbook 时产生的。当你指定 --role 但缺少必要的目录结构时,Runner 会回退到默认行为,导致路径解析错误。

这个脚本展示了如何将本课所学整合到一个工具中。

3.6 小结

本课我们学习了:

  • 如何运行 Ad-Hoc 命令,快速执行模块化任务。
  • 如何直接运行 Ansible 角色,并传递变量。
  • 多种清单指定方式,灵活适应不同环境。
  • 深入解析输出工件,为集成监控、日志分析打下基础。

现在,你已经能够用 Runner 应对更多自动化场景了。下一课我们将深入 Python API,将 Runner 嵌入到自己的应用中,实现真正的"自动化引擎"。

相关推荐
写Cpp的小黑黑2 小时前
WHEP 拉流技术详解(基于一个 html/js demo)
后端
GetcharZp2 小时前
告别 Selenium!这款 Go 语言神器,让网页自动化与爬虫快到飞起!
后端
天下无贼2 小时前
【Python】2026版——FastAPI 框架快速搭建后端服务
后端·python·aigc
橙序员小站2 小时前
当所有人都在做 Agent,我想聊聊被遗忘的基础设施
后端·开源·aigc
小蚂蚁i2 小时前
LangChain 完全学习手册:看完就能上手
后端·python·ai编程
Memory_荒年2 小时前
TiDB:当 MySQL 遇上分布式,生了个“超级混血儿”
java·数据库·后端
一步一个脚印一个坑2 小时前
用 APM 全链路追踪,29ms 内定位到 Docker 部署的 SSL 配置错误
javascript·后端·监控
aircrushin2 小时前
端到端AI决策架构如何重塑实时协作体验?
前端·javascript·后端
苦瓜小生2 小时前
【黑马点评学习笔记 | 实战篇 】| 6-Redis消息队列
redis·笔记·后端