VPA 频繁扩缩容怎么解决?3 个阈值参数配置,让 Kubernetes Pod 资源彻底稳定
【免费下载链接】autoscalerAutoscaling components for Kubernetes项目地址: https://gitcode.com/GitHub_Trending/au/autoscaler
凌晨两点,监控群里弹出一条告警:订单服务的 Pod 又在重启了。翻事件日志才发现,这不是偶发——过去一周里,Vertical Pod Autoscaler(VPA)几乎每 10 分钟就改一次 CPU 请求,每次改动都伴随一轮 Pod 重建,业务曲线跟着上下抖动。问题出在哪?答案藏在 VPA 的阈值配置里:默认情况下,VPA 对推荐值不加任何上下限约束,用量稍微一动,它就跟着动。本文以这个真实故障为线索,讲清楚如何用 minAllowed / maxAllowed、controlledResources、updateMode 三个阈值参数,把调整频率从"十分钟一次"压到"一天一次"。
复盘一次线上抖动:波动没有边界,调整就没有终点
先看这次故障的时间线:
- 现象:CPU 实际用量在 300m 到 800m 之间来回摆,VPA 推荐值跟着每次采样结果变化,每 10 分钟触发一次更新,Pod 反复重建。
- 根因:推荐值没有设上限和下限。用量涨一点,推荐值就往上跳一格;回落了,又往下一格。VPA 本意是持续观察 Pod 用量并给出推荐(机制细节可看 vertical-pod-autoscaler/docs/faq.md),但缺了"边界感",小幅波动被放大成了频繁扩缩容。
- 教训:阈值不是可选项,而是 VPA 能否稳定工作的前提。推荐值应该被限制在一个合理区间内,区间内的波动直接忽略,只有用量真正突破区间才值得调整。
下面这张架构图能帮你定位 VPA 的工作链路:推荐器算出建议值,admission controller 在 Pod 创建时写入请求,updater 负责存量 Pod 的更新(必要时驱逐重建)。频繁重启的根源通常就出在 updater 这一环。
第一招:用 minAllowed 和 maxAllowed 给推荐值装一个"限速带"
这两个字段写在 VPA 的resourcePolicy.containerPolicies里,分别圈定每个容器 CPU、内存推荐值能取到的下限和上限(字段定义见 vertical-pod-autoscaler/docs/api.md)。
可以把它理解成高速路的双侧护栏:车流(推荐值)只能在 500m 到 800m 这条"限速带"里走,带内的颠簸不触发任何动作。回到上面的故障,只要把 CPU 推荐值锁进这个区间,VPA 推荐器(部署参数参考 vertical-pod-autoscaler/deploy/recommender-deployment.yaml)再遇到 300m–800m 的来回摆动时,产出的推荐值始终贴着护栏,不会每次采样都改写请求。
配置时的经验法则:下限按"应用能正常跑"的最小用量定,上限按"预算允许"的最大用量定,两者之间的宽度就是你能接受的波动空间。
第二招:用 controlledResources 划分地盘,CPU 交给 HPA
如果 CPU 伸缩本来就有 HPA 在管,那最干净的做法是让 VPA 只管内存,把 CPU 彻底让出去——这就是controlledResources的用法(默认值是["cpu", "memory"],两者全管)。
- 写
["memory"]:VPA 只推荐内存,CPU 归 HPA 按副本数伸缩,两个控制器各管一摊,互不打架; - 写
["cpu"]:反过来,只托管 CPU(适合内存用量非常平稳、主要瓶颈是算力的场景)。
地盘划清楚之后,调整频率天然下降:一个控制器不再需要追着另一个控制器的动作反复修正。
第三招:把 updateMode 设为 InPlaceOrRecreate,更新不再等于重启
updatePolicy.updateMode决定了 VPA 拿到新推荐值之后怎么落地,共四种可选:
| 取值 | 行为 |
|---|---|
Off | 只出推荐值,不动存量 Pod,新 Pod 生效 |
Auto | 默认值,行为视集群能力而定 |
Recreate | 重建 Pod 使新请求生效,一定伴随重启 |
InPlaceOrRecreate | 优先原地 resize,做不到再回退重建 |
对频繁调整的场景,InPlaceOrRecreate是最优解:原地更新让容器直接在原 Pod 上调整资源,业务连接不断、流量不中断;只有原地 resize 不可行(节点资源不足、更新超时、QoS 等级会变化等)才回退到重建。四种模式的语义细节见 vertical-pod-autoscaler/docs/api.md,原地更新的限制与回退条件见 vertical-pod-autoscaler/docs/features.md。
一份可以直接抄走的 VPA 阈值配置
三个参数合到一起,完整配置如下(仓库里的示例见 vertical-pod-autoscaler/examples/hamster.yaml):
apiVersion: "autoscaling.k8s.io/v1" kind: VerticalPodAutoscaler metadata: name: order-service-vpa spec: targetRef: apiVersion: "apps/v1" kind: Deployment name: order-service resourcePolicy: containerPolicies: - containerName: '*' minAllowed: cpu: 500m # 推荐值下限:低于此值不再下调 memory: 200Mi maxAllowed: cpu: 800m # 推荐值上限:高于此值不再上调 memory: 500Mi controlledResources: ["cpu", "memory"] # 若 CPU 由 HPA 管理,可改为 ["memory"] updatePolicy: updateMode: "InPlaceOrRecreate" # 优先原地更新,失败才重建应用后观察一到两个调整周期:只要用量在 500m–800m 区间内波动,事件流里应该看不到任何新的资源更新记录。
三个最容易踩的坑,以及对应的排查手段
坑一:配置了却没生效。十有八九是 admission controller 没在运行——新 Pod 的请求全靠它写入,它不在,推荐值就只是"建议"。先执行kubectl get pod -n kube-system | grep vpa-admission-controller确认 Pod 存在且 Ready,再看它的日志定位原因;组件清单与部署文件参考 vertical-pod-autoscaler/deploy/,排查步骤在 vertical-pod-autoscaler/docs/faq.md 里有完整指引。
坑二:原地更新失败。InPlaceOrRecreate不是万能的,它依赖集群具备原地 resize 能力:Kubernetes 版本需 ≥ 1.33,且要在集群侧开启InPlacePodVerticalScaling特性门。版本或特性门不满足时,更新会静默回退成重建,看起来就像"改了配置但还重启"。
坑三:推荐值"异常"。如果 Pod 的 limits 被 namespace 里的 LimitRange 卡得过死,VPA 的推荐结果和实际写入值会出现偏差——VPA 优先遵循自己的资源策略,但 LimitRange 过严时会相互拉扯。发现推荐值不对劲时,先检查对应 namespace 的 LimitRange 配置再下结论。
结语:阈值是利用率与稳定性之间的天平
把三个参数配完,那个每 10 分钟重启一次的订单服务,调整频率降到了每天一次,CPU 请求稳定在 500m–800m 区间,业务曲线恢复了平滑。这背后其实是一个简单的权衡:minAllowed 压得太低等于没配,maxAllowed 抬得太高又浪费预算;controlledResources 划得越窄,控制器之间越安静;updateMode 越激进,落地越丝滑。所以最终答案永远是——先看应用真实用量分布,再决定护栏放哪里。阈值配对了,资源利用率与业务稳定性才能在同一台天平上站住。
【免费下载链接】autoscalerAutoscaling components for Kubernetes项目地址: https://gitcode.com/GitHub_Trending/au/autoscaler
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考