news 2026/10/1 17:53:54

Kubernetes HPA 实战:从原理到自动扩容配置与避坑指南

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Kubernetes HPA 实战:从原理到自动扩容配置与避坑指南

半夜两点被监控电话吵醒,登录集群一看,某个服务的 Pod 已经被流量打到 CPU 100%,而 Deployment 的副本数还停留在白天的两个。这种手动kubectl scale的运维方式,说到底就是拿人肉当控制器——反应慢、容易漏、凌晨尤其痛苦。

Kubernetes 里解决这个问题的标准答案,就是 HPA(HorizontalPodAutoscaler,水平 Pod 自动伸缩器)。它做的事情非常纯粹:盯着 Pod 的资源指标,发现负载高了就自动加副本,负载降了就自动减副本,全程不需要人参与。这篇文章我按照“为什么需要它 → 它的原理是什么 → 怎么配置和验证 → 踩过哪些坑”这条线,把 HPA 从入门到落地一次讲透。内容适用于已经会用 Deployment 和 Service、打算给业务加上自动伸缩能力的读者,也适合正在排查“为什么 HPA 不生效”的人。

1. 为什么要用 HPA:从手动扩缩容到基于负载的自愈

1.1 手动扩缩容的真实痛点

先看一个最常见的场景。你有一个 Web 服务,Deployment 里replicas: 2,正常情况下两个副本扛得住日均流量。但流量这个东西从来不会画一条直线——早上 10 点开始爬升,中午 12 点冲到峰值,下午又掉下去。如果全程靠人盯着监控,要么在流量高峰前提前扩容(需要预测,预测不准就是浪费),要么等告警响了再扩容(已经晚了,用户在超时)。

手动扩容还有另一个问题:人容易陷入“点按钮”的惯性。今天加两个副本,明天觉得不够又加两个,时间一长,Deployment 里可能躺着十几个副本,但实际上流量根本没到那个量级。多出来的 Pod 不只是占着配额,它们每分每秒都在消耗 CPU、内存和金钱。真正合理的副本数应该是动态的:流量大就多开,流量小就收敛。

1.2 HPA 的定位与适用场景

HPA 是 Kubernetes 内置的控制器,它做的事情和你在监控面板上看到“CPU 超过 80%”然后手动敲kubectl scale差不多,区别在于它不需要睡觉、不会漏看、而且从观测到扩缩容的延迟远低于人的反应速度。

用一句话概括:HPA 根据 Pod 的实际负载(CPU、内存或自定义业务指标),自动调整 ReplicaSet 的期望副本数,让服务始终在一个合理的容量水位上运行。它适合两类场景:

  • 流量有明显的峰谷波动,比如 Web 服务、活动页、API 网关
  • 业务指标跟资源消耗强相关,比如队列积压越多,处理 Pod 就得多开

不适合的场景也很明确:如果你的服务是状态化的,比如单写多读的数据库、主从架构里不能随便扩副本的组件,HPA 就不能乱动,因为它不管数据分片和一致性,只知道“你要几个副本我就给你调成几个”。

1.3 HPA、VPA、Cluster Autoscaler,三者怎么分工

刚接触弹性伸缩的人容易把这三个概念搞混,我放在一起说清楚。

HPA 管的是水平方向,即调整同一个 Pod 模板的副本数量。它不关心 Pod 里的容器规格是多少,CPU 2 核也好 8 核也罢,HPA 只看“当前实例数够不够”。

VPA(VerticalPodAutoscaler)管的是垂直方向,即调整 Pod 里容器的 CPU 和内存 request/limit。它解决的是“单 Pod 能力不足”的问题,比如某个容器要 4 核但只申请了 1 核,VPA 会帮你把资源规格调上去并重建 Pod。

Cluster Autoscaler 管的则是集群这一层,当 HPA 想扩容但节点资源不够时,它负责给集群增加新的工作节点。

