保护开关是一个能立刻生效的闸门
保护开关的设计目标很单一:在出问题或缺人手的时候,能用最短路径让某类操作停下来。它和审批流程是互补关系——审批负责事前把关,开关负责事中止损。一个可用的开关必须满足几个条件:生效路径短、作用范围清晰、默认处于安全态、开关状态人人可见、并且有人知道怎么用。开关做得好,事故的持续时间可以缩短一个量级;做得差,则会在最需要它的时候发现它并没有生效。
基本信息
| 适用对象 | 批量执行入口、发布流水线、自动扩缩容与自动修复任务 |
|---|---|
| 典型开关 | 变更冻结、批量执行开关、提权开关、发布开关 |
| 生效要求 | 路径短、无需等待长流程、状态全局可见 |
| 默认状态 | 安全态优先,即默认受阻、显式放行 |
| 配套要求 | 开关本身的使用需记录与定期演练 |
设计要点
- 单一职责:一个开关对应一类动作面,避免一个大开关牵动全部流程
- 默认安全:缺省情况下批量与破坏性动作不执行,需要显式开启
- 快速生效:开启后应立即影响下一次执行,而不是等配置同步或重建
- 状态可见:谁在什么时候因为什么原因打开,需可查询且显示在执行入口
- 自动恢复:临时开关应带过期时间,避免忘记关闭导致长期停摆
- 定期演练:开关本身也要验证可用,否则关键时刻才发现失效
开关实现思路
开关实现思路
freeze_file=/etc/ops/change-freeze # 开关存放位置固定且权限受限
if [ -f "$freeze_file" ]; then
echo "变更冻结中:$(grep -v '^#' $freeze_file | head -1)" >&2 # 说明原因
exit 2
fi
touch "$freeze_file" && date -u >> "$freeze_file" # 开启冻结并记录时间
logger -t ops-freeze -p local0.warn "change freeze enabled by $USER" # 留审计
rm -f "$freeze_file" # 解除冻结
journalctl -t ops-freeze --since '1 day ago' | tail # 事后复查开关使用记录开关类型与关注点
| 开关 | 作用 | 滥用风险 |
|---|---|---|
| 变更冻结 | 禁止一切变更与发布 | 长期不解除导致积压与绕过 |
| 批量执行开关 | 阻止覆盖多主机的操作 | 被临时打开后忘记收回 |
| 提权开关 | 限制特权动作 | 临时开启期间缺少监控 |
| 发布开关 | 停止发布与回滚能力 | 与回滚需求冲突时被人为绕过 |
| 自动伸缩开关 | 稳定容量避免抖动 | 长期关闭削弱弹性能力 |
开关要能应付「找不到人」的场景:深夜出问题时,值班人员需要在一分钟内理解如何让批量操作停下来。设计时把开关的作用、影响和恢复步骤写进值班手册,并让执行入口在冻结期间直接显示原因。
开关数量需要控制。每类动作一个开关、总数控制在个位数,才可能记得住;开关过多时人们会分不清该用哪个,最后干脆绕过整套机制。