news 2026/11/6 1:42:15

Kubernetes HPA 弹性伸缩实战:从算法原理到避坑指南

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Kubernetes HPA 弹性伸缩实战:从算法原理到避坑指南

1. 为什么需要HPA:从手动扩缩容到弹性伸缩

做 Kubernetes 运维的人,迟早要面对 HPA——HorizontalPodAutoscaler 这套机制。HPA 解决的问题其实很朴素:业务流量涨上去了,副本数就得跟着涨;流量下去了,多余副本也不能继续白白占着资源。过去手工kubectl scale deployment web-demo --replicas=10也能做,但凌晨三点被告警叫起来手动扩容的滋味,经历过的人都不想再有第二次。HPA 就是把这套“看指标、定副本、执行扩缩容”的判断逻辑自动化,让副本数始终贴合实际压力。

HPA 的官方名称很难念,HorizontalPodAutoscaler,它只负责“水平扩容”:多做几份副本,把流量分摊到更多 Pod 上。与之相对的是“垂直扩容”,也就是给单个 Pod 增加 CPU、内存配额,这套机制叫 VPA。两者适用场景不同,HPA 更常见,因为互联网应用绝大多数是无状态服务,都适合用多副本扛流量。HPA 能自动调整 Deployment、StatefulSet 等工作负载的副本数,也可以配合 ClusterAutoscaler 让整个节点池跟着弹性伸缩,形成从“Pod 层”到“Node 层”的完整弹性链路。

这篇文章我会从 HPA 的底层算法讲起,再给出一套可以直接抄走的 YAML 配置,然后用实际压测场景说明观测方法,最后整理我在生产环境里踩过的坑。不管你是刚接触 Kubernetes 的新手,还是已经被“副本抖动”“指标采集不到”折磨过的运维老手,都能从这篇文章里找到可以直接用的东西。文章里的所有配置我都尽量贴近官方默认行为,同时说明每个字段背后的必要性,这样你才能知道哪些可以删,哪些必须留。

2. HPA 到底怎么工作:控制回路与目标副本数算法

2.1 控制回路:谁在循环执行这件事

HPA 不是独立的 Pod,也不是单独的二进制服务,它是 kube-controller-manager 里的一个控制回路。控制器默认每隔一段时间就执行一次完整的“采集指标 -> 计算期望副本数 -> 调整副本数”流程。官方文档里把这个间隔称为 horizontal-pod-autoscaler-sync-period,默认是 15 秒。了解这个时间间隔很重要,因为 HPA 不是实时的,你要看到的扩容动作通常带有 15 秒左右的延迟。如果再加上指标数据自身的采集间隔,从流量突增到新 Pod 被创建,中间隔二三十秒是完全正常的。

控制回路读取的指标来自 metrics.k8s.io、custom.metrics.k8s.io 或 external.metrics.k8s.io 这三类 API。CPU、内存这类基础资源指标走 metrics.k8s.io,一般由 metrics-server 提供;应用自定义指标比如 QPS、队列长度、gRPC 并发连接数,走 custom.metrics.k8s.io,一般由 Prometheus Adapter 这类组件提供;外部指标比如云厂商消息队列堆积量,走 external.metrics.k8s.io。HPA 的通用逻辑是先向这些 API 发起请求,拿到当前副本数对应的 Pod 指标集合,再计算当前平均值,最后和目标值做比较。

这套机制里最容易被忽略的一点是:HPA 的目标值不是“当前总指标要小于目标值”,而是“当前每个 Pod 的平均值要靠近目标值”。以 CPU 为例,假设目标利用率 50%,如果当前 Pod 的平均利用率 80%,HPA 就会扩容;如果当前平均值只有 30%,HPA 就会缩容。它管理的粒度始终是“平均每 Pod”,而不是整个 Deployment 的总量。理解这一点,后面很多配置困惑都会迎刃而解。

2.2 期望副本数公式:所有扩容决策的数学基础

HPA 的期望副本数计算公式在官方文档里有明确说明,可以写成:

期望副本数 = ceil(当前副本数 * 当前指标平均值 / 目标指标平均值)

这里的 ceil 是向上取整。假设当前有 3 个副本,每个 Pod 平均 CPU 使用量为 500m,目标平均使用量为 200m,那么根据公式:

期望副本数 = ceil(3 * 500 / 200) = ceil(7.5) = 8