这三者的关系是一条上下游链路:HPA 判断业务需要更多 Pod → 节点资源不足,Pod Pending → Cluster Autoscaler 加节点。实际落地时,大部分公司是 HPA + Cluster Autoscaler 搭配用,VPA 用得相对少,主要是它调整规格需要重启 Pod,对在线业务有侵入性。

2. 从指标采集到副本调整:HPA 的工作链路与核心算法

2.1 一条完整的指标流转链路

HPA 不是凭空知道 Pod 负载的,它背后有一条完整的链路,理解这条链路对排查问题至关重要。

第一步是指标采集。Kubernetes 从 1.20 左右开始,内置的 cAdvisor 会随 kubelet 一起采集节点和容器的基础指标(CPU、内存等),并通过 kubelet 的/metrics/resource接口暴露出来。这些指标属于Heapster 时代的遗产,Kubernetes 官方不再直接消费它们,而是要求集群里部署一个指标聚合组件——最常见的是metrics-server,社区标准实现。metrics-server 通过 kubelet 的 Summary API 定时抓取指标,然后通过 Kubernetes 的 Aggregation API 对外提供服务接口(/apis/metrics.k8s.io/v1beta1)。

第二步是指标获取。HPA 控制器每隔默认 15 秒(--horizontal-pod-autoscaler-sync-period)就会通过 metrics API 拉取目标 Pod 的指标。注意,HPA 拿到的不是单个 Pod 的瞬时值,而是一个时间段内的平均值。metrics-server 本身只保留最近 1-2 分钟的数据,而且它是从 kubelet 的 cadvisor 缓存里取值的,所以 HPA 看到的指标天然有几十秒到一分钟左右的延迟。

第三步是副本计算。HPA 控制器根据拿到的指标,用一套固定的算法算出目标副本数,然后调用 Scale 子资源(作用于 Deployment/StatefulSet 对应的 Scale 对象)更新期望副本数,Deployment 控制器再接住这个变更,触发 ReplicaSet 扩容或缩容。

这里有一个很多人忽略的细节:HPA 更新的是 Scale 对象的spec.replicas,而 Deployment 会把spec.replicas同步到当前状态。所以你在 YAML 里写的replicas字段是一个“初始值”,HPA 接管之后会不断改写 Scale 的副本数,但不会改你 Deployment YAML 里的原始副本字段。这意味着用kubectl edit deployment把 replicas 改回 2 是无效的,HPA 会在下一个同步周期内再改回来。

2.2 扩缩容算法:HPA 怎么算“需要几个 Pod”

HPA 的扩缩容算法是整个机制的核心,公式非常简单,但理解它才能真正用好 HPA:

desiredReplicas = ceil(currentReplicas × (currentMetric / desiredMetric))

解释一下各变量的含义:

  • currentReplicas:当前副本数
  • currentMetric:当前指标值。对于 CPU 利用率这种 cluster 范围的指标,HPA 拿到的是一段时间内所有目标 Pod 的 CPU 使用率平均值(按容量百分比算)
  • desiredMetric:你在 HPA 配置里设定的target,比如targetAverageUtilization: 50表示目标平均利用率 50%

举个例子。假设当前有 4 个副本,每个副本的 CPU request 是 1 核,当前实际每个 Pod 平均用了 0.8 核,利用率 80%;如果目标利用率是 50%,那么:

desiredReplicas = ceil(4 × (80% / 50%)) = ceil(6.4) = 7

HPA 会把副本数从 4 调成 7。如果当前实际利用率是 20%:

desiredReplicas = ceil(4 × (20% / 50%)) = ceil(1.6) = 2

算法会尝试把副本数降回 2。

这里有一个重要的设计:当只有 1 个 Pod 时,扩容大概率不是按比例走的,而是直接翻倍。因为按比例算的话,1 个 Pod 利用率 100%,目标 50%,结果是 ceil(2) = 2,但如果 1 个 Pod 被打垮了,可能是几百倍的流量,HPA 的“限制单次扩容比例”机制就是为了防止这种情况依赖线性推理。从 Kubernetes 1.18 开始,HPA 引入了扩容速率限制(通过behavior字段配置),默认行为是每 15 秒最多扩容一倍副本数,每 5 分钟最多缩容一半。这是为了防止副本数震荡——比如流量稍微抖动一下,副本数在 10 和 12 之间来回跳,对稳定性影响很大。

