Skip to content

可观测性:从事件到可验证证据 ​

专题索引 / 上一篇:持久化存储:PVC 到 Linux VFS

可观测性不是“系统有日志”。它是一组证据契约:某个动作发生后,哪些状态变化会留下什么记录;记录由谁采集、会保留多久、能否与同一次请求关联,以及它究竟能证明到哪一步。

text
应用 / 内核 / Kubernetes 组件发生事件
  -> 生成日志、metric sample、span、Event 或 tracepoint
  -> SDK、runtime 或 agent 采集
  -> collector 做批处理、重试、采样或聚合
  -> 存储系统索引、压缩、保留
  -> 查询、告警、关联与故障结论

前面页面中的 PVC=Bound、CSI mount、Service endpoint、NetworkPolicy drop、fsync,都不是同一种事件。把它们塞进一条无结构日志,会丢掉时间、归属和查询能力。

1. 五种证据各自回答什么 ​

证据主要回答不能单独证明
结构化日志某组件在某时刻做了什么、看到什么错误全局发生率、完整调用链或用户已看见结果
metrics一段时间内的次数、速率、分位数、资源使用某个具体请求为何失败
trace / span一次同步或异步工作跨组件的因果与耗时所有请求都已保存,或业务结果一定正确
Kubernetes Event / status控制器观察到的资源生命周期与条件高保真审计日志或数据面逐包结果
kernel tracepoint / profiler调度、I/O、网络、系统调用等底层执行证据应用业务语义

它们不是互相替代关系。指标发现“错误率上升”,trace 缩小到一类请求,日志给出错误细节,内核 trace 再判断是调度、I/O 还是网络路径造成的等待。

2. 相关性是数据契约,不是检索技巧 ​

一个 HTTP 请求跨网关、应用、数据库和异步队列时,必须有能传递的关联身份:

text
request_id:业务或入口层的稳定请求关联
trace_id:一次分布式 trace 的全局身份
span_id:trace 内单个操作
causation_id:异步任务由哪个动作触发
attempt_id:同一业务动作的第几次执行

HTTP 常用 W3C Trace Context 的 traceparent 传递 trace/span 上下文。异步消息不能只复制“当前线程变量”:生产者、消费者、重试和批处理必须定义父子 span、span link 或 causation ID 的语义,否则时间线看似连续,实际会把不同尝试混在一起。

关联 ID 应进入日志字段和 trace 属性;但不应把 user_id、request_id、完整 URL 或订单号直接作为 Prometheus metric label。metrics 的 label 组合会形成时序基数,任意请求 ID 会让内存、索引和查询成本失控。

3. 数据从哪里来,在哪些地方会丢 ​

日志 ​

容器常把 stdout/stderr 交给 runtime,runtime 写 Node 本地的容器日志文件;日志 agent tail 文件或读取 runtime 接口,再向后端发送。应用崩溃、Node 磁盘满、日志轮转、agent backpressure、采集配置错误都可能让日志不完整。

日志格式至少应包含时间、级别、组件、事件名、关联 ID 和经过脱敏的错误上下文。把长堆栈、请求体、密钥或个人数据默认全量采集,通常会让检索、安全和成本一起失控。

Metrics ​

Prometheus 风格的 metrics 通常由目标暴露一个 scrape endpoint,采集端定时拉取并写成时间序列;也可经 collector remote write 到长期存储。counter、gauge、histogram 是不同数据模型:例如延迟分位数必须从 histogram bucket 或等价分布数据计算,不能从任意平均值还原。

采集失败、scrape 间隔、target 重启、样本保留与 downsampling 都会影响结论。监控图上没有数据,可能是系统空闲、采集失败、标签筛选错误或保留期已过,不能直接读成“没有发生”。

Trace ​

trace 由多个 span 组成。span 需要开始/结束时间、服务与操作名、状态、关联上下文和有限的属性。高吞吐系统会采样:未采样请求可能只有 metrics 或日志,因此“查询不到 trace”只能说明当前采集策略下没有这条 trace,不等于请求不存在。

Kubernetes Event 与 status ​

Event 适合说明 controller 或 kubelet 观察到的调度、拉镜像、挂载、探针等资源动作,但它有聚合和保留限制。status.conditions 是资源当前观察状态,适合自动化判断收敛;两者都不是替代应用审计日志的长期事实库。

内核证据 ​

Linux tracepoint、ftrace、perf、eBPF profiler 能在低层说明线程何时被唤醒、是否等待 I/O、发生了哪些网络或调度事件。它们通常是按需打开且有开销,不能把所有低层事件长期无差别存储;要先由应用和指标定义问题窗口,再抓取足够窄的系统证据。

4. 一次“请求超时”的证据链 ​

text
t0 网关收到 request_id / trace_id
t1 应用 span 开始,记录依赖调用
t2 数据库或下游 span 变慢,或系统线程进入 I/O wait
t3 超时计数与延迟 histogram 增加
t4 网关写入最终状态;用户端是否收到响应另有客户端证据

正确的结论应逐段限定:

观察能先得出的结论还缺什么
P99 上升某类操作的尾延迟变差哪个请求、哪一段依赖
trace 显示 DB span 长该请求在 DB 调用上等待DB 是慢还是连接池、网络或锁在等待
应用日志有 timeout应用按超时路径处理了服务端动作是否最终成功或晚到完成
kernel trace 有 block I/O 等待线程确实受 I/O 路径影响业务操作和具体存储资源的对应关系

这和客户端渲染的 t0..t8 是同一方法:不跨过中间完成点,不用单一工具替整个链路下结论。

5. 架构上的分层与成本控制 ​

text
应用语义层:事件名、错误分类、业务关联 ID、SLO
采集层:SDK、runtime、agent、collector、采样和脱敏
存储层:时序库、日志索引、trace backend、对象存储
查询层:仪表盘、告警、追踪查询、排障工作流

每层都需要明确 owner。开发者拥有业务语义和错误分类;平台团队拥有采集可靠性、容量和访问控制;SRE 或服务 owner 共同定义 SLO、告警阈值和响应手册。把这些责任混成“平台会自动监控”,最后通常得到大量仪表盘和很少可行动结论。

成本也按信号类型分别管理:metrics 控制 label 基数与保留;logs 控制字段大小、采样、脱敏和索引;traces 控制采样率与属性;内核采集限制时间窗口和目标进程。先定义故障时必须回答的问题,再决定采多少,而不是反过来。

6. 源码与资料入口 ​

本文给出的是证据模型,不承诺某个采集器或后端的实现。字段、采样、保留、访问控制和脱敏策略应在目标系统中作为版本化的数据契约维护。

学习规划与研究资料库