HPA 会把 Deployment 的副本数从 3 调整到 8。这个过程是“按比例推测”的:如果每 Pod 用量是目标的 2.5 倍,那就大约需要 2.5 倍数量的 Pod,才能把平均值压回目标线附近。

但公式并不是直接算出多少就立刻设置多少,控制器代码里还存在一个“数量级限制”。官方为了平滑伸缩,在 v1 和 v2 的实现里,每次扩容最多把副本数翻倍;如果没有现成的 Pod,首次扩容可以到 maxReplicas。缩容也有限制:每次缩容最大只会缩掉一半副本。这是为了保护系统,避免指标波动时副本数像过山车一样大起大落。尤其对于有突发流量但持续时间很短的业务,一次从 3 副本直接扩到 100 副本会造成巨大浪费,而“最多翻倍”的策略相当于给扩容加了一层节流阀。

需要注意,公式里“当前指标平均值”的采集窗口并不是实时瞬时值,而是控制器在--horizontal-pod-autoscaler-tolerance范围内做比较。默认 tolerance 是 0.1,也就是当期望副本数与当前副本数的比例为 0.9 到 1.1 之间时,HPA 认为“当前副本数基本满足需求”,不会做任何调整。这就是为什么很多场景下 CPU 已经 55% 了,HPA 却依然没有反应——因为目标 50%,偏差 10% 以内属于死区。想更敏感,可以调整 kube-controller-manager 启动参数,但生产环境建议不要轻易调小,否则极易抖动。

2.3 两种度量方式:直接值与利用率

HPA v2 的配置里,目标指标可以写成两类。第一类是“直接值”,比如 target.averageValue 或 target.value,目标是一个绝对数字。对于 Pod 内上报的自定义指标,比如“每个 Pod 当前有 20 个请求在排队”,target 就可以设为 10 或 3 这类绝对值。控制器的计算方式很简单:当前所有 Pod 的指标值求和后再除以 Pod 数,然后和 target 的平均值比较。

第二类是“利用率”,主要用于 CPU 和内存,配置为 target.averageUtilization。利用率是“当前使用量 / 当前 Pod 的资源请求量”的百分比。比如 Pod 的 CPU request 是 100m,实际使用 80m,那么当前利用率就是 80%。HPA 对这种指标计算期望副本数时,公式不变,只需要把“当前指标平均值 / 目标平均值”替换成“当前平均利用率 / 目标平均利用率”。

为什么利用率一定要基于 request 而不是 limit?因为 request 是调度器用来保证 Pod 可获得最小资源的依据,也是 Kubernetes 给 Pod 承诺的“起步配额”。limit 只是容器不能超过的上限,拿 limit 算利用率会让结果失真:一个 Pod limit 很大但实际用量很小,算出来的利用率和它真实压力完全不成正比。所以配置 HPA 的 CPU/内存指标之前,先确认你的 Deployment 里每个容器的 resources.requests 都写得清清楚楚,否则 HPA 八九不离十会报“no metrics returned”。这一点我在后面“常见问题”里还会反复强调。

3. 从零配置一个 HPA 实例

3.1 准备 metrics-server 或对应的指标采集层

在配置 HPA 之前,先确认集群里有没有安装指标采集组件。对于 CPU 和内存这类资源指标,最常用的是 metrics-server。它不是 Prometheus,不做长期存储,只提供当前节点和 Pod 的瞬时资源数据。把 metrics-server 装进集群后,API Server 才会出现 metrics.k8s.io 这个聚合 API,kubectl top nodes和kubectl top pods也才能正常使用。

验证方法很简单,执行两条命令:

kubectl top nodes kubectl top pods -A

如果都能返回 CPU 和内存数据,说明 metrics-server 工作正常。如果你用的是云厂商托管 Kubernetes 集群,大部分都已经默认集成了 metrics-server,这时候可以跳过这一步。如果你的业务指标是 QPS、队列深度、gRPC 连接数这类自定义数据,就需要额外部署 Prometheus,并配置 Prometheus Adapter,让它把 Prometheus 里的指标通过 custom.metrics.k8s.io API 暴露出来。这个链路比 metrics-server 复杂很多,我后面会单独说配置要点。

3.2 创建带资源请求的 Deployment 和服务

