Ansible 的调试与优化
1. Ansible 的任务调试技巧 ------ 执行前检查
1.1 空跑(Dry Run)Playbook
bash
ansible-playbook -C filename.yml
- 作用:模拟执行 Playbook,不真正修改目标主机状态。
- 原理:Ansible 会运行所有任务,但不会对远程主机产生副作用(如写文件、安装包等)。
- 适用场景 :
- 上线前验证 Playbook 是否会触发变更;
- 检查语法或逻辑是否正确。
⚠️ 注意:某些模块(如
shell、command)无法完全模拟,仍可能执行命令。建议配合check_mode: no控制。
1.2 查看配置文件差异(--diff)
bash
ansible-playbook --diff --limit node02 filename.yml
- 参数说明 :
--diff:显示文件内容变更前后的差异(类似git diff)。--limit node02:仅在node02主机上执行。
- 适用场景 :
- 修改 Nginx、SSH、systemd 等配置文件时,确认改动是否符合预期;
- 审计配置变更内容。
✅ 仅对支持
diff的模块有效(如copy、template、lineinfile)。
1.3 使用 debug 模块输出错误信息
yaml
- name: modify01
copy:
content: "hello test\n"
dest: /opt/sdadsdad/atest.txt
register: get_file
ignore_errors: yes
- name: modify02
debug:
msg: "{{ get_file.msg }}"
- 关键点 :
register:将任务结果保存为变量(如get_file);ignore_errors: yes:即使任务失败也不中断 Playbook;debug:打印变量中的信息(如msg、changed、failed等)。
- 适用场景 :
- 调试文件写入失败原因;
- 获取命令执行的 stdout/stderr;
- 在 CI/CD 中记录中间状态。
2. Ansible 的任务调试 ------ 执行中检查
2.1 使用 assert 模块进行条件断言
yaml
- name: modify01
copy:
content: "hello test\n"
dest: /opt/aaaatest.txt
register: get_file
ignore_errors: yes
- name: exit playbook
assert:
that: get_file is changed
success_msg: "File was changed successfully!"
fail_msg: "No change detected, exiting playbook."
- name: modify02
debug:
msg: "Continuing..."
- 参数说明 :
that:条件表达式(Jinja2 语法);success_msg/fail_msg:成功/失败时的提示信息;- 若条件为假,Playbook 立即终止。
- 与
failed_when对比 :assert更语义化,适合做"前置检查";failed_when更灵活,可基于复杂逻辑判断失败。
- 适用场景 :
- 确保关键步骤已生效(如证书更新、服务重启);
- 防止后续任务在无效状态下执行。
2.2 从特定任务开始执行(--start-at-task)
bash
ansible-playbook --start-at-task "modify02" test2.yml
- 行为 :跳过
modify02之前的所有任务,从该任务开始执行后续所有任务。 - 注意 :
- 任务名必须与 Playbook 中
name:完全一致; - 若无
name,则按模块名匹配(不推荐)。
- 任务名必须与 Playbook 中
- 适用场景 :
- 调试后半段逻辑;
- 跳过耗时的初始化步骤(如 yum install)。
2.3 交互式执行(--step)
bash
ansible-playbook --step test2.yml
- 交互选项 :
yes:执行当前任务;no:跳过当前任务;continue:后续所有任务自动执行。
- 适用场景 :
- 逐步验证高风险操作(如删除文件、修改防火墙);
- 教学演示或新手调试。
3. Ansible 核心调优思想
3.1 性能监控:回调插件(Callback Plugins)
在 ansible.cfg 中启用:
ini
[defaults]
callback_whitelist = timer, profile_tasks, cgroup_perf_recap
[callback_cgroup_perf_recap]
control_group = ansible_profile
- 插件功能 :
timer:显示整个 Playbook 耗时;profile_tasks:显示每个任务的执行时间;cgroup_perf_recap:通过 cgroup 监控 CPU、内存、PID。
启用 cgroup 监控(需 Linux 支持)
bash
# 安装工具
yum install libcgroup-tools -y
# 创建 cgroup
cgcreate -a group:user -t group:user -g cpuacct,memory,pids:ansible_profile
# 使用 cgroup 执行 Playbook
cgexec -g cpuacct,memory,pids:ansible_profile ansible-playbook test.yml
- 适用场景 :
- 分析资源瓶颈;
- 评估大规模部署对控制节点的压力。
4. 任务优化技巧
4.1 避免无效循环,使用模块原生多参数支持
❌ 不推荐:
yaml
- name: Install packages (bad)
yum:
name: "{{ item }}"
state: present
loop:
- nginx
- redis
- git
✅ 推荐:
yaml
- name: Install packages (good)
yum:
name:
- nginx
- redis
- git
state: present
- 优势:减少 SSH 连接次数,提升效率。
4.2 减少 lineinfile,改用 Jinja2 模板
lineinfile:逐行匹配修改,性能差,易出错;template:一次性生成完整配置文件,更高效可靠。
yaml
- name: Deploy config via template
template:
src: app.conf.j2
dest: /etc/app.conf
- 适用场景:Nginx、Postfix、Prometheus 等复杂配置。
4.3 文件传输优先使用 synchronize(基于 rsync)
yaml
- name: Sync large directory
synchronize:
src: /local/data/
dest: /remote/data/
delegate_to: localhost
- 优势:增量同步、压缩传输、断点续传;
- 对比
copy:copy适合小文件,synchronize适合大目录或频繁更新。
5. SSH 多路复用(Multiplexing)
在 ansible.cfg 中配置:
ini
[ssh_connection]
ssh_args = -C -o ControlMaster=auto -o ControlPersist=60s
- 作用 :
- 复用 SSH 连接,避免每次任务都重新认证;
ControlPersist=60s:连接空闲 60 秒后关闭。
- 效果:显著减少高并发下的 SSH 握手开销。
- 适用场景:多任务、多主机、频繁操作同一组服务器。
6. 启用流水线执行(Pipelining)
在 ansible.cfg 中启用:
ini
[defaults]
pipelining = True
- 原理 :将 Python 脚本通过 SSH stdin 直接传入执行,省去临时文件拷贝。
- 前提 :
-
被控端
/etc/sudoers中禁用requiretty:bashDefaults:your_user !requiretty -
(RHEL8+ 默认已禁用)
-
- 优势:减少磁盘 I/O 和网络往返,提升速度 10%~30%。
7. 提高并发数(forks)
在 ansible.cfg 中设置:
ini
[defaults]
forks = 20 # 默认为 5
- 说明:同时操作的主机数量;
- 建议 :
- 控制节点 CPU/内存充足时可提高;
- 过高可能导致 SSH 拒绝连接或被控端负载过高。
- 动态调整 :可通过
-f 10命令行覆盖。
8. 异步任务(Async & Poll)
yaml
- name: Long-running task
shell: |
for i in {1..20}; do
sleep 3
ls -l /opt/ab.txt && break
done
async: 100 # 最大运行时间(秒)
poll: 5 # 每 5 秒检查一次状态
- 参数说明 :
async:任务最大允许运行时间;poll:>0:定期轮询状态;0:立即返回,任务在后台运行(fire-and-forget)。
- 适用场景(✅ 推荐) :
- 长时间运行任务(如数据迁移、编译);
- 大规模主机并行执行;
- 不关心即时结果的任务。
- 不适用场景(❌ 避免) :
- 后续任务依赖此任务结果;
- 任务本身很快(<1s)。
总结:最佳实践速查表
| 场景 | 推荐做法 |
|---|---|
| 上线前验证 | ansible-playbook -C --diff |
| 调试失败原因 | register + debug |
| 关键步骤校验 | assert |
| 跳过前面任务 | --start-at-task |
| 逐步执行 | --step |
| 提升传输效率 | 用 template 代替 lineinfile,用 synchronize 代替 copy |
| 减少 SSH 开销 | 启用 ControlPersist + pipelining |
| 大规模部署 | 提高 forks + 使用 async |
| 性能分析 | 启用 profile_tasks + cgroup_perf_recap |