痛点:90% 的团队在浪费资源或埋雷
在 Kubernetes 集群中,为 Pod 设定 requests 和 limits 是运维的基本功。但现实是:
- 设高了:CPU/Memory 大量空闲,集群利用率不到 30%,账单触目惊心
- 设低了:Pod 频繁 OOMKilled 或被 CPU throttle,业务抖动、告警不断
- 一设永不动:业务流量变化后,半年前的 requests 早已不匹配实际负载
HPA(水平自动扩缩容)解决的是"加减副本数"的问题,但单 Pod 的资源规格不合理,靠 HPA 怎么也救不回来。这时候就需要 VPA(Vertical Pod Autoscaler) — 自动调整单个 Pod 的 CPU/Memory requests,实现"纵向右定"。
方案:VPA 三大组件协作
VPA 由三个核心组件组成:
| 组件 | 职责 |
|---|---|
| Recommender | 分析历史 metrics,计算推荐的 requests/limits |
| Updater | 驱逐资源不匹配的 Pod,触发重建 |
| Admission Controller | 在新 Pod 创建时注入推荐的 resource 值 |
工作流程:Recommender 持续观测 → 生成推荐值 → Updater 驱逐旧 Pod → Admission Controller 给新 Pod 注入正确 requests。
实操步骤
第 1 步:部署 VPA
# 使用官方仓库部署(推荐 v1.2.x+)
git clone https://github.com/kubernetes/autoscaler.git
cd autoscaler/vertical-pod-autoscaler
# 部署全部组件到 kube-system 命名空间
./hack/vpa-up.sh
# 验证部署
kubectl get pods -n kube-system | grep vpa
# 预期输出:
# vpa-admission-controller-xxx Running
# vpa-recommender-xxx Running
# vpa-updater-xxx Running
第 2 步:创建 VPA 对象(推荐 Off 模式起步)
生产环境强烈建议先用 Off 模式观察推荐值,不要直接上 Auto:
apiVersion: autoscaling.k8s.io/v1
kind: VerticalPodAutoscaler
metadata:
name: my-app-vpa
namespace: production
spec:
targetRef:
apiVersion: apps/v1
kind: Deployment
name: my-app
updatePolicy:
updateMode: "Off" # 仅推荐,不自动执行
resourcePolicy:
containerPolicies:
- containerName: "*"
minAllowed:
cpu: 50m
memory: 64Mi
maxAllowed:
cpu: 2000m
memory: 4Gi
controlledResources: ["cpu", "memory"]
kubectl apply -f vpa-my-app.yaml
第 3 步:查看推荐值并评估
等待 24-48 小时积累数据后查看推荐:
kubectl describe vpa my-app-vpa -n production
输出中关注 Recommendation 部分:
Recommendation:
Container Recommendations:
Container Name: my-app
Lower Bound:
Cpu: 100m
Memory: 128Mi
Target:
Cpu: 250m
Memory: 512Mi
Upper Bound:
Cpu: 800m
Memory: 1536Mi
Uncapped Target:
Cpu: 250m
Memory: 512Mi
- Target:推荐值,适合作为 requests
- Lower Bound:最低安全值
- Upper Bound:峰值对应的上限,适合作为 limits 的参考
第 4 步:切换到 Auto 模式(可选)
确认推荐值合理后,切换为自动执行:
spec:
updatePolicy:
updateMode: "Auto" # 自动驱逐并重建 Pod
配合 PodDisruptionBudget 避免批量驱逐:
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
name: my-app-pdb
namespace: production
spec:
maxUnavailable: 1
selector:
matchLabels:
app: my-app
避坑指南
坑 1:VPA 与 HPA 同时管理 CPU 导致冲突
问题:VPA 调 CPU requests,HPA 也基于 CPU 利用率扩缩副本,两者打架。
解决:让 VPA 仅管理 Memory,HPA 管理 CPU:
# VPA 仅控制 memory
spec:
resourcePolicy:
containerPolicies:
- containerName: "*"
controlledResources: ["memory"]
controlledValues: RequestsOnly
或者使用 Kubernetes 1.27+ 的 In-Place Resource Resize(alpha 特性)配合 MultidimPodAutoscaler 同时处理。
坑 2:Auto 模式频繁驱逐 Pod 导致业务中断
问题:流量波动大时,VPA 频繁驱逐重建 Pod。
解决:
- 设置合理的 minAllowed/maxAllowed 收敛推荐范围
- 配合 PodDisruptionBudget 限制同时驱逐数量
- 对延迟敏感服务使用 updateMode: "Initial"(仅在 Pod 创建时生效,不主动驱逐)
坑 3:新 Pod 冷启动期间推荐值不准
问题:VPA Recommender 需要积累 metrics 历史,新部署的服务推荐值可能偏离。
解决:
- 至少观察 48 小时再信任推荐值
- 利用 minAllowed 设定安全底线,防止推荐值过低
- 结合 Prometheus 的 container_cpu_usage_seconds_total 和 container_memory_working_set_bytes 交叉验证
生产建议:VPA + Goldilocks 实现全集群可视化
单独看 kubectl describe vpa 效率太低。推荐部署 Goldilocks,它为命名空间下所有 Deployment 自动创建 VPA(Off 模式),并提供 Web Dashboard 展示推荐值:
# 安装 Goldilocks
helm install goldilocks fairwinds-stable/goldilocks \
--namespace goldilocks --create-namespace
# 为目标命名空间启用
kubectl label namespace production goldilocks.fairwinds.com/enabled=true
访问 Dashboard 即可看到所有服务的 requests 推荐值、当前值、偏差百分比 — 一目了然哪些服务在浪费资源。
总结
| 场景 | 推荐策略 |
|---|---|
| 刚接手集群,不确定 requests 设多少 | VPA Off 模式观察 48h → 手动调整 |
| 长期运行服务,流量平稳 | VPA Auto + PDB 保护 |
| HPA 已在管 CPU | VPA 仅管 Memory,避免冲突 |
| 全集群资源优化 | Goldilocks Dashboard 批量审计 |
核心结论:VPA 不是银弹,但它是从"拍脑袋定 requests"走向"数据驱动的资源配置"的关键一步。生产落地路径:Off 观察 → Initial 保守 → Auto 全自动,循序渐进,配合 PDB 和 Goldilocks 使用效果最佳。