从零开始的云原生之旅(十):HPA 完全指南:从原理到实践
从零开始的云原生之旅(十):HPA 完全指南:从原理到实践
配置 HPA 后,看着 Pod 自动扩缩容,太爽了!
📖 文章目录
- 前言
 - 一、HPA 核心概念深度解析 
- 1.1 HPA 的三个核心问题
 - 1.2 HPA 计算公式详解
 - 1.3 指标类型详解
 
 - 二、HPA 配置文件完全解读 
- 2.1 基础配置结构
 - 2.2 Metrics 配置详解
 - 2.3 Behavior 行为控制
 - 2.4 完整配置示例
 
 - 三、部署第一个 HPA 
- 3.1 创建 HPA 配置
 - 3.2 应用 HPA
 - 3.3 验证 HPA 状态
 - 3.4 我踩的坑:TARGETS 显示 unknown
 
 - 四、观察自动扩容 
- 4.1 准备监控窗口
 - 4.2 触发扩容
 - 4.3 扩容过程解析
 - 4.4 扩容时间线
 
 - 五、观察自动缩容 
- 5.1 停止负载
 - 5.2 缩容过程解析
 - 5.3 为什么缩容这么慢?
 
 - 六、HPA 行为策略详解 
- 6.1 ScaleUp 策略
 - 6.2 ScaleDown 策略
 - 6.3 稳定窗口的作用
 - 6.4 策略组合示例
 
 - 七、多指标 HPA 配置 
- 7.1 CPU + 内存双指标
 - 7.2 多指标计算逻辑
 - 7.3 指标优先级
 
 - 八、HPA 调优技巧 
- 8.1 如何让 HPA 更敏感?
 - 8.2 如何避免频繁抖动?
 - 8.3 如何快速扩容、缓慢缩容?
 - 8.4 如何设置合理的阈值?
 
 - 九、常见问题排查 
- 9.1 HPA 不工作
 - 9.2 HPA 显示 unknown
 - 9.3 HPA 扩容太慢
 - 9.4 HPA 频繁抖动
 - 9.5 Pod 被 OOMKilled
 
 - 结语
 
前言
在上一篇文章中,我完成了 HPA 的所有准备工作:
- ✅ 安装了 Metrics Server
 - ✅ 优化了资源配置
 - ✅ 添加了负载测试接口
 
现在,终于到了最激动人心的时刻 - 配置 HPA,看着 Pod 自动扩缩容!
这篇文章,我会:
- ✅ 深入理解 HPA 的工作原理
 - ✅ 手把手配置 HPA
 - ✅ 观察和分析自动扩缩容过程
 - ✅ 掌握 HPA 调优技巧
 - ✅ 记录所有踩过的坑
 
一、HPA 核心概念深度解析
1.1 HPA 的三个核心问题
HPA(HorizontalPodAutoscaler)要回答 3 个问题:
1. 什么时候扩容/缩容?→ 根据指标判断(CPU、内存、自定义指标)2. 扩容/缩容到多少个副本?→ 根据公式计算期望副本数3. 扩容/缩容的速度是多少?→ 根据 behavior 策略控制
 
1.2 HPA 计算公式详解
HPA 的核心计算公式:
期望副本数 = ceil(当前副本数 × (当前指标值 / 目标指标值))
 
ceil: 向上取整函数
举例 1 - CPU 扩容:
当前状态:
- 当前副本数: 2
- 当前 CPU 使用率: 140%
- 目标 CPU 使用率: 70%计算:
期望副本数 = ceil(2 × (140% / 70%))= ceil(2 × 2)= 4结果: 扩容到 4 个副本
 
举例 2 - 内存扩容:
当前状态:
- 当前副本数: 4
- 当前内存使用率: 90%
- 目标内存使用率: 80%计算:
期望副本数 = ceil(4 × (90% / 80%))= ceil(4 × 1.125)= ceil(4.5)= 5结果: 扩容到 5 个副本
 
举例 3 - 缩容:
当前状态:
- 当前副本数: 10
- 当前 CPU 使用率: 30%
- 目标 CPU 使用率: 70%计算:
期望副本数 = ceil(10 × (30% / 70%))= ceil(10 × 0.43)= ceil(4.3)= 5结果: 缩容到 5 个副本
 
