可观测性 — 三种(或者四种)信号
一句话总结
监控是“回答我预先设定的问题”,可观测性则是**“具备回答事先未曾想到的问题的能力”**。之所以区分各种 signal,是因为它们能够回答的问题各不相同。
为什么需要了解这一点
在单服务器时代,一个日志文件就够了。到了微服务中,一个请求会经过十个服务,仅靠日志无法知道其中哪里变慢。而且 Pod 会终止后重新启动,因此开始调查时,留下日志的主体往往已经消失。
所以,“发生故障就登录服务器查看”的方式无法成立。因为根本没有可登录的服务器,或服务器已经被替换。必须预先把数据发送到外部。
工作原理
三大支柱,以及第四种信号
| Signal | 回答的问题 | 成本 | 代表工具 |
|---|---|---|---|
| 指标(Metrics) | 现在有多糟?从何时开始? | 低(聚合数值) | Prometheus |
| 日志(Logs) | 当时究竟发生了什么? | 中等至高 | Loki, Elasticsearch |
| 追踪(Traces) | 这个请求在哪里花费了时间? | 高(通常采样) | Jaeger, Tempo |
| 剖析(Profiles) | 谁消耗了这个进程的 CPU/内存? | 高 | Pyroscope |
调查顺序通常也是如此:先用指标发现异常并缩小范围,再用追踪找出具体区段,最后通过日志阅读该区段的详情。 如果从日志开始翻找,就像在干草堆里找针。
Kubernetes 中的采集路径
- 指标:各组件和应用公开
/metrics→ Prometheus 定期 pull - 日志:容器的 stdout/stderr → 节点磁盘上的文件 → DaemonSet collector 读取并发送
- 追踪:应用完成 instrumentation 后通过 OTLP push → collector → backend
这里有一个 KCNA 强调的要点:容器日志必须发送到 stdout/stderr。 如果应用写入自己的文件,Pod 终止时日志会一同消失,collector 也看不到。 12-factor 中“日志是事件流”所说的正是这一点。
OpenTelemetry 解决的问题
过去,每个 backend 都使用不同的 SDK。从 Jaeger 切换到其他工具时,必须再次修改应用代码。OTel 通过**标准化 instrumentation API/SDK 与传输协议(OTLP)**来解除这种依赖。instrumentation 只做一次,backend 则通过 collector 配置更换。
Kubernetes 原生提供的观测材料
- 事件——位于
kubectl describe pod的下方。调度失败、image pull 失败、probe 失败等 控制平面作出判断的依据会留在这里。这是翻查日志前应该查看的位置。 - 状态(status)——
.status.conditions与.status.phase。 - metrics-server——
kubectl top使用的最基本资源用量,不会长期保存。
可靠性术语
- SLI——实际测量的指标(例如成功请求比例)
- SLO——该指标的目标(例如 30 天内 99.9%)
- SLA——未能达到目标时的合同赔偿。它不是技术概念,而是合同概念
- 错误预算——如果 SLO 为 99.9%,便有 0.1% 可以违反的预算。预算有剩余时可以更快部署, 耗尽时则专注于稳定化,以此作为决策标准
实际工作中的表现
作者的 home lab 中有两个鲜明体现可观测性的案例。
第一是 Cilium 的 Hubble。它无需注入任何 sidecar,直接通过 eBPF 在内核中观测,实际输出如下。
07:50:38.064: ebpf-demo/client:47918 -> ebpf-demo/api:80 http-request FORWARDED (HTTP/1.1 GET http://api/)
07:50:38.223: ebpf-demo/client:47932 -> ebpf-demo/api:80 http-request DROPPED (HTTP/1.1 POST http://api/)
07:50:38.223: ebpf-demo/client:47932 <- ebpf-demo/api:80 http-response FORWARDED (HTTP/1.1 403 0ms POST)
方法、路径、响应码和延迟全部可见,而且明确标出了策略导致的 DROPPED。
关键在于能够通过记录而不是猜测得知“为什么被阻止”。
同一集群中的 nginx 在应用策略前是 GET 200 / POST 200,应用后则分化为
GET 200 / POST 403,这种变化原样留在 flow log 中。
第二是前面介绍的 KubeVirt 案例。所有组件状态都是 AllComponentsReady,VM 却没有启动。
状态字段只表示“我已经启动”,并不表示“我负责的功能确实可用”。
所以,作者对集群的验证不是状态查询,而是实际行为的 14 个场景(节点 Ready、
控制平面组件、CNI、CoreDNS、worker 调度、Pod 间通信、服务 DNS + HTTP 200),并确认
통과 14 / 실패 0。可观测性的最终形式是合成检查(synthetic check)。
下个测验将检查什么
本课程最后一个测验会同时检查 CNCF 生态系统与可观测性。 接下来是 KCSA——从攻击者的视角重新审视迄今学到的结构。