Ansible 的 block-rescue-always 是面向部署意图的异常响应设计,block 封装强耦合操作链并统一控制条件,rescue 在 block 失败时执行预定义补救动作,always 无论成败均执行闭环收尾。

Ansible 的 block 与 rescue 不是“重试机制”,而是面向部署意图的异常响应设计——它不保证操作绝对不失败,但确保每次失败都有明确的补偿路径和可观测出口。
用 block 封装强耦合操作链
把必须成套执行、彼此依赖的任务放进一个 block。比如“停服务→改配置→启服务”三步,缺一不可;若只停不启,系统就处于不可用状态。
- 所有任务统一受一个
when控制,避免每个任务单独写条件导致逻辑分散 - block 内任意任务返回
failed(非skipped或ok),立即中断后续任务,不继续“带病推进” - 适合场景:LVM 卷创建、数据库迁移前置检查、中间件配置热更等有明确成功边界的操作
用 rescue 做确定性补救动作
rescue 不是兜底重试,而是执行你预先定义好的“失败后该做什么”。它的触发条件唯一且清晰:仅当 block 中出现 failed 时运行。
- 典型做法包括:恢复备份配置、清理已写入的临时文件、关闭半开连接、记录错误上下文到日志、发送告警通知
- 可配合
fail模块主动制造失败,例如校验目标路径不存在时提前中止,让流程快速落入 rescue 处理分支 - 注意:rescue 里的任务本身失败不会再次触发 rescue,也不会阻断 always 执行
结合 always 实现闭环收尾
always 是真正意义上的“无论如何都走一遍”的收口环节,无论 block 成功、失败或被跳过,它都会执行。
- 常见用途:归档本次部署日志、更新部署状态标记文件(如写入
/var/run/deploy.status=failed)、重启监控探针、释放锁文件 - 如果 always 中某任务失败,Ansible 默认只报 warning,不影响整体流程;如需严格保障,可在任务中加
ignore_errors: yes - 它和 rescue 的分工很明确:rescue 处理“出错了怎么办”,always 处理“做完之后必须收什么尾”
一个贴近生产的配置回滚示例
以 Nginx 配置更新为例,block 负责变更,rescue 负责回滚,always 确保日志落盘:
- block 中先备份原配置,再写入新模板,最后 reload 服务
- 若 reload 失败(比如语法错误),rescue 立即 copy 回备份配置,并 restart 服务恢复可用性
- always 中追加一条时间戳日志到统一日志文件,供审计与排障使用
这种结构让剧本具备了类事务语义:步骤可分组、失败有对策、收尾必执行。不复杂但容易忽略。

















