直接调用metrics-server的/apis/metrics.k8s.io/v1beta1/namespaces/{ns}/pods/{pod} api获取pod实时cpu和内存使用量最轻量低延迟,但需先部署metrics-server并用kubectl top验证;响应中usage.cpu为字符串如"123m",须解析为毫核或纳秒,且数据仅保留2分钟。

直接用 metrics-server 的 REST API 拿实时指标最轻量、延迟最低;Prometheus 适合做历史趋势和聚合分析,但别指望它跟 kubectl top 数值完全一致。
怎么拿到 Pod 实时 CPU 和内存使用量
调用 /apis/metrics.k8s.io/v1beta1/namespaces/{ns}/pods/{pod} 是最快路径,但前提是集群已部署 metrics-server。没装的话所有请求都返回 404 Not Found 或 503 ServiceUnavailable,不是代码问题,是服务缺失。
- 先在终端跑
kubectl top pod -n default验证通不通,不通就别写 Go —— 90% 的“拿不到数据”卡在这步 - Go 里用
rest.InClusterConfig()获取配置,别手动拼Bearer Token或硬编码地址 - 响应中
usage.cpu是字符串,如"123m",得自己解析成毫核(123)或纳秒(123000000),不能直接当整数json.Unmarshal -
metrics-server默认只保留 2 分钟窗口数据,查超时的点会返回空,别误判为 Pod 没上报
为什么用 Prometheus 查 CPU 总是跟 kubectl top 对不上
因为两者数据源和计算逻辑完全不同:kubectl top 拿的是 metrics-server 的瞬时采样值,而 Prometheus 抓的是 container_cpu_usage_seconds_total 这类累计计数器,必须做 rate() 才能转成“利用率”。
- 错误写法:
avg(container_cpu_usage_seconds_total{pod="xxx"})—— 这是累计秒数,数值随时间线性上涨 - 漏掉
by (pod):多容器 Pod 的结果会被合并,单个容器 CPU 飙高却看不出来 - 时间范围太短(如
[1m]):遇到抓取抖动直接出NaN - 正确分母要用 Node 实际 CPU 核数,不能硬写
4或8,云上 VM 核数可能动态变化
Go 调 Prometheus API 容易卡死的三个坑
不设超时、不检查返回体、反复新建 client,三者任一都会让监控 goroutine hang 住甚至拖垮整个服务。
-
api.Client必须复用,别在循环里反复api.NewClient(),否则连接池快速耗尽 - Prometheus 错误不走 HTTP 状态码:即使返回
200,body 里也可能有"status":"error"和"errorType":"bad_data" -
time参数必须是 Unix 时间戳(秒级),传字符串如"2024-05-01T12:00:00Z"会静默失败 - 刚启动的 Pod,
rate()在前两个采样点内无法计算,返回空数组,Go 解包前要检查result.Data.Result长度
Watch Pod 状态变化时收不到删除事件
watch.Event.Type == watch.Deleted 只在对象**彻底从 etcd 删除后**触发;而 kubectl delete 后 Pod 先进 Terminating 状态(仍在 list 中),几秒后才真正消失。很多监控逻辑误把 Terminating 当作“已删除”,导致漏判。
- 判断退出应看
pod.Status.Phase:只要不是"Pending"或"Running",都算异常状态(包括"Failed"、"Succeeded"、"Unknown"、"Terminating") - 更及时的做法是监听
DeletionTimestamp != nil,只要非空就代表删除流程已开始,应立即触发告警 - 用
cache.NewInformer替代裸Watch,它能捕获Update事件里的phase变更,比等Delete更可靠
真正难的不是调哪个接口,而是理解每个数据源的语义边界:metrics-server 给的是“此刻快照”,Prometheus 给的是“过去一段速率”,Watch/Informer 给的是“状态变迁流”。混用却不区分,监控就只剩一堆对不上的数字。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!