关键点:
- 使用率 > 目标 → 扩容
 - 使用率 < 目标 → 缩容
 - 使用率 ≈ 目标 → 不变
 
1.3 指标类型详解
HPA 支持 4 种指标类型:
| 类型 | 说明 | 使用场景 | 示例 | 
|---|---|---|---|
| Resource | CPU、内存 | 最常用,90% 的场景 | CPU > 70% 扩容 | 
| Pods | 每个 Pod 的自定义指标 | 业务指标 | QPS > 100 扩容 | 
| Object | Kubernetes 对象的指标 | Service、Ingress | Ingress RPS > 1000 | 
| External | 外部指标 | 云平台、第三方服务 | SQS 队列长度 > 100 | 
本篇重点:Resource 类型(CPU 和内存)
二、HPA 配置文件完全解读
2.1 基础配置结构
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:name: api-hpa                    # HPA 名称
spec:scaleTargetRef:                  # 要控制的对象apiVersion: apps/v1kind: Deploymentname: cloudnative-api          # Deployment 名称minReplicas: 2                   # 最少副本数maxReplicas: 10                  # 最多副本数metrics:                         # 指标配置- type: Resourceresource:name: cputarget:type: UtilizationaverageUtilization: 70behavior:                        # 行为策略(可选)scaleUp: {}scaleDown: {}
 
2.2 Metrics 配置详解
CPU 指标配置:
metrics:
- type: Resource                   # 资源类型resource:name: cpu                      # CPU 指标target:type: Utilization            # 利用率类型averageUtilization: 70       # 目标 70%
 
计算方式:
CPU 利用率 = (实际使用的 CPU / requests.cpu) × 100%例如:
- requests.cpu: 100m
- 实际使用: 70m
- 利用率: 70%
 
内存指标配置:
metrics:
- type: Resourceresource:name: memory                   # 内存指标target:type: UtilizationaverageUtilization: 80       # 目标 80%
 
为什么内存阈值通常比 CPU 高?
- CPU 可以超用(throttling)
 - 内存超用 → OOMKilled(进程被杀)
 - 所以内存要留更多buffer(80% vs 70%)
 
绝对值配置(不常用):
metrics:
- type: Resourceresource:name: memorytarget:type: AverageValue           # 绝对值类型averageValue: "100Mi"        # 每个 Pod 平均 100Mi
 
2.3 Behavior 行为控制
为什么需要 behavior?
默认的 HPA 行为可能不符合你的需求:
- 扩容可能太慢(流量突增时)
 - 缩容可能太快(导致抖动)
 - 需要细粒度控制
 
Behavior 结构:
behavior:scaleUp:                         # 扩容策略stabilizationWindowSeconds: 0  # 稳定窗口(0 = 立即)policies:- type: Percent                # 百分比策略value: 100                   # 每次翻倍periodSeconds: 15            # 每 15 秒- type: Pods                   # 绝对数量策略value: 4                     # 或者增加 4 个periodSeconds: 15selectPolicy: Max              # 选择最激进的策略scaleDown:                       # 缩容策略stabilizationWindowSeconds: 300  # 5 分钟稳定期policies:- type: Podsvalue: 1                     # 每次减少 1 个periodSeconds: 60            # 每 60 秒selectPolicy: Min              # 选择最保守的策略
 
关键参数解释:
| 参数 | 作用 | 典型值 | 
|---|---|---|
| stabilizationWindowSeconds | 稳定窗口,防止抖动 | 扩容: 0-60s, 缩容: 300-600s | 
| type: Percent | 按百分比调整 | 50%(增加一半), 100%(翻倍) | 
| type: Pods | 按绝对数量调整 | 1-5 个 | 
| periodSeconds | 策略周期 | 15-60 秒 | 
| selectPolicy | 策略选择 | Max(激进), Min(保守) | 
2.4 完整配置示例
# k8s/v0.3/api/hpa.yaml
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:name: cloudnative-api-hpalabels:app: cloudnative-apiversion: v0.3
spec:# 1. 控制目标scaleTargetRef:apiVersion: apps/v1kind: Deploymentname: cloudnative-api# 2. 副本数范围minReplicas: 2                   # 最少保持 2 个(高可用)maxReplicas: 10                  # 最多扩展到 10 个# 3. 扩缩容指标metrics:# CPU 指标- type: Resourceresource:name: cputarget:type: UtilizationaverageUtilization: 70     # CPU 超过 70% 扩容# 内存指标- type: Resourceresource:name: memorytarget:type: UtilizationaverageUtilization: 80     # 内存超过 80% 扩容# 4. 扩缩容行为behavior:# 扩容策略:快速响应scaleUp:stabilizationWindowSeconds: 0    # 不等待,立即扩容policies:- type: Percentvalue: 100                     # 可以翻倍periodSeconds: 15              # 每 15 秒评估- type: Podsvalue: 2                       # 或者加 2 个periodSeconds: 60selectPolicy: Max                # 选择扩容更多的策略# 缩容策略:保守缓慢scaleDown:stabilizationWindowSeconds: 300  # 5 分钟稳定期policies:- type: Podsvalue: 1                       # 每次只减 1 个periodSeconds: 60              # 每 60 秒评估selectPolicy: Min                # 选择保守策略
 