2.3 target 值设置与“稳定窗口”的权衡

targetAverageUtilization不是一个随便填的数字,它决定 HPA 的灵敏度。设得太低,比如 30%,意味着副本数会非常激进地跟随流量波动,流量稍微上来一点,HPA 就扩容,集群资源消耗很快;设得太高,比如 90%,副本数长期处于高位水位,一旦流量突然增长,HPA 还没反应过来,Pod 已经 CPU 被打满,服务开始超时。

更关键的是,target 的基准是Pod 的 request 值,不是机器实际容量。比如你给容器设置了requests.cpu: 500m,那么 100% 利用率指的是用了 500m 的一半。HPA 只看请求配额的使用率,跟节点实际负载无关。这也是为什么很多人配了 HPA 之后发现副本数一直不对的原因——如果 request 设得很小,利用率很容易冲到 100%,HPA 就会疯狂扩容;如果 request 设得过大,利用率一直很低,HPA 就永远不扩容,但实际机器已经扛不住了。

关于稳定性,K8s 在 1.18 之后给了两个维度来缓解抖动:

  • --horizontal-pod-autoscaler-cpu-initialization-period(默认 5 分钟):Pod 启动后的前 5 分钟内,CPU 指标不会被当作扩容依据,因为新 Pod 正在冷启动,CPU 值波动较大。
  • --horizontal-pod-autoscaler-initial-readiness-delay(默认 30 秒):Pod 刚被标记为 Ready 后的 30 秒内,指标同样不参与计算。

这两个参数的意义在于:不要让新 Pod 的初始 CPU 毛刺干扰整体扩容判断。生产环境里我一般不建议改这两个参数,保持默认即可。

3. 实操配置与验证:一个完整的 HPA 配置和压测观察

3.1 前置条件:确认 metrics-server 已部署

HPA 要跑起来,前提是集群里有 metrics-server,否则kubectl get hpa看到的永远是<unknown>的指标状态。

检查方法很简单:

kubectl -n kube-system get pods | grep metrics-server kubectl get --raw "/apis/metrics.k8s.io/v1beta1/nodes" | head

第一个命令看 metrics-server Pod 是否处于 Running;第二个命令直接请求 metrics API,如果返回了 JSON 格式的节点指标数据,说明链路是通的。

如果是自己搭的集群(比如 kubeadm),需要额外部署 metrics-server,官方 YAML 直接应用即可:

kubectl apply -f https://github.com/kubernetes-sigs/metrics-server/releases/latest/download/components.yaml

但这里有一个容易踩的坑:如果 kubelet 走的是 HTTP 而不是 HTTPS 的本地端口,metrics-server 的默认 TLS 检测会失败,需要给它的启动参数加上--kubelet-insecure-tls和--kubelet-preferred-address-types=InternalIP。早年我帮人排查过很多次“为什么 metrics-server 一直 CrashLoopBackOff”,最后都是这个原因。

我自己通常会在部署完 metrics-server 后立刻执行下面这条命令,确认节点和 Pod 的指标都能正常取到:

kubectl top nodes kubectl top pods -n my-service

如果kubectl top nodes有输出,说明 metrics API 正常,HPA 的基础设施就算就绪了。

3.2 编写 HPA v2 配置:多指标 + 自定义扩缩容策略

从 Kubernetes 1.23 开始,autoscaling/v2已经是稳定 API,推荐只用 v2。我写一个实际能用的配置:

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