很多新手把 HPA 配置得漂漂亮亮,但 Deployment 里的容器没有写 resources.requests,结果 HPA 一直无法获取 CPU 利用率。所以我建议你先在测试环境里把一个最简单的 Deployment 跑起来,并且把 request 写好。下面这个配置是一个标准的无状态 Web 服务:

apiVersion: apps/v1 kind: Deployment metadata: name: web-demo namespace: default spec: replicas: 1 selector: matchLabels: app: web-demo template: metadata: labels: app: web-demo spec: containers: - name: web image: registry.example.com/web-demo:latest ports: - containerPort: 8080 resources: requests: cpu: 100m memory: 128Mi limits: cpu: 500m memory: 256Mi

这里我特意给容器设置了requests.cpu: 100m。HPA 在计算 CPU 利用率时,会把 Pod 实际用量除以 100m 再乘 100%,得到当前的利用率百分比。如果没有任何 request,HPA 就缺少计算分母,cached 数据也找不到有效的指标来源,事件里就会出现failed to get cpu utilization或missing request for cpu这类报错。

为了便于测试,再创建一个 Service,否则你只能从集群外部或通过临时 Pod 压测。你可以用最简单的 ClusterIP 类型:

apiVersion: v1 kind: Service metadata: name: web-demo-svc spec: selector: app: web-demo ports: - port: 80 targetPort: 8080

3.3 创建 HPA 并理解每个字段

现在创建 HPA 对象。这里我给出的是 autoscaling/v2 版本,这是当前 HPA 功能的完整版本,支持多指标、自定义指标、行为控制等高级特性。v1 只支持 CPU,不要在新环境里使用了。

apiVersion: autoscaling/v2 kind: HorizontalPodAutoscaler metadata: name: web-demo-hpa namespace: default spec: scaleTargetRef: apiVersion: apps/v1 kind: Deployment name: web-demo minReplicas: 1 maxReplicas: 10 metrics: - type: Resource resource: name: cpu target: type: Utilization averageUtilization: 50 behavior: scaleUp: stabilizationWindowSeconds: 0 policies: - type: Percent value: 100 periodSeconds: 15 - type: Pods value: 4 periodSeconds: 15 selectPolicy: Max scaleDown: stabilizationWindowSeconds: 300 policies: - type: Percent value: 100 periodSeconds: 60

拆开解释一下:

  • scaleTargetRef指向要扩缩容的工作负载。我这里的kind是 Deployment,所以 HPA 只会修改这个 Deployment 的.spec.replicas字段。
  • minReplicas和maxReplicas划定副本数边界。生产建议 minReplicas 至少 2,保证高可用;如果成本敏感,测试环境可以 1。
  • metrics数组里的type: Resource表示这是资源指标;name: cpu指定指标名;target.type: Utilization表示按利用率算;averageUtilization: 50表示目标是所有 Pod 的平均 CPU 利用率 50%。
  • behavior里我定义了扩容策略和缩容策略。扩容时,type: Percent, value: 100表示每次最多扩容当前副本数的 100%,比如当前 4 个副本,最多扩展到 8 个;type: Pods, value: 4表示每次最多增加 4 个 Pod。两条策略同时给出,selectPolicy: Max表示选二者中允许值更大的那次操作。
  • stabilizationWindowSeconds是稳定窗口,缩容我保留 300 秒,也就是 5 分钟内连续满足缩容条件才会真正缩容。这个值对防止抖动很关键。

创建命令:

kubectl apply -f hpa.yaml kubectl get hpa web-demo-hpa

如果能正常运行,kubectl get hpa的TARGETS列会显示类似5%/50%的信息,前面是当前值,后面是目标值。

3.4 压测与观察:确认扩容真的会发生

要验证 HPA 是否正常工作,必须人为制造压力。我更推荐用专门的压力测试工具,比如hey、wrk、ab,或者直接在集群内跑一个临时 Pod,循环请求 Service。以hey为例:

kubectl run load-generator --image=registry.example.com/hey --restart=Never -- \ -z 5m -c 20 -q 500 http://web-demo-svc

这里重点不是工具本身,而是你要注意观察。用另一个终端持续查看:

kubectl get hpa web-demo-hpa -w kubectl get deploy web-demo -w kubectl top pods -l app=web-demo