三、部署第一个 HPA
3.1 创建 HPA 配置
创建文件 k8s/v0.3/api/hpa.yaml(内容见上面的完整示例)。
3.2 应用 HPA
# 应用 HPA 配置
kubectl apply -f k8s/v0.3/api/hpa.yaml# 输出:
# horizontalpodautoscaler.autoscaling/cloudnative-api-hpa created
 
3.3 验证 HPA 状态
Step 1: 查看 HPA 列表
kubectl get hpa
 
预期输出:
NAME                   REFERENCE                     TARGETS           MINPODS   MAXPODS   REPLICAS   AGE
cloudnative-api-hpa    Deployment/cloudnative-api    <unknown>/70%, <unknown>/80%   2         10        2          10s
 
等待 15-30 秒后再查看:
kubectl get hpa cloudnative-api-hpa
 
预期输出:
NAME                   REFERENCE                     TARGETS         MINPODS   MAXPODS   REPLICAS   AGE
cloudnative-api-hpa    Deployment/cloudnative-api    5%/70%, 15%/80%   2         10        2          45s
 
✅ TARGETS 显示实际值了!
TARGETS 字段解读:
5%/70%, 15%/80%
│  │    │  │
│  │    │  └─ 目标内存利用率: 80%
│  │    └──── 目标 CPU 利用率: 15%
│  └───────── 当前内存利用率: 70%
└──────────── 当前 CPU 利用率: 5%
 
Step 2: 查看详细信息
kubectl describe hpa cloudnative-api-hpa
 
输出示例:
Name:                                                  cloudnative-api-hpa
Namespace:                                             default
Labels:                                                app=cloudnative-apiversion=v0.3
Annotations:                                           <none>
CreationTimestamp:                                     Sun, 02 Nov 2025 16:30:00 +0800
Reference:                                             Deployment/cloudnative-api
Metrics:                                               ( current / target )resource cpu on pods  (as a percentage of request):  5% (5m) / 70%resource memory on pods  (as a percentage of request):  15% (19456Ki) / 80%
Min replicas:                                          2
Max replicas:                                          10
Deployment pods:                                       2 current / 2 desired
Conditions:Type            Status  Reason              Message----            ------  ------              -------AbleToScale     True    ReadyForNewScale    recommended size matches current sizeScalingActive   True    ValidMetricFound    the HPA was able to successfully calculate a replica count from cpu resource utilization (percentage of request)ScalingLimited  False   DesiredWithinRange  the desired count is within the acceptable range
Events:           <none>
 
关键字段解释:
- Metrics: 当前值 / 目标值
 - AbleToScale: 是否可以扩缩容
 - ScalingActive: 指标是否有效
 - Events: 扩缩容事件(初始时为空)
 
3.4 我踩的坑:TARGETS 显示 unknown
问题现象:
$ kubectl get hpa
NAME                   TARGETS           REPLICAS
cloudnative-api-hpa    <unknown>/70%     2
 
可能原因:
原因 1: Metrics Server 未安装或未就绪
# 检查 Metrics Server
kubectl get deployment metrics-server -n kube-system# 如果不存在或不就绪,重新安装
kubectl apply -f https://github.com/kubernetes-sigs/metrics-server/releases/latest/download/components.yaml# 本地环境需要打补丁
kubectl patch deployment metrics-server -n kube-system --type='json' -p='[{"op": "add","path": "/spec/template/spec/containers/0/args/-","value": "--kubelet-insecure-tls"}
]'
 
