为什么需要基于自定义指标的弹性伸缩
Kubernetes 内置的 Horizontal Pod Autoscaler(HPA)默认只支持 CPU 和内存两种资源指标。然而在真实生产环境中,CPU 使用率并不能准确代表业务的并发压力——比如一个 Web 服务可能 CPU 占用很低,但请求队列已经堆积;一个消息消费者可能内存充足,但消费积压导致延迟飙升。单纯依赖资源指标往往导致扩缩容滞后或误判,造成资源浪费或服务抖动。
Prometheus 作为云原生生态的事实标准监控系统,能够采集任意业务指标(如 http_requests_total、queue_depth、grpc_latency_seconds)。通过将 Prometheus 指标注册为 Kubernetes 的自定义指标,HPA 可以像使用 CPU 一样根据业务负载动态调整副本数。这种方式让弹性伸缩回归业务本质:用业务指标衡量实际压力,而非间接的资源消耗。
HPA 自定义指标的工作机制
Kubernetes HPA 通过 metrics.k8s.io(资源指标)、custom.metrics.k8s.io(自定义指标)和 external.metrics.k8s.io(外部指标)三个 API 组获取数据。自定义指标特指那些由用户应用程序暴露的、与特定 Pod 或 Namespace 相关的度量值。当 HPA 检测到自定义指标值偏离目标阈值时,它会计算期望副本数并执行扩缩容。
实现这一链条的关键组件是 Prometheus Adapter(旧称 k8s-prometheus-adapter)。它运行在集群内部,定期从 Prometheus 查询指标,经过转换后暴露为 custom.metrics.k8s.io 或 external.metrics.k8s.io 端点,供 HPA 控制器消费。
整体架构与核心组件
Prometheus 数据源
Prometheus 通过 pull 方式采集应用暴露的指标(如 /metrics 端点),存储时间序列数据。你需要保证目标应用已经正确暴露了有价值的业务指标,并且 Prometheus 已配置好 ServiceMonitor 或直接抓取。
Prometheus Adapter
Adapter 负责两个核心翻译:
- 指标发现:通过配置文件中的
rules定义哪些 Prometheus 查询应该被暴露为 Kubernetes 自定义指标。 - API 注册:将查询结果以
/apis/custom.metrics.k8s.io/v1beta1的形式注册到 API 聚合层。
HPA 对象
HPA 使用 type: Pods(针对每个 Pod 的指标)或 type: Object(针对集群内对象的指标,如 Service)来引用自定义指标。HPA 控制器每隔默认 15 秒轮询一次指标 API,根据当前值与目标值计算副本数。
完整配置步骤
前提条件
确保集群满足:
- Kubernetes 版本 ≥ 1.11(建议 1.20+)
- 集群已启用 API 聚合层(默认开启)
- Prometheus 已部署且能成功抓取目标应用指标
步骤一:部署 Prometheus Adapter
推荐使用 Helm 安装,这样配置更灵活:
helm repo add prometheus-community https://prometheus-community.github.io/helm-charts
helm repo update
helm install prometheus-adapter prometheus-community/prometheus-adapter -n monitoring -f values.yaml
核心在于 values.yaml 中的 rules 配置段。例如,我们要将名为 http_requests_per_second 的 Prometheus 指标暴露给 HPA:
rules:
- seriesQuery: '{__name__=~"http_requests.*", namespace!=""}'
resources:
overrides:
namespace: {resource: "namespace"}
pod: {resource: "pod"}
name:
matches: "http_requests_(.*)"
as: "${1}_per_second"
metricsQuery: 'sum(rate(<>{<>}[2m])) by (<>)'
关键字段说明:
seriesQuery:告诉 Adapter 去 Prometheus 搜索哪些 metric。resources.overrides:将 Prometheus label(如 pod)映射到 Kubernetes 资源。name:自定义指标的名字(最终出现在 HPA 中)。metricsQuery:实际的 PromQL 查询模板,<>等是模板变量。
步骤二:验证自定义指标可用
部署完成后,通过 kubectl 查看注册的指标:
kubectl get --raw /apis/custom.metrics.k8s.io/v1beta1 | jq .
kubectl get --raw /apis/custom.metrics.k8s.io/v1beta1/namespaces/default/pods/*/http_requests_per_second
如果返回正确数据(例如某个 Pod 的当前值),说明 Adapter 工作正常。
步骤三:创建 HPA 对象
假设我们有一个 Deployment 名为 my-web-service,期望每个 Pod 的每秒请求数不超过 1000。创建如下 HPA:
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: my-web-hpa
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: my-web-service
minReplicas: 2
maxReplicas: 20
metrics:
- type: Pods
pods:
metric:
name: http_requests_per_second
target:
type: AverageValue
averageValue: 1000
这里 type: Pods 表示指标是每个 Pod 独有的,averageValue 表示所有 Pod 平均值的目标。如果使用 type: Object 则可以指定 Service 级别的指标。HPA 会持续比较每个 Pod 的实际值与目标值,当平均值超过 1000 时自动扩容,低于 1000 时缩容(需考虑冷却时间)。
验证弹性伸缩与回滚方案
验证方法
可以使用压测工具(如 wrk、hey)向应用发送请求,观察 HPA 的行为:
kubectl get hpa -w
kubectl get pods -l app=my-web-service
同时通过 Prometheus 监控 http_requests_per_second 指标的变化,确认 HPA 的扩缩容决策与业务负载同步。一般需要几分钟的预热期,因为 Adapter 的数据缓存和 Prometheus 的采集间隔可能导致延迟。
风险与应对
- 指标延迟:Prometheus 通常以 15~30s 为间隔抓取,加上 Adapter 的缓存,HPA 决策可能滞后。建议在 HPA 的行为策略(behavior)中设置合理的稳定窗口和扩容加速。
- Adapter 过载:当自定义指标数量庞大时,Adapter 可能成为性能瓶颈。需监控 Adapter 的响应时间,必要时增加副本或拆分规则。
- 指标缺失导致 HPA 降级:如果某个 Pod 的指标暂时未采集到,HPA 会跳过该 Pod 忽略。确保应用始终暴露指标,且 Prometheus 配置了重试。
回滚到原生指标
若自定义指标方案出现问题,可以快速回退:
- 修改 HPA 的
metrics字段,将自定义指标替换回 CPU:type: Resource+resource: cpu。 - 或者删除 HPA,重新创建基于 CPU 的 HPA(如果之前有备份)。
建议在测试环境充分验证后再上线。同时保留一份原有的 HPA 配置 YAML,便于紧急回滚。
哪些场景最适合使用自定义指标 HPA
- Web/API 服务:基于请求速率(QPS/RPS)扩容比 CPU 更敏感及时。
- 消息队列消费者:根据队列深度(如 Kafka 堆积量)自动扩缩消费者 Pod。
- 流处理作业:根据处理延迟或吞吐量动态调整 worker 数量。
- 游戏服务器:根据在线玩家数(自定义指标)调整游戏房间 Pod。
相反,对于纯粹计算密集型的任务(如批处理作业),CPU 指标可能仍是更简单的选择。
常见陷阱与优化思路
- 命名冲突:自定义指标名称在集群中必须唯一。如果多个应用暴露相同名称的指标,HPA 可能会错误关联。
- 聚合层级选择:是使用
type: Pods还是type: Object?如果指标已经聚合到 Service 级别(如整个服务的平均 RPS),用 Object 更简单;如果是每个 Pod 独立统计(如连接数),用 Pods。 - PromQL 性能:复杂的 PromQL 查询会增加 Adapter 和 Prometheus 的负担。尽量使用简单的 rate/avg,并设置合理的 range duration。
总结
基于 Prometheus 自定义指标的 HPA 让 Kubernetes 的弹性伸缩从资源层上升到业务层,是云原生应用实现精细化运维的重要工具。通过部署 Prometheus Adapter 并配置适当的规则,你可以让 HPA 感知诸如请求速率、队列深度、业务延时等真正驱动扩容的指标。本文给出了从部署到验证、回滚的完整路径,实践中应结合业务特点选择指标类型,并建立监控告警机制避免指标异常导致的扩缩容故障。将自定义指标 HPA 与 Kubernetes 原生的行为策略(稳定窗口、扩容率限制)相结合,能构建出既灵敏又稳健的自动扩缩容体系。
延伸阅读
