tags:
– Kubernetes
– K8s系列
– DevOps
– VPA
– Cluster Autoscaler
– 自动扩缩
– 弹性伸缩
K8s 系列 | 第 18 天:VPA 与 Cluster Autoscaler:资源与集群层的自动扩缩
第 18/30 天
引言
前两篇文章我们深入探讨了 HPA(水平 Pod 自动扩缩)的机制与实践。HPA 通过增减 Pod 副本数来应对负载变化,但有些场景下,HPA 并不是最佳选择——比如单体应用难以水平扩展,或者 Pod 的资源请求设置不合理导致资源浪费或性能瓶颈。这时,我们需要另外两个强大的自动扩缩组件:VPA(Vertical Pod Autoscaler,垂直 Pod 自动扩缩器) 和 Cluster Autoscaler(集群自动扩缩器)。
VPA 负责在 Pod 级别自动调整 CPU/内存的请求与限制,让每个 Pod 获得”刚好够用”的资源;Cluster Autoscaler 则在集群级别自动增减 Worker 节点数量,确保集群资源池与工作负载需求相匹配。三者结合(HPA + VPA + Cluster Autoscaler)构成了 Kubernetes 生产环境中完整的弹性伸缩体系。
本文将从原理到实战,详细讲解 VPA 和 Cluster Autoscaler 的工作机制、部署配置与最佳实践。
核心概念
什么是 VPA?
VPA(Vertical Pod Autoscaler)自动调整 Pod 中容器的 CPU 和内存资源请求(Requests)与限制(Limits),避免资源浪费或不足。与 HPA 增加/减少副本数不同,VPA 改变的是每个副本的资源规格。
VPA 的三种更新模式:
| 模式 | 行为 | 适用场景 |
|---|---|---|
Auto |
自动更新 Pod 资源,并在需要时驱逐重建 | 生产环境推荐 |
Recreate |
与 Auto 类似,始终通过驱逐重建来应用新资源值 | 需要严格保证生效时 |
Initial |
只在 Pod 创建时设置资源值,之后不再更改 | 新建工作负载的基线调优 |
Off |
仅提供资源推荐,不自动应用任何更改 | 仅做资源分析审计 |
核心原理: VPA 部署为三个组件:
- Recommender — 基于历史指标(来自 Metrics Server 或 Prometheus)计算推荐资源值
- Updater — 检查 Pod 的当前资源是否偏离推荐值,驱逐需要更新的 Pod
- Admission Controller — 拦截新建 Pod 的请求,重写其资源 Requests/Limits 为推荐值
什么是 Cluster Autoscaler?
Cluster Autoscaler(CA)自动调整集群的 Worker 节点数量。当 Pod 因资源不足而 Pending(挂起等待调度)时,CA 会扩容新节点;当节点长期低负载且其上所有 Pod 都可被调度到其他节点时,CA 会缩容释放节点。
工作流程:
Pod Pending(无可用节点)
↓
Cluster Autoscaler 检测到不可调度的 Pod
↓
调用云厂商 API 创建新节点(或内部资源池分配)
↓
节点就绪,Pod 调度成功
↓
长期低负载时,CA 排空(Drain)节点并缩容
云厂商支持: AWS(ASG)、GCP(MIG)、Azure(VMSS)、阿里云(ESS)、华为云(AS)等均有原生集成。裸金属或私有云可通过 clusterapi 或自定义 cloud provider 实现。
实战步骤
环境准备
确保集群已安装 Metrics Server:
kubectl apply -f https://github.com/kubernetes-sigs/metrics-server/releases/latest/download/components.yaml
kubectl get deployment metrics-server -n kube-system
第一步:部署 VPA
VPA 不是核心组件,需要单独安装:
# 下载 VPA 部署清单
git clone https://github.com/kubernetes/autoscaler.git
cd autoscaler/vertical-pod-autoscaler
# 部署所有组件(Recommender + Updater + Admission Controller)
./hack/vpa-up.sh
# 验证部署
kubectl get pods -n kube-system | grep vpa
预期输出类似:
vpa-admission-controller 1/1 Running
vpa-recommender 1/1 Running
vpa-updater 1/1 Running
第二步:创建示例应用并配置 VPA
创建一个 Deployment 用于演示:
apiVersion: apps/v1
kind: Deployment
metadata:
name: vpa-demo
namespace: default
spec:
replicas: 2
selector:
matchLabels:
app: vpa-demo
template:
metadata:
labels:
app: vpa-demo
spec:
containers:
- name: stress
image: polinux/stress
resources:
requests:
cpu: 50m
memory: 50Mi
command: ["stress"]
args:
- "--cpu"
- "1"
- "--vm"
- "1"
- "--vm-bytes"
- "80M"
- "--timeout"
- "300s"
创建对应的 VPA 对象,让 VPA 为其提供资源推荐:
apiVersion: autoscaling.k8s.io/v1
kind: VerticalPodAutoscaler
metadata:
name: vpa-demo-vpa
namespace: default
spec:
targetRef:
apiVersion: "apps/v1"
kind: Deployment
name: vpa-demo
updatePolicy:
updateMode: "Auto"
resourcePolicy:
containerPolicies:
- containerName: "*"
minAllowed:
cpu: 50m
memory: 50Mi
maxAllowed:
cpu: 2
memory: 2Gi
controlledResources: ["cpu", "memory"]
注意:
minAllowed和maxAllowed设置了资源调整的上下界,防止 VPA 过度调整导致 Pod 无法启动或资源浪费。
应用配置并观察推荐值:
kubectl apply -f vpa-demo-deploy.yaml
kubectl apply -f vpa-demo-vpa.yaml
# 等几分钟后查看 VPA 推荐值
kubectl describe vpa vpa-demo-vpa
在 Status.Recommendation.ContainerRecommendations 下会看到类似输出:
Container Recommendations:
stress:
Lower Bound:
Cpu: 50m
Memory: 524288k
Target:
Cpu: 280m
Memory: 587202k
Upper Bound:
Cpu: 685m
Memory: 1048576k
- Target — VPA 建议使用的资源值(将写入 Pod)
- Lower Bound — 资源下限,跌破此值应重新评估
- Upper Bound — 资源上限,超出此值应重新评估
第三步:部署 Cluster Autoscaler
以阿里云(ACK)为例,其他云厂商的配置参数类似但 API 不同:
# 假设集群 ID 为 c2345678901234567,区域为 cn-hangzhou
kubectl apply -f https://raw.githubusercontent.com/kubernetes/autoscaler/master/cluster-autoscaler/cloudprovider/alicloud/examples/cluster-autoscaler.yaml
# 修改 Deployment 的环境变量,指定节点池 ID 和区域
如果是 AWS EKS 环境:
apiVersion: apps/v1
kind: Deployment
metadata:
name: cluster-autoscaler
namespace: kube-system
spec:
replicas: 1
selector:
matchLabels:
app: cluster-autoscaler
template:
metadata:
labels:
app: cluster-autoscaler
spec:
serviceAccountName: cluster-autoscaler
containers:
- image: registry.k8s.io/autoscaling/cluster-autoscaler:v1.30.0
name: cluster-autoscaler
command:
- ./cluster-autoscaler
- --v=4
- --stderrthreshold=info
- --cloud-provider=aws
- --skip-nodes-with-local-storage=false
- --expander=least-waste
- --node-group-auto-discovery=asg:tag=k8s.io/cluster-autoscaler/enabled,k8s.io/cluster-autoscaler/<cluster-name>
- --balance-similar-node-groups=true
- --skip-nodes-with-system-pods=false
关键参数说明:
| 参数 | 作用 |
|---|---|
--expander=least-waste |
选择扩容时资源浪费最少的节点组 |
--skip-nodes-with-local-storage=false |
允许缩容有本地存储的节点 |
--balance-similar-node-groups |
保持相似节点组实例数量平衡 |
--max-nodes-total |
集群最大节点数,防止失控扩容 |
--scale-down-delay-after-add |
新节点加入后的缩容等待时间(默认 10 分钟) |
第四步:模拟触发 Cluster Autoscaler
创建一个大量请求资源的 Deployment,迫使 Pod Pending:
apiVersion: apps/v1
kind: Deployment
metadata:
name: ca-trigger-demo
namespace: default
spec:
replicas: 10
selector:
matchLabels:
app: ca-trigger
template:
metadata:
labels:
app: ca-trigger
spec:
containers:
- name: busybox
image: busybox
command: ["sleep", "3600"]
resources:
requests:
cpu: "1"
memory: "1Gi"
kubectl apply -f ca-trigger.yaml
# 观察 Pending 状态
kubectl get pods -w | grep Pending
# 查看 Cluster Autoscaler 日志
kubectl logs -n kube-system deployment/cluster-autoscaler --tail=50
CA 日志中会显示类似信息:
I0704 08:00:00.000000 1 static_autoscaler.go:239] 10 unschedulable pods
I0704 08:00:00.000000 1 scale_up.go:394] Scale-up: setting group ess-k8s-nodes size to 3->4
常见问题
1. VPA 与 HPA 能否同时使用?
不建议对同一指标同时使用 VPA 和 HPA。 如果 HPA 基于 CPU 使用率扩缩副本,同时 VPA 也在调整 CPU Request,二者会互相干扰,导致振荡行为。合理做法是:
- HPA 基于自定义指标(如 QPS、请求延迟)+ VPA 调整 基础资源 Requests
- 或者:HPA + Cluster Autoscaler 组合使用,VPA 用于非 HPA 的工作负载
2. VPA 驱逐 Pod 导致服务中断怎么办?
VPA 在 Auto 模式下通过驱逐重建来更新资源值。应对策略:
– 与 PodDisruptionBudget(PDB) 配合使用,确保最小可用副本数
– 对于无状态应用影响较小,有状态应用需谨慎
– 可以先使用 Initial 模式观察推荐值,确认合理后再切换为 Auto
3. Cluster Autoscaler 缩容太慢或误缩容?
- 调整
--scale-down-delay-after-add/--scale-down-delay-after-delete等延迟参数 - 使用
--scale-down-unneeded-time控制节点低负载后等待多久才缩容(默认 10 分钟) - 通过
--max-node-provision-time控制扩容超时
4. VPA 推荐值不准确?
- 确保 Metrics Server 或 Prometheus 采集正常
- VPA Recommender 需要至少 8 小时的历史数据才能给出稳定推荐
- 短期突发的流量峰值会导致推荐值偏高,可人工设定
maxAllowed上限
5. 私有云或裸金属如何使用 Cluster Autoscaler?
对于非云环境,有两种方案:
– Cluster API:通过声明式方式管理裸金属/虚拟化节点
– 自定义 Cloud Provider:实现 cloud provider 接口对接内部资源管理系统
三剑客协同架构
在生产环境中,HPA、VPA 和 Cluster Autoscaler 三者协同工作,构成完整的弹性伸缩体系:
用户请求 → [HPA: 增减 Pod 副本数] → 副本数变化 → [Cluster Autoscaler: 增减节点数]
↕
[VPA: 调整 Pod 资源规格]
推荐的分层策略:
| 层面 | 组件 | 职责 | 响应速度 |
|---|---|---|---|
| 应用层 | HPA | 基于业务指标增减副本 | 秒级~分钟级 |
| Pod 资源层 | VPA | 优化单个 Pod 的资源请求 | 分钟级 |
| 集群资源层 | Cluster Autoscaler | 动态调整节点数量 | 分钟级~十分钟级 |
总结
VPA 和 Cluster Autoscaler 是 Kubernetes 弹性伸缩体系中不可或缺的两大组件:
- VPA 解决的是”每个 Pod 该用多少资源”的问题,通过历史数据推荐最优资源值,减少资源浪费和性能瓶颈。适合单体应用、资源需求波动有规律的工作负载。
- Cluster Autoscaler 解决的是”集群需要多少节点”的问题,当资源不足时自动扩容节点,资源过剩时自动缩容节支。
- 三者结合(HPA + VPA + Cluster Autoscaler)可以实现从应用层到基础设施层的全栈自动弹性伸缩,是生产环境 K8s 集群的标配。
最佳实践速查表:
– ✅ 所有生产集群都应部署 Cluster Autoscaler,设定节点数上下限
– ✅ 无状态应用优先使用 HPA,有状态或单体应用考虑 VPA
– ✅ VPA 先用 Off 模式观察推荐值,分析合理后再开启 Auto
– ✅ 为关键服务配置 PDB,避免 VPA 驱逐导致服务中断
– ✅ Cluster Autoscaler 的 --expander 使用 least-waste 或 price 策略节省成本
下期预告
第 19 天:Job 与 CronJob:批处理与定时任务实战
在 K8s 中,并不是所有工作负载都需要 7×24 小时运行。批处理、数据导出、定时备份、日志清理等任务用 Job 和 CronJob 来处理再合适不过。下一篇文章我们将深入讲解 Job 的并行机制、CronJob 的调度陷阱,以及大规模批处理任务的资源管理策略。敬请期待!
📚 K8s 系列目录导航
– 第 1 天:Kubernetes 核心概念与架构全景解析
– 第 2 天:kubeadm 搭建第一个 K8s 集群
– 第 3 天:Pod 详解与生命周期管理
– 第 4 天:Deployment 与 ReplicaSet
– 第 5 天:Service 与网络基础
– 第 6 天:Namespace 与资源配额
– 第 7 天:ConfigMap 与 Secret
– 第 8 天:Volume 与 PersistentVolume
– 第 9 天:StorageClass 与动态存储供给
– 第 10 天:StatefulSet 有状态应用管理
– 第 11 天:Ingress 与 Ingress Controller
– 第 12 天:NetworkPolicy 网络安全策略
– 第 13 天:Headless Service 与服务发现
– 第 14 天:CSI 存储插件与生产存储选型
– 第 15 天:污点与容忍度
– 第 16 天:Node Affinity 与 Pod Affinity
– 第 17 天:HPA 水平自动扩缩
– 第 18 天:VPA 与 Cluster Autoscaler(本篇)
– 更多更新中……
本文为 K8s 30 天系列的第 18 篇,由自动化博客工作流生成。















暂无评论内容