正常情况下,流量拉起来后,CPU 利用率会迅速超过 50%,然后 HPA 开始逐步增加副本数。因为我在 behavior 里把稳定窗口设为 0、每次扩容最多增加 4 个 Pod,你会发现副本数像台阶一样往上爬,而不是瞬间跳到最大。流量结束后,缩容需要等 5 分钟稳定窗口,这期间副本数保持不变,之后逐渐回落到 minReplicas。

3.5 kubectl 命令行方式:能省则省的手工场景

如果想快速测试或临时调整,也可以用kubectl autoscale创建 HPA:

kubectl autoscale deployment web-demo \ --min=2 \ --max=10 \ --cpu-percent=50

这个命令只创建 CPU 利用率 50% 的 HPA,自动使用 autoscaling/v2 API。它生成的 metric 配置和你手写的averageUtilization: 50是一样的。命令行方式适合临时测试,但生产环境建议把 YAML 文件提交到 Git,方便 review 和回滚。我自己的习惯是:集群里的 HPA 全部由 GitOps 管理,任何人不得手工kubectl autoscale,避免线上配置漂移。

4. 核心细节与配置项拆解

4.1 autoscaling/v2 与 v1 的差异

Kubernetes 1.18 之后,HPA 的稳定版本就是 autoscaling/v2,v2beta2 已经废弃。v1 的 HorizontalPodAutoscaler 只支持 CPU 这一个指标,且不能配置 behavior。如果你在网上找到的教程还是apiVersion: autoscaling/v1、字段里写着minReplicas/maxReplicas/targetCPUUtilizationPercentage,那大概率是旧资料,别直接抄。v2 统一了指标结构,把 CPU、内存、自定义指标、外部指标都放在metrics数组里,结构更清晰。迁移也不难:把 v1 改造成 v2 的 CPU 指标写法,只需要把targetCPUUtilizationPercentage替换成 metrics 数组中的 Resource 类型。

4.2 目标指标类型:Resource、Pods、Object、External

HPA v2 的metrics数组里可以配置四种类型,每种类型对应不同的指标来源:

  • Resource对应 metrics.k8s.io,主要就是 CPU 和内存。target 支持Utilization和AverageValue。内存不能用 Utilization 吗?实际上averageUtilization也支持内存,但内存利用率容易出现“回收后回落”的问题,生产里用内存作为唯一扩缩容指标要格外小心。
  • Pods对应 custom.metrics.k8s.io,指标必须来自 Pod 本身,而且每个 Pod 上报的指标是独立的。target 只支持AverageValue。比如每个 Pod 的当前任务队列长度为 10,希望平均不超过 3,就配置为target.averageValue: 3。
  • Object对应 custom.metrics.k8s.io,它描述某个自定义对象的指标,比如 Ingress 的 QPS、Service 的请求延迟,不直接挂在 Pod 上。配置里要同时写describedObject来指定对象类型和名称。
  • External对应 external.metrics.k8s.io,适合从集群外部读取指标,比如云厂商的消息队列堆积量、SLO 监控指标等。

它们在 API 对象上的写法差异比较大,我贴一个Object类型的示例:

metrics: - type: Object object: describedObject: apiVersion: networking.k8s.io/v1 kind: Ingress name: web-ingress metric: name: nginx_ingress_controller_requests_per_second target: type: Value value: 1000

这是让 HPA 根据 Ingress 上的总 QPS 来决定副本数,目标 1000 QPS。注意这里的指标名必须是你注入到 Kubernetes 自定义指标 API 里的真实 metric 名称,不是 Prometheus 里的原始指标名。Adapter 层需要做一次映射。

4.3 多指标组合:HPA 如何决定最终副本数

一个 HPA 对象可以在metrics数组里写多个指标。比如同时配置 CPU 利用率和自定义 QPS。控制器会对每个指标分别计算“期望副本数”,最后取所有结果里的最大值。这个设计很符合业务直觉:只要其中一个指标已经“喊渴”,就应该扩容,否则单看 CPU 可能掩盖了请求积压。

举个例子,Deployment 当前副本数是 4。按 CPU 利用率计算,期望副本数是 6;按 QPS 平均值算,期望副本数是 9。那么 HPA 最终会把副本数调整到 9。缩容时也是一样,必须所有指标的期望副本数都低于当前副本数,才可能触发缩容。这可能导致某些场景下副本数“下不来”——比如 CPU 已经很低了,但自定义指标仍然偏高。遇到这种情况不能靠调 HPA 的 minReplicas 硬压,应该先查业务指标为什么居高不下。

