cpu/内存指标用targetaverageutilization,自定义指标(如qps)必须用targetaveragevalue;hpa不自动换算,混用会静默忽略;go需通过prometheus标准暴露指标并匹配metricselector。

HPA 配置里 targetAverageUtilization 和 targetAverageValue 到底该选哪个
看指标类型决定——CPU/内存用 targetAverageUtilization,自定义指标(比如 QPS、请求延迟)必须用 targetAverageValue。K8s 不会帮你自动换算:设成 targetAverageUtilization: 70 对 CPU 是“容器平均使用率 70%”,但对自定义指标直接报错 invalid metric source。
- CPU/内存指标走
metrics-server,天然支持百分比计算,targetAverageUtilization是最简路径 - Go 应用暴露的
http_requests_total或go_gc_duration_seconds属于 Prometheus 自定义指标,HPA 必须通过prometheus-adapter转成External或Object类型,然后用targetAverageValue指定阈值(比如每秒 100 个请求) - 别在 HPA YAML 里混用两种 target 字段,K8s 会静默忽略其中一个,扩容不触发还查不出原因
Go 程序里怎么暴露能被 HPA 读取的真实业务指标
不能只靠 expvar 或默认 /debug/metrics——HPA 不认这些格式。得走 Prometheus 标准暴露路径,且指标名、标签、类型要和 HPA 的 metricSelector 完全匹配。
- 用
prometheus/client_golang注册Gauge或Counter,例如:http_requests_total{method="POST",status="200"} - 在 HTTP handler 里主动
inc(),别依赖中间件自动埋点——压测时中间件可能被绕过,导致指标偏低,HPA 误判负载不足 - 指标采样周期要短(建议 ≤15s),否则 HPA 基于旧数据扩缩容,压测中看到延迟飙升却等 2 分钟才扩容
- 加一个健康检查 endpoint(如
/healthz),HPA 扩容前会先调它,如果 Go 程序启动慢或 GC 卡顿,这里超时会导致新 Pod 一直不加入服务发现
压测时 HPA 不扩容?先盯住 kubectl describe hpa 里的 Conditions
90% 的“不扩容”问题出在 Conditions 字段,不是逻辑写错了,是依赖链断了。
-
ScalingActive: False→ 检查metrics-server是否运行,kubectl top pods能否查到 CPU 数据 -
AbleToScale: False→ 常见于 RBAC 权限缺失,ServiceAccount 缺少custom.metrics.k8s.io的get权限 -
ScalingLimited: True→ 当前副本数已达maxReplicas,但压测流量还在涨——别急着改配置,先确认是不是指标采集延迟导致 HPA 还没看到真实峰值 - 用
kubectl get --raw /apis/custom.metrics.k8s.io/v1beta1/namespaces/default/pods/*/http_requests_total直接查原始指标值,比看 HPA Events 更快定位数据断点
Go 应用自身资源限制(resources.limits)怎么设才不拖累 HPA
limit 设太高,Pod 启动慢、GC 压力大、实际吞吐上不去,HPA 以为“还能撑”,结果压测时雪崩;设太低,频繁 OOMKilled,HPA 不停重建 Pod,压测曲线全是锯齿。
立即学习“go语言免费学习笔记(深入)”;
- CPU limit 建议 ≤2,Go runtime 在 >2 核时调度开销明显上升,
runtime.GOMAXPROCS默认等于 limit,别盲目设成4 - memory limit 必须高于 Go 程序常驻内存 + 峰值 GC 堆(可用
pprof抓/debug/pprof/heap看 live objects),留 20% 余量防突发分配 - 务必配
requests,且requests == limits(即禁用超售),否则 K8s 调度器按 requests 分配节点,但 HPA 按 limits 计算利用率,两者对不上 - 压测前跑一次
go tool pprof -http=:8080 http://pod-ip:6060/debug/pprof/heap,确认没有 goroutine 泄漏或大对象堆积
真正卡住压测效果的,往往不是 HPA 配置多复杂,而是 Go 程序没把指标打准、资源限制没对齐调度器预期、或者 metrics-server 根本没采集到数据——这三处一漏,压测就变成猜谜。