HPA 入门:一个 CPU 指标如何让 Pod 从 1 个变成 4 个?
Last modified:
一个 HPA 只看到了 164% 的 CPU 利用率,为什么最后会得到 4 个 Pod,而不是 2 个或 3 个?停止负载后,CPU 已经降到 1%,它又为什么没有马上缩容?
本文从这两个现象出发,用一次 1 → 4 → 1 的 kind 实验回答一个问题:
一个指标,经过哪些步骤才会变成真正可用的 Pod?
这是 HPA 实验系列的第一篇:
- 本文:CPU 指标与基本控制循环
- 应用的 RPS 和处理带宽如何驱动扩缩容?
- 队列已经空了,正在处理的任务能安全结束吗?
- HPA 已经要求 4 个副本,为什么只有 1 个可用?
先看答案:HPA 只负责修改期望副本数
|
|
HPA 周期性读取指标,计算期望副本数,再更新工作负载的 /scale 子资源。随后由 Deployment、ReplicaSet、调度器和 kubelet 完成创建与启动。HPA 写入 4,不代表已经有 4 个 Pod 可以接收流量。
这条链路至少要观察两个值:
| 值 | 回答的问题 |
|---|---|
spec.replicas / HPA desiredReplicas |
控制器想要几个 Pod? |
Deployment readyReplicas |
现在有几个 Pod 真正可用? |
实验环境
实验在 macOS / Apple Silicon 上运行,Docker 使用 OrbStack。配置、脚本和原始记录固定在 k8sdev c48f140。
| 组件 | 版本 |
|---|---|
| kind | v0.32.0 |
| Kubernetes | v1.35.0 |
| Metrics Server | v0.8.1 |
| Prometheus / Adapter | v3.5.0 / v0.12.0 |
检出固定版本并创建隔离集群:
|
|
脚本只操作 kind-hpa-lab,若同名集群已经存在会停止。Metrics Server 为适配本地 kind 使用 --kubelet-insecure-tls;生产环境应配置可信证书。
CPU 目标到底是什么
worker 的 CPU request 是 100m:
|
|
HPA 将目标设为 request 的 50%:
|
|
Utilization: 50 不是宿主机 CPU 的 50%,也不是 CPU limit 的 50%。如果 request 改为 200m,同一个目标就相当于每 Pod 100m。若希望目标始终是绝对用量,可以写成:
|
|
资源指标支持 Utilization 与 AverageValue;应用自定义指标没有资源 request 作为分母,通常使用 AverageValue。第二篇会用 RPS 和 B/s 实测这种差别。
从 164% 算出 4 个副本
先等资源指标就绪,再启动持续 CPU 负载:
|
|
在指标完整、Pod 已就绪且忽略容忍区间等修正时,可用下面的比例式理解计算:
|
|
首次运行记录:
| 时间(UTC) | CPU / condition | desired | Ready |
|---|---|---|---|
| 13:59:35 | 1m / 1% |
1 | 1 |
| 14:00:14 | 164% / 50% |
4 | 1 |
| 14:00:24 | 扩容完成 | 4 | 4 |
| 14:01:27 | 463%,TooManyReplicas |
4 | 4 |
最后一行说明副本已经碰到 maxReplicas: 4,不表示 CPU 已回到目标范围。原始采样见 lab/evidence。
9 月 8 日又从固定提交重新创建集群。高负载时保存的 HPA 状态包含具体指标和限制原因:
|
|
原始比例建议是 ceil(1 × 387 / 50) = 8,随后被 maxReplicas: 4 限制。Deployment 达到 4 Ready 后停止负载;降载采样为 1m / 1%,HPA 状态是 currentReplicas=4、desiredReplicas=1,最终 Deployment 也回到 1 Ready。新旧两轮都验证了同一控制路径,而具体 CPU 数值会随宿主机和采样时刻变化。
实际算法还会做保守修正:
- 指标比例落在默认容忍区间内时,不改变副本数。
- 部分 Pod 缺指标时,扩容按低用量、缩容按高用量估算,避免过度调整。
- CPU 路径会单独处理尚未就绪和刚启动的 Pod。
- 完全取不到指标时返回错误,不会把负载当成零。
对应实现可以从 Kubernetes v1.35.0 的 GetResourceReplicas 开始阅读。
CPU 已降到 1%,为什么没有马上缩容
停止负载:
|
|
结果不是 4 → 1 立即发生:
| 时间(UTC) | 观测 | 副本 |
|---|---|---|
| 14:02:27 | CPU 1%,ScaleDownStabilized |
4 |
| 14:02:29 | HPA 发起缩容 | 1 |
| 14:02:42 | 终止完成 | 1 Ready |
缩容稳定窗口保留近期的副本建议,并使用窗口内较大的建议约束缩容。它保存的是副本建议,不是对 CPU 指标求平均。第四篇会把稳定窗口、限速和故障路径放在同一条排障链路中实测。
回答开头的问题
164% 先通过比例计算得到 4,再受容忍区间、缺失指标、minReplicas、maxReplicas 和行为策略修正。HPA 只把最终结果写成 Deployment 的期望副本数;后续控制器、调度器、kubelet 和 readiness 才把它变成可用容量。
所以,一个指标不会直接变成 Pod。它先变成副本建议,再变成期望状态,最后才可能变成 Ready Pod。 这也是后面三篇分析自定义指标、队列任务和故障现象时共同使用的主线。
实验结束后删除集群:
|
|