13.1. 自动伸缩与批处理调度:HPA、KEDA、Karpenter 与 Volcano
扩容不触发,通常不是 HPA 坏了,而是指标链路、资源请求、节点容量或调度约束其中一环断了。自动伸缩要按「Pod 数 → Pod 资源 → 节点数」三层拆开看,批处理则要把队列与调度器一起考虑。
- 层级:
L4 · 实战
- 难度:
进阶
- 预计:
50 分钟
- 前置:
HPA、requests/limits、调度基础
13.1.1. 三层伸缩
层 |
工具 |
解决 |
|---|---|---|
Pod 数量 |
HPA、KEDA |
副本不够 / 事件驱动 |
Pod 资源 |
VPA |
requests/limits 不合理 |
节点数量 |
Cluster Autoscaler、Karpenter |
节点容量不足 / 成本 |
重平衡 |
Descheduler |
碎片、热点、亲和漂移 |
批处理 |
Volcano、Kueue |
队列、 gang scheduling、配额 |
先判断瓶颈:HPA 显示 ScalingLimited 可能是节点没容量;VPA 建议值可能是负载周期变化;KEDA 不触发可能是 ScaledObject 的指标查询失败。
13.1.2. HPA 与 VPA
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: demoapp
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: demoapp
minReplicas: 2
maxReplicas: 10
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 60
behavior:
scaleDown:
stabilizationWindowSeconds: 300
VPA 适合「副本数不宜频繁变化、单 Pod 资源需要调整」的服务;它需要重建 Pod 才能应用新 requests,不能和 HPA 同时基于 CPU 工作。
apiVersion: autoscaling.k8s.io/v1
kind: VerticalPodAutoscaler
metadata:
name: demoapp
spec:
targetRef:
apiVersion: apps/v1
kind: Deployment
name: demoapp
updatePolicy:
updateMode: "Off"
先用 Off 观察推荐值,再切 Initial/Auto。生产环境不要直接对核心服务开 Auto,重建 Pod 的抖动可能比资源浪费更贵。
13.1.3. KEDA:事件驱动
KEDA 在 HPA 前面加一层事件感知,支持 Kafka 积压、RabbitMQ 队列、Prometheus 查询、Cron 等触发器。
apiVersion: keda.sh/v1alpha1
kind: ScaledObject
metadata:
name: order-consumer
spec:
scaleTargetRef:
name: order-consumer
minReplicaCount: 0
maxReplicaCount: 20
triggers:
- type: kafka
metadata:
bootstrapServers: kafka:9092
consumerGroup: order-consumer
topic: orders
lagThreshold: "100"
KEDA 可以把副本缩到 0,但冷启动与消息积压的延迟要单独评估;在线 API 不建议缩到 0。
13.1.4. 节点伸缩:CA 与 Karpenter
Cluster Autoscaler:当 Pod Pending 且节点池达到上限时扩容;兼容性好,配置多。
Karpenter:根据 Pod 的 resources/affinity/taints 直接选择实例类型,按需创建节点,适合 AWS 等云。
Descheduler:定期重平衡,解决节点碎片、热点与亲和漂移;要配合 PDB,避免同时驱逐太多。
节点伸缩的边界:Pod 的 requests 太大、亲和太严、污点不匹配时,扩容也不会成功。先看 Pending 事件,再看节点池配额。
13.1.5. 批处理:Volcano 与 Kueue
Volcano:gang scheduling、队列、公平共享,适合 AI/大数据批任务。
Kueue:Kubernetes 原生队列与配额管理,和 Job/JobSet 集成好。
批处理不要和在线服务共用同一节点池;用 taint/toleration 与 PriorityClass 隔离,避免批任务把在线服务挤掉。
13.1.6. 实验:VPA 推荐值 + KEDA 缩容
kubectl apply -f vpa-demoapp.yaml
kubectl describe vpa demoapp
kubectl apply -f keda-scaledobject.yaml
kubectl get scaledobject
kubectl get hpa
观察 VPA 的 status.recommendation 与 KEDA 创建的 HPA。把 Kafka 消息灌入,观察副本从 0/1 扩到 N,再停止生产,观察缩容窗口。
13.1.7. 验证清单
HPA 能读到指标,
ScalingActive=True。扩容受
maxReplicas/节点容量约束时,能在事件中看到原因。VPA 推荐值与实际使用量匹配,更新策略符合预期。
KEDA 缩到 0 后能冷启动,积压下降后能缩回。
节点伸缩与 PDB 配合,drain 不会中断全部副本。
批任务与在线服务通过 taint/priority 隔离。
13.1.8. 排错表
现象 |
原因 |
处理 |
|---|---|---|
HPA |
metrics-server 未就绪 |
查 |
HPA 不扩 |
副本已达 max / 节点无容量 |
看 |
VPA 不生效 |
updateMode Off / 需要重建 |
改 updateMode,观察驱逐 |
KEDA 不触发 |
触发器认证/查询错误 |
|
CA 不扩 |
节点池上限/实例类型无库存 |
查云配额与 |
驱逐过多 |
PDB 缺失/Descheduler 过激 |
配 PDB、调阈值 |
13.1.9. 进阶挑战
用 KEDA 按 Kafka lag 扩容,观察缩容窗口。
用 VPA
Off模式给一个服务定 requests,再对比 HPA 行为。用 Descheduler 重平衡一个热点节点,确保 PDB 生效。
用 Volcano 跑一个 gang scheduling 的批任务。
13.1.10. 小结
伸缩分三层:副本、资源、节点;先定位瓶颈再选工具。
HPA 依赖指标链路,VPA 依赖重建,KEDA 依赖事件源。
节点伸缩受 requests/affinity/taints/配额约束。
批处理要与在线服务隔离,队列与 gang scheduling 是两件事。