原因 2: Pod 未设置 resources.requests
# 检查 Pod 配置
kubectl get pod -l app=cloudnative-api -o yaml | grep -A 5 "resources:"# 确保有 requests 配置:
# resources:
#   requests:
#     cpu: 100m
#     memory: 128Mi
 
原因 3: 指标还没收集(刚启动)
# 等待 30-60 秒让 Metrics Server 收集数据
sleep 30
kubectl get hpa cloudnative-api-hpa
 
原因 4: Pod 未就绪
# 检查 Pod 状态
kubectl get pods -l app=cloudnative-api# 确保所有 Pod 都是 Running 且 READY 是 1/1
 
原因5:负载太高了,Pod没办法及时处理健康探针和准备探针,Pod不断重启,无法收集信息
四、观察自动扩容
4.1 准备监控窗口
强烈建议打开 4 个终端窗口同时监控:
终端 1 - HPA 实时监控:
kubectl get hpa cloudnative-api-hpa -w
 
终端 2 - Pod 实时监控:
kubectl get pods -l app=cloudnative-api -w
 
终端 3 - 资源使用监控(PowerShell):
while ($true) {Clear-HostWrite-Host "=== $(Get-Date -Format 'HH:mm:ss') ===" -ForegroundColor Cyankubectl top pods -l app=cloudnative-apiStart-Sleep -Seconds 5
}
 
终端 4 - 执行命令:
# 用于发送负载请求
 
4.2 触发扩容
方式 1: 循环发送 CPU 负载(PowerShell):
# 获取 Service URL(Minikube)
$serviceUrl = minikube service cloudnative-api-service --url# 循环发送 50 个请求
for ($i = 1; $i -le 50; $i++) {Write-Host "Request $i" -ForegroundColor YellowInvoke-WebRequest -Uri "$serviceUrl/api/v1/workload/cpu?iterations=30000000" -TimeoutSec 30 | Out-NullStart-Sleep -Milliseconds 100
}
 
方式 2: 并发发送请求(Bash):
# 并发 10 个请求
for i in {1..10}; do(curl -s "$SERVICE_URL/api/v1/workload/cpu?iterations=30000000" &)
done
 
4.3 扩容过程解析
观察终端 1(HPA)的变化:
TIME    TARGETS         REPLICAS
16:30   5%/70%, 15%/80%    2        ← 初始状态:低负载
16:31   85%/70%, 25%/80%   2        ← 负载上升:CPU 超过目标
16:31   85%/70%, 25%/80%   4        ← 扩容触发:2 → 4
16:32   65%/70%, 30%/80%   4        ← 新 Pod 分担负载
16:33   45%/70%, 20%/80%   4        ← 趋于稳定
 
观察终端 2(Pod)的变化:
NAME                               READY   STATUS              AGE
cloudnative-api-xxxxxxxxx-aaa      1/1     Running             10m    ← 原有
cloudnative-api-xxxxxxxxx-bbb      1/1     Running             10m    ← 原有
cloudnative-api-xxxxxxxxx-ccc      0/1     Pending             1s     ← 新建(等待调度)
cloudnative-api-xxxxxxxxx-ddd      0/1     Pending             1s     ← 新建(等待调度)
cloudnative-api-xxxxxxxxx-ccc      0/1     ContainerCreating   5s     ← 创建容器
cloudnative-api-xxxxxxxxx-ddd      0/1     ContainerCreating   5s
cloudnative-api-xxxxxxxxx-ccc      1/1     Running             15s    ← 就绪
cloudnative-api-xxxxxxxxx-ddd      1/1     Running             15s    ← 就绪
 
观察终端 3(资源)的变化:
=== 16:30:00 ===
NAME                               CPU(cores)   MEMORY(bytes)
cloudnative-api-xxxxxxxxx-aaa      15m          85Mi          ← 空闲
cloudnative-api-xxxxxxxxx-bbb      18m          90Mi=== 16:31:00 ===
NAME                               CPU(cores)   MEMORY(bytes)
cloudnative-api-xxxxxxxxx-aaa      180m         150Mi         ← 高负载!
cloudnative-api-xxxxxxxxx-bbb      175m         145Mi=== 16:32:00 ===
NAME                               CPU(cores)   MEMORY(bytes)
cloudnative-api-xxxxxxxxx-aaa      95m          120Mi         ← 负载分散
cloudnative-api-xxxxxxxxx-bbb      90m          118Mi
cloudnative-api-xxxxxxxxx-ccc      88m          115Mi         ← 新 Pod
cloudnative-api-xxxxxxxxx-ddd      92m          120Mi         ← 新 Pod
 
