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

hpa-demoapp.yaml
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 工作。

vpa-demoapp.yaml
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 等触发器。

keda-scaledobject.yaml
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 unknown

metrics-server 未就绪

查 kubectl top、metrics APIService

HPA 不扩

副本已达 max / 节点无容量

看 ScalingLimited、Pending Pod

VPA 不生效

updateMode Off / 需要重建

改 updateMode,观察驱逐

KEDA 不触发

触发器认证/查询错误

kubectl describe scaledobject

CA 不扩

节点池上限/实例类型无库存

查云配额与 cluster-autoscaler 日志

驱逐过多

PDB 缺失/Descheduler 过激

配 PDB、调阈值

13.1.9. 进阶挑战

  1. 用 KEDA 按 Kafka lag 扩容,观察缩容窗口。

  2. 用 VPA Off 模式给一个服务定 requests,再对比 HPA 行为。

  3. 用 Descheduler 重平衡一个热点节点,确保 PDB 生效。

  4. 用 Volcano 跑一个 gang scheduling 的批任务。

13.1.10. 小结

  • 伸缩分三层:副本、资源、节点;先定位瓶颈再选工具。

  • HPA 依赖指标链路,VPA 依赖重建,KEDA 依赖事件源。

  • 节点伸缩受 requests/affinity/taints/配额约束。

  • 批处理要与在线服务隔离,队列与 gang scheduling 是两件事。

13.1.11. 延伸阅读