4.4 behavior 字段:缩容保护与扩容限速的正确写法

behavior是 v2 引入的一等公民字段,它分scaleUp和scaleDown两个子块。每块都由stabilizationWindowSeconds、policies和selectPolicy组成。很多人看见这三个属性就晕,我用一句大白话总结:稳定窗口是“观望多久”,policies 是“一次最多动多少”,selectPolicy 是“多个策略同时生效时听谁的”。

稳定窗口的作用非常直观。默认缩容稳定窗口是 300 秒,扩容稳定窗口是 0 秒。为什么缩容要观望 5 分钟?因为流量波峰过去后,指标下降往往是缓慢且波动的,立刻缩容会导致副本数跟着流量一起震荡,结果就是集群资源利用率很低,但 Pod 一直在反复创建和删除。设置了稳定窗口后,控制器会记住这段时间内所有“期望副本数”,在窗口内只倾向于选择最小合理值或最大合理值。具体行为可以在官方 behavior API 文档里看到,但普通使用只需要记结果:

  • scaleDown.stabilizationWindowSeconds: 300表示 5 分钟内不会被马上缩到低水位。
  • scaleUp.stabilizationWindowSeconds: 0表示指标一上来,扩容不等待。

policies是策略列表。每条策略有type和value。type 可以是Pods或Percent。periodSeconds表示“在一个周期内最多执行多少次”。比如type: Percent, value: 100, periodSeconds: 15,意思是每 15 秒允许增加 100% 当前副本数,也就是每次最多翻番。如果你把value: 4, type: Pods写成一个 Pods 策略,它和 Percent 策略并存,HPA 会按selectPolicy决定。selectPolicy有三个候选值:Max选较大操作、Min选较小操作、Disabled表示这种方向上的伸缩被完全禁止。Disabled很不常用,但有些团队为了“只扩容不缩容”会这么配,我不建议,因为那是掩耳盗铃,还不如直接把 minReplicas 调到期望值。

4.5 和其他控制器协同:PDB、ClusterAutoscaler 与资源配额

HPA 不是 Kubernetes 里唯一的伸缩机制,它需要和几个“邻居”配合好。

PodDisruptionBudget(PDB)用于控制自愿驱逐时最多能中断多少 Pod。当你缩容时,HPA 不会直接删除 Pod,而是修改 Deployment 的 replicas,随后 ReplicaSet 控制器按一定顺序终止多余的 Pod。如果集群里有节点维护、Spot 实例回收、蓝绿发布这类操作,PDB 会约束“最多允许几个 Pod 同时不可用”。假如 HPA 想把副本从 10 缩到 2,但 PDB 限制最多只能有 1 个 Pod 同时中断,那么缩容过程会变得很慢,甚至长时间停在中间副本数。这不是故障,而是保护机制在起作用。生产上你要预期到这种互相折衷。

ClusterAutoscaler 是节点层弹性的关键。HPA 扩容出来的 Pod 如果当前节点资源不足,会卡在 Pending 状态。ClusterAutoscaler 会观察 Pending Pod,触发节点池扩容。反过来说,HPA 缩容之后节点负载下降,ClusterAutoscaler 也可能缩容节点。二者配合得好,整个集群就是“应用压测涨 Pod,节点不够涨机器”的完整弹性链路;配合得不好,会出现“HPA 想扩容,但节点资源不够,Pod 一直Pending,越挤压越严重”的尴尬。我见过很多私有云环境没装好 ClusterAutoscaler,HPA 扩容到接近资源上限后就卡死,所有新 Pod 都在 Pending,这时候先排查节点可用资源,而不是怀疑 HPA 配置有误。

资源配额(ResourceQuota)也能拦住 HPA 的扩容。如果 namespace 里设置了 CPU request 总配额,HPA 把 replicas 调上去,但 Pod 创建时配额不足,ReplicaSet 会反复创建失败。这种问题非常隐蔽,因为 HPA 的状态还是正常的,副本数也显示已更新,但实际可用副本数根本不够。排查时一定要看 ReplicaSet 的事件或者kubectl get events里的FailedCreate记录。

5. 实战遇到的坑和排查技巧实录

5.1 指标没数据:HPA 报 no metrics returned

我在测试环境最常遇见的 HPA 问题是kubectl describe hpa的 Events 里出现failed to get cpu utilization: unable to get metrics for resource cpu: no metrics returned from the metrics API。这几乎都是因为 metrics-server 没正常工作,或者容器没有 resources.requests。

