Ansible需根据ansible_facts.pkg_mgr动态选择yum或apt模块:pkg_mgr为yum/dnf时用yum模块并设update_cache: yes和state: latest,为apt时用apt模块配update_cache: yes与upgrade: dist,避免硬编码导致模块未找到或更新失效。

用 yum 和 apt 模块更新依赖前,先确认目标节点包管理器类型
Ansible 不会自动判断远程主机该走 yum 还是 apt —— 它只按任务里写的模块执行。混用或硬编码会导致部分节点报错 "module not found" 或 "No module named 'apt'"(尤其在 CentOS/AlmaLinux 用 apt 时)。真实场景中,常见做法是用 ansible_facts.pkg_mgr 动态选择模块:
-
pkg_mgr == "yum"→ 用yum模块(RHEL/CentOS/Alma/Rocky 8+ 默认) -
pkg_mgr == "dnf"→ 也走yum模块(Ansible 2.10+ 已统一支持 dnf 作为 yum 模块后端) -
pkg_mgr == "apt"→ 用apt模块(Debian/Ubuntu)
别依赖 os_family 判断,有些定制镜像会改 /etc/os-release 却没换包管理器。
yum 模块更新系统依赖要加 state: latest 和 update_cache: yes
很多人写 yum: name=openssl state=latest 却发现没更新到最新版,原因是本地元数据过期。RHEL 系列默认不自动刷新缓存,必须显式声明:
-
update_cache: yes相当于运行yum makecache,建议始终开启 -
state: latest才会升级(present只装不升) - 批量更新所有依赖?用
name: "*" state: latest,但生产环境慎用 —— 可能触发内核、glibc 等关键包升级,需重启或导致服务中断 - 想跳过某些包?用
exclude: kernel*,python3*(注意 shell glob 语法,不是正则)
apt 模块更新必须先 update_cache: yes,且默认不升级已安装包
apt 模块行为和 yum 不同:即使设了 state: latest,若不先刷新缓存,它只会检查已安装版本是否匹配缓存里的“当前最新”,而缓存可能几周没更新。典型错误现象是执行后返回 "changed: false",实际却没升。
- 必须配对使用:
update_cache: yes+cache_valid_time: 3600(避免每轮都重刷) -
upgrade: dist才等价于apt-get dist-upgrade(处理依赖变更),upgrade: yes仅对应apt-get upgrade(跳过需删除/重装的包) - 更新单个包如
libssl1.1,直接写name: libssl1.1 state: latest即可;不用像 yum 那样担心 epoch 冲突 —— apt 自动选最高版本
跨节点批量更新要防止单点失败中断整个 play
默认 Ansible 遇到一个节点失败就停,但系统更新常有临时性失败(如网络抖动、锁文件冲突)。用以下组合降低风险:
-
ignore_errors: yes仅适用于非关键节点,不能掩盖真实问题 - 更稳妥的是
any_errors_fatal: no(作用于 play 级)+max_fail_percentage: 20(允许最多 20% 节点失败) - 加
become: yes和become_method: sudo,确保有 root 权限;某些 Ubuntu 节点默认禁用 root ssh,必须走 sudo - 更新前建议加
command: apt-mark showhold或shell: rpm -q --qf '%{NAME} %{EPOCH}:%{VERSION}-%{RELEASE}\n' $(rpm -q --qf '%{NAME}\n' | grep -E '^(kernel|glibc)$')做快检,避开被 hold 的包
真正麻烦的不是命令怎么写,而是更新后是否要 reboot、systemd 服务是否 reload、以及旧动态库是否被新进程继续引用 —— 这些得靠后续 task 或外部监控补位,Ansible 本身不处理运行时状态迁移。

















