最可靠方式是直接调用 metrics.k8s.io/v1beta1 API,但前提是 metrics-server 已部署且运行正常;否则返回 404 或 503,非代码问题而是服务缺失。

直接调用 metrics.k8s.io/v1beta1 API 是最可靠方式,但前提是 metrics-server 已部署且运行正常;否则所有请求都会返回 404 Not Found 或 503 ServiceUnavailable,不是代码问题,是服务缺失。
确认 metrics-server 是否就绪
Go 程序无法绕过 metrics-server 直接读 Pod CPU/Memory——它不是 kube-apiserver 原生资源,而是独立的 Metrics API 聚合服务。没它,clientset.MetricsV1beta1() 就是空壳。
- 先在终端执行
kubectl top pod -n default,能出数据再写 Go 代码;失败就别往下走了 - 检查 metrics-server Pod 状态:
kubectl get pods -n kube-system | grep metrics-server,必须是Running - 查它的日志:
kubectl logs -n kube-system deploy/metrics-server,常见报错如x509: certificate signed by unknown authority表示 TLS 配置异常 - 注意:metrics-server 默认只保留最近 2 分钟的数据,查太老的时间点会返回空,别误判为指标没上报
用 client-go 初始化 MetricsV1beta1 客户端
不能复用 CoreV1 的 clientset,必须显式构造 MetricsV1beta1 客户端,并确保导入正确包和版本(k8s.io/metrics@v0.26.0 适配 K8s v1.26+)。
- 集群内运行时用
rest.InClusterConfig(),**不要硬编码 token 或 kubeconfig 路径** - 导入时注意路径:
"k8s.io/metrics/pkg/client/clientset/versioned"(不是api或apis子目录) - 初始化后务必检查错误:
if err != nil { log.Fatal(err) },常见错误是 GroupVersion 不匹配或 RBAC 权限不足 - RBAC 必须包含对
nodes/metrics和pods/metrics的get权限,仅list/watch不够
读取单个 Pod 的 CPU 和内存用量
metrics-server 返回的 usage.cpu 和 usage.memory 是字符串(如 "123m"、"456Mi"),不能直接转 int64,得用 k8s.io/apimachinery/pkg/api/resource 解析。
使用 uber-go/dig 在 Golang 中实现依赖注入——基于反射容器,提供 Provide/Invoke、dig.In/dig.Out 参数与结果对象,支持命名依赖等
- 调用路径是:
client.Pods(namespace).Get(ctx, podName, metav1.GetOptions{}) - 响应里的
Usage字段是resource.Quantity类型,调用.AsInt64()才能得到纳秒级 CPU 或字节数内存 - 别忽略单位转换:CPU “123m” = 123 毫核 = 123 × 10⁶ 纳秒/秒;内存 “456Mi” = 456 × 1024² 字节
- 若返回
nil或Zero(),大概率是 Pod 还没上报(刚启动)、被 metrics-server 丢弃(标签不合法),或 namespace 不匹配
避免踩进 client-go 的典型陷阱
controller-runtime 用户容易混淆 Metrics 客户端和普通资源客户端——sigs.k8s.io/controller-runtime/pkg/client 不支持 Metrics API,必须用原生 client-go 的 MetricsV1beta1。
- 别试图用
mgr.GetClient()去查 metrics,它只管 CRD 和 CoreV1 资源 - 不要把
MetricsV1beta1客户端塞进 controller-runtime 的 Manager,它不识别这个 Group - QPS/Burst 设置过高(如
1e6)可能触发 metrics-server 限流,建议保持默认或设为10~50 - 如果用自定义 Scheme 注册了其他类型,确保没覆盖
metricsv1beta1.AddToScheme(scheme),否则解码失败静默返回空结构
真正卡住的地方往往不在 Go 代码本身,而在 metrics-server 的部署状态、RBAC 权限粒度、以及你查的那个 Pod 是否已稳定上报至少一次指标——它不会补历史数据,也不会容忍标签里有非法字符(比如 Pod 名含下划线)。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!