逐项解释关键字段:

  • scaleTargetRef指定 HPA 管理哪个工作负载。kind 可以是 Deployment,也可以是 StatefulSet,甚至直接指向 ReplicaSet。
  • minReplicas和maxReplicas是硬边界。minReplicas 不能设成 0,除非你明确想用“无负载时缩到 0”的极致省资源模式——但那样第一个请求进来需要冷启动,体验会很差。生产环境一般设 2 到 3 个起步副本。
  • metrics列表里我配了两个指标:CPU 和内存。HPA 取的是所有指标的交集满足扩容、并集满足缩容吗?不是,这点要特别注意:HPA 对多个指标的处理方式是取对扩容最有利的那个值。即只要任一指标达到触发扩容条件,就执行扩容;只有当所有指标都满足缩容条件时,才缩容。所以 CPU 和内存两个指标都配上,相当于“任一指标超了就扩容”,保护面更宽。

另外解释一下behavior这一段,这是在 v2 API 里新增的精细控制能力:

  • scaleUp里我设的stabilizationWindowSeconds: 0,意思是扩容不设稳定窗口,越多判断越及时。policies表示在 15 秒内最多可以扩当前副本数的 100%,也就是翻倍。这样做是为了应对突发流量。
  • scaleDown里stabilizationWindowSeconds: 300,是 5 分钟缩容稳定窗口。policies用的是Pods类型,表示 60 秒内最多只缩 1 个副本。这就是大家常说的“快速扩容、缓慢缩容”模式。

关于稳定窗口的机制我多说一句:缩容稳定窗口的作用是“在窗口期内,如果此前出现过更高的指标,HPA 就推迟缩容决策”。比如 10 分钟前流量冲高,HPA 扩到了 8 个副本,现在流量降了 30% 持续 2 分钟,如果没有稳定窗口,HPA 可能会立刻缩容;有了 300 秒窗口,HPA 会认为“这 30% 的下跌可能是一时的”,所以等观察满 5 分钟再决定。这个机制对防止“缩完又要扩”非常有效。

3.3 用 kubectl 验证 HPA 状态与扩容过程

配置写好后,直接应用:

kubectl apply -f hpa.yaml kubectl get hpa

如果配置正确,输出大致长这样:

NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE web-server-hpa Deployment/web-server 21%/60%, 35%/80% 2 10 2 10s

TARGETS里显示的是“当前值/目标值”,当前值和目标值都列出来,便于判断当前离扩容阈值还有多远。这里 21%/60% 表示当前 CPU 利用率 21%,目标 60%;内存同理。

然后模拟负载。我一般用hey或wrk压测工具,直接对 Service 的 ClusterIP 发请求:

# 在集群内开一个临时 Pod 跑压测,避免走公网链路 kubectl run -it --rm load-generator --image=busybox --restart=Never -- sh # 在容器里发起请求,地址换成自己服务的 ClusterIP while true; do wget -q -O- http://<service-ip>/; done

不依赖额外工具的更简单方案是直接跑hey:

hey -z 5m -c 50 -q 100 http://<service-ip>/

压测期间再开一个终端,观察:

kubectl get hpa -w kubectl get pods -l app=web-server -w

你会看到 TARGETS 里 CPU 利用率往上冲,一旦超过 60%,HPA 开始把 REPLICAS 往上调。调到 3、4、5… 直到压测停止后,TARGETS 里的 CPU 利用率回落,但缩容是缓慢的——因为behavior.scaleDown设置了 300 秒的稳定窗口。这是符合预期的。

有个细节必须提一下:压测时最好把-c(并发数)设为单个 Pod 能承受上限的几倍,而不是一把梭。如果压测工具把 CPU 打到 100%,HPA 扩容后新的 Pod 也会被立即打满,最终副本数直接冲到 maxReplicas,你反而观察不到“逐步扩容”的过程。调到中等压力量(比如利用率冲到 80-90%),扩容节奏更清晰。

4. 常见问题与排查技巧实录

4.1 指标一直是<unknown>或者TARGETS为空

这个问题十次有八次出在 metrics-server 上。处理步骤我整理成了一份速查表:

