隧道进程可能仍在运行,而受保护的连接已经不可用;网页打不开并不能证明隧道坏了。当一项探测代表所有层时,重启策略会重启错误的组件,并把这称为自动化。下面每项检查都会说明它观察的层、失败时触发的动作,以及动作生效的证据。最后一步是把整套内容变成凌晨三点任何人都能照着做的页面。

步骤 1:说清每项检查观察哪一层

在写下任何探测之前,先问每一项究竟能看到什么。存活检查证明守护进程在运行,握手或对等列表证明关系存在,经过路由的请求证明投递,域名查询证明解析。它们正是按这个顺序失效的,而且前一层不保证后一层。一个绿色的进程检查,旁边就是一条已经死掉的隧道,这是正常情况,不是矛盾。

按这个顺序写下四项检查,并给出每一项的确切命令和预期输出。说不清预期输出的探测,每个看到告警的人都会读出不同的意思。把同一份清单放进告警正文,而不只是运维手册,这样半夜被叫醒的人会先遇到层,再遇到症状。每条命令都要能在执行它的主机上直接复制。

然后把应用检查作为第五项单独加上。某个页面的账户服务挂了,并不构成重启隧道的理由。

步骤 2:把每种失败绑定到一个动作

对每项检查,决定什么要重启、什么继续保持阻断、什么要叫人来处理。隧道层的失败可以成为重启隧道的理由;解析器失败指向客户端上的 DNS 集成;应用层的失败几乎从不该碰隧道。

说明失败不允许做什么,因为危险的默认值往往是放行。不健康状态绝不能变成放行直连应用流量的许可,因为悄悄绕过隧道的兜底路径会抹掉隧道存在的理由。也要收窄动作:因为一个目标变慢就重启共享组件,会把局部问题变成整个舰队的问题。它还会毁掉你查找原因所需的证据。

步骤 3:让探测保持无害且低成本

使用小的只读请求:一个静态资源、一个会报告自身依赖的健康端点,或到你所控制端口的 TCP 连接。避免凭据、隐私浏览以及每个周期都会改变状态的操作,因为会写入的探测就是按计划运行的压力测试。

记录每个探测的目标、路由预期和超时。路由预期是人们最容易漏掉的字段,而它正是以后读告警时把隧道故障和路由错误区分开的东西。根据你承诺的恢复时间推导周期和失败阈值,并让超时短于周期。下一个探测开始时仍在运行的探测会把一次失败报告两次,看起来像抖动。

步骤 4:逐层弄断,观察正确的探测变红

停掉隧道进程,确认进程检查失败,而 DNS 可能仍从缓存应答。改一条路由,确认经过路由的请求失败,而进程和握手仍然健康。只弄断 DNS,确认应用检查报告的是解析问题而不是隧道错误。如果两项探测永远一起动,你拥有的检查比你想象的少。

用同样的纪律测试恢复方向。恢复该层之后,探测应当无需手动重启就自行恢复,触发过的动作也不应留下任何绕过路径。在相信绿色状态之前先观察一个完整周期,因为只能手动恢复的探测会掩盖断掉的恢复路径。

步骤 5:把运维手册放在告警指向的地方

一页五行就能承载整个设计:层、命令、预期结果、失败时的动作、负责人。为每项探测再加一行,写明它故意不测什么。正是这一行阻止下一个人添加第六项检查,那种什么都测、什么都区分不出来的检查。从告警正文里链接这一页,否则事故进行中没人会打开它。

在容器部署中,依赖条件只塑造启动顺序,仅此而已。Compose 的启动顺序与健康条件文档说明了就绪状态如何决定服务启动的先后;这些都不在事后强制出站策略,也不会在隧道断开时默认拒绝。持续强制需要自己的策略和自己的探测,并写在同一页上。

当正确的层恢复,而且没有人把打不开的网站当成隧道坏了时,运维手册才算完成。这测试的是文档,不是隧道。

相关文章