每个运营环境中都充斥着各种检查:健康检查、监控查询、部署后的测试、防火墙变更后的核查。它们的价值不在于显示绿色,而在于出问题时会变红。恰恰是这后一半很少被检验。一项从未报警过的控制措施,可能意味着一切正常——也可能意味着它根本无法报警。从外部看,这两种情况一模一样。
本文所讨论的模式十分普遍,与所用工具和环境规模无关。文中的例子是假设性的,但具有典型性。
四种结果,而不是两种
大多数检查只知道两种结局:通过或未通过。这是不够的。至少还应加上另外两种结果:
- 通过: 测量已经进行,结果符合预期。
- 失败: 测量已经进行,并发现了一个缺陷。
- 错误: 测量没有进行——连接未能建立,查询无效,响应为空。
- 跳过: 检查被有意略过,其理由在结果中保持可见。
关键的区别在于“错误”与“通过”之间。“系统坏了”和“我没能查明”需要不同的应对,但两者都必须引起注意。危险在于错误路径与“什么也没发现”路径给出同一个值:那样一来,检查恰恰在它最没有资格报告“一切正常”的时刻报告了“一切正常”。
“跳过”也绝不能被当作绿色放行。一次所有单项检查都被略过的运行,什么也没有测量——而它应当如实报告这一点。
检查如何在不撒谎的情况下撒谎
下面这些模式并不起眼。正因如此,它们通常能顺利通过评审。
用否定代替预期。 假设某个健康检查检验一个地址是否“不以状态 200 响应”,因为那里预期会发生重定向。但这个条件在 403、500 时同样成立——在根本没有建立连接时也成立。请明确检查预期的状态码,并把没有响应视为一种独立的结果。
把错误对象当作零。 假设某个监控查询统计命中次数,例如失败的登录。如果查询在语法上无效,系统会返回一个不含命中数的错误对象。一个把缺失字段读作 0 的脚本,随后就会报告“无异常”。缺失的值不等于零。请先确认收到了有效的响应,再对其进行评估。
找到太多东西的文本搜索。 在日志中搜索某条错误信息的人,也会找到人们讨论这条错误信息的每一处——在工单、聊天记录和注释中。来源、事件类型或状态码等结构化字段比自由文本更可靠。
找到自己的探针。 进程检查中的一个经典问题:像 ps aux | grep dienst 这样的搜索往往会返回一个命中——也就是 grep 命令本身(而 pgrep 会排除自身)。要找的服务可能早已停止。
向错误的对象提出正确的问题
一项检查可能在技术上无懈可击,却仍然答非所问。一个常见的模式:直接在服务器上测试 Web 应用程序的检查,看不到访问者可能遇到的 DNS、CDN 或证书问题。这类直接检查有其用途,但回答的是另一个问题。在访问者与服务器之间,还有域名解析、可能存在的负载均衡器或 CDN,以及证书链。这条路径上的故障,对服务器上的检查来说是不可见的——检查报告绿色,而访问者看到的却是错误页面。
两种测量都有其合理性,只是不能相互替代。Google 的 SRE 一书为此区分了白盒监控与黑盒监控:前者深入系统内部,后者以症状为导向,反映正在发生的问题:“系统此刻没有正常工作。”(“The system isn’t working correctly, right now.”)因此,每一个可公开访问的应用程序在发布时,都应包含一项从访问者视角出发的检查——通过公共名称,并验证证书链。
“一切仍能正常工作”不是防火墙检查
防火墙变更后,通常会检查允许的服务是否仍可访问。这是必要的,但只能证明没有东西坏掉。防火墙究竟有没有在过滤,这项测试并不能说明——一台没有任何有效规则的防火墙同样能通过它。
为此需要一个反向探测:从一个必须被拦截的来源,向一个必须被封锁的端口发起连接尝试。只有当这次尝试失败时,过滤才算得到证明。重要的是,探测必须来自被检查系统之外;从主机自身发起的测试,可能经由根本不受这些规则约束的路径。
缺失的控制不会自己报告
最令人不适的情形涉及保护机制本身:审批规则、告警规则、自动封锁。举个例子:一家企业将其邮件服务器迁移到新平台。拦截带有可执行文件附件的那条规则,在迁移时没有被一并带过去。没有人察觉。没有故障,没有警告,日志里也没有任何异常——一条不存在的规则,也无从记录任何东西。对所有相关人员来说,运营看起来就像一个平静的月份。
因此,仅仅设置一项控制是不够的。只有当它经证实确实触发过——例如通过一个有针对性的测试用例——其效果才算得到证明。一旦配置发生根本性变化——平台更换、较大的更新或迁移之后——这项证明都应重复进行。而且它不应仅仅来自被检查的系统本身:一个环境关于自身的报告,只能包含它自己知道的东西。独立的视角——一次从外部发起的测试发送、第二种工具、另一个人——能揭示自我报告所遗漏的东西。
BSI 在 IT 基本保护模块 DER.1 中规定,应在定期审计中检查检测系统“是否仍然是最新且有效的”。同一文件将以下情况列为一种威胁:错误的配置可能导致检测系统“无法正常运行”。SRE 一书从一个相关的观察中得出了一个严厉的结论:很少被用到的数据收集、聚合和告警配置——在某些 SRE 团队中不到每季度一次——应当列入删除候选。
检查清单:每一项检查都必须失败一次
- 证明检查能够失败。 让每一项新检查针对一个已知有缺陷的输入运行一次,亲眼看着它变红。一项没人见过它失败的检查,并未被证明是一项检查。
- 给错误一个独立的结果——与通过和未通过分开,有自己的状态或退出码。
- 检查预期的结果,而不是它的否定: 具体的状态码、具体的值、具体的页面标题。
- 在解读响应之前,先检查响应是否到达。 空不等于绿。
- 问对对象: 分别测量源站与访问者视角,并将两者都记录下来。
- 让略过可见。 “已跳过,因为……”应当写进结果。
- 修正检查,而不是阈值。 如果一项检查报告有误,应当修复的是它的错误处理——而不是把条件放宽到让不明确的情况落在绿色一侧。
此外,反向对照的构建方式应确保它明天仍会给出同样的结果。如果拿生产环境中一个当下存在的故障来测试检查,那么得到的是一项故障一旦修复就会变绿的对照——此后它便什么也证明不了。为此,结果已知的存储测试数据比实时状态更可靠。
sector7 如何提供支持
我们协助搭建或集成日志与 SIEM 平台,并与您一起定义用例、告警规则和 Playbook——详情请见网络安全。对于受托管的环境,我们的 NOC 全天候自动化监控;日常运营的具体情况,请见托管服务与支持。
来源
- Site Reliability Engineering, 第 6 章: Monitoring Distributed Systems – Google,访问于 2026-09-30
- IT-Grundschutz-Kompendium, Baustein DER.1 Detektion von sicherheitsrelevanten Ereignissen, Edition 2023 (PDF) – BSI,访问于 2026-09-30