现象可能原因排查方法
kubectl get hpa显示<unknown>/60%metrics-server 没部署kubectl -n kube-system get pods看 metrics-server 状态
metrics-server Pod CrashLoopBackOffkubelet 是 HTTP 端口,TLS 校验失败给 metrics-server 加--kubelet-insecure-tls参数
metrics-server 正常但kubectl top nodes为空kubelet 10250 端口被防火墙或网络策略拦了检查节点到 kubelet 端口的网络连通性
仅有部分节点指标缺失个别节点 kubelet 异常journalctl -u kubelet查看对应节点日志

我自己遇到过最隐蔽的一个情况是:控制平面里有多个节点,metrics-server 通过preferred-address-types解析节点地址时,选了InternalIP,但集群的网络里有些节点的 InternalIP 互相不通。这种问题用--kubelet-preferred-address-types=InternalIP也会遇到,后来我直接在 kubelet 启动参数里把绑定地址固定好,指标才全部正常。

4.2 扩容很疯狂但缩容很迟钝

这种现象多数不是 bug,而是你没理解 HPA 的默认行为。

在autoscaling/v2里,如果你没有写behavior字段,默认的扩缩容策略是:扩容每 15 秒最大翻倍,缩容每 5 分钟最大缩一半。这样设计的本意是“快速响应流量增长,保守处理流量下降”。

但是实战中很多人的抱怨是“流量降了 20 分钟,副本数都没怎么动”。这就要看你的业务容忍度了。如果你是电商大促后想快速回收资源,默认的 5 分钟稳定窗口可能太长了。可以通过behavior里设置更大的scaleDown速率来解决:

behavior: scaleDown: stabilizationWindowSeconds: 60 # 缩短稳定窗口 policies: - type: Percent value: 50 periodSeconds: 15

把稳定窗口从 300 秒改成 60 秒,并且允许每 15 秒缩 50%,缩容就会快得多。不过我要提醒:缩得太快可能导致流量峰谷交替时副本数剧烈摆动。建议先保持默认,观察几天,再根据业务节奏调整。

4.3 单副本 Pod 突然被打挂,但 HPA 没有反应

这是 HPA 最让人困惑的场景之一。原因要从指标链路来看:Pod 被打挂之后,kubelet 采集不到容器 CPU 指标(容器已经不存在了),metrics-server 拿不到数据,HPA 就拿不到指标来计算副本数。简单说,容器的死亡导致它成了一个“指标黑洞”,HPA 根本看不到这个 Pod 的负载,自然不会触发扩容。

解决办法有两个思路:

第一,给业务容器加上合理的readinessProbe。如果 Pod 健康检查失败,K8s 会把 Pod 从 Service Endpoints 摘掉,但 Pod 本身还在 Running(或者 CrashLoopBackOff),此时指标是能采集到的。一旦 HPA 发现 CPU 指标上涨,它会扩容,新的 Pod 加进 Endpoints 里,业务就能恢复。这套“探针 + HPA”的组合拳能保命。

第二,不要只依赖资源指标做扩容,可以配置自定义指标(比如基于 Prometheus 的请求 QPS)。HPA 原生支持通过custom.metrics.k8s.io或external.metrics.k8s.io接口接入外部指标。当业务的关键指标是“请求队列长度”“QPS 超过阈值”等业务信号,而 CPU/内存还没及时反映时,自定义指标才是更灵敏的触发源。

比较典型的做法是用 Prometheus Adapter 把 Prometheus 里的http_requests_total等指标暴露成 HPA 可用指标。这个配置对新手有点门槛,但非常值得投入时间。我先给一个最小样例规范,实际扩展时只需修改metricsQuery里的 PromQL 即可。

# 这是 Prometheus Adapter 的 ConfigMap 片段 apiVersion: v1 kind: ConfigMap metadata: name: custom-metrics-config data: config.yaml: | rules: - seriesQuery: 'http_requests_total{namespace!="",pod!=""}' resources: overrides: namespace: {resource: "namespace"} pod: {resource: "pod"} metricsQuery: 'sum(rate(<<.Series>>{<<.LabelMatchers>>}[1m])) by (<<.GroupBy>>)'

对应的 HPA 配置:

apiVersion: autoscaling/v2 kind: HorizontalPodAutoscaler metadata: name: web-server-qps-hpa spec: scaleTargetRef: apiVersion: apps/v1 kind: Deployment name: web-server minReplicas: 2 maxReplicas: 10 metrics: - type: Pods pods: metric: name: http_requests_qps target: type: AverageValue averageValue: 100

这里type: Pods表示按每个 Pod 的指标值计算,HPA 会把所有 Pod 的 http_requests_qps 加总后除以副本数,再跟averageValue: 100比较。如果每实例每秒请求数超过 100,就扩容。

4.4 明明 CPU 很高,但 HPA 就是不扩容——问题出在 request 上

这是很多新手的困惑,也是最容易被忽略的一点。HPA 的 CPU 利用率计算方式是:

当前CPU使用量 ÷ 该Pod的CPU requests 容量

也就是说,如果你的容器requests.cpu: 2,实际只用了 0.5,那么利用率是 25%。如果你设的目标是 60%,它根本不会扩容。但你跑到节点上一看,机器的总 CPU 已经 80% 了,你会觉得 HPA 是瞎子——不是 HPA 瞎,是你不理解它算的是“相对 request 的利用率”。

这个设计本身有道理:HPA 只关心“这个 Pod 觉得自己已经用了多少资源”,而不关心“宿主机的总水位”。因为调度和 QoS 都是基于 request 的,如果 Pod 用了超过 request 的用量,它会成为节点上优先被驱逐的对象。但反过来,如果 request 设置偏大,HPA 的扩容阈值就变迟钝,这会导致“机器快扛不住了,但 HPA 认为每个 Pod 还有很多余量”。

解决办法是:梳理业务容器的 request,让它们尽量贴近真实用量。判断方法是看这个 Pod 一周内的kubectl top pod资源曲线,取 P95 值作为 request 参考。不要盲目给高 request,尤其在开了 HPA 之后,高 request 等于给自动扩容戴了枷锁。

4.5 多个 HPA 同时作用于同一个 Deployment,互相打架

K8s 官方是禁止同一类资源被多个 HPA 绑定的。如果你同时kubectl apply两个指向同一个 Deployment 的 HPA,后一个会报already exists之类的冲突错误,或者行为诡异。

但这个限制挡不住团队协作时的“事故现场”:开发 A 建了一个按 CPU 扩容的 HPA,开发 B 不知道,又建了一个按业务 QPS 扩容的 HPA,两个 HPA 指向同一个 Deployment,结果系统在 5 分钟内来回执行两套不同的扩容逻辑,副本数在 3 和 10 之间疯狂摆动。

我的习惯是:把 HPA 和被它管理的 Deployment 放在同一个目录下管理,并且在命名上强制关联,比如web-server对应的 HPA 一律叫web-server-hpa。用 GitOps 维护的话,加上 CI 里的资源冲突检查就能完全避免。

4.6 扩容后 Pod 一直 Pending,HPA 也不报错——这是资源不足

HPA 把副本数调上去之后,如果集群节点没有足够的 CPU/内存配额,新的 Pod 会一直停在 Pending 状态。此时你会看到一个很奇怪的现象:kubectl get hpa显示 REPLICAS 已经变成 8,但kubectl get pods里只有 3 个 Running,其余 5 个 Pending。

这个问题 HPA 自己不会报错,因为从 HPA 的角度它已经把期望副本数交给 Deployment 了,是调度器搞不定。这时要看的是:

kubectl describe pod <pending-pod>

如果事件里是Insufficient cpu或0/2 nodes are available,说明节点资源满了。解决办法除了加节点之外,还可以:

  • 检查cluster-autoscaler是否已部署并且正常工作(如果集群有自动扩节点能力,它会自动加节点)
  • 暂时把 HPA 的maxReplicas调低,避免创建过多 Pending Pod 占满资源
  • 给不同优先级的工作负载设置PriorityClass,保证核心服务在资源竞争时优先调度

