
这玩意儿,Kubernetes HPA,说简单也简单,只要一个 kubectl autoscale 就能搞定。但是,真正上了生产,你才会发现,那该死的“抖动”有多折磨人——一下扩容成 10 个,资源占满;一下又缩成 2 个,QPS 飙升又开始扩容... 最后整个集群 CPU 都被你的 HPA 吃掉了,业务还没扛住。😱
说实话,HPA 从来不是一个“开箱即用”的东西。 它更像一把双刃剑,用好了是降本增效的神器,用错了就是性能震荡的元凶。
今天,我就把在 InsurTech 场景下踩过的坑、调过度的经验,总结成 10 个核心技巧分享出来。希望能帮你少走弯路。
targetAverageUtilization 和 stabilizationWindowSeconds这俩参数是 HPA 的“稳定器”,必须配合使用。
targetAverageUtilization:目标利用率。它是一个相对值,而非绝对值。我通常会把 Pod 的资源请求(requests)作为基准,而不是限制(limits)。为什么?因为请求是调度器评估资源的基础,用它算更准。stabilizationWindowSeconds:稳定窗口。它告诉 HPA 在做出缩容(或扩容)决策前,观察多久的指标。默认是 5 分钟,对于大部分业务来说足够了,但对于突发流量场景,可以加到 3-5 分钟来避免“潮汐式抖动”。📝Notes: 不要把这个窗口设得太大,比如 10 分钟。如果指标一直处于较低水平,HPA 需要等待很久才能缩容,会浪费资源。
custom 和 external 指标CPU 和内存的利用率,只能反应容器层面的“健康状况”,但无法反映真实的业务负载。比如,你的服务是 I/O 密集型的,CPU 利用率低但 QPS 爆涨,这时候用 CPU HPA 就完全是“瞎子”。
我强烈建议你引入自定义指标,如 QPS、请求延迟、消息队列深度等。这些才是真正的“业务信号”。
# 部署 Prometheus Adapter,将 Prometheus 中的指标暴露给 HPA
kubectl apply -f https://raw.githubusercontent.com/kubernetes-sigs/prometheus-adapter/main/deploy/manifests/.这玩意儿经常被忽略。如果你没有给关键业务配置 PDB,那么在节点维护或滚动更新时,HPA 可以瞬间杀死所有 Pod,直接导致服务中断。
推荐做法: 为每个 HPA 管理的 Deployment 配置一个 PDB,确保在任何时候,至少有 minAvailable 个 Pod 在运行。
单个节点资源耗尽怎么办?HPA 只能管 Pod 的扩缩,管不了节点的扩展。如果不配合 Cluster Autoscaler(CA),你会面临“扩容到一半,节点资源耗尽”的尴尬局面。
最佳实践: 当 HPA 需要扩容时,CA 会监控节点资源。如果节点资源不足,CA 会自动申请新节点,等节点就绪后,HPA 再把 Pod 调度上去。但这也有坑,请看第 6 点。
你的镜像太大了?启动脚本太复杂了?数据库连接池预占资源太多?这些都会导致 Pod 启动缓慢,甚至在启动后的一段时间内无法提供正常服务。
这样,HPA 会继续增加 Pod 数量以补齐缺口,导致“过度扩容”。
我的建议:
这是 HPA + CA 最常见的坑。你设置了较低的 targetAverageUtilization,集群资源不足,CA 触发了扩容。节点几分钟后 ready,HPA 看到 Pod 跑起来了,但此时负载已经下降,HPA 立刻开始缩容...
结果: Pod 白跑了,节点白开了。😑
解决方案: 合理设置 stabilizationWindowSeconds 和 scale-down-delay(部分 HPA 实现支持)。另外,可以在 Deployment 中设置 terminationGracePeriodSeconds 给 Pod 足够的优雅退出时间,避免浪涌。
我见过太多人只配置 HPA,却从不去看它的状态。kubectl describe hpa 里的 Conditions 字段会告诉你 HPA 当前是否能计算指标、是否能获取指标、以及是否正在执行扩缩容。如果看到 FailedGetResourceMetric 或 FailedGetCustomMetric,赶紧排查。
HPA v2 支持同时配置多个指标(如 CPU + QPS)。当所有指标都满足条件时,HPA 才会缩容(AND 逻辑)。但扩容时,只要任一指标超标,就会触发扩容(OR 逻辑)。
这个设计很合理:扩容要激进,缩容要保守。
防止扩容后所有新 Pod 都被调度到同一个节点上。结合 CA,可以避免因单个节点故障影响整个服务。我推荐用 topologySpreadConstraints 实现。
kubectl run 压测不要等到线上出问题才来验证配置是否正确。
# 创建一个负载压力 Pod
kubectl run -i --tty load-generator --rm --image=busybox --restart=Never -- /bin/sh -c \"while true; do wget -q -O- <你的服务地址>; done\"通过观察 kubectl get hpa -w,你可以直观地看到 Pod 数量如何根据负载变化。
HPA 不是银弹,但它确实是 Kubernetes 弹性伸缩的核心。上面这 10 个技巧,你每用一个,就离“稳定、高效、省钱”的运维目标更近一步。
最后,我还要强调一点:投资于可观测性。没有全面的日志和指标,你永远无法真正理解 HPA 在做什么。这可能是比配置 HPA 更重要的事。
🎉🎉🎉
📚️参考文档
[1] Horizontal Pod Autoscaling - Kubernetes 官方文档: https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale/