直接用 client-go 拉取指标会失败,因为自定义指标需通过 custom.metrics.k8s.io/v1beta1 聚合 api 提供,而非直接访问 /metrics 或 kubelet;必须实现三个标准 http 端点并严格返回 custommetricvaluelist 结构,且 tls、路径、类型、权限任一环节出错均导致 hpa 静默忽略。

为什么直接用 client-go 拉取指标会失败
Kubernetes 的自定义指标(Custom Metrics)不通过标准的 metrics-server API 提供,而是走 custom.metrics.k8s.io/v1beta1 这类聚合 API。你用 client-go 直连 /metrics 或 kubelet 端点,拿到的是 cAdvisor 或 kube-state-metrics 的原始数据,不是 Kubernetes 资源模型里可被 HPA 消费的 CustomMetricValueList。这类采集器本质是「API Server 聚合层后端」,必须实现特定的 HTTP 接口契约。
必须实现的三个核心 HTTP 端点
你的 Go 服务要被 metrics-server 或 HPA 正确调用,至少得响应以下路径(路径前缀由 APIService 配置决定,但后缀固定):
-
/apis/custom.metrics.k8s.io/v1beta1/:返回空APIResourceList,表明支持该组版本 -
/apis/custom.metrics.k8s.io/v1beta1/namespaces/{ns}/services/{svc}/{metricName}:按服务名查单个指标值(如http_requests_total) -
/apis/custom.metrics.k8s.io/v1beta1/namespaces/{ns}/pods/{pod}/{metricName}:按 Pod 名查指标(用于 Pod 级 HPA)
每个端点返回的 JSON 必须严格符合 CustomMetricValueList 结构,否则 metrics-server 解析失败并静默跳过——这是最常被忽略的兼容性断点。
用 net/http 实现时怎么避免类型错位
Go 中不要自己手写 JSON 字段名拼接;直接用官方 k8s.io/metrics/pkg/apis/custom_metrics 中的类型(注意版本匹配,v0.26+ 对应 k8s 1.26+)。示例片段:
评估 Kubernetes 集群安全态势,覆盖 RBAC、工作负载安全、网络策略、基础设施即代码(IaC)、运行时监控和密钥管理等 30 项控制项……
func serveServiceMetric(w http.ResponseWriter, r *http.Request) {
vars := mux.Vars(r)
ns, svc, metric := vars["namespace"], vars["name"], vars["metric"]
// 假设从 Prometheus 拉取
val, _ := queryPrometheus(fmt.Sprintf(
`sum(rate(%s{namespace="%s",service="%s"}[2m]))`,
metric, ns, svc,
))
list := &custom_metrics.CustomMetricValueList{
Items: []custom_metrics.CustomMetricValue{{
DescribedObject: custom_metrics.CrossVersionObjectReference{
Kind: "Service",
Name: svc,
APIVersion: "v1",
},
MetricName: metric,
Timestamp: metav1.Now(),
Value: resource.MustParse(fmt.Sprintf("%.0f", val)),
}},
}
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(list)
}
关键点:DescribedObject.Kind 必须是 HPA 引用对象的真实 Kind(Service、Pod、Deployment),不能写成 service 小写;Value 必须是 resource.Quantity 类型,不能传 float64 或 string。
部署后 metrics-server 查不到你的指标?先检查这三件事
APIService 注册成功 ≠ 指标可用。常见卡点:
-
kubectl get apiservice v1beta1.custom.metrics.k8s.io -o wide看STATUS是否为True;若为False,看Conditions.Message—— 多半是 TLS 证书不被 metrics-server 信任(你的服务必须提供合法 TLS,或用--insecure-skip-tls-verify临时绕过) - metrics-server 日志里搜
failed to get metrics from custom metrics API,它默认只重试 1 次就放弃,超时时间短(默认 30s),你的 handler 必须在 25s 内返回 - HPA yaml 中
metrics[].type写成Object还是Pod,决定了 metrics-server 调哪个 endpoint;如果写Object却没实现/services/...路径,就不会触发你的 handler
真正麻烦的不是写代码,而是让 Kubernetes 的指标发现链路每一环都对上签名、路径、类型和权限——哪怕 DescribedObject.APIVersion 多写一个 v,HPA 就会安静地当它不存在。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!