这里我特别推荐把 HPA 和节点伸缩器配套使用。HPA 只管副本数,不管节点容量,如果集群固定就那几个节点,HPA 扩到 maxReplicas 也只会在 Pending 里等死。有了 Cluster Autoscaler,HPA 扩容 → 节点不够 → 自动加节点 → Pod 调度成功,这才是一条完整的弹性链路。

4.7 缩容总把老副本缩掉,新启动的 Pod 又被误杀

这个坑比较隐蔽。HPA 缩容时,ReplicaSet 会按照从新到旧的顺序删 Pod(即先删最新创建的)。但如果你刚滚动更新完,老副本还处于 terminating,新副本正在启动,HPA 又触发了缩容,它可能删掉正在启动的新 Pod,导致滚动更新过程被打断。

处理方式有两个层面:

第一,在 Deployment 里合理设置strategy.rollingUpdate.maxSurge和maxUnavailable。maxSurge表示更新时可以多出的副本数,maxUnavailable表示更新期间允许 unavailable 的副本数。如果两者之和小于 HPA 的扩容余量,滚动更新和 HPA 之间的冲突会减少。

第二,更可控的做法是在 HPA 的behavior.scaleDown里加selectPolicy: Disabled,或者用 Pod 级别--terminationGracePeriodSeconds延长优雅终止时间,让老 Pod 有足够时间处理存量请求,尽量避免“刚起来就被杀”的局面。

实际上很多团队已经抛弃了用 HPA 直接管 Deployment 的做法,而是用一个中间层——比如把 HPA 指向Deployment + PDB(PodDisruptionBudget)组合。PDB 的语义是“任何一次主动驱逐(包括 Node 运维、Cluster Autoscaler 缩容)最多只能导致 N 个 Pod 不可用”,它能把缩容的破坏力约束在一个可控范围内。

4.8 网络相关:排查 HPA 性能问题的快捷路径

HPA 本身不涉及网络,但你是不是搜到了类似 “preflight” 这种东西?网上经常出现 “kubernetes v1.26.0 preflight running pre-flight checks” 之类的词。这是 kubeadm 在初始化集群时做的预检,不是 HPA 的功能。但这个预检里有一条跟你后续排查 HPA 有关的点值得注意:**kubeadm 预检会检查各节点之间的网络连通性、kubelet 是否安装,以及 API Server 是否可访问。**如果这些不通过,集群都装不完整,更谈不上 HPA。所以你在做整体排障时,先把 kubeadm 的 preflight 状态和 kubelet 日志看一遍,省掉很多弯路。

5. 生产环境配置 HPA 的经验沉淀

最后分享几个我反复在项目里验证过的东西,不展开讲原理,全是实用判断。

target 值的设定建议从 CPU 60% 起步。这是我个人的默认值。太低(30%)HPA 太敏感,副本数波动大;太高(90%)留给扩容反应的时间太短,流量突然增长容易直接打穿。60% 左右留出了“单副本还能扛一小段时间”的安全垫。内存 target 我一般设得更高一些,比如 80%——因为内存不像 CPU 可以快速释放,Pod 内存涨上去只能靠重启才降得下来,设太低会导致频繁扩容。

request 值一定要做校准,否则 HPA 的计算基准是失真的。你可以把“kubectl top pods -n namespace --sort-by=cpu”打印下来,对比一下每个容器真实用量和 request 的比例。相差超过 3 倍的,我建议直接把 request 调到真实 P95 用量,这样 HPA 的扩容决策才有实际参考价值。

HPA 不能完全替代容量规划。它处理的是流量正常波动范围内的伸缩,如果某个业务要做大促、秒杀,还是需要预先压测、提前扩容集群,把 HPA 当作大促期间的“安全网”而不是“主力选手”。在极端流量面前,任何自动扩缩容都有一定延迟,提前备好资源比事后补救靠谱得多。

