饮墨

子安饮墨馀三斗,留与卿儿作赋来

Kubernetes VPA 垂直自动扩缩容:告别拍脑袋设定 resource requests

痛点:90% 的团队在浪费资源或埋雷

在 Kubernetes 集群中,为 Pod 设定 requestslimits 是运维的基本功。但现实是:

  • 设高了: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_totalcontainer_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 使用效果最佳。

您还没有登录,请登录后发表评论。