4.4 扩容时间线
完整的扩容时间线:
T+0s    负载开始,CPU 从 5% 上升
T+15s   Metrics Server 采集到新指标
T+15s   HPA 检查指标,发现 CPU 85% > 70%
T+16s   HPA 计算:ceil(2 × 85% / 70%) = 3但由于 behavior 策略允许翻倍,决定扩到 4
T+16s   HPA 更新 Deployment.replicas = 4
T+17s   Deployment 创建 2 个新 Pod(Pending)
T+20s   调度器分配节点,Pod 状态变为 ContainerCreating
T+25s   容器启动,应用初始化
T+30s   Startup Probe 通过
T+35s   Readiness Probe 通过,Pod 变为 Running (1/1)
T+35s   Service 开始将流量分发到新 Pod
T+40s   负载均衡,CPU 从 85% 降至 65%
T+50s   系统稳定
 
关键延迟:
- Metrics 采集延迟:15 秒
 - HPA 计算延迟:<1 秒
 - Pod 启动延迟:15-20 秒
 - 总延迟:30-40 秒
 
五、观察自动缩容
5.1 停止负载
# 按 Ctrl+C 停止发送请求# 或者等待所有请求完成
 
5.2 缩容过程解析
观察 HPA 的变化:
TIME    TARGETS         REPLICAS
16:35   45%/70%, 20%/80%   4        ← 负载停止
16:36   15%/70%, 18%/80%   4        ← CPU 降低
16:37   10%/70%, 16%/80%   4        ← 仍然 4 个
16:38   8%/70%, 15%/80%    4        ← 稳定窗口中...
16:39   5%/70%, 15%/80%    4        ← 稳定窗口中...
...     (等待 5 分钟)
16:40   5%/70%, 15%/80%    4        ← 稳定窗口中...
16:41   5%/70%, 15%/80%    3        ← 缩容:4 → 3
16:42   6%/70%, 16%/80%    3        ← 观察中
16:43   5%/70%, 15%/80%    2        ← 缩容:3 → 2
16:44   5%/70%, 15%/80%    2        ← 回到最小值
 
观察 Pod 的变化:
=== 16:41:00 ===
cloudnative-api-xxxxxxxxx-aaa      1/1     Running       10m
cloudnative-api-xxxxxxxxx-bbb      1/1     Running       10m
cloudnative-api-xxxxxxxxx-ccc      1/1     Running       5m
cloudnative-api-xxxxxxxxx-ddd      1/1     Terminating   5m    ← 被终止=== 16:43:00 ===
cloudnative-api-xxxxxxxxx-aaa      1/1     Running       10m
cloudnative-api-xxxxxxxxx-bbb      1/1     Running       10m
cloudnative-api-xxxxxxxxx-ccc      1/1     Terminating   5m    ← 又一个被终止=== 16:44:00 ===
cloudnative-api-xxxxxxxxx-aaa      1/1     Running       10m   ← 保留
cloudnative-api-xxxxxxxxx-bbb      1/1     Running       10m   ← 保留
 
5.3 为什么缩容这么慢?
缩容比扩容慢得多!为什么?
原因 1: 稳定窗口(Stabilization Window)
behavior:scaleDown:stabilizationWindowSeconds: 300  # 5 分钟
 
- HPA 会观察过去 5 分钟内的最高指标值
 - 只有持续 5 分钟低于目标,才会缩容
 - 防止频繁抖动
 
原因 2: 保守的缩容策略
policies:
- type: Podsvalue: 1              # 每次只减 1 个periodSeconds: 60     # 每 60 秒
 
- 每分钟最多缩减 1 个 Pod
 - 从 4 → 2 需要 2 分钟(还要加上稳定窗口)
 