先按这个顺序排查:

kubectl get apiservice v1beta1.metrics.k8s.io kubectl top nodes kubectl top pods

如果kubectl top nodes正常,说明 metrics-server 向 API Server 注册成功,数据链路没问题。接着看 Deployment 里的 Pod 是否所有容器都写了 resources.requests。注意,如果一个 Pod 里有多个容器,HPA 的 CPU 利用率会按所有容器 request 之和作为分母,所有容器当前用量之和作为分子。有一个容器没写 request,都会导致整个 Pod 的利用率无法计算。

5.2 指标值波动导致副本抖动

HPA 的默认 tolerance 是 0.1,也就是目标值和当前值差距在 10% 以内时不动。但即使有 tolerance,指标峰谷交替明显时,copy 还是可能出现“扩 2 个、缩 1 个、再扩 2 个”的抖动。这个问题的解法不是把 sync-period 调大,而是把缩容稳定窗口调大。我给生产环境定的经验值是scaleDown.stabilizationWindowSeconds: 600,也就是流量下降后至少观望 10 分钟再缩容。如果你是 CPAU 类型的高延迟应用,还可以把扩容稳定窗口也设置成 60 秒,避免一次性扩容太过激进。

5.3 单副本无法扩容

有一种现场:Deployment 副本数是 1,HPA 的目标是 CPU 50%,当前 CPU 已经 90%,但 HPA 就是不扩容,TARGETS 里显示<unknown>/50%或90%/50%,事件里也没有任何 action。原因可能是 HPA 控制器第一次同步的时候拿不到 Pod 的指标,Pod 处于启动过程中,而 controller-manager 有--horizontal-pod-autoscaler-initial-readiness-delay参数,默认 30 秒。在这 30 秒内,Pod 即使已经 Ready,HPA 也不会用它的指标作为计算依据。另外还有一个常见原因:你的 Deployment 的 Pod 被某种控制器(比如另外一个人工kubectl scale操作)改过副本数,导致 HPA 认为当前副本数已经不是它期望的数值,暂时收敛到新的基线。这个问题不容易一眼看出,但只要等待下一次 sync 周期,HPA 会自己修正。

5.4 利用率计算与你预期不一致

我见过很多次:业务方说 CPU 用了 200%,但 HPA 显示 50%。这类问题几乎都出在 request 设置上。HPA 是拿“当前 CPU 使用量 / 当前 CPU request”算利用率的。如果你的容器 request 是 1 核,实际使用 2 核,利用率就是 200%。如果你的容器 request 是 2 核,实际使用 2 核,利用率就是 100%。业务觉得“CPU 很高”,是因为只看了容器实际使用量和 limit 的关系,而 HPA 看的是 request。想对齐认知,要么统一以 request 作为资源成本口径,要么干脆改用target.averageValue而不是averageUtilization。用 averageValue 的话,公式直接变成“当前每 Pod 平均使用量 / 目标平均使用量”,不再受 request 影响。比如你想让每 Pod 平均 CPU 不超过 250m,就可以写:

metrics: - type: Resource resource: name: cpu target: type: AverageValue averageValue: 250m

这招非常实用,尤其适合团队里对“利用率”概念理解不一致的场景。

5.5 与资源 limit 的关系:limit 不参与计算,但会影响调度

上面的公式我说了很多次 request 是分母,接下来要说 limit 的作用。limit 虽然不参与 HPA 计算,但影响运行稳定性。如果 Pod 里没设置 limit,或者 limit 设得很大,而业务压力又一直上涨,HPA 扩容速度可能跟不上 CPU 爆掉的速度。尤其很多 Java 类应用,内存压力上来后开始 Full GC,CPU 飙升,HPA 还没来得及扩容,Pod 已经被 OOMKilled 或宿主机压垮。所以我的建议是:

  • request 尽量贴近真实日常使用,不要拍脑袋。
  • limit 至少留 30% 到 50% 冗余。
  • 针对 CPU 密集型业务,最好同时配置 CPU 和内存两类 HPA 指标,避免只看 CPU 忽略了内存维度。

5.6 快速定位命令合集

如果你手里的 HPA 表现诡异,我推荐按下面顺序执行:

