3.6 幂等性:模块的承诺与例外


3.6 幂等性:模块的承诺与例外

本节摘要:幂等性是 Ansible 一切可靠性的地基,但它不是运行时的魔法,而是编写时的纪律。本节把幂等拆成三层——模块天然幂等、写法决定幂等、逃生舱口手工幂等——并用一组对照示例展示破坏幂等的典型手法与修复方式。这是 7.3 节故障实录的理论前置。

把幂等说到底

第 1 章给过定义:同一操作执行一次与多次,效果相同。现在把这句话翻译成工程语义。一个幂等剧本带来的四件具体好处:重跑安全(失败恢复简化为"修复后重跑");变更可度量(changed 计数真实反映本次运行改了什么);干跑可信(check 模式能准确预告变更);漂移可观测(同一剧本反复跑,每次都 changed 的任务就是漂移现场)。反过来说,破坏幂等的剧本一次性丢掉这四件礼物——它的运行结果永远只能靠人肉检查。

三层幂等模型

第一层,模块天然幂等。copy、template、user、service、package 这类资源模块把"检查-比对-执行"封装在内部,调用者免费获得幂等。这一层你什么都不用做,前提是确实在用它们。

第二层,写法决定幂等。同一件事用不同模块做,幂等性天差地别。经典的反面教材是配置文件管理:

# 反例:用 lineinfile 之外的方式管理整段配置 - name: 每次运行都会 changed 的写法 ansible.builtin.shell: "echo 'server_tokens off;' >> /etc/nginx/conf.d/hardening.conf" # 后果:每次运行追加一行,文件无限膨胀,永远 changed # 正解一:lineinfile 管单行(幂等:行存在且内容一致则 ok) - name: 确保安全配置行存在 ansible.builtin.lineinfile: path: /etc/nginx/conf.d/hardening.conf line: "server_tokens off;" create: true # 正解二:整文件托管用 template 或 copy(幂等:内容一致则 ok) - name: 渲染完整加固配置 ansible.builtin.template: src: hardening.conf.j2 dest: /etc/nginx/conf.d/hardening.conf mode: "0644"

第二层还有几个高频翻车点:unarchive 每次都解压覆盖(多数场景应改用包管理或先 stat 判断版本);git 模块在 detached 状态外的反复拉取属正常,但搭配 shell 调 git 就丢了 changed 判定;cron 模块幂等的前提是通过它管理任务,用 shell 往 crontab 追加则每次 changed。共同规律:凡"追加、覆盖、执行"类动作,先找有没有对应的声明式资源模块。

第三层,逃生舱口手工幂等。command 与 shell 模块默认每次执行、每次 changed,补齐手段有两个,都见过了,这里给完整形态:

# 手段一:creates 参数——产物存在即跳过 - name: 初始化数据目录(只需执行一次) ansible.builtin.command: cmd: /opt/stardust/bin/init-db.sh creates: /var/lib/stardust/.initialized # 手段二:changed_when——按输出语义判定 - name: 重载配置(仅在实际生效时算变更) ansible.builtin.command: /usr/sbin/nginx -s reload register: reload_out changed_when: reload_out.rc == 0 # 手段三:组合判断——先探测再执行 - name: 检查迁移是否已执行 ansible.builtin.stat: path: /var/lib/stardust/.migration-v42 register: mig - name: 执行数据库迁移(仅一次) ansible.builtin.command: /opt/stardust/bin/migrate.sh when: not mig.stat.exists register: mig_run - name: 落地迁移标记 ansible.builtin.file: path: /var/lib/stardust/.migration-v42 state: touch mode: "0644" when: mig_run is changed

手段三的"探测-执行-标记"三段式是把任意脚本包装成幂等任务的通用模式:stat 探测状态、command 执行、file 模块落标记。它多写几行,换来的是这个任务从此可以放心放进任何重跑场景。

幂等状态的转移视角

从状态机角度看,幂等模块的每一次运行都是一次"现状向期望的收敛":目标可能在 absent 与 present 两态之间,运行只是把现状推到期望态,已在期望态则零动作。理解这个视角后,"changed=0 的运行不是白跑,而是又一次收敛验证"就有了直观含义。

图 3-6:一次任务运行的幂等状态机

图 3-6:一次任务运行的幂等状态机

幂等自检的三个手段

手段一,连跑两遍看 RECAP:第二遍 changed 应当归零,凡是归不了零的任务逐一审问。手段二,check 加 diff 干跑:发布前 ansible-playbook --check --diff,把将要发生的变更以对比形式过目——前提是剧本没有破坏 check 兼容性的写法(依赖执行结果的条件任务在干跑下会失真)。手段三,把"幂等审问"纳入评审固定问题:这个任务重跑会怎样?changed 判定依据是什么?如果作者答不顺,任务里多半藏着雷。

幂等性的团队治理

个人写法的幂等可以靠自觉,团队规模的幂等要靠治理,三个抓手。抓手一,lint 规则卡口:逃生舱口任务缺 changed_when 或 creates 即标红——把 3.6 节的纪律变成机器检查,规则写法在 6.1 节有示例。抓手二,巡检指标:把"每周巡检运行的 changed 计数"做成趋势图,健康系统的巡检 changed 应长期为零,出现持续非零就是漂移或幂等破坏的信号——这个指标的成本几乎为零,却是幂等健康度的唯一客观读数。抓手三,事故回填:每次"反复执行导致意外变更"的故障,都必须产出一条新的 lint 规则或审问问题,让同型事故失去第二次机会。三抓手的共同思路是把幂等从"模块的能力"上升为"系统的可观测属性"——能力是模块给的,属性是治理守住的。当新成员问"为什么我们队 shell 模块管得这么严",把巡检趋势图调给他看,比任何条文都有说服力。


作者与出处
原作者: 灏天文库
来源:灏天文库
整理: 灏天文库整理
由灏天文库平台收录,内容或由平台用户上传,仅供学习交流
发布者: 作者: 灏天文库 转发
评论区 (0)
U