2. Kubernetes 原生 HPA 原理:HPA 工作流程、metrics-server、资源指标与自定义指标

在深入 KEDA 之前,必须透彻理解 Kubernetes 原生的水平 Pod 自动伸缩器(HPA)。HPA 是控制面弹性伸缩的基石,KEDA 本质上是对 HPA 的扩展与增强。本章将拆解 HPA 的核心工作流程、关键组件 metrics-server,以及资源指标与自定义指标的区别。

2.1 HPA 核心工作流程

HPA 作为一个控制循环组件,定期(默认每 15 秒)通过 API Server 查询目标指标,计算期望副本数,并更新工作负载的副本数。其完整流程分为四个阶段:

  1. 指标采集:HPA Controller 通过 API Server 获取 metrics-server 或自定义指标 API 提供的指标数据。
  2. 指标聚合与归一化:将采集到的原始指标(如 CPU 使用率、QPS)转换为目标利用率百分比或值。
  3. 副本数计算:使用公式 期望副本数 = ceil(当前副本数 × (当前指标值 / 期望指标值)) 进行计算。
  4. 滚动更新与状态写入:HPA Controller 更新工作负载(Deployment/StatefulSet)的 spec.replicas,并记录伸缩事件到 HPA 资源的 status 字段。
关键公式说明: 当指标为资源类型(如 CPU)时,当前指标值 是所有 Pod 的均值;当指标为 Pod 类型(如 QPS)时,当前指标值 是所有 Pod 的当前值之和。HPA 会忽略处于 Pending 或 Unknown 状态的 Pod。
HPA 控制循环工作流程 HPA 控制循环工作流程 HPA Controller 查询 metrics-server / 自定义指标 API 计算期望副本数 更新 Deployment/StatefulSet replicas 默认周期:15s 冷却时间: 扩容 3min / 缩容 5min

2.2 metrics-server:资源指标的基石

metrics-server 是 Kubernetes 集群中资源指标(CPU、内存)的聚合器。它通过 kubelet 的 Summary API 从每个节点采集 Pod 和节点的资源使用数据,并暴露给 HPA 和 kubectl top 命令。

特性 说明
数据来源 每个节点上的 kubelet cAdvisor 接口
采集粒度 默认每 60 秒从 kubelet 拉取一次数据
存储方式 仅保存在内存中,不持久化,无历史数据
暴露 API metrics.k8s.io 聚合 API
资源消耗 极低,通常只需 0.1 CPU 和 50MB 内存
生产建议: metrics-server 是 HPA 资源指标伸缩的必备组件。如果集群中未部署,HPA 将无法获取 CPU/内存指标,导致自动伸缩失效。建议使用官方最新版本,并配置资源请求与限制。

2.3 资源指标与自定义指标

HPA 支持三种指标类型,理解它们的差异是配置正确伸缩策略的前提。

指标类型 数据来源 典型示例 适用场景
资源指标 metrics-server CPU 使用率、内存使用量 通用型工作负载,无状态应用
Pod 自定义指标 Prometheus Adapter / 自定义 API QPS、请求延迟 P99、队列深度 有状态应用、消息处理、API 网关
对象自定义指标 Prometheus Adapter / 自定义 API Ingress 流量、消息队列积压数 基于外部系统状态的伸缩

2.4 自定义指标接入架构

自定义指标需要额外的适配器组件(如 Prometheus Adapter、Kubernetes 自定义指标 API 实现)将外部监控系统的指标转换为 HPA 可消费的格式。下图展示了资源指标与自定义指标在 HPA 中的协同路径。

HPA 指标来源架构 HPA 指标来源架构 kubelet (cAdvisor) metrics-server metrics.k8s.io API Prometheus / 外部系统 Prometheus Adapter custom.metrics.k8s.io API HPA Controller 两种指标路径最终汇聚到 HPA 控制器

2.5 HPA 配置示例

以下是一个同时使用资源指标和 Pod 自定义指标的 HPA 配置示例:

apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: web-app-hpa
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: web-app
  minReplicas: 2
  maxReplicas: 10
  metrics:
  - type: Resource
    resource:
      name: cpu
      target:
        type: Utilization
        averageUtilization: 70
  - type: Pods
    pods:
      metric:
        name: http_requests_per_second
      target:
        type: AverageValue
        averageValue: 1000
  behavior:
    scaleDown:
      stabilizationWindowSeconds: 300
      policies:
      - type: Pods
        value: 1
        periodSeconds: 60
    scaleUp:
      stabilizationWindowSeconds: 0
      policies:
      - type: Percent
        value: 100
        periodSeconds: 15
注意: 当同时配置多个指标时,HPA 会分别计算每个指标对应的期望副本数,并取其中的 最大值 作为最终伸缩目标。这可能导致扩容比预期更激进,建议配合 behavior 字段设置合理的伸缩策略。

2.6 HPA 的局限性

虽然 HPA 是 Kubernetes 原生的弹性伸缩方案,但在实际生产中存在以下不足,这也正是 KEDA 要解决的核心问题:

  • 指标源有限:原生 HPA 无法直接对接消息队列(Kafka、RabbitMQ)、数据库连接池、自定义事件源等。
  • 无事件驱动能力:HPA 基于轮询,无法实现“零工作负载时缩零”的事件驱动模式。
  • 冷却策略僵化:默认的扩容/缩容冷却时间无法满足快速波动的业务场景。
  • 无外部状态感知:无法根据外部系统的健康状态或业务指标进行精细化伸缩。