弹性伸缩策略 (HPA/VPA/KEDA)
一句话:弹性伸缩是容量规划的自动化执行——HPA 按 CPU/内存扩 Pod,VPA 调整 Pod 资源配额,KEDA 按事件队列深度扩缩,Cluster Autoscaler 加节点。
弹性伸缩全景
graph TD
subgraph Pod 级
HPA[HPA<br/>水平扩缩 Pod 数]
VPA[VPA<br/>垂直调资源配额]
KEDA[KEDA<br/>事件驱动扩缩]
end
subgraph 节点级
CA[Cluster Autoscaler<br/>Pod Pending 加节点]
KARPENTER[Karpenter<br/>更快的节点供给]
end
subgraph 触发源
CPU[CPU/内存]
CUSTOM[自定义指标<br/>QPS/队列深度]
EVENT[事件源<br/>Kafka/Redis/PG]
end
CPU --> HPA
CPU --> VPA
CUSTOM --> HPA
CUSTOM --> KEDA
EVENT --> KEDA
HPA -->|Pod Pending| CA
KEDA -->|Pod Pending| CA
HPA 详解
工作原理
HPA 周期(默认 15 秒):
1. 查询指标(CPU/内存/自定义)
2. 计算: 期望副本数 = ceil(当前副本数 × (当前指标 / 目标指标))
3. 对比当前副本数,决定扩缩
4. 调用 Deployment scale
配置示例
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: api-gateway
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: api-gateway
minReplicas: 4
maxReplicas: 20
metrics:
# CPU 指标
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 65
# 内存指标
- type: Resource
resource:
name: memory
target:
type: Utilization
averageUtilization: 75
# 自定义指标(需 Prometheus Adapter)
- type: Pods
pods:
metric:
name: http_requests_per_second
target:
type: AverageValue
averageValue: "2000"
behavior:
scaleUp:
stabilizationWindowSeconds: 30
policies:
- type: Percent
value: 100
periodSeconds: 60
- type: Pods
value: 4
periodSeconds: 60
selectPolicy: Max
scaleDown:
stabilizationWindowSeconds: 300
policies:
- type: Percent
value: 25
periodSeconds: 120
selectPolicy: Min
HPA 扩缩公式
期望副本数 = ceil(当前副本数 × (当前指标值 / 目标指标值))
示例:
当前: 4 副本,CPU 平均 80%
目标: CPU 65%
期望 = ceil(4 × (80 / 65)) = ceil(4.92) = 5 副本
边界:
期望 < minReplicas → 取 minReplicas
期望 > maxReplicas → 取 maxReplicas
VPA 详解
工作原理
VPA 三种模式:
1. Auto (默认): 自动调整 request,需要重启 Pod
2. Recreate: 调整时重建 Pod
3. Initial: 只在 Pod 创建时设置 request,不修改运行中的
注意: VPA 和 HPA 不能同时用 CPU/内存指标(会冲突)
配置示例
apiVersion: autoscaling.k8s.io/v1
kind: VerticalPodAutoscaler
metadata:
name: worker-app
spec:
targetRef:
apiVersion: apps/v1
kind: Deployment
name: worker-app
updatePolicy:
updateMode: Auto # Auto / Off / Initial
resourcePolicy:
containerPolicies:
- name: worker
minAllowed:
cpu: 100m
memory: 200Mi
maxAllowed:
cpu: 4
memory: 8Gi
controlledResources: ["cpu", "memory"]
KEDA 详解
优势
KEDA vs HPA:
HPA: 适合 CPU/内存/QPS 驱动(稳态流量)
KEDA: 适合事件驱动(突发流量、队列积压)
KEDA 独特能力:
- 缩到 0(HPA minReplicas 最少 1)
- 支持多种事件源(Kafka/Redis/PG/AWS SQS/...)
- 更灵活的扩缩策略
配置示例:Kafka 消费者自动扩缩
apiVersion: keda.sh/v1alpha1
kind: ScaledObject
metadata:
name: kafka-consumer-scaler
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: kafka-consumer
minReplicaCount: 0 # 无消息时缩到 0
maxReplicaCount: 30
pollingInterval: 15 # 每 15 秒检查一次
cooldownPeriod: 60 # 缩容前等 60 秒
triggers:
- type: kafka
metadata:
bootstrapServers: kafka:9092
consumerGroup: order-consumer-group
topic: orders
lagThreshold: "100" # 每消费组 lag > 100 时扩容
offsetResetPolicy: latest
partitionLimitation: "0,1,2" # 限定分区
KEDA 支持的事件源
| 事件源 | 扩缩依据 |
|---|
| Kafka | 消费者 lag(积压量) |
| Redis | 队列长度 / List 长度 |
| PostgreSQL | 查询结果(如行数) |
| AWS SQS | 队列深度 |
| RabbitMQ | 队列消息数 |
| Prometheus | 自定义指标 |
| Cron | 定时扩缩(如整点扩容) |
Cluster Autoscaler
工作原理
当 Pod 处于 Pending 状态时:
1. CA 检查 Pending 原因
2. 如果是资源不足 → 触发新节点加入
3. 等待节点 Ready
4. 调度 Pod 到新节点
缩容时:
1. 找利用率低的节点
2. 驱逐 Pod(drain)
3. 删除节点
云厂商集成
| 云 | CA 实现 | 特点 |
|---|
| AWS | EKS Cluster Autoscaler / Karpenter | 原生集成 Auto Scaling Group |
| 阿里云 | ACK Cluster Autoscaler | 按 ESS 弹性伸缩组 |
| 腾讯云 | TKE CA | 按伸缩组 |
| 自建 | Cluster API + CA | 需自己管理节点 |
扩缩策略最佳实践
| 场景 | 推荐方案 | 原因 |
|---|
| Web API | HPA (CPU + QPS) + CA | 流量驱动、快速扩容 |
| 消息消费者 | KEDA (Kafka lag) | 事件驱动、可缩到 0 |
| 批处理 | KEDA (Cron) | 定时扩缩 |
| 数据库 | 不弹性(固定资源) | 有状态不宣频繁扩缩 |
| GPU 推理 | KEDA + DRA | GPU 资源驱动 |
扩缩参数调优表
| 参数 | 推荐值 | 说明 |
|---|
| HPA scaleUp stabilization | 30s | 防止频繁扩容 |
| HPA scaleDown stabilization | 300s | 防止频繁缩容 |
| HPA maxSurge (Percent) | 100% | 扩容速度:翻倍 |
| HPA scaleDown (Percent) | 25% | 缩容速度:温和 |
| KEDA pollingInterval | 15-30s | 检查频率 |
| KEDA cooldownPeriod | 60-120s | 缩容等待 |
| CA scanInterval | 10s | 节点扩缩检查频率 |
常见问题 / 坑点
| 问题 | 原因 | 解决方案 |
|---|
| HPA 不扩容 | 指标没配好 | 检查 Prometheus Adapter / custom metrics API |
| 扩容太慢 | Pod 启动慢 | 优化镜像大小 + readinessProbe + 预热 |
| 缩容导致抖动 | 缩容太快 | 增加 stabilizationWindowSeconds |
| VPA 和 HPA 冲突 | 同时调 CPU | VPA 只调内存,HPA 调 CPU;或只用一个 |
| CA 加节点太慢 | 云厂商供给慢 | 用 Karpenter / 预留节点池 |
| KEDA 缩到 0 后不扩 | 事件源连不上 | 检查 trigger 连接配置 |
关联知识
参考资源
状态