为什么要这样设计?
场景 1:快速扩容
- 流量突增 → 服务卡顿 → 用户流失
- 影响:严重!
- 策略:立即扩容(0 秒稳定窗口)场景 2:快速缩容
- 流量短暂下降 → 立即缩容 → 流量再次上升 → 又要扩容
- 影响:频繁抖动,浪费资源
- 策略:缓慢缩容(5 分钟稳定窗口)
 
设计原则:
宁可多保留一会儿 Pod(多花点钱)
也不能让服务卡顿(影响用户体验)
六、HPA 行为策略详解
6.1 ScaleUp 策略
策略 1:百分比策略
scaleUp:policies:- type: Percentvalue: 50          # 增加 50%periodSeconds: 60
 
举例:
当前: 4 个 Pod
策略: 50% 每 60 秒
计算: 4 × 50% = 2
结果: 每分钟最多增加 2 个 Pod
 
策略 2:绝对数量策略
scaleUp:policies:- type: Podsvalue: 3           # 增加 3 个periodSeconds: 60
 
举例:
当前: 2 个 Pod
策略: +3 每 60 秒
结果: 每分钟最多增加 3 个 Pod
 
策略 3:组合策略
scaleUp:policies:- type: Percentvalue: 100         # 翻倍periodSeconds: 15- type: Podsvalue: 4           # 或者 +4periodSeconds: 15selectPolicy: Max    # 选择更激进的
 
举例:
当前: 3 个 Pod
策略 1(翻倍): 3 × 100% = 3 → 总共 6 个
策略 2(+4): 3 + 4 = 7 个
selectPolicy: Max → 选择 7 个
 
6.2 ScaleDown 策略
保守策略(推荐):
scaleDown:stabilizationWindowSeconds: 300  # 5 分钟policies:- type: Podsvalue: 1                       # 每次 -1periodSeconds: 60              # 每分钟selectPolicy: Min                # 保守
 
激进策略(不推荐):
scaleDown:stabilizationWindowSeconds: 60   # 仅 1 分钟policies:- type: Percentvalue: 50                      # 减半periodSeconds: 30selectPolicy: Max                # 激进
 
为什么不推荐激进缩容?
- 容易导致频繁抖动
 - 用户体验差(响应时间忽快忽慢)
 - 反而浪费资源(不断创建/删除 Pod)
 
6.3 稳定窗口的作用
没有稳定窗口的问题:
16:00  流量高 → CPU 80% → 扩到 6 个
16:02  流量降 → CPU 40% → 缩到 3 个
16:04  流量高 → CPU 80% → 扩到 6 个
16:06  流量降 → CPU 40% → 缩到 3 个
...    不断抖动!
 
有稳定窗口(5 分钟):
16:00  流量高 → CPU 80% → 扩到 6 个
16:02  流量降 → CPU 40% → 开始观察
16:03  流量高 → CPU 70% → 取消缩容
16:05  流量降 → CPU 40% → 开始观察
16:10  持续低负载 5 分钟 → 缩到 3 个
 
稳定窗口算法:
HPA 在决定缩容时,会查看过去 N 秒的历史指标
取其中的最大值进行计算例如:稳定窗口 = 300 秒
16:10 时的指标历史:
- 16:05: 40%
- 16:06: 50%  ← 最大值
- 16:07: 45%
- 16:08: 42%
- 16:09: 40%
- 16:10: 38%计算时使用: 50%(最大值)
只有当 50% < 70% 且持续 5 分钟,才缩容
 
6.4 策略组合示例
场景 1:电商秒杀(快速扩容,慢速缩容)
behavior:scaleUp:stabilizationWindowSeconds: 0policies:- type: Percentvalue: 200             # 可以 3 倍扩容periodSeconds: 15- type: Podsvalue: 10              # 或者直接 +10periodSeconds: 15selectPolicy: MaxscaleDown:stabilizationWindowSeconds: 600  # 10 分钟policies:- type: Podsvalue: 1periodSeconds: 120     # 每 2 分钟 -1selectPolicy: Min
 
场景 2:夜间定时任务(允许快速缩容)
behavior:scaleUp:stabilizationWindowSeconds: 30policies:- type: Podsvalue: 5periodSeconds: 60scaleDown:stabilizationWindowSeconds: 60   # 仅 1 分钟policies:- type: Percentvalue: 50              # 可以快速减半periodSeconds: 30
 