kubectl get hpa -A kubectl describe hpa web-demo-hpa kubectl get --raw "/apis/metrics.k8s.io/v1beta1/namespaces/default/pods" | head kubectl get --raw "/apis/autoscaling/v2/namespaces/default/horizontalpodautoscalers/web-demo-hpa/status" | jq . kubectl get events -n default --sort-by='.lastTimestamp' | grep -i hpa kubectl logs -n kube-system -l k8s-app=metrics-server --tail=200

第一条看状态,第二条看事件,第三条确认 Pod 级 metrics API 有没有返回数据,第四条直接看 HPA 的 status 子资源里保存的最近一次计算记录,第五条找集群事件,最后一条看 metrics-server 自己的日志。这套命令在大多数疑难杂症里都能定位到七七八八。

5.7 常见问题速查表

现象常见原因快速解法
HPA 显示<unknown>/50%metrics-server 不可用kubectl top nodes验证,检查 apiservice
一直无法扩容Deployment 容器缺 resources.requests补全 requests.cpu
扩容过慢扩容策略限速调整 behavior.scaleUp.policies
缩容过快导致抖动稳定窗口太小设置 scaleDown.stabilizationWindowSeconds
副本停在中间数不缩PDB 限制中断数量查看 PDB 状态和 maxUnavailable
新 Pod 一直 Pending节点资源不足或配额限制kubectl describe pod看事件
HPA 状态但无生效副本数ReplicaSet 创建失败kubectl get rs -o yaml看条件

这张表没办法覆盖所有情况,但能覆盖我实际运维里 80% 的 HPA 问题。剩下那 20%,大多和你的自定义指标采集链路有关,得从 Prometheus Adapter 的日志和 custom.metrics API 返回结果里一层层往下查。

做 Kubernetes 弹性伸缩这几年,我自己最大的体会是:HPA 本身不是一个“配置完就万事大吉”的组件,它像是一个精密的控制系统,你给它什么数据,它就给你什么行为。指标不准确、request 设置不合理、稳定窗口配置过短,都会让它“看起来不太聪明的样子”。如果你能先把 CPU 指标跑通,理解期望副本数公式,再一步步加上自定义指标和 behavior 控制,HPA 就会变成一个非常可靠的自动运维帮手。最后再分享一个小建议:任何 HPA 改动上线前,都要像改业务代码一样做一次小流量压测,毕竟副本数背后都是真金白银的资源账单。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/11/6 1:42:15

影刀RPA深度实战:京东商品数据批量采集与SKU价格抓取完整方案

影刀RPA深度实战&#xff1a;京东商品数据批量采集与SKU价格抓取完整方案 作者&#xff1a;林焱 标签&#xff1a; #影刀RPA #京东采集 #SKU抓取 #价格监控 #电商数据 #爬虫替代 开篇&#xff1a;为什么京东采集比淘宝难三倍 去年我给一个3C卖家做竞品价格监控&#xff0c;用…

作者头像 李华
网站建设 2026/10/29 20:27:30

有向图简单路径算法详解:DFS与BFS实现及优化

1. 有向图简单路径到底在解决什么问题有向图的简单路径&#xff0c;说白了就是在一张有向图里&#xff0c;找一条从起点到终点的路径&#xff0c;且路径上不能有重复的顶点。这个定义听起来简单&#xff0c;但真正动手写代码的时候&#xff0c;你会发现里面藏着不少门道。我在带…

作者头像 李华
网站建设 2026/10/19 10:53:19

MFC中种子填充算法的工程实现与避坑指南

1. 项目概述&#xff1a;为什么在MFC里实现种子填充&#xff0c;远不止“画个实心圆”那么简单你打开《计算机图形学》实验指导书&#xff0c;翻到第5页&#xff0c;“区域填充——种子填充算法&#xff08;MFC中&#xff09;”这行字印得工整&#xff0c;旁边还配了个带边界的…

作者头像 李华
网站建设 2026/10/29 19:30:31

UCI-HAR时间序列分类实战:从数据可视化到建模全流程解析

做时间序列分类的时间长了&#xff0c;总会发现一个规律&#xff1a;无论你手头的数据来自传感器读数、金融行情&#xff0c;还是工业设备的振动信号&#xff0c;建模之前的数据可视化与问题分析&#xff0c;往往决定了后面所有工作的上限。UCI-HAR这个数据集&#xff0c;是我在…

作者头像 李华