3. Kubernetes HPA 原理与实践:HPA工作机制、配置示例、自定义指标适配

3.1 HPA 核心工作机制

Horizontal Pod Autoscaler(HPA)是 Kubernetes 内置的弹性伸缩控制器,通过周期性采集 Pod 资源指标(如 CPU、内存)或自定义指标,动态调整工作负载的副本数。其核心控制循环遵循“采集 → 聚合 → 计算 → 伸缩”的闭环流程。

关键控制参数:
  • --horizontal-pod-autoscaler-sync-period:默认 15 秒,控制 HPA 轮询指标的时间间隔。
  • --horizontal-pod-autoscaler-tolerance:默认 0.1(10%),当期望副本数与当前副本数偏差小于该阈值时,不触发伸缩。
  • --horizontal-pod-autoscaler-cpu-initialization-period:Pod 启动后 CPU 指标稳定等待期,默认 5 分钟。
HPA 控制循环流程图 HPA 控制循环流程图 ① 指标采集 ② 指标聚合 ③ 期望副本计算 ④ 决策判断 ⑤ 执行伸缩 采集来源 • metrics-server(CPU/内存) • Prometheus Adapter(自定义) • 外部指标 API 计算公式 期望副本 = 当前副本 × (当前指标值 / 目标指标值) 决策规则 • 偏差 > 10% 才触发 • 冷却窗口防止抖动

3.2 HPA 配置示例

以下是一个基于 CPU 和内存指标的 HPA 配置,适用于生产环境中的无状态微服务。

apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: web-app-hpa
  namespace: production
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: web-app
  minReplicas: 2
  maxReplicas: 20
  metrics:
  - type: Resource
    resource:
      name: cpu
      target:
        type: Utilization
        averageUtilization: 70
  - type: Resource
    resource:
      name: memory
      target:
        type: AverageValue
        averageValue: 512Mi
  behavior:
    scaleDown:
      stabilizationWindowSeconds: 300
      policies:
      - type: Percent
        value: 10
        periodSeconds: 60
    scaleUp:
      stabilizationWindowSeconds: 0
      policies:
      - type: Percent
        value: 100
        periodSeconds: 60
      - type: Pods
        value: 4
        periodSeconds: 60
      selectPolicy: Max
配置要点:
  • stabilizationWindowSeconds:缩容冷却窗口设为 300 秒,避免频繁缩容导致 Pod 抖动。
  • selectPolicy: Max:扩容时选择最大策略,确保突发流量下快速扩容。
  • averageUtilization vs AverageValue:CPU 使用百分比指标,内存使用值指标,避免内存基线波动导致误判。

3.3 自定义指标适配

当业务指标(如 QPS、队列深度、连接数)无法通过 CPU/内存反映时,需要引入自定义指标适配器。Kubernetes 生态中常用的方案是 Prometheus Adapter,它可以将 Prometheus 中的指标暴露为 HPA 可消费的自定义指标 API。

3.3.1 自定义指标适配架构

自定义指标适配架构图 自定义指标适配架构图 应用 Pod 暴露 /metrics 端点 Prometheus 抓取 & 存储指标 Prometheus Adapter 转换 → 自定义指标 API HPA 查询 custom.metrics.k8s.io 关键 API 端点 /apis/custom.metrics.k8s.io/v1beta1 — 自定义指标 /apis/external.metrics.k8s.io/v1beta1 — 外部指标(如云服务队列长度)

3.3.2 Prometheus Adapter 配置示例

以下配置将 Prometheus 中的 http_requests_per_second 指标暴露为 HPA 可用的自定义指标。

# prometheus-adapter-values.yaml
rules:
  custom:
  - seriesQuery: 'http_requests_per_second{namespace!="",pod!=""}'
    resources:
      overrides:
        namespace: {resource: "namespace"}
        pod: {resource: "pod"}
    name:
      matches: "http_requests_per_second"
      as: "requests_per_second"
    metricsQuery: 'sum(rate(http_requests_per_second{<<.LabelMatchers>>}[2m])) by (<<.GroupBy>>)'

3.3.3 基于自定义指标的 HPA 配置

apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: web-app-qps-hpa
  namespace: production
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: web-app
  minReplicas: 2
  maxReplicas: 30
  metrics:
  - type: Pods
    pods:
      metric:
        name: requests_per_second
      target:
        type: AverageValue
        averageValue: 100
自定义指标适配避坑指南:
  • 指标命名冲突:自定义指标名称不要与 Kubernetes 内置资源指标(cpu、memory)重名,否则 HPA 可能解析错误。
  • 指标延迟:Prometheus 抓取间隔 + Adapter 缓存可能导致指标延迟 30-60 秒,扩容响应不如 CPU 指标快。
  • Adapter 高可用:生产环境至少部署 2 个 Prometheus Adapter 副本,避免单点故障导致 HPA 无法获取指标。

3.4 指标类型对比

指标类型 API 端点 典型用例 数据源 延迟
Resource metrics.k8s.io CPU、内存利用率 metrics-server < 15 秒
Pods custom.metrics.k8s.io QPS、请求延迟、连接数 Prometheus Adapter 30-60 秒
Object custom.metrics.k8s.io Ingress 流量、Service 错误率 Prometheus Adapter 30-60 秒
External external.metrics.k8s.io 云服务队列长度、数据库连接数 云厂商 Adapter 1-5 分钟

3.5 生产环境最佳实践

  • 多指标组合:同时配置 CPU 和自定义指标,CPU 指标作为快速响应层,自定义指标作为精确控制层。
  • 扩容优先、缩容保守:设置 scaleUp.stabilizationWindowSeconds: 0 和 scaleDown.stabilizationWindowSeconds: 300,避免流量尖峰时扩容滞后。
  • Pod 启动就绪检测:结合 readinessProbe 和 initialDelaySeconds,确保新 Pod 在指标采集窗口内完成初始化。
  • 监控 HPA 自身状态:通过 kubectl describe hpa 查看事件和指标状态,配置告警规则监控 HPA 伸缩失败事件。
关键命令速查:
# 查看 HPA 状态
kubectl get hpa -n production

# 查看 HPA 详细事件
kubectl describe hpa web-app-hpa -n production

# 测试自定义指标 API 是否可用
kubectl get --raw "/apis/custom.metrics.k8s.io/v1beta1" | jq .

# 查看特定 Pod 的自定义指标值
kubectl get --raw "/apis/custom.metrics.k8s.io/v1beta1/namespaces/production/pods/*/requests_per_second" | jq .