具有状态感知能力的 Ansible 模块比较现状与声明的目标。已经匹配时报告 ok,不匹配时可向目标收敛并报告 changed。这取决于模块及参数,不是对所有任务的统一保证。

Ansible 任务可以声明可重复收敛的目标状态

Ansible 的 playbook 按顺序编排任务。具有状态感知能力的模块可以记录机器应该拥有的状态,在部署中途失败后比较真实现状并补齐差异。收敛来自所选模块与参数,并不是执行引擎保证任何任务重跑都安全。它是一份可以执行的契约:inventory 决定对象,模块实现比对,操作者审阅即将发生的变化。 只写终点,不写每一步 命令式 shell 脚本会说“按顺序执行这些命令”;面向状态的任务则说“这个包应该已安装、这个文件应该是这些字节、这个服务应该启用并运行”。模块在动作前比较目标主机与目标状态,已经满足的任务报告 ok,只有不一致才报告 changed。同一份声明可以用于全新的机器、只配置了一半的机器,也可以用于被人手工改过的机器。 这里的目标不能只是模糊意图。state: present、模板的精确内容、所有者和权限、服务的 enabled/running 都是契约的一部分。把多台机器共用的值放到变量或 role 没问题,但最终值应该对审阅者可见。隐藏的默认值,或者绕过模块直接改变状态的命令,都会让这份契约难以推理。每一个 task 都应回答“运行完成后应该看到什么”,而不是“我习惯先敲哪一条命令”。 模块让重跑逐渐收敛 多数内置模块都围绕幂等性设计。ansible.builtin.copy 会先比较文件内容和元数据,只有不同才替换;ansible.builtin.package 向包管理器询问目标状态;ansible.builtin.service 使用 state: started 时只在运行状态不符时调整;state: restarted 则要求每次运行都重启。第二次运行应该是一份安静的确认,而不是再次重启、追加重复行或再写一条记录。幂等不是“什么都不做”,而是“已经达到目标,所以没有必要再做”。 并非所有动作天然幂等。直接用 command 创建用户、轮换密钥或调用外部 API,若没有条件限制就会重复副作用。优先找专用模块;没有时先 register 查询结果,再用 when 判断是否执行,或者使用精确的 creates/removes 文件条件。changed_when 只决定变更报告和 handler 通知,不控制任务是否执行;设成 false 不能阻止重复变更,还可能隐瞒真实副作用。对外部接口仍要定义超时、重试与部分成功后的恢复方法,不能把网络调用假装成普通文件复制。 ...

一月 17, 2027 · 2 分钟 · XB Field Notes