运行手册

部署运行手册

可以照着做的上线流程。与部署实践的分工是:那页决定「选哪种方案」,本页决定「怎么把它推上去并且能退回来」。

执行顺序:回滚演练排在第一步

多数团队把回滚放在最后 —— 那正是它来不及用的原因。每两步之间都有一道闸门,条件不满足就不要进入下一步。

① 建回滚通道并演练 闸门:实测切回耗时,并写入值班手册 ② 基线测量(≥ 7 天) 闸门:P95 与失败率有连续样本可比 ③ 灰度 A:5%(技术团队) 闸门:无兼容性异常,且失败率未超基线 ④ 灰度 B:20%(跨办公区) 闸门:跨区域均稳定,无单点依赖 ⑤ 全量 + 持续监控 保留回退开关至少一个版本周期 失败 → 不要上线 失败 → 先补样本 失败 → 原地排查,别放量 失败 → 退回批次 A 并记录 异常 → 按阈值自动或手动回退

① 建回滚通道并演练 —— 为什么排第一

如果回滚通道不预先建好,故障时的「回退」往往只有一条路:临时改回明文。 那等于把刚建立的全部保护一次性撤掉,而且没人来得及评估这个决定。

更重要的是要演练一次。没演练过的回滚方案,在真出问题时通常会发现:

  • 切回步骤依赖某台已经下线的机器
  • 切回后需要手动重启终端,而终端在使用者手里
  • 切回本身就要 20 分钟,而被故障影响的业务等不了

演练的产出是一个数字:从决定回退到恢复服务,实际需要多久。这个数字要写进值班手册, 因为它决定了「阈值该设多严」—— 若切回要 20 分钟,就不该等到失败率 5% 才动手。

② 基线测量 —— 没有基线就无法判断「变好了没」

加密 DNS 常见的问题不是「坏」,而是「慢了一点」「偶发失败」。没有基线,这两种问题都会无法判定。

# 建议至少采集这些(换成你自己的域名与解析器)
for d in $(cat domains.txt); do
  dig @127.0.0.1 "$d" +noall +stats +time=3
done
# 或直接用 reset 工具类持续打点,按区域分组
# 关键:同时记录【解析器】与【协议】,否则事后无法归因

要测的不只是延迟,还要区分失败的类型:

  • NXDOMAIN —— 域名确实不存在(正常结果,不是故障)
  • 超时 —— 网络或解析器不可达
  • SERVFAIL —— 解析器活着但无法给出答案(常见于 DNSSEC 校验失败或上游异常)

把这三类混在一个「失败率」里,是后面无法定位问题的常见原因。

③ 灰度 A:5% —— 先覆盖「能被你直接问到的人」

第一批选技术团队与测试终端,理由不是「他们重要」,而是他们出事会告诉你, 而普通用户出事只会默默换个网络或放弃。

这批重点看的是兼容性而不是性能:

  • 有没有应用绕过系统解析器直连明文 53
  • 内网域名、VPN、容器环境是否正常(这类环境最容易出问题)
  • 证书校验是否在所有终端都通过(严格模式下失败表现为「完全无响应」)

准出条件:无兼容性异常,且失败率未超过基线。任一项不满足,就原地排查,不要放量 —— 带着未解释的异常扩大范围,后面会无法归因。

④ 灰度 B:20% —— 开始验证「跨区域」

第一批成功不代表第二批会成功,因为覆盖的网络路径变了。这个阶段最容易暴露的问题是按区域分布的:

  • 某些区域到解析器的路径更差,延迟明显高于基线
  • 某些出口做了端口策略,导致部分区域必须回落
  • 某个区域实际上只走单一上游 —— 这是单点依赖,要在全量前发现

准出条件:各区域指标都在可接受范围内,且不存在单点依赖。 发现某区域只能走一个上游时,先补第二上游再继续。

⑤ 全量 + 持续监控

放量不等于结束。这个阶段要盯的是悄悄劣化,而不是明显故障:

  • 失败率是否缓慢上升(可能是某个上游在退化)
  • 缓存命中率是否下降(可能是 TTL 或分流策略改坏了)
  • 证书到期时间(严格模式下过期会造成整体不可用)

回退开关要保留至少一个版本周期 —— 有些问题(例如特定应用的兼容性) 要等到某个业务场景真正被触发才暴露。

1 / 5

回滚:三种方式,代价差别很大

「回滚」不是一种动作。选哪种决定了故障持续多久、以及这次上线会不会白做。

方式 代价 适用时机
切换上游
换解析器,保留加密
低。保护不丢失,通常秒级到分钟级 某个上游退化或不可用时的首选。多数「回滚」其实应该是这个
切回旧配置
回到变更前状态
中。需要终端层面的配置下发或重启 协议层本身有问题、且切换上游无效时
退回明文
关闭加密
高。保护归零,且事后往往没人再把它打开 只应在没有其它手段、且已明确记录原因时使用
实践中最常见的失误是:故障一来就直接退回明文,因为那是操作最简单的一条。 正确做法是把「切换上游」训练成第一反应 —— 它保留了保护,代价也小得多。 这件事只有靠演练才能变成条件反射,所以它被排在流程第一步。

把「失败率上升」拆成三类病因

告警只会告诉你「失败了」。下面这组判别方法决定你往哪个方向查。

现象 多半是 一步确认
只有某些域名失败,其它正常 上游或权威侧问题,与加密无关 换一个解析器问同一个域名,若仍失败则是域名侧问题
所有域名都失败,且无响应(不是报错) 严格模式下证书校验失败,或加密通道不通 看是否 DNSOverTLS=opportunistic 下能恢复
失败率随区域变化 该区域的出口策略或链路质量问题 按区域分组看指标,确认是否集中于某一出口
间歇性失败,重试可恢复 多个上游之间结果不一致,或某个上游抖动 分别对每个上游连续 dig,比对成功率
延迟整体上升但失败率正常 解析器变远,或缓存命中率下降 看缓存命中率与 P95,而不是只看均值

这几条与排错与运维里的单机判断树是互补的: 那页面向「一台机器打不开」,本页面向「一批终端失败率上升」。判据相同,但前者靠命令、后者靠分组指标。

上线后要留下什么

不是为了流程好看,而是因为下一次排查会依赖这些记录。

必须留档的四样

  • 生效配置快照 —— 含各区域的实际下发值,而不是「设计值」
  • 基线数据 —— 否则下一个接手的人无法判断当前是否正常
  • 回滚演练的实测耗时 —— 决定阈值该设多严
  • 例外清单 —— 哪些终端或域名没纳入(这类信息最容易只在某个人脑子里)

容易被忽略的一点

「设计配置」与「生效配置」往往不一致:某台机器手工改过、某个区域漏下发、某个终端回退了但没人记录。

所以快照要从终端侧反查(例如 resolvectl status 的输出汇总), 而不是直接复制配置管理系统的预期值。这两者的差异,正是下次故障排查里最耗时的部分。