Kubernetes自定义指标HPA伸缩实战:Prometheus Adapter到KEDA的完整方案

Kubernetes HPA为什么需要自定义指标

Kubernetes原生的Horizontal Pod Autoscaler默认只支持CPU和内存两种资源指标触发扩缩容。对于Web服务来说,CPU利用率并不是最佳的伸缩信号——当请求队列积压时CPU可能仍然空闲(等待IO),而当CPU飙高时延迟已经恶化。基于请求延迟(Latency)、队列深度(Queue Depth)、QPS等业务指标的HPA才是生产级自动伸缩的正确姿势。

自定义指标HPA的实现链路为:应用暴露指标到Prometheus采集到Prometheus Adapter转换到Kubernetes API Server注册到HPA Controller消费。这条链路中任何一个环节配置错误都会导致HPA无法工作。

Prometheus Adapter部署与配置

Prometheus Adapter的核心作用是将Prometheus中的时序数据转换为Kubernetes自定义指标API格式。HPA Controller通过Kubernetes API查询这些指标,而Adapter充当了API聚合层的后端。

使用Helm部署:

helm repo add prometheus-community https://prometheus-community.github.io/helm-charts
helm install prometheus-adapter prometheus-community/prometheus-adapter \
    --set prometheus.url=http://prometheus-server.monitoring.svc \
    --set prometheus.port=80 \
    --set rules.default=false \
    --namespace monitoring --create-namespace

关键配置在于自定义指标发现规则(rules),通过ConfigMap定义PromQL到Kubernetes指标的映射:

rules:
  custom:
  - seriesQuery: 'http_requests_total{namespace!="",pod!=""}'
    resources:
      overrides:
        namespace: {resource: "namespace"}
        pod: {resource: "pod"}
    name:
      matches: "^(.*)_total"
      as: "${1}_per_second"
    metricsQuery: 'sum(rate(<<.Series>>{<<.LabelMatchers>>},1m)) by (<<.GroupBy>>)'

这段配置做了以下映射:从Prometheus的http_requests_total指标中提取namespace和pod标签,转换为Kubernetes的Pod级别自定义指标http_requests_per_second,值取1分钟速率的sum。

HPA自定义指标伸缩策略编写

Adapter部署完成后,编写HPA资源:

apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: web-api-hpa
  namespace: production
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: web-api
  minReplicas: 3
  maxReplicas: 50
  metrics:
  - type: Pods
    pods:
      metric:
        name: http_requests_per_second
      target:
        type: AverageValue
        averageValue: "1000"
  - type: Pods
    pods:
      metric:
        name: http_request_duration_seconds
      selector:
        matchLabels:
          quantile: "0.99"
      target:
        type: AverageValue
        averageValue: "500m"

该策略定义了两个触发条件:单Pod平均QPS超过1000时扩容,P99延迟超过500ms时扩容。两个条件取最大值,任何一个触发都会执行扩容。

排错:自定义指标HPA的常见故障

故障一:HPA显示unable to get metric

这是最常见的错误。排查步骤:

# 检查Adapter是否注册了自定义指标API
kubectl get --raw "/apis/custom.metrics.k8s.io/v1beta1" | jq .

# 检查特定指标是否可查询
kubectl get --raw "/apis/custom.metrics.k8s.io/v1beta1/namespaces/production/pods/*/http_requests_per_second" | jq .

# 查看Adapter日志
kubectl logs -n monitoring deploy/prometheus-adapter | grep -i error

如果API注册成功但指标为空,说明PromQL查询返回了空结果。在Prometheus中直接执行该PromQL确认数据存在,常见原因是标签名不匹配或namespace标签缺失。

故障二:指标可查询但HPA不触发扩容

检查指标值是否真的超过阈值,以及HPA的tolerance(默认10%)。如果指标值仅超出阈值5%,在tolerance范围内不会触发。另外检查scaleTargetRef指向的Deployment是否设置了resources.requests,HPA依赖requests计算利用率百分比。

KEDA:事件驱动的自动伸缩方案

当伸缩信号不来自Prometheus而是来自消息队列、数据库等外部系统时,Prometheus Adapter方案链路过长。KEDA(Kubernetes Event-Driven Autoscaling)直接对接数据源,无需中间转化层。

以Kafka消费者延迟为例:

# 安装KEDA
helm repo add kedacore https://kedacore.github.io/charts
helm install keda kedacore/keda --namespace keda --create-namespace

# 定义ScaledObject
apiVersion: keda.sh/v1alpha1
kind: ScaledObject
metadata:
  name: order-processor-scaler
spec:
  scaleTargetRef:
    name: order-processor
  minReplicaCount: 2
  maxReplicaCount: 30
  triggers:
  - type: kafka
    metadata:
      bootstrapServers: kafka:9092
      consumerGroup: order-group
      lagThreshold: "100"
      offsetResetPolicy: latest

KEDA的Kafka Trigger直接查询Broker的consumer lag,当lag超过100条时触发扩容。相比Prometheus Adapter方案,少了PromQL到Adapter再到API Server的转换链路,延迟降低数秒。

KEDA已原生支持70+种数据源触发器,包括RabbitMQ、Redis Stream、PostgreSQL、AWS SQS、阿里云MQ等。对于消息驱动型微服务架构,KEDA比Prometheus Adapter方案更适合。

混合伸缩策略:资源指标加业务指标加事件驱动

生产环境中单一伸缩信号容易误判。推荐组合策略:

1. CPU/内存作为保底伸缩信号,防止资源耗尽。

2. 业务指标(QPS/延迟)作为主伸缩信号,对业务流量精确响应。

3. 事件驱动(KEDA)作为补充,对异步任务队列深度响应。

4. 设置scaleDownStabilizationWindowSeconds=300,避免指标波动导致频繁缩容。

5. 对关键服务设置minReplicas=3和PodDisruptionBudget,确保缩容不破坏可用性。

原创文章,作者:小编,如若转载,请注明出处:https://www.yunthe.com/kubernetes-zi-ding-yi-zhi-biao-hpa-shen-suo-shi-zhan/

(0)
小编小编
上一篇 17小时前
下一篇 17小时前

相关推荐