云原生可观测性:凌晨三点那个“健康”的Pod,为什么让我对着屏幕骂娘?
凌晨三点,手机像催命一样震。我眯着眼摸过来,值班群里已经炸了:用户支付失败,客服电话被打爆。我第一反应是打开监控面板——CPU、内存、网络、磁盘,四个绿灯,比我的体检报告还漂亮。Pod状态显示Running,就绪探针全部通过。那一刻我差点把手机扔了。操,这玩意儿到底在监控什么?
故事还没完。我登上跳板机,kubectl logs 一敲,返回一行冰冷的提示:容器已经重启过,之前的日志随着旧容器一起灰飞烟灭。好家伙,出事的时候日志正好没了。指标说健康,日志看不见,追踪系统?那玩意儿只覆盖了不到三成的服务。最后靠着一个同事模糊的记忆,想起上周改过某个ConfigMap的默认值,才把问题摁住。忙完天都亮了,我盯着天花板想:云原生可观测性,这词儿我们天天挂在嘴边,真到要命的时候,怎么跟纸糊的似的?
监控说“我很好”,为什么你信了?
传统监控的逻辑特别朴素:我提前假设好“坏”长什么样,比如CPU超过80%、接口响应超过500ms,然后盯着这些指标,一旦越线就报警。这就像你在家里装了个温度计,只要温度低于零度就启动暖气。问题是,云原生环境里的“坏”根本不在你的剧本里。
一个Pod,它可能因为某个Go程序里的死锁,CPU只有2%,内存纹丝不动,网络请求全卡在内部队列——从外面看,它健康得能去跑马拉松。可用户点下去,转圈圈。你的监控指标一个都没触发,因为你压根没定义“死锁”这个指标。更操蛋的是,Pod重启之后,旧容器的CPU曲线直接被抹掉,你连回溯的机会都没有。
说白了,监控回答的是“我预设的那些问题发生了吗?”。可观测性回答的是“我没预设到的问题,发生了我能不能查出来?”。前者像门卫,只认名单上的人;后者像侦探,能根据现场的一根头发丝还原作案过程。
云原生Kubernetes Pod故障排查与日志界面截图
我见过不少团队,把可观测性理解成“监控的豪华升级版”——指标采集加个Prometheus,日志搞个ELK,再上个Jaeger,齐活。然后呢?出了事照样抓瞎。为什么?因为三套系统各玩各的。指标告诉你某个服务P99延迟飙了,日志告诉你那段时间有一堆timeout,追踪告诉你有个下游调用特别慢。可你没法一键把这三条信息串起来。你得手动对时间戳,得翻找同一个traceID的日志,得猜是哪个指标异常导致了哪个trace变慢。这活儿,人干多了会折寿。
可观测性的灵魂,其实是“上下文”
我后来想明白了。云原生可观测性真正的价值,不是采集多少数据,而是数据之间能不能自动关联。你有一个请求的traceID,就能顺着它跳到对应的日志行,再点一下就能看到那个时间段这个Pod的CPU和网络指标。反过来,你看到一个异常指标,能直接下钻到那几秒内所有相关的日志和追踪。这才叫“可观测”。
举个例子。我们有个服务偶尔报500,频率极低,一周可能就两三次。日志里只能看到一句“context deadline exceeded”,没了。你说是哪个下游超时?不知道。是网络抖动还是数据库慢查询?不知道。后来在代码里强行把traceID打进日志,同时给所有HTTP client加了拦截器,把下游调用的耗时和状态码也附在trace上。下次再报错,直接点开那个trace,火焰图一拉——原来是一个很少触发的缓存穿透场景,导致某个冷门接口连接池被打满,拖累了主链路。如果没有trace和日志的关联,这个bug能查到你怀疑人生。
但这里有个坑:很多人的日志和追踪确实都有traceID,可格式不统一。日志里打的是大写的TraceID,追踪系统里是小写的trace_id,关联脚本写错一个字母都对不上。更别提有些老服务压根不打日志到stdout,你采集都采集不到。可观测性这玩意儿,三分靠技术,七分靠规范。没有统一的埋点标准、没有强制的日志格式、没有团队共识,你再好的工具也是摆设。
分布式追踪链路火焰图与日志关联分析示意图
还有成本。我见过一个团队,把每个请求的完整请求体和响应体都写成日志,一天几十TB。老板看到账单脸都绿了。可观测性不是让你把一切都倒进数据湖,那是数据囤积癖。正确的姿势是:默认采样,按需开启全量。比如正常请求只记录关键字段和耗时,只有出错或者慢请求才把完整上下文丢出来。再配合动态采样率,流量高峰自动降采样,省钱又不丢关键信息。这道理跟行车记录仪一样,平时循环覆盖,遇到碰撞自动锁存那几十秒。
别神化它,可观测性也有够不着的地方
别神化它,可观测性也有够不着的地方
说句冷话:可观测性不是银弹。你就算把指标、日志、追踪全打通了,有些问题你还是得靠猜。比如一个第三方SDK内部的内存泄漏,它不暴露任何自定义指标,日志也只在崩溃那一刻吐一行。你只能看到进程OOM,但为什么OOM?它不告诉你。这时候可观测性能做的,就是帮你排除掉“不是你的代码的问题”,然后你去找供应商扯皮。这已经很有价值了,但别指望它像上帝视角一样什么都知道。
另一个误区是把可观测性当福尔摩斯用——平时不烧香,出了事才去查。我见过一个团队,报警只配了最基础的CPU和内存,连个业务指标都没有。问就是“我们有可观测性平台,出事可以查”。结果真出事了,他们连“从哪个服务开始查”都不知道。可观测性像城市里的摄像头,平时你看录像能破案,但如果你连摄像头都没装对位置,关键路口全是盲区,那录像就是废片。你得先想清楚要观测什么,再谈工具。黄金指标(延迟、流量、错误、饱和度)是底线,业务层面的关键路径指标更得提前埋好。
还有个边界:可观测性对“非确定性故障”特别无力。比如一个偶发的、跟时序相关的并发bug,可能一周才触发一次。你采样率再高,也未必能抓到现场。这时候只能靠代码审查、混沌工程去主动制造故障来暴露问题。可观测性是被动接收信号,主动探测是另一码事。两者得配合。
说实话,我现在对“可观测性”这词有点过敏。太多厂商把它包装成一个点一下按钮就能AI定位根因的魔法盒子。放屁。真实世界里的可观测性,是苦活累活:统一日志格式、给每个Span打上业务标签、跟团队吵架说服他们加埋点、半夜对着火焰图一点一点抠。但做完这些之后,下次再遇到凌晨三点的报警,你至少能对着屏幕说:“哦,是那个下游的缓存穿透,改个TTL就行。”而不是像我那晚一样,除了骂娘什么也干不了。