Kubernetes弹性伸缩为什么需要HPA和VPA双引擎
Kubernetes容器编排中,弹性伸缩是保障服务稳定性和资源利用率的核心机制。HPA(Horizontal Pod Autoscaler)通过增减Pod副本数应对流量变化,VPA(Vertical Pod Autoscaler)通过调整Pod资源请求优化单Pod资源配置。两者解决的是不同层面的问题:HPA扩容解决”排不下的请求”,VPA调优解决”浪费资源的Pod”。
生产环境常见错误:只配HPA不配VPA,导致大量Pod资源配置偏高(内存申请4Gi实际只用800Mi),集群资源利用率低;或者只配VPA不配HPA,单Pod资源再大也扛不住流量洪峰。正确做法是两者配合使用,VPA保障合理基线,HPA应对弹性峰值。
HPA v2核心配置与指标类型
HPA v2支持三种指标源:Resource(CPU/内存)、Pods(自定义Pod指标)、Object/External(外部指标)。从Kubernetes 1.27起,HPA v2成为稳定API(autoscaling/v2)。
基础CPU伸缩配置:
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: web-api-hpa
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: web-api
minReplicas: 3
maxReplicas: 50
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 70
- type: Resource
resource:
name: memory
target:
type: Utilization
averageUtilization: 80
关键参数说明:
– minReplicas: 3:最小副本数,保障基础可用性
– maxReplicas: 50:最大副本数,防止无限扩容消耗集群资源
– averageUtilization: 70:CPU使用率目标70%,超过此值触发扩容
HPA计算公式:desiredReplicas = ceil[currentReplicas × (currentMetric / desiredMetric)]。例如3副本CPU使用率140%,目标70%,则 ceil[3 × (140/70)] = 6。
自定义指标HPA:QPS驱动扩容
CPU/内存是间接指标,对Web服务而言QPS(每秒请求数)是更直接的扩容信号。需要配合Prometheus Adapter将Prometheus指标暴露给HPA:
# Prometheus Adapter配置(ConfigMap)
apiVersion: v1
kind: ConfigMap
metadata:
name: prometheus-adapter-config
data:
config.yml: |
rules:
- seriesQuery: 'http_requests_total{namespace!="",pod!=""}'
resources:
overrides:
namespace: {resource: namespace}
pod: {resource: pod}
name:
matches: "http_requests_total"
as: "http_requests_per_second"
metricsQuery: 'sum(rate(http_requests_total{namespace="<<.Namespace>>",pod=~"<<.PodName>>.*"}[2m])) by (pod)'
HPA使用自定义QPS指标:
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: web-api-qps-hpa
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: web-api
minReplicas: 3
maxReplicas: 100
metrics:
- type: Pods
pods:
metric:
name: http_requests_per_second
target:
type: AverageValue
averageValue: 1000
每个Pod平均QPS超过1000时触发扩容,比CPU指标响应更快——QPS上升时CPU还没来得及飙升,HPA已经提前扩容。
HPA扩缩容行为控制与冷却
Kubernetes 1.18+支持behavior字段,精细控制扩缩容速率,防止流量毛刺导致的频繁抖动:
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: web-api-hpa
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: web-api
minReplicas: 3
maxReplicas: 50
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 70
behavior:
scaleUp:
stabilizationWindowSeconds: 0
policies:
- type: Percent
value: 100
periodSeconds: 60
- type: Pods
value: 5
periodSeconds: 60
selectPolicy: Max
scaleDown:
stabilizationWindowSeconds: 300
policies:
- type: Percent
value: 10
periodSeconds: 60
selectPolicy: Min
扩容策略解读:
– selectPolicy: Max:取Percent和Pods两个策略中扩容幅度更大的那个
– Percent: 100:每分钟最多翻倍扩容(3→6→12→24)
– Pods: 5:每分钟最多新增5个Pod
– 当副本数少于5时Pods策略生效,多于5时Percent策略生效
缩容策略解读:
– stabilizationWindowSeconds: 300:缩容前观察5分钟,防止流量短暂下降后回升导致的抖动
– Percent: 10:每分钟最多缩容10%的副本
– selectPolicy: Min:保守缩容,避免过快缩减
VPA资源推荐与自动调整
VPA有三个运行模式:
– Off:仅推荐,不自动调整(推荐用于初始部署阶段)
– Recommend:仅更新推荐,不重启Pod
– Auto:自动调整Pod资源请求并重启Pod
apiVersion: autoscaling.k8s.io/v1
kind: VerticalPodAutoscaler
metadata:
name: web-api-vpa
spec:
targetRef:
apiVersion: apps/v1
kind: Deployment
name: web-api
updatePolicy:
updateMode: "Auto"
resourcePolicy:
containerPolicies:
- containerName: '*'
minAllowed:
cpu: 100m
memory: 128Mi
maxAllowed:
cpu: "4"
memory: 8Gi
controlledResources: ["cpu", "memory"]
VPA推荐结果查看:
kubectl describe vpa web-api-vpa
# 输出中的Recommendation段
# Target: cpu=500m, memory=512Mi (推荐值)
# Lower Bound: cpu=200m, memory=256Mi (下限)
# Upper Bound: cpu=2, memory=4Gi (上限)
# Uncapped Target: cpu=450m, memory=480Mi (原始推荐值)
VPA的重要限制:Auto模式下调整资源会重建Pod(删除旧Pod创建新Pod),对有状态服务不友好。因此VPA更适合无状态服务,有状态服务建议使用Recommend模式人工审核后再调整。
HPA与VPA共存配置
HPA和VPA不能同时基于同一指标(CPU/内存)进行伸缩,否则会产生冲突。正确的共存方式:
– VPA负责CPU/内存资源的right-sizing(自动调整为合理值)
– HPA基于自定义指标(QPS、延迟、队列深度等)做水平伸缩
# VPA配置:只管CPU/内存right-sizing
apiVersion: autoscaling.k8s.io/v1
kind: VerticalPodAutoscaler
metadata:
name: web-api-vpa
spec:
targetRef:
apiVersion: apps/v1
kind: Deployment
name: web-api
updatePolicy:
updateMode: "Auto"
---
# HPA配置:基于QPS水平扩容
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: web-api-hpa
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: web-api
minReplicas: 3
maxReplicas: 50
metrics:
- type: Pods
pods:
metric:
name: http_requests_per_second
target:
type: AverageValue
averageValue: 1000
这种配置下,VPA持续优化每个Pod的资源请求(避免过度分配),HPA在流量增长时水平扩容(增加Pod数),两者互不干扰。
预测式扩容:KEDA与CronTrigger
HPA是响应式扩容——指标超过阈值才开始扩容,Pod启动需要时间(Java应用可能30-60秒),导致流量洪峰期间短暂过载。对于可预测的周期性流量(如每天早晚高峰),可以用KEDA的CronTrigger提前扩容:
apiVersion: keda.sh/v1alpha1
kind: ScaledObject
metadata:
name: web-api-cron-scaler
spec:
scaleTargetRef:
name: web-api
minReplicaCount: 3
maxReplicaCount: 50
triggers:
- type: cron
metadata:
timezone: Asia/Shanghai
start: 0 8 * * 1-5 # 工作日8点开始
end: 0 20 * * 1-5 # 工作日20点结束
desiredReplicas: "20" # 高峰期预扩到20副本
KEDA CronTrigger在指定时间段将副本数调整到目标值,配合HPA的maxReplicas上限,高峰期由HPA在20基础上继续扩容,非高峰期回退到3副本。这样就实现了”预扩容+弹性伸缩”的两级策略。
弹性伸缩监控与告警
弹性伸缩本身的健康状态也需要监控——HPA可能因为指标缺失而无法工作,或者因为Cluster Autoscaler资源不足导致Pod一直Pending:
# 查看HPA状态
kubectl get hpa web-api-hpa
# 关键字段
# TARGETS: 70%/70% (当前/目标) - 正常
# TARGETS: <unknown>/70% - 指标源故障
# REPLICAS: 3/3 - 未触发扩容
# REPLICAS: 3/20 - 已扩容到20
# 检查HPA事件
kubectl describe hpa web-api-hpa | grep -A5 Events
# 常见异常
# "the HPA was unable to compute the replica count" - 指标获取失败
# "failed to get memory utilization" - metrics-server未部署
# "insufficient cpu, memory" - 集群资源不足,Pod Pending
Prometheus告警规则:
groups:
- name: hpa_alerts
rules:
- alert: HPAUnableScale
expr: kube_hpa_status_condition{condition="ScalingLimited",status="true"} == 1
for: 10m
labels:
severity: warning
annotations:
summary: "HPA {{ $labels.hpa }} 扩容受限"
- alert: HPAReplicasAtMax
expr: kube_hpa_status_current_replicas == kube_hpa_spec_max_replicas
for: 15m
labels:
severity: critical
annotations:
summary: "HPA {{ $labels.hpa }} 已达最大副本数"
HPA达到最大副本数意味着当前配置可能无法承载更大流量,需要检查是否需要增加maxReplicas或优化应用性能。VPA达到最大资源限制同理,需要评估是否需要水平拆分服务。
以上方案从HPA基础配置、自定义指标驱动、扩缩容行为控制、VPA资源调优、双引擎共存到预测式扩容,覆盖了Kubernetes弹性伸缩在生产环境中的完整落地路径。
原创文章,作者:小编,如若转载,请注明出处:https://www.yunthe.com/kuberneteshpa-yu-vpa-tan-xing-shen-suo-shi-zhan-cong-zhi/