七、多指标 HPA 配置
7.1 CPU + 内存双指标
metrics:
# CPU 指标
- type: Resourceresource:name: cputarget:type: UtilizationaverageUtilization: 70# 内存指标
- type: Resourceresource:name: memorytarget:type: UtilizationaverageUtilization: 80
 
7.2 多指标计算逻辑
HPA 会为每个指标单独计算期望副本数,然后取最大值。
示例:
当前副本数: 2指标 1 - CPU:
- 当前: 50%
- 目标: 70%
- 计算: ceil(2 × 50% / 70%) = 2指标 2 - 内存:
- 当前: 85%
- 目标: 80%
- 计算: ceil(2 × 85% / 80%) = 3最终结果: max(2, 3) = 3 个副本
 
逻辑:
期望副本数 = MAX(根据 CPU 计算的副本数,根据内存计算的副本数,...其他指标
)
 
为什么取最大值?
- 确保所有指标都满足
 - 避免某个指标超限
 
7.3 指标优先级
问题:CPU 和内存哪个更重要?
# ❌ 错误:只配置 CPU
metrics:
- type: Resourceresource:name: cputarget:averageUtilization: 70# 问题:内存可能达到 100%,导致 OOMKilled
 
# ✅ 正确:同时配置 CPU 和内存
metrics:
- type: Resourceresource:name: cputarget:averageUtilization: 70
- type: Resourceresource:name: memorytarget:averageUtilization: 80# 任何一个超标都会触发扩容
 
建议:
- 始终配置 CPU 和内存双指标
 - CPU 阈值:60-70%
 - 内存阈值:70-80%(留更多 buffer)
 
八、HPA 调优技巧
8.1 如何让 HPA 更敏感?
降低目标利用率:
# 更敏感(容易触发扩容)
metrics:
- type: Resourceresource:name: cputarget:averageUtilization: 50  # 降低到 50%
 
效果:
- CPU 超过 50% 就扩容
 - 更早响应负载变化
 - 但会增加资源成本
 
降低 requests:
resources:requests:cpu: "50m"     # 降低 requestslimits:cpu: "500m"    # limits 不变
 
效果:
- 利用率 = 实际使用 / requests
 - requests 越小,利用率越容易超标
 - 更容易触发 HPA
 
8.2 如何避免频繁抖动?
增加稳定窗口:
behavior:scaleDown:stabilizationWindowSeconds: 600  # 增加到 10 分钟
 
增加缩容间隔:
behavior:scaleDown:policies:- type: Podsvalue: 1periodSeconds: 120  # 增加到 2 分钟
 
增加 minReplicas:
spec:minReplicas: 3  # 提高最小值maxReplicas: 10
 
效果:
- 保持更多 Pod,减少缩容次数
 - 更好的抗冲击能力
 
8.3 如何快速扩容、缓慢缩容?
这是最佳实践!
behavior:scaleUp:stabilizationWindowSeconds: 0     # 立即扩容policies:- type: Percentvalue: 100periodSeconds: 15                # 快速翻倍selectPolicy: MaxscaleDown:stabilizationWindowSeconds: 300   # 5 分钟观察policies:- type: Podsvalue: 1periodSeconds: 60                # 缓慢缩容selectPolicy: Min
 
原理:
- 扩容影响用户体验 → 必须快
 - 缩容只影响成本 → 可以慢
 
8.4 如何设置合理的阈值?
经验值表:
| 应用类型 | CPU 阈值 | 内存阈值 | 原因 | 
|---|---|---|---|
| API 服务 | 60-70% | 70-80% | 平衡性能和成本 | 
| 计算密集型 | 70-80% | 60-70% | CPU 是瓶颈 | 
| 内存密集型 | 50-60% | 70-80% | 内存是瓶颈,要留 buffer | 
| 关键业务 | 50-60% | 60-70% | 性能优先 | 
| 非关键业务 | 70-80% | 80-90% | 成本优先 | 
测试方法:
- 先设置保守值(50%/60%)
 - 压测观察
 - 逐步提高阈值
 - 找到性能和成本的平衡点
 
九、常见问题排查
9.1 HPA 不工作
现象:负载很高,但 HPA 不扩容
排查步骤:
# 1. 检查 HPA 状态
kubectl describe hpa cloudnative-api-hpa# 查看 Conditions 部分:
# - AbleToScale: 是否可以扩缩容
# - ScalingActive: 指标是否有效
# - ScalingLimited: 是否达到上限
 
