主题
19 — 自动伸缩深度教材
自动伸缩是 K8s 的核心竞争力。本章覆盖 HPA/VPA/KEDA/Cluster Autoscaler 原理、协同、生产调优。
1. 四种伸缩机制
┌──────────────────┬────────────────────┬─────────────────────┐
│ 组件 │ 伸缩对象 │ 触发条件 │
├──────────────────┼────────────────────┼─────────────────────┤
│ HPA │ Pod 副本数 │ CPU/内存/自定义指标 │
│ VPA │ Pod resources │ 历史资源使用 │
│ KEDA │ Pod 副本数 │ 外部指标(MQ/Redis) │
│ Cluster Autoscaler│ Node 数量 │ Pending Pod │
└──────────────────┴────────────────────┴─────────────────────┘2. HPA(Horizontal Pod Autoscaler)
yaml
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: web-app-hpa
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: web-app
minReplicas: 2
maxReplicas: 20
behavior: # 伸缩行为控制
scaleUp:
stabilizationWindowSeconds: 60 # 扩容前稳定 60 秒
policies:
- type: Percent
value: 100 # 每次最多扩容 100%
periodSeconds: 60
scaleDown:
stabilizationWindowSeconds: 300 # 缩容前稳定 5 分钟(防止抖动)
policies:
- type: Percent
value: 10 # 每次最多缩容 10%
periodSeconds: 60
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 70 # CPU 使用率 70% 触发扩容
- type: Resource
resource:
name: memory
target:
type: Utilization
averageUtilization: 80bash
# 查看 HPA 状态
kubectl get hpa
# NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS
# web-app-hpa Deployment/web-app 45%/70% 2 20 5
# 调试 HPA
kubectl describe hpa web-app-hpa
# 查看 Events 中的伸缩决策
# HPA 不生效的常见原因:
# 1. metrics-server 未安装或不可用
# 2. Pod 未设置 resources.requests(无法计算使用率)
# 3. HPA min=max(固定副本数)3. VPA(Vertical Pod Autoscaler)
yaml
apiVersion: autoscaling.k8s.io/v1
kind: VerticalPodAutoscaler
metadata:
name: web-app-vpa
spec:
targetRef:
apiVersion: apps/v1
kind: Deployment
name: web-app
updatePolicy:
updateMode: "Auto" # Auto: 自动重启调整 / Off: 只建议不执行
resourcePolicy:
containerPolicies:
- containerName: app
minAllowed:
cpu: 100m
memory: 128Mi
maxAllowed:
cpu: 4
memory: 8Gibash
# VPA 建议值
kubectl describe vpa web-app-vpa
# 查看 Recommendation 中的 Target/Lower Bound/Upper Bound
# VPA vs HPA 冲突:
# VPA 和 HPA 不能同时基于 CPU/内存伸缩
# 解决方案:VPA Off + HPA 基于自定义指标4. KEDA(Kubernetes Event-Driven Autoscaling)
yaml
# KEDA 支持的外部指标源:
# Kafka/RabbitMQ 队列长度、Redis 列表长度、Prometheus 查询、AWS SQS 等
apiVersion: keda.sh/v1alpha1
kind: ScaledObject
metadata:
name: worker-scaler
spec:
scaleTargetRef:
name: worker
minReplicaCount: 0 # 可以缩到 0
maxReplicaCount: 50
triggers:
- type: kafka
metadata:
bootstrapServers: kafka:9092
consumerGroup: worker-group
topic: tasks
lagThreshold: "100" # 队列延迟超过 100 条触发扩容
- type: prometheus
metadata:
serverAddress: http://prometheus:9090
metricName: queue_length
query: sum(kafka_consumer_lag)
threshold: "1000"5. Cluster Autoscaler
Cluster Autoscaler 工作原理:
扩容:检测到 Pending Pod(无法调度)→ 请求云 API 创建新节点
缩容:检测到低使用率节点(<50%)且 Pod 可迁移 → 排空并删除节点
生产配置:
--scale-down-delay-after-add=10m # 新节点加入后 10 分钟内不缩容
--scale-down-unneeded-time=10m # 节点空闲 10 分钟后才缩容
--scale-down-utilization-threshold=0.5 # 使用率 <50% 才考虑缩容
--max-node-provision-time=15m # 节点创建超时
--max-nodes-total=100 # 总节点上限
PDB 保护:Cluster Autoscaler 缩容时会尊重 PDB6. 面试高频问题
Q: HPA 和 VPA 如何协同使用?
最佳实践:
1. VPA updateMode: Off(只建议不执行)
2. 参考 VPA 建议设置合理的 requests
3. HPA 基于 requests 百分比进行水平伸缩
4. 或者:VPA 管理内存 + HPA 基于 CPU/自定义指标水平伸缩
禁止:VPA 和 HPA 同时基于 CPU 伸缩(会冲突)Q: 如何实现缩到 0(完全停止)?
HPA 不支持 minReplicas=0
解决方案:
1. KEDA:支持缩到 0(基于外部事件触发)
2. 自定义 Controller:监听队列长度,0 时停止
3. Knative:Serverless 模式,无流量时缩到 0