Ansible 执行时出现 Killed 通常是操作系统触发了 OOM Killer,优先检查系统日志确认内存溢出,再通过减少并发 forks 临时缓解。
先说结论:这是典型的内存不足导致进程被系统强制终止,需立即排查主机内存水位。
- 先确认:查看 dmesg 或系统日志寻找 OOM 记录(关键词:Out of memory)
- 先处理:调整 ansible.cfg 中的 forks 参数降低并发
- 再验证:小批量运行 playbook 观察内存波动
命令速用版
以下命令可快速定位是否为内存问题:
# 查看内核日志中是否有 OOM 杀死记录(兼容多种内核版本)
dmesg -T | grep -iE "Out of memory|oom-killer"
# 查看当前内存使用情况
free -m
# 查看 Ansible 默认并发数
ansible-config dump | grep FORKS为什么会这样
Linux 内核在可用内存极低时会触发 OOM Killer 机制,强制杀死占用内存较高的进程以保护系统稳定。Ansible 默认会在控制节点启动多个 Python 子进程(由 forks 参数控制)来并行执行任务,当主机内存不足以支撑这些进程及其加载的模块时,操作系统会直接发送 SIGKILL 信号,终端便显示 Killed。
分步处理
1. 确认 OOM 记录:执行 dmesg -T | grep -iE "Out of memory|oom-killer",如果看到 ansible 或 python 相关进程被 kill,确认为内存不足。
2. 计算合适的 forks 值:根据控制节点可用内存估算。工程经验参考:每 100MB-200MB 可用内存支持 1 个 fork(视模块复杂度而定)。
# 示例:若可用内存约为 1000MB,建议设置
# forks = 5 到 10 之间
# 保守起见,建议从 5 开始测试3. 降低并发数:编辑 ansible.cfg 文件,找到 [defaults] 部分,设置 forks = 5 或更低。如果没有配置文件,可通过环境变量 export ANSIBLE_FORKS=5 临时调整。
4. 优化 Playbook:检查是否有一次性加载大量数据的任务,考虑使用 loop 分批处理,避免单次任务内存峰值过高。
5. 临时增加 Swap:如果无法立即增加物理内存,可临时创建 Swap 文件应急,但需注意这会降低执行速度。
如何根据内存大小计算 forks 值
Ansible 官方未提供严格公式,但根据工程实践,可参考以下估算逻辑:
- 基础开销:每个 fork 进程启动至少占用 50MB-100MB 内存。
- 模块开销:复杂模块(如 setup, 大量 JSON 处理)可能额外占用 100MB+。
- 估算公式:建议 Forks 数 = (可用物理内存 MB - 系统保留内存) / 200。
- 安全策略:生产环境建议预留 50% 内存给系统及其他服务,不要占满。
怎么验证是否生效
再次执行之前的 playbook,同时在一个新终端运行 watch -n 1 free -m 观察内存变化。如果任务能正常完成且 dmesg 中不再出现新的 OOM 记录,说明调整有效。
常见坑
1. 不要盲目增加 Swap:Swap 只能防止进程被杀,不能解决内存瓶颈,过高依赖 Swap 会导致 Ansible 执行极慢。
2. 注意 delegate_to:使用 delegate_to 时,任务会在指定主机运行,内存压力可能转移到被委托主机,需同时检查该主机内存。
3. 模块差异:某些 Ansible 模块(如涉及大量 JSON 处理的模块)内存占用远高于普通命令模块,排查时需考虑任务类型。
参考来源
- Ansible Official Documentation, Configuration settings, https://docs.ansible.com/
- Linux Kernel Documentation, Out of Memory Handling, https://www.kernel.org/doc/html/latest/admin-guide/mm/oom.html