go服务需暴露prometheus格式/metrics指标,经prometheus adapter转换后hpa才能识别;须正确配置指标命名、端口、rbac及hpa yaml中averagevalue等字段。

Go 服务本身不“自定义 HPA 指标”,而是暴露 Prometheus 格式指标,再由 Prometheus Adapter 转成 HPA 可识别的 custom.metrics.k8s.io 接口数据——跳过这层适配,HPA 根本看不到你的业务指标。
Go 服务必须暴露 /metrics 且符合 Prometheus 规范
HPA 不直接抓 Go 进程,它只查 custom.metrics.k8s.io API;而该 API 的数据源几乎全是 Prometheus。所以第一步不是写 HPA YAML,是让 Go 正确吐出指标:
- 用
prometheus/client_golang注册Gauge(如go_app_queue_length)或Counter(如http_requests_total),**不能用大写字母或下划线命名 label**(user_id✅,UserID❌) - HTTP handler 必须挂载在
/metrics,且监听0.0.0.0:8080(Pod 内部网络可达) - Pod 的
container.ports需显式声明该端口,Service 若需复用同一端口,得加targetPort映射 - **严禁加 Basic Auth 或 bearer token**:
metrics-server和prometheus-adapter默认不带认证头拉取
prometheus-adapter 的 rules 配置必须精确匹配指标名和 label
Adapter 不是自动发现工具,它靠 rules 列表把原始 Prometheus 指标“翻译”成 K8s metrics API 能返回的结构。常见失败点:
-
seriesQuery必须能 match 到你的指标名,例如go_app_queue_length{job="go-microservice"}→seriesQuery: "go_app_queue_length" - 若想按 Deployment 维度聚合(HPA 所需),
resources必须设namespaced: true,并指定overrides把 label 映射为namespace和name -
metricsQuery中的sum(rate(...))时间窗口要合理(通常2m),太短易抖动,太长响应滞后 - 调试时直接
curl -k https://<k8s-apiserver>/apis/custom.metrics.k8s.io/v1beta2/namespaces/default/deployments/go-microservice/go_app_queue_length</k8s-apiserver>,看是否返回含value的 JSON;空数组=规则没匹配上
autoscaling/v2 HPA YAML 中 external 或 object 指标字段极易填错
v2 是唯一支持自定义指标的稳定版本,但结构比 v1 复杂得多。手写 MetricSpec 极易触发 Invalid value: "null" 错误:
-
type: External时,external.metricName和external.metricSelector.matchLabels必须同时存在;漏掉metricSelector就报 null -
target必须用averageValue(不是value),K8s 1.23+ 已弃用value字段 - 更稳妥的做法:先用
kubectl get hpa go-hpa -o yaml拉一个已生效的 HPA,复制其metrics块当模板,避免类型校验陷阱 - 动态指标名场景(如多租户不同队列名),改用
unstructured.Unstructured构造,绕过 client-go 对ExternalMetricSource的强结构约束
RBAC 和目标对象状态是常被忽略的硬性前提
即使指标和 YAML 全对,HPA 也会静默失效:
- 创建 HPA 的 ServiceAccount 必须有
autoscaling/v2的horizontalpodautoscalerscreate/update权限,apiGroups: ["autoscaling"]缺一不可 -
scaleTargetRef指向的 Deployment 必须与 HPA 同 namespace,且已处于Available状态(kubectl get deploy确认READY列非 0/0) - HPA 控制器默认每 15s 同步一次,但首次计算前会等待至少 5 分钟指标历史(防止冷启动误扩),别刚部署就查
kubectl describe hpa看 “unknown” 就以为失败
真正卡住人的从来不是 Go 怎么写指标,而是 adapter 规则里一个 label 名拼错、HPA YAML 里少了个 averageValue、或者 RBAC 没授权 get 权限导致控制器连 HPA 对象都读不到——这些地方没日志、不报错,只沉默。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!











