1. 引言

Ansible 作为主流的无代理自动化运维工具,凭借其简洁的 YAML 语法和无需安装 Agent 的特性,在服务器配置管理、应用部署、任务编排等领域得到广泛应用。然而,在实际生产环境中,运维人员时常会遭遇各种故障——从最基础的连接失败,到复杂的变量覆盖、模块执行异常等。本文基于真实运维场景,系统梳理 Ansible 常见故障的排查思路与解决步骤,并总结可落地的最佳实践,帮助运维团队提升自动化稳定性。


2. 连接失败排查

2.1 SSH 连接问题

故障场景:执行 ansible all -m ping 时,部分主机返回 UNREACHABLE,错误信息类似:

fatal: [web-01]: UNREACHABLE! => {"changed": false, "msg": "Failed to connect to the host via ssh: Permission denied (publickey,gssapi-keyex,gssapi-with-mic,password).", "unreachable": true}

排查步骤

1. **验证 SSH 基础连通性**:在控制节点手动执行 `ssh user@host`,确认是否能正常登录。若失败,检查:

– 目标主机是否开启 SSH 服务(systemctl status sshd

– 防火墙是否放行 22 端口(iptables -L -n | grep 22

– SSH 密钥是否已正确分发(ssh-copy-id

2. **检查 Ansible 配置**:查看 `/etc/ansible/ansible.cfg` 或项目级 `ansible.cfg`,确认:

host_key_checking = False(避免首次连接主机指纹确认)

private_key_file 指向正确的私钥路径

remote_user 是否具备 sudo 权限

3. **测试多因素认证**:若目标主机启用 SSH 双因子认证,需在 `ansible.cfg` 中设置 `pipelining = False`,否则可能导致连接中断。

解决示例

# 在 ansible.cfg 中增加配置
[defaults]
host_key_checking = False
private_key_file = ~/.ssh/id_rsa_ansible
remote_user = deploy

[ssh_connection]
pipelining = True   # 启用流水线加速,但需确保 sudo 不需要 tty

2.2 权限不足导致失败

故障场景:Playbook 中执行需要 root 权限的任务(如安装软件包),返回 "msg": "Missing sudo password"

排查步骤

1. 确认目标主机 `/etc/sudoers` 中是否允许 `deploy` 用户执行 sudo 且无需密码:

`

deploy ALL=(ALL) NOPASSWD: ALL

`

2. 在 Playbook 中指定 `become: yes` 和 `become_method: sudo`,并确保 `ansible_become_password` 未在 inventory 中明文暴露(建议使用 `ansible-vault` 加密)。

故障复现与修复

# 错误写法:缺少 become 参数
- name: Install nginx
  apt:
    name: nginx
    state: present

# 正确写法
- name: Install nginx with sudo
  become: yes
  apt:
    name: nginx
    state: present

2.3 Python 版本兼容性

故障场景:连接成功但执行模块时报错 "module_stdout": "/bin/sh: python: command not found"

原因:目标主机未安装 Python 或仅安装 Python 3(Ansible 2.5+ 默认依赖 Python 3,但部分旧模块仍需要 Python 2)。

排查步骤

1. 登录目标主机检查 Python 版本:`python –version` 或 `python3 –version`

2. 在 inventory 中为每台主机指定 `ansible_python_interpreter`:

`ini

[webservers]

web-01 ansible_python_interpreter=/usr/bin/python3

web-02 ansible_python_interpreter=/usr/bin/python3

`

自动化修复:使用 raw 模块先安装 Python(需依赖 shell 可用):

- name: Ensure Python is installed
  raw: test -e /usr/bin/python || (apt -y update && apt install -y python3)
  become: yes

3. 模块执行失败

3.1 模块参数错误

故障场景:使用 copy 模块时,src 路径不存在导致任务失败。

排查方法

• 开启 `-vvvv` 调试模式,查看模块实际发送的参数和返回的 JSON 数据。

• 使用 `check_mode: yes` 先做语法验证(不实际执行)。

示例

ansible-playbook deploy.yml -vvvv --check

定位到错误

fatal: [web-01]: FAILED! => {"changed": false, "msg": "Source /opt/conf/nginx.conf not found"}

解决:修正 src 路径或使用 file 模块创建缺失目录。

3.2 幂等性被破坏

故障场景:同一个 Playbook 重复执行时,每次都会触发 changed 状态,且可能导致服务重启。

根源:模块未实现幂等性。例如使用 command 模块执行 mkdir -p /data,虽然目录已存在,但任务仍报告 changed

最佳实践

• 优先使用 Ansible 原生模块(`file`、`copy`、`template`),它们天然具有幂等性。

• 若必须使用 `command`/`shell`,通过 `creates` 或 `when` 条件控制执行:

`yaml

– name: Create data directory

command: mkdir -p /data

args:

creates: /data

`


4. 超时与重试

4.1 任务执行超时

故障场景:通过 shell 模块执行耗时命令(如数据库迁移),任务默认超时时间(30秒)不足。

配置方法

• 在 Playbook 级别设置 `timeout`:

`yaml

– name: Run long migration

shell: /opt/scripts/migrate.sh

async: 600 # 最长等待 600 秒

poll: 10 # 每 10 秒轮询一次状态

`

• 全局超时可在 `ansible.cfg` 中设置:

`ini

[defaults]

timeout = 60

`

4.2 网络抖动导致重试

故障场景:批量操作时,部分主机因网络瞬时中断导致任务失败。

解决方案:启用 Ansible 内置重试机制,在 Playbook 中添加 retriesdelay

- name: Install package with retry
  apt:
    name: curl
    state: present
  register: result
  until: result is success
  retries: 3
  delay: 5

5. 变量覆盖问题

5.1 变量优先级混乱

故障场景:在 group_vars 中定义 nginx_port: 8080,但在 Playbook 中 vars 部分又定义了 nginx_port: 80,最终使用哪个值?

变量优先级(从高到低)

1. `–extra-vars` 命令行参数

2. Playbook 中 `vars`/`vars_files`

3. Inventory 中 `host_vars` > `group_vars`

4. `role` 中的 `defaults/main.yml`(最低)

调试技巧:在任务前使用 debug 模块打印变量值:

- name: Debug nginx_port
  debug:
    msg: "The port is {{ nginx_port }}"

5.2 变量引用错误

故障场景"The variable 'app_version' is undefined"

排查步骤

1. 检查变量是否在 `group_vars` 或 `host_vars` 中定义。

2. 确认角色依赖是否加载(`meta/main.yml` 中的 `dependencies`)。

3. 使用 `ansible-inventory –list` 查看解析后的变量树。


6. 调试技巧

6.1 使用 `-vvvv` 查看完整通信

ansible-playbook deploy.yml -vvvv 2>&1 | tee debug.log

输出包含:

• SSH 连接详情(是否使用密钥、认证方式)

• 模块传输的 JSON 参数

• 目标主机返回的原始输出

• 变量解析后的具体值

6.2 利用 `debug` 模块定位问题

- name: Show facts
  debug:
    var: ansible_facts['os_family']

- name: Show complex variable
  debug:
    msg: "{{ item.key }} -> {{ item.value }}"
  loop: "{{ my_dict | dict2items }}"

6.3 检查模式(Check Mode)

ansible-playbook deploy.yml --check --diff

• `–check`:模拟执行,不实际修改系统

• `–diff`:显示文件变更差异(适用于 `template`/`copy` 模块)


7. 最佳实践

7.1 确保 Playbook 的幂等性

• **原则**:无论执行多少次,结果相同且不产生副作用。

• **检查清单**:

– 避免使用 command/shell 执行非幂等操作

– 使用 state: presentstate: absent 控制资源状态

– 服务重启操作放在 handlers 中,仅当配置变更时触发

7.2 规范化的目录结构

推荐项目结构:

ansible-project/
├── ansible.cfg
├── inventory/
│   ├── production/
│   │   ├── hosts
│   │   └── group_vars/
│   └── staging/
├── roles/
│   ├── common/
│   │   ├── tasks/
│   │   ├── handlers/
│   │   ├── templates/
│   │   └── defaults/
│   └── nginx/
└── playbooks/
    ├── deploy.yml
    └── site.yml

7.3 版本控制与敏感信息管理

• **版本控制**:将所有 Playbook、Roles、Inventory 纳入 Git 管理。

• **敏感信息加密**:使用 `ansible-vault` 加密包含密码、密钥的变量文件:

`bash

ansible-vault encrypt group_vars/production/vault.yml

ansible-playbook deploy.yml –ask-vault-pass

`

• **CI/CD 集成**:在 Jenkins/GitLab CI 中预先执行 `ansible-lint` 和 `ansible-playbook –syntax-check`。

7.4 日志与监控

• 启用 Ansible 日志记录:在 `ansible.cfg` 中设置 `log_path = /var/log/ansible.log`

• 结合 ELK 或 Prometheus 分析执行失败趋势

• 对关键 Playbook 设置告警:通过 `failed_when` 和 `ignore_errors` 精细控制


8. 总结

Ansible 故障排查的核心在于:理解 SSH 连接机制、掌握变量优先级规则、善用调试工具、坚持幂等性设计。建议运维团队建立故障知识库,将每次事故的排查步骤、根因分析、解决方案记录下来,形成团队资产。同时,通过持续集成、代码审查、自动化测试等手段,从源头降低故障率。

自动化运维不是一蹴而就的,而是一个持续迭代、不断优化的过程。掌握本文的排查思路与最佳实践,将帮助你在面对 Ansible 故障时更从容、更高效。

📚 推荐阅读

💎 加入知识星球「渗透实战安全圈」

第一时间获取最新安全技术文章、工具分享和实战案例

立即加入 →

💻 安全运维 / Linux运维 / 渗透测试 技术支持
业务需求可联系博客作者

By admin

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注