工作负载指标与自动伸缩
一个消费者 Deployment 的 HPA 显示 current 20% / target 70%,队列却已经积压 80 万条消息。团队把最大副本从 20 调到 100,副本数仍没有变化:CPU 不是这个系统的需求信号,消费者在等待下游限流,增加副本只会制造更多重试。另一个服务启用 VPA 后,CPU request 被提高,基于 CPU utilization 的 HPA 随即认为负载下降并缩容,两套控制器都按自己的算法正确执行,却把业务推向振荡。
自动伸缩的第一步不是安装控制器,而是确定需求如何变成指标、指标是否新鲜、控制器能写哪个对象、动作多久生效以及业务怎样证明容量恢复。HPA、VPA 与 KEDA 分别解决副本、单 Pod 资源和事件信号问题;它们可以协同,但必须拥有互不冲突的输入和字段。
资源事实是所有控制器的共同地基
调度器按 requests 预留容量,HPA 的 CPU/内存 utilization 以 request 为分母,VPA 从历史使用推导 request,节点伸缩器又用 request 模拟新节点是否能容纳 Pending Pod。一个随手填写的 100m/128Mi 会同时污染四条控制链。
CPU 可压缩,超出 limit 通常表现为 CFS 节流;内存不可压缩,超过 limit 可能触发 OOM。QoS、LimitRange、ResourceQuota、Pod Overhead 和 Init Container 的资源计算都会改变实际可调度容量。资源基线文章会用“节点看似空闲但 Pod Pending”和“Pod 可调度但持续 OOM”两组反例建立判断。
指标链要证明值、时间和身份
Resource Metrics API 只提供 Pod、Node 的 CPU 与内存快照;Metrics Server 是它的参考实现,不是长期监控、精确计费或容量预测平台。Custom Metrics API 把 Kubernetes 对象关联到业务指标,External Metrics API 表达队列等集群外信号。适配器必须把 PromQL、标签和对象身份稳定映射,否则同名指标可能读取到错误租户或陈旧序列。
kubectl get apiservice | grep metrics
kubectl get --raw '/apis/metrics.k8s.io/v1beta1/nodes' | jq '.items[0].timestamp,.items[0].window'
kubectl get --raw '/apis/custom.metrics.k8s.io/v1beta1' | jq '.resources[].name'
kubectl get --raw '/apis/external.metrics.k8s.io/v1beta1' | jq '.resources[].name'四个 API 都可能独立失败。kubectl top 正常只证明 Resource Metrics 可读,不能证明自定义指标规则、外部凭证或 HPA selector 正确。Kubernetes 资源指标流水线和自定义指标支持给出了这些 API 的职责边界。
HPA 控制副本,不负责创造节点
HPA 读取指标、计算期望副本并写目标的 /scale 子资源。behavior.scaleUp、behavior.scaleDown、policies 与 stabilization window 用来限制变化速度,不是修复错误信号。冷启动 Pod、缺失指标、尚未就绪样本和多指标最大值选择都会改变结果。
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: checkout
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: checkout
minReplicas: 3
maxReplicas: 30
behavior:
scaleDown:
stabilizationWindowSeconds: 300副本变多后仍可能全部 Pending,因此 HPA 验证必须继续观察调度、节点供给、Pod Ready 和业务 SLO。HPA 官方概念应作为算法与稳定字段的依据。
VPA 先推荐,再决定是否允许中断
VPA 由 Recommender、Updater 和 Admission Controller 组成。Off 只给建议,Initial 在创建时注入资源,Recreate 通过重建应用建议,InPlace 或 InPlaceOrRecreate 取决于目标集群能力和工作负载条件。生产不应继续把已弃用的 Auto 当作默认答案。
推荐需要足够长且具有代表性的样本。发布峰值、定时任务、内存泄漏、sidecar 和短期故障都可能污染结果。先对比 recommendation、P50/P95/峰值、OOM 与节流,再通过变更流程调整 request;PDB、单副本服务和启动缓慢应用要特别评估重建风险。
KEDA 把事件变成伸缩信号
KEDA 的 ScaledObject 面向 Deployment 等可伸缩对象,ScaledJob 面向事件驱动批任务。Operator 负责从零激活,生成的 HPA 负责从一到多;TriggerAuthentication 与 ClusterTriggerAuthentication 决定外部系统凭证边界。
队列深度不能直接等同副本数。每个实例处理速率、消息可见性超时、下游配额、失败重试和冷启动共同决定目标。反向实验应撤销指标源凭证或返回空值,观察 fallback、condition、队列积压和业务告警,而不是只看 ScaledObject 是否存在。
组合治理从字段所有权开始
为每个控制器列出读取事实、写入字段、最小/最大边界、冻结方法和 GitOps 协作方式。HPA 与 GitOps 不能同时持续写 replicas;VPA 修改 CPU request 会改变基于 CPU utilization 的 HPA 分母;KEDA 创建并管理 HPA 时,不应再由另一套发布模板覆盖同名对象。
replicas -> HPA 或 KEDA 生成的 HPA
cpu request -> 应用声明 / VPA,二选一为生产写入者
memory request -> 应用声明 / VPA,二选一为生产写入者
min/max -> 平台容量政策,经 GitOps 交付但不覆盖运行状态迁移时先让新控制器只观察,记录影子决策;切换唯一写入者后保留静态回退值。故障时按指标、控制器、调度和节点供给顺序冻结,避免多个团队同时手动修改。
权限、成本和长期责任要进入上线门槛
Metrics Adapter 可读取业务指标,KEDA 可能访问云队列,VPA Admission Controller 修改 Pod,HPA 写 /scale。这些权限要限制 Namespace、对象和身份,外部凭证优先使用 workload identity;日志和 Dashboard 不展示连接串、租户标签或容量敏感信息。
控制器本身也消耗 CPU、内存和 API QPS。指标基数、轮询频率、HPA 数量、VPA 历史与 webhook 延迟需要容量测试。团队应维护指标新鲜度、伸缩决策延迟、振荡次数、达到上限次数、失败 condition 和回退演练,并在升级前核对 CRD、API、feature gate 与 Kubernetes 兼容矩阵。
阅读与实验顺序
先建立 requests、limits、QoS 和驱逐的资源直觉,再验证 Metrics Server 与三类指标 API;随后分别完成 HPA、VPA、KEDA 正反实验,最后处理多控制器所有权。每个实验都在隔离 Namespace 中运行,记录起止时间、对象 UID、Event 和业务结果,结束后删除 CR、ClusterRoleBinding、Secret 与外部测试资源。
当团队能回答“信号为何出现、控制器写了什么、Pod 为何能或不能运行、业务何时恢复”,自动伸缩才从一个演示功能变成可治理的生产能力。