常见原因:
原因 1:已达到 maxReplicas
ScalingLimited  True  TooManyReplicas  the desired replica count is more than the maximum replica count
 
解决:增加 maxReplicas
原因 2:Pod 无 resources.requests
ScalingActive  False  FailedGetResourceMetric  missing request for cpu
 
解决:在 Deployment 中添加 resources.requests
原因 3:Metrics Server 问题
ScalingActive  False  FailedGetResourceMetric  unable to get metrics for resource cpu
 
解决:检查并修复 Metrics Server
9.2 HPA 显示 unknown
见本文 3.4 我踩的坑:TARGETS 显示 unknown
9.3 HPA 扩容太慢
原因分析:
- Metrics 采集延迟(15 秒)
 - HPA 检查间隔(15 秒)
 - Pod 启动时间(10-30 秒)
 
优化方案:
方案 1:降低阈值
metrics:
- type: Resourceresource:name: cputarget:averageUtilization: 50  # 降低阈值
 
方案 2:激进的扩容策略
behavior:scaleUp:stabilizationWindowSeconds: 0policies:- type: Percentvalue: 200     # 可以 3 倍扩容periodSeconds: 15
 
方案 3:提高 minReplicas
spec:minReplicas: 5   # 保持更多 Pod
 
9.4 HPA 频繁抖动
现象:副本数不断变化(2 → 4 → 2 → 4)
原因:
- 稳定窗口太短
 - 缩容策略太激进
 - 阈值设置不合理
 
解决方案:
behavior:scaleDown:stabilizationWindowSeconds: 600  # 增加到 10 分钟policies:- type: Podsvalue: 1periodSeconds: 120  # 每 2 分钟 -1
 
9.5 Pod 被 OOMKilled
现象:扩容过程中,Pod 突然被杀
kubectl describe pod cloudnative-api-xxx
# 查看 Events:
# OOMKilled  Container cloudnative-api was killed due to OOM
 
原因:内存 limits 太小
解决:
resources:requests:memory: "128Mi"limits:memory: "512Mi"  # 提高 limits(原来 256Mi)
 
结语
这篇文章中,我深入学习了 HPA 的配置和实战:
✅ 我学到了什么
-  
HPA 核心原理
- 计算公式:期望副本数 = 当前副本数 × (当前指标 / 目标指标)
 - 多指标取最大值
 - 每 15 秒检查一次
 
 -  
HPA 配置详解
- scaleTargetRef:控制目标
 - metrics:扩缩容指标(CPU、内存)
 - behavior:扩缩容策略
 - minReplicas/maxReplicas:范围控制
 
 -  
Behavior 策略
- scaleUp:快速响应(0 秒稳定窗口)
 - scaleDown:保守缩容(300 秒稳定窗口)
 - 稳定窗口防止抖动
 
 -  
扩缩容过程
- 扩容:30-40 秒
 - 缩容:5+ 分钟
 - 扩容快、缩容慢是最佳实践
 
 -  
调优技巧
- 降低阈值 → 更敏感
 - 增加稳定窗口 → 避免抖动
 - CPU 60-70%, 内存 70-80%
 - 始终配置双指标
 
 -  
常见问题
- unknown → Metrics Server 或 requests 问题
 - 不扩容 → 达到上限或指标无效
 - 频繁抖动 → 缩容策略太激进
 
 
🎯 实战成果
- ✅ 成功配置 HPA
 - ✅ 观察到自动扩容(2 → 4)
 - ✅ 观察到自动缩容(4 → 2)
 - ✅ 理解并优化 behavior 策略
 - ✅ 掌握问题排查方法
 
🚀 下一步
下一篇文章,我会:
- ✅ 使用 k6 进行专业的压测
 - ✅ 验证 HPA 在真实负载下的表现
 - ✅ 分析性能指标和扩缩容效果
 - ✅ 给出完整的性能报告
 
敬请期待《压测实战:验证弹性伸缩效果》!
相关文章:
- 上一篇:云原生的核心优势:自动弹性伸缩实战
 - 下一篇:压测实战:验证弹性伸缩效果
 
项目代码:GitHub - cloudnative-go-journey
