changed 到底表示什么
幂等工具把结果分成两类:本次执行实际改动了目标,目标本来就符合期望。后者常被误读——有人把它当失败(以为没生效),有人把它当成功(以为已经做完),两种读法都不对。正确判读是回到期望状态本身:如果目标当前状态与期望一致,报告未变更是正常结果;要确认交付是否达成,看状态校验而不是看变更标记。
基本信息
| 变更标记 | 本次执行有改动为真,已符合期望为假 |
|---|---|
| 确认手段 | 以状态校验为准,而不是变更标记 |
| 重复执行 | 第二次执行应为无变更,否则幂等性存在问题 |
| 非幂等动作 | 重启、追加写、迁移等需条件化或加保护 |
| 异常组合 | 标记有变更但状态未变,通常说明命令返回与事实不符 |
典型使用场景
- 配置管理周期巡检:报告全部无变更,说明配置未发生漂移
- 部署脚本重复执行:第二次应无变更,验证幂等性是否成立
- 故障重试:重试前先判断目标状态,避免重复追加或重复创建
- 检查模式判读:区分「符合期望」与「未执行」两种无变更来源
- 流水线重复运行:无变更时跳过发布步骤,缩短流水线时间
状态与判读结论
| 状态 | 含义 | 判读结论 |
|---|---|---|
| 有变更 | 本次执行实际改动了目标 | 确认改动内容符合变更单描述 |
| 无变更 | 目标已符合期望状态 | 正常结果,既非失败也非未执行 |
| 失败 | 执行过程出错 | 先看错误定位,不要直接重跑 |
| 跳过 | 条件未命中,未执行 | 核对条件与变量,不能按成功计 |
| 反复执行仍报变更 | 动作不易收敛,幂等性不足 | 改为状态判定式逻辑 |
| 报变更但状态未变 | 命令返回与事实不符 | 追加状态校验并修正脚本 |
把非幂等动作条件化
把非幂等动作条件化
- name: 仅在配置变化时重载服务 # 无条件重启属于非幂等动作
service:
name: nginx
state: reloaded
when: config_changed | bool # 只有真的改了配置才触发重载
- name: 校验最终状态 # 判读以状态为准,不以变更标记为准
command: nginx -t
changed_when: false # 只读校验不产生变更标记
register: verify_out
- name: 输出判读结果
debug:
msg: "配置有效={{ verify_out.rc == 0 }}"幂等的判读基准是期望状态,不是是否执行过命令。报告无变更时,要能拿出状态证据说明目标已符合期望,而不是仅凭一句「已跳过」。
重启、追加写、数据迁移、计费类动作用在重试路径上会重复生效。这类动作必须条件化或加保护,否则一次重试就可能造成重复扣费、日志重写或迁移数据重复。