Kubernetes弹性伸缩实战:HPA、VPA与集群自动伸缩全解析 Kubernetes弹性伸缩这套东西我前前后后折腾了快三年。最开始以为它就是给Deployment配个HPACPU到了80%就多开几个Pod后来才发现这套体系的深度远不止于此。如果你也在维护K8s集群或者正准备给业务加上弹性伸缩能力这篇内容应该能帮你少踩几个坑。我会把Pod层面的水平伸缩、垂直伸缩、节点层面的集群伸缩以及各种自定义指标的玩法串起来讲偏实战。1. 弹性伸缩到底解决了什么问题以及为什么它不等于多开几个Pod1.1 从一次容量事故说起我的一个模拟项目X遇到过非常典型的问题一个面向外部用户查询的服务平时流量平稳CPU使用率常年维持在15%左右。但每个月总有那么几次突发流量请求量会在几分钟内翻三到五倍。最开始我们是人工扩容收到告警后手动拉副本数等流量降下来再收缩。听起来好像可行但实际运营中会发现两个致命伤第一是响应太慢告警、登录、执行扩容命令、等Pod Ready整套流程跑完至少三五分钟第二是容易过度扩容或者扩错实例组。后来我们开始用Kubernetes原生的HPA做CPU-based弹性伸缩把副本数从3扩到20流量高峰能扛住但很快发现另一个问题CPU指标有滞后性而且很多业务的瓶颈根本不在CPU。比如有些查询服务数据库连接池和内存才是瓶颈有些消息处理服务队列长度才是真正的晴雨表。单纯看CPU会导致该扩的时候不扩不该缩的时候拼命缩。1.2 弹性伸缩在K8s里的三个层次很多人把弹性伸缩等同于HPA这是一个比较常见的认知局限。实际上Kubernetes弹性伸缩至少可以拆成三个层次Pod数量伸缩最常用的是HPAHorizontal Pod Autoscaler根据负载指标调整副本数。解决的是一个服务需要几个实例才够的问题。Pod资源伸缩也就是VPAVertical Pod Autoscaler自动调整Pod的CPU和内存资源请求值。解决的是单个Pod给多大资源才合适的问题。集群节点伸缩常见的是Cluster Autoscaler或者各云厂商的节点池自动扩缩容。解决的是集群节点够不够用的问题。这三个层次往往是组合使用的而不是选一个。比如说HPA判定业务需要多开10个Pod但当前集群的资源不够了Pod可能Pending。这时候就需要节点层面的伸缩来补充算力。反过来如果节点弹性跟不上HPA的扩容请求副本数扩不起来整个弹性链路还是断的。1.3 举一个容易误判的业务场景还有一个经常被误解的场景离线任务。有些批处理任务用CronJob跑运行时间半小时资源消耗波动很大。有人在CronJob上配了HPA结果发现Pod要等下一批次才可能被扩缩因为HPA本身不会扫描已经结束的Pod。如果业务形态是短时任务那弹性伸缩的切入点应该是队列长度触发、Job并发数控制而不是简单的DeploymentHPA。所以设计弹性伸缩方案之前第一件事不是写YAML而是理清楚业务的流量模型是持续高负载还是突发间歇是CPU密集还是IO密集响应时间敏感还是吞吐量优先这些答案决定了该用哪一层伸缩、配什么指标、设多少阈值。2. HPA核心机制拆解指标采集、副本计算和冷却窗口2.1 HPA的完整工作循环HPA本质上是一个控制循环控制器。它的工作方式大致是这样的从指标系统读取当前Pod的平均负载值拿这个值和目标值比较按公式算出期望副本数把Deployment/StatefulSet的副本数改成期望值等待一段时间同步周期再次进入循环。它默认的同步周期是15秒。也就是说HPA每隔15秒去metrics-server拉一次指标。注意这个指标拉取的负载数据来源是metrics-server采集的节点和Pod资源使用率而metrics-server本身又有自己的采集间隔通常是15秒到30秒。整条链路下来从业务负载真正上升到你看到Pod开始扩容往往有30秒到1分钟的延迟。理解了这条链路你就能解释很多奇怪现象。比如你家指标明明已经是CPU 90%了但HPA等了半天才有动作。多数时候不是配置写错了而是指标链路本身存在采集延迟和聚合延迟。2.2 期望副本数的计算公式HPA计算期望副本数用的是这个公式desiredReplicas ceil[currentReplicas * (当前指标值 / 期望指标值)]举个例子预期目标是CPU使用率50%当前有4个Pod实测平均CPU是75%那么期望副本数就是ceil[4 * (75/50)] ceil(6) 6个Pod。这个公式看着简单但有几个隐藏含义需要理解清楚它用的是所有Pod指标的平均值不是中位数也不是最大值。这意味着少量Pod跑得很高、其他Pod空闲时平均值可能不大扩容不会那么激进。指标是当前实际使用量除以请求量的百分比不是绝对CPU核心数。要看客户端的CPU使用率必须设置好Pod的requests否则HPA拿不到百分比。ceil取整意味着只要比值不是整数就向上取整所以扩容比缩容更激进一些。我还遇到过直接用绝对值做HPA的场景比如按QPS扩容。这种自定义指标的计算公式是一样的但指标的采集方式完全不一样后面专门讲。2.3 一套能直接参考的HPA配置下面是一份生产环境里跑过的HPA配置比较稳可以直接参考apiVersion: autoscaling/v2 kind: HorizontalPodAutoscaler metadata: name: api-server-hpa namespace: production spec: scaleTargetRef: apiVersion: apps/v1 kind: Deployment name: api-server minReplicas: 5 maxReplicas: 50 metrics: - type: Resource resource: name: cpu target: type: Utilization averageUtilization: 60 behavior: scaleDown: stabilizationWindowSeconds: 300 policies: - type: Percent value: 20 periodSeconds: 60 scaleUp: stabilizationWindowSeconds: 0 policies: - type: Pods value: 10 periodSeconds: 60这份配置里的stabilizationWindowSeconds是稳定窗口也是很影响实际体验的参数。先说缩容侧它表示在这么多秒内HPA看到的期望副本数如果比当前小不会立刻缩而是要等窗口期过了才执行。这能避免CPU一抖动就疯狂缩容然后又要扩容的振荡问题。我生产环境里给缩容配了300秒也就是5分钟。短暂的小负载波动不会触发缩容效果比较明显。扩容侧我配了0秒稳定窗口因为突发流量场景下晚扩一秒业务就多一点超时风险。policies是扩缩容速率控制。type: Percent表示按当前副本数的比例type: Pods表示按固定个数。上面的配置意思是每分钟最多按当前20%的比例缩容扩容时每分钟最多增加10个Pod。这个速率限制能防止HPA一下子把副本数拉到最大把后端数据库或下游服务打爆。2.4 冷却窗口为什么是弹性伸缩最容易忽略的细节冷却窗口看起来只是等一会儿再动手但它在真实负载曲线下的作用非常大。想象一个规律波动的服务每隔20分钟来一波小高峰。如果不配缩容稳定窗口HPA在高峰过后立刻检测到CPU降低会马上把副本缩回去。然后下一波高峰又来了又开始扩容。一天下来Pod创建销毁了几十次列表页看起来就像在抽风P95延迟反而可能变高。稳定窗口的本质是用时间去换判断的稳健性。但窗口也不是越大越好。如果设了30分钟缩容稳定窗口意味着流量高峰过去之后半个小时内副本数都不会下降这段时间的节点资源是被白白占用的成本当然也在持续消耗。另外一个很常见的坑多处配置冲突。比如HPA的缩容稳定窗口是300秒但Deployment的spec.strategy.rollingUpdate里如果设置了maxSurge: 0和maxUnavailable: 1那么在缩容时可能出现旧的Pod要等滚动更新超时才能被删除的情况。也就是说HPA已经决定缩了但因为滚动更新策略的限制Pod真正消失还要再等一段时间。所以一个稳的弹性伸缩配置一定要同时考虑三件事指标阈值、稳定窗口、以及Deployment自身的滚动更新策略。3. 进阶玩法自定义指标、Prometheus Adapter和事件驱动伸缩3.1 为什么内置的CPU和内存指标经常不够用CPU和内存使用率是基础但很多业务场景下它们并不是最敏感的指标。举几个我实际处理过的例子消息消费服务瓶颈在消费速度指标看的是消息队列里堆积的消息数量CPU可能一直很低。对外API网关瓶颈在吞吐量和P99延迟CPU和内存都看不出问题但请求量已经上来了。定时任务调度器按任务队列长度判断是否需要加WorkerCPU和内存都是平稳的。这些场景下内置的Resource类型的指标根本没有反映业务的真实负载。这时候要么用custom.metrics.k8s.ioAPI接入外部指标要么用external.metrics.k8s.ioAPI接入集群外部指标。常见做法是Prometheus配合Prometheus Adapter或者直接上KEDA。3.2 Prometheus Adapter的指标接入链路用Prometheus Adapter做自定义指标HPA整体链路是这样的业务Pod - Prometheus采集指标 - Prometheus Adapter暴露custom metrics API - HPA定期拉取指标 - 计算副本数这里最值得注意的一点是HPA拿到的指标必须是Pod的平均值或某个聚合值而不是原始的时间序列数据。比如你想按QPS扩容Prometheus里存储的是每个Pod的http_requests_total计数器这个计数器的rate值会随着Pod实例数量变化而变化。如果你直接拿总QPS做平均值逻辑上是对的sum(rate(http_requests_total[2m])) by (namespace, deployment) / 副本数但Prometheus Adapter的配置里如果写不好targetValue和averageValue很容易出现指标计算错误。我之前做过一套配置按每个Pod的QPS作为指标target平均值为100。Prometheus Adapter的metricsQuery是这么写的- seriesQuery: {__name__http_requests_total,namespace!,pod!} resources: overrides: namespace: { resource: namespace } pod: { resource: pod } metricsQuery: sum(rate(.Series{.LabelMatchers}[2m])) by (.GroupBy)这里的关键是seriesQuery要选的粒度和HPA期望的指标粒度一致。HPA的type: Pods指标表示它要求每个Pod都有一个独立指标值Adapter必须按Pod拆开返回。如果你在PromQL里用sum by (namespace)而不是sum by (pod)返回出来的就不是Pod维度指标HPA会报错或者计算出荒诞的结果。Prometheus Adapter带来的另一个麻烦是你得自己保证指标连续性。Promethus默认不采集会打散Pod指标旧的Pod被删掉后如果HPA还拿着已经消失的Pod做平均可能出现指标数量比当前副本数多的情况进而把期望副本数算得很低。解决这几个问题最省事的方式是直接在HPA的指标配置里用averageValue它表示所有后端Pod的平均值期望是XX而不是每个Pod必须是XX这样指标源本来就是一个聚合值不会因为Pod数变化而剧烈抖动。3.3 事件驱动伸缩用KEDA监听队列长度如果说Prometheus Adapter还是围绕指标在转那KEDA更进一步它把事件抽象成了触发源。比如Kafka积压消息数、RabbitMQ队列长度、MySQL慢查询数、甚至是云厂商的消息队列指标都可以直接触发伸缩。KEDA的工作机制是部署一个ScaledObject对象它描述我要监控哪个Deployment、监听什么事件源、阈值是多少、最小最大副本数是多少。KEDA内部会启动一个scaler循环不断从外部事件源拉取指标然后通过修改HPA的副本数或者直接对Deployment扩缩容来实现伸缩。下面是一个基于RabbitMQ队列长度伸缩的ScaledObject配置示例apiVersion: keda.sh/v1alpha1 kind: ScaledObject metadata: name: consumer-scaledobject namespace: production spec: scaleTargetRef: name: consumer-deployment minReplicaCount: 2 maxReplicaCount: 30 triggers: - type: rabbitmq metadata: protocol: amqp queueName: task_queue mode: QueueLength value: 20这份配置的意思是task_queue的队列长度如果超过20条开始扩容消费者低于这个阈值后随时间逐渐缩容到minReplicaCount。事件驱动伸缩比纯粹的指标伸缩更贴近业务语义但它依赖外部事件源的SDK和认证配置。比如RabbitMQ trigger需要配置hostKafka trigger需要broker地址和SASL认证。KEDA文档写得还可以但实战中经常出现的问题有两个一个是事件源配置错误导致scraper一直报错但Deployment就是没反应另一个是网络隔离导致KEDA所在的Pod访问不了内网消息队列。我的建议是如果要引入KEDA先在测试环境用EventSource和TriggerAuthentication把连接验证打通再上ScaledObject。不要上来就直接把ScaledObject配到生产因为这里的错误排查链路比较长KEDA日志、消息队列侧日志、HPA事件三层都可能出问题。3.4 自定义指标伸缩的副本数计算逻辑差异用自定义指标做HPA时公式和CPU一模一样但有两处容易混淆type: PodsaverageValue: 100表示HPA按所有Pod的平均值做计算。如果你的指标是按Pod拆分返回的HPA自己会去算平均。type: Objecttarget: Value/AverageValue表示指标来自某个外部对象比如一个Prometheus里的Service指标一个Ingress指标。这时候HPA把外部对象的值和targetValue比较参与计算的只有一个数值不需要做Pod平均。假如你的业务已经通过Service Mesh把QPS聚合成了一个Service维度的指标那用type: Object会简单直接得多。这个类型不太像自定义指标的名字那么自定义它本质上就是选一个集群内/外部的对象拿它的指标值来判断扩缩容。4. VPA垂直伸缩自动调整Pod资源规格的正确姿势和限制4.1 VPA的三个运行模式VPA是另一个容易让人心动又容易踩坑的组件。它可以自动修改Pod的CPU和内存requests和limits让你不用再人工猜一个请求值。VPA有三种模式Off模式只计算推荐值不自动更新Pod。你可以通过kubectl get vpa -o yaml查看推荐值然后手动修改。Auto模式自动更新Pod的资源配置。注意更新可能触发Pod重建因为资源字段变了就需要重新调度。Initial模式只在Pod创建时设置初始资源请求之后不调整。VPA的实现原理也不复杂VPA Recommender从Metrics Server采集Pod的历史资源使用情况结合VPA对象中设置的容器名生成推荐请求值。然后由Updater决定哪些Pod需要更新并通过webhook在Pod创建或更新时注入推荐值。4.2 VPA和HPA一起用一个经典冲突陷阱VPA和HPA同时配置在同一个Deployment上如果HPA使用CPU或内存作为指标那这两个组件就可能互相打架。VPA把Pod的requests调大了CPU使用率不变的话使用量/请求量这个百分比会变小HPA看到指标下降就会去缩容。反过来也一样HPA扩容增加了Pod数VPA通过每个Pod的使用率又可能把请求值调小或者调大导致HPA再次调整副本数。两个控制器对着同一组对象做闭环控制最终很容易出现振荡。现在K8s社区对VPA和HPA的关系是VPA和HPA不能同时使用CPU或内存作为HPA的指标。如果HPA用的是自定义指标或者外部指标VPA只调整CPU和内存请求两者基本可以共存。但为了稳妥生产环境里我还是把它们用在不同的服务上。比如对无状态Web服务用HPA按QPS或CPU扩缩容requests值人工设好。对有状态服务、推荐型服务这类偶尔需要大内存的服务用VPA的Off模式先观察两周再切到Auto模式同时不配HPA。聊天里经常有人问为什么我的VPA Auto模式改完资源Deployment的Pod一直处于ContainerCreating多数时候是因为VPA把内存请求加到超过节点可用内存或者和LimitRange冲突了。VPA会计算推荐值没错但不会帮你看节点资源够不够。4.3 我建议的VPA落地策略如果你问我VPA到底要不要上我的态度是比起HPA来说VPA更适合作为资源规范化工具而不是实时弹性方案。什么意思就是你应该让VPA跑一段时间输出合理的请求值和限制值然后手动把推荐值固化到Deployment里或者只在Initial模式下使用。让它实时自动调整是高风险操作因为自动调整会触发Pod重建影响可用性调整不基于实时的流量突变而是基于历史数据所以面对突发流量能力很弱场景和LimitRange、ResourceQuota、节点污点等配置冲突时很难一眼看出来哪里有约束。如果你只是想让集群的资源利用率更高VPA的Off模式已经够用了。5. 集群节点层面的弹性Cluster Autoscaler的工作原理和配置细节5.1 CA的扩张和收缩逻辑Pod层面的HPA调整的是副本数但如果集群没有足够的节点承载这些Pod新Pod就会一直Pending。Cluster AutoscalerCA就是来解决这个问题的。它的逻辑比HPA更直白每隔一段时间扫描所有Pending的Pod检查Pod是否因为资源不足而无法调度如果确实是资源不足触发节点池扩容新节点加入集群节点加入后调度器把Pending Pod调度到新节点上。缩容侧的逻辑是反过来的CA会检查节点利用率如果某个节点上所有Pod加起来可以重新调度到其他节点就驱逐Pod并移除节点。5.2 CA的参数调整和生产建议CA可以配置的地方很多但下述几个参数对稳定性影响比较大--max-nodes-total集群最大节点数这个必须设防止节点池无限扩张成本失控。--scale-down-delay-after-add新节点加入后多少秒内不参与缩容评估默认10分钟。如果流量刚刚过去新节点上的Pod马上又被调度走节点利用率变低CA可能几秒内就想把这个新节点缩掉但新节点上可能还有正在启动的Pod直接缩掉会导致Pod被重新调度到旧节点造成抖动。--scale-down-utilization-threshold节点CPU/内存利用率低于多少才开始评估缩容默认0.5也就是低于50%。这个值要看业务如果业务本身CPU就低建议调到0.3以下否则节点会被反复缩掉和重新创建。--expander当有多个节点池可选时选择弹性策略。常用的是random和least-waste。在多可用区部署的场景下我比较建议用带优先级或可用区约束的expander避免所有新节点都堆到同一个可用区。以某云厂商提供的节点池自动扩缩容为例它在底层其实就是托管版的CA你在控制台设置节点池的最小和最大节点数它自动帮你执行。自建K8s集群的话自己维护CA需要在Pod里配云厂商AK/SK和IAM权限也是有一定工作量的一步。5.3 CA、HPA和VPA三者如何配合如果讲到这里还有点抽象用一个真实的流量周期来说明三个组件如何协同业务流量升高HPA检测到CPU或自定义指标超过阈值把Deployment副本数从10加到20新Pod创建后调度器发现现有节点剩余资源不够把这些Pod标为PendingCA扫描到Pending Pod触发节点池扩容新增1~2个节点新节点Ready后Pod调度上去开始处理流量流量回落HPA缩容到8个副本节点利用率下降CA评估后把多余节点移除。整个过程里HPA响应秒级到分钟级CA响应分钟级VPA则是小时级到天级的调整节奏。三者各管一段但如果某一个掉链子整个弹性链路都会卡住。比如我遇到过CA因为云资源配额不足导致节点一直创建失败结果HPA把副本数加到了30但30个Pod全是Pending业务雪崩。所以无论用哪种方式一定要在监控里同时盯住三个阶段HPA的决定、Pod的调度状态、节点的Ready状态。6. 踩坑实录HPA不生效、扩容振荡、指标缺失的完整排查链路6.1 指标采集断链是最普遍的原因很多HPA不生效的问题根子不在HPA本身而是指标链路断了。常见的检查方式是kubectl top pod -n production如果这条命令能返回每个Pod的CPU和内存数据说明metrics-server工作正常。如果一直报error: metrics not available yet那就是metrics-server还没有采集到数据。常见原因包括metrics-server版本过旧或者kubelet的--authentication-token-webhook配置导致metrics-server无法认证。如果是自定义指标检查链路就更长。先看Prometheus里有没有业务指标curl http://prometheus-server/api/v1/query?queryrate(http_requests_total[5m])如果Prometheus里没有数据就是采集端的问题。如果Prometheus有数据但HPA显示unknown,那问题就出在Prometheus Adapter把PromQL暴露成Custom Metrics API这一步。你可以在控制平面节点上用下面的命令查看kubectl get --raw /apis/custom.metrics.k8s.io/v1beta1/namespaces/production/pods/*/http_requests_qps这条命令能直接看到HPA拿到的指标形态。很多人在Prometheus Adapter里写PromQL时没用by (pod)导致API返回的是个标量HPA没法把它按Pod拆分错误日志里会写unable to fetch metrics from custom metrics API。6.2 扩容振荡和缩容过渡案例有一次一个朋友反馈他家的HPA每分钟都在扩缩容副本数在3到10之间来回跳。我第一反应是检查CPU行为的配置结果他的目标利用率设在30%业务Pod的requests又设得很低实际CPU使用率会在30%上下波动导致期望副本数一直在2-6之间摇摆。为了改善振荡我是这样处理的把目标CPU利用率从30%调到60%降低指标波动的敏感性加上缩容稳定窗口300秒让波动被时间过滤掉扩容策略限制每分钟不超过4个Pod避免扩容过快查看Pod的requests值把过低的请求值修正到和容器实际使用量匹配的水平。这里反映出很多人的一个误区HPA的目标值往往是根据理论负载拍的而不是根据实际业务曲线拍的。如果你没有压测数据就不要把目标利用率设太低因为它会让HPA的反馈环路变得太激进。振荡的另一个常见来源是多个容器共享Pod资源。HPA算平均利用率时用的是整个Pod的CPU请求总量或者内存请求总量。如果一个Pod里有3个容器其中2个容器请求值很低但是平时几乎不消耗CPU另一个容器才是业务主力那么利用率会被稀释。最稳妥的做法是核心业务容器单独一个Pod或者只用第一个容器的指标。6.3 排水策略和Canary发布影响还有种场景容易被忽略你在做Canary发布或者滚动更新时HPA可能把正在退出的旧版本Pod也当作指标源。比如Deployment的maxSurge设置了一个额外Pod那么HPA看到的副本数可能短暂地比实际运行服务的Pod多1个。如果没有额外的容错期望副本数可能会被低估。所以如果业务发布频繁我建议给HPA关联的Deployment设置比较明确的maxUnavailable让旧Pod在HPA计算时尽量少引入噪声。比如maxUnavailable: 1、maxSurge: 1这样既保证发布可用性又不会让临时Pod对HPA指标产生太大的干扰。6.4 从kubectl describe hpa里读出问题kubectl describe hpa xxx是快速定位HPA问题的最好入口。它能显示三块关键信息Status.Metrics显示当前指标值和目标值。如果这里全是unknown说明指标根本没取到。Events显示HPA的扩容和缩容记录。如果事件里一直说failed to get cpu utilization就是指标API的问题如果说New size: 5; reason: All metrics below target说明HPA已经判定需要缩容但没有执行。Conditions显示ScalingActive、ScalingLimited、AbleToScale这三个条件。如果ScalingLimited为True说明HPA想扩容但碰到了maxReplicas上限经常有人配了maxReplicas5流量一高就卡住还以为是HPA坏了。掌握这套排查方式后再遇到HPA问题基本不用猜了。7. 弹性伸缩压测验证与生产落地的经验建议7.1 用什么方式压测比较有效配置写完之后绝大部分问题要在压测阶段暴露。我推荐用一套简单的压测工具组合一个能生成并发请求的工具配合K8s自身的监控工具比如kubectl top pod、kubectl get hpa -w以及Prometheus的可视化看板。具体的验证步骤是这样设定一个基础副本数比如5用一个压测工具向目标Service发起递增的并发请求比如从50并发起步每30秒增加50直到500并发同时观察HPA的变化和Pod启动情况检查扩容速率是否跟上流量增长Pod有没有Pending停止压测观察缩容行为是否按预期平稳下降。压测时有一个容易被忽略的点压测机本身也会消耗资源如果压测机不在集群内或者坐在集群里节点上没有独立配额可能挤占业务资源导致CPU指标异常拉升。最好把压测工具部署在独立节点池或者集群外以确保指标干净。7.2 一组经过调优的参数参考根据不同负载类型我常用下面几组不同的HPA配置模版CPU驱动、通用Web服务目标利用率60%扩容每分钟最多10个Pod缩容稳定窗口300秒按20%速度缩容。QPS驱动、高并发网关目标每个Pod平均QPS 200扩容策略取固定5个Pod加比例5%缩容稳定窗口600秒避免只在高峰期开起来。消息消费服务优先用事件驱动伸缩队列长度阈值根据单Pod消费速率设定缩容窗口可以短一点60~120秒。参数不是一成不变的这些只是起点。真实业务一定要根据压测和线上周期数据持续调。我的习惯是每个季度重新看一遍Prometheus里CPU、QPS、Pod数的时间序列对明显不合理的阈值做一次修订。7.3 生产环境落地前的一份检查清单最后分享一份我自己每次上线弹性伸缩前都会过一遍的清单你可以直接拿来参考所有工作负载是否都设置了合理的requests和limits没有的话HPA指标会失真HPA、VPA是否配置在同一类资源上确认两者不会互相打架集群节点是否有余量CA是否配置了最小和最大节点限制缩容稳定窗口是否阻挡了正常流量回落扩容速率是否可能导致下游爆炸指标链路是否打通kubectl top pod有数据、Prometheus有数据、Custom Metrics API有数据是否设置了针对HPA的监控告警比如ScalingLimited触发、Pending副本数大于0等压测是否覆盖了最大流量、持续流量和突刺流量三种形态。现在Kubernetes的弹性伸缩已经不是什么新鲜功能了HPA、VPA、CA这些组件都是成熟方案。但我见过的很多事故往往不是组件本身的问题而是配置方各管各、指标选了不合适的值、链路断了一截还不知道。把这条链路的每一个环节都盯住才是稳定的保障。如果你最近也在调HPA或者CA建议从今天开始记录下你的三个关键数据业务的实际QPS波动、每个Pod的CPU峰值、以及扩容响应时间。攒上两周再去看很多参数问题一眼就能定位。