给 HPA 加告警,而不是只靠它自我管理。观察 HPA 副本数是否已经冲到maxReplicas就是一个重要的告警阈值。HPA 扩容到了上限说明自动伸缩已经触顶,业务很可能扛不住了,这时候要人工介入(比如限流、降级、加节点)。只依赖 HPA 不加监控,等于在高速路上只开巡航不开眼。

最后一个小技巧:把kubectl get hpa -w加到你的日常巡检命令里。这个命令能实时看到 TARGETS 和 REPLICAS 的变化,比看监控面板更直接。我经常在排查问题时开着它,配合kubectl get events --sort-by='.lastTimestamp'看事件流,基本能把 HPA 的每次决策前因后果还原出来。

HPA 用好了,你的服务就像有了一个不知疲倦的调度员——流量涨了它先上,流量跌了它慢慢撤。它不能替你解决所有稳定性问题,但能帮你把那些最琐碎的“手动扩缩容”从工作清单里划掉,让你把精力留给真正需要人判断的事情上。

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

线性代码:从嵌套深渊到平直控制流的重构实践

1. 为什么"代码走直线"成了我评审时的执念提到"线性代码"这个说法&#xff0c;不少人的第一反应是&#xff1a;代码本来不就是从上往下跑的吗&#xff1f;我之所以对这个词念念不忘&#xff0c;是因为三年前的一次 code review。组里一个小伙子提了个 PR&a…

作者头像 李华
网站建设 2026/10/1 17:53:47

分层树形算力体系:MoE商业化落地的原子级成本治理方案

1. 为什么“分层树形算力体系”不是又一个技术名词&#xff0c;而是MoE商业化卡点的手术刀最近三个月&#xff0c;我连续跟进了7家专注大模型应用落地的创业团队&#xff0c;其中5家卡在同一个地方&#xff1a;模型越做越准&#xff0c;客户越用越贵&#xff0c;毛利却从预期的…

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

单卡复现PaperClip:基于KV Cache压缩的LLM长上下文显存优化指南

先纠正一个容易搞混的印象&#xff1a;PaperClip 这名字看着像办公用品&#xff0c;实际上在 LLM 推理优化圈子里指代的是基于 KV Cache 压缩思路的一类开源项目。我花了两个周末把它读到源码级别&#xff0c;又在自己那台单卡机器上完整复现了一遍&#xff0c;期间踩了不少坑。…

作者头像 李华
网站建设 2026/10/1 17:51:35

SAP特殊库存T库存详解:第三方订单直发业务的核心逻辑

做SAP MM顾问的&#xff0c;多多少少都会跟特殊库存打交道。E库存&#xff08;寄售&#xff09;、K库存&#xff08;分包&#xff09;、Q库存&#xff08;项目&#xff09;这些都是高频词&#xff0c;但有一个T库存&#xff0c;很多人可能只是听过名字&#xff0c;甚至做了几年…

作者头像 李华
网站建设 2026/10/1 17:50:44

基于Python的股票价格走势预测:从数据准备到LSTM回测

简介&#xff1a;这是一套基于TensorFlow实现的股票价格走势预测示例&#xff0c;面向对金融数据挖掘、时间序列预测感兴趣的Python开发者和量化分析初学者。项目通过tushare接口获取股票历史行情&#xff0c;并对缺失值、日期索引等做必要处理&#xff1b;利用pandas完成数据清…

作者头像 李华
网站建设 2026/10/1 17:50:30

飞飞怀旧客户端源码逆向解析与VS2008编译实战

简介&#xff1a;本资源为《怀旧飞飞》老版本服务端源代码压缩包&#xff0c;面向游戏开发初学者、服务器架构学习者及MMORPG技术研究者&#xff0c;提供完整可研读的早期商业网游服务端实现范例。包内共2000个文件&#xff0c;以627个cpp和906个h/cpp头文件构成核心逻辑主体&a…

作者头像 李华