3. ScaledObject 详解:CRD 定义、Trigger 配置与弹性策略

ScaledObject 是 KEDA 中定义事件驱动弹性伸缩策略的核心自定义资源(CRD)。它告诉 KEDA 要监控哪个工作负载、使用什么触发器、伸缩范围是多少以及轮询与冷却的行为。本章将逐一拆解 ScaledObject 的每个关键字段,帮助你掌握从定义到生产配置的完整知识。

3.1 ScaledObject CRD 定义与核心结构

ScaledObject 的 API 版本为 keda.sh/v1alpha1,kind 为 ScaledObject。其 spec 主要包含四个部分:工作负载引用、触发器列表、伸缩范围、高级行为控制。以下是一个完整的 ScaledObject YAML 示例:

apiVersion: keda.sh/v1alpha1
kind: ScaledObject
metadata:
  name: my-scaledobject
  namespace: default
spec:
  scaleTargetRef:
    name: my-deployment
    apiVersion: apps/v1
    kind: Deployment
  triggers:
    - type: prometheus
      metadata:
        serverAddress: http://prometheus.monitoring:9090
        metricName: http_requests_total
        query: sum(rate(http_requests_total[1m]))
        threshold: "100"
  minReplicaCount: 1
  maxReplicaCount: 10
  pollingInterval: 30
  cooldownPeriod: 300
  advanced:
    restoreToOriginalReplicaCount: false
    horizontalPodAutoscalerConfig:
      behavior:
        scaleDown:
          stabilizationWindowSeconds: 60
          policies:
            - type: Percent
              value: 50
              periodSeconds: 60
关键点:ScaledObject 本身不直接管理 Pod,而是通过创建 HPA(HorizontalPodAutoscaler)来间接控制 Deployment/StatefulSet 的副本数。KEDA 负责将外部事件指标转换为 HPA 可理解的指标。

3.2 Scaling Triggers 配置:事件源接入

Triggers 是 ScaledObject 的核心,决定了何时触发伸缩。每个 trigger 包含 type 和 metadata 两个字段。KEDA 支持 50+ 种触发器类型,常见的有:

触发器类型 典型场景 关键 metadata 参数
prometheus 基于自定义指标(如 QPS、延迟) serverAddress, query, threshold
kafka 基于 Kafka 分区堆积消息数 bootstrapServers, topic, lagThreshold
rabbitmq 基于 RabbitMQ 队列长度 host, queueName, queueLength
aws-sqs-queue 基于 AWS SQS 消息数 queueURL, queueLength, awsRegion
cron 基于时间计划(定时伸缩) timezone, start, end, desiredReplicas

每个 trigger 的 metadata 字段是键值对形式,具体参数由触发器类型决定。KEDA 会定期查询这些指标源,当指标值超过 threshold 时触发扩容,低于时触发缩容。

多触发器组合:可以在 triggers 列表中配置多个触发器,KEDA 会取所有触发器中计算出的最大期望副本数作为最终目标。例如同时监控 Prometheus QPS 和 Kafka 堆积数,哪个指标更紧张就按哪个扩容。

3.3 Min/Max Replica 设置:伸缩边界控制

minReplicaCount 和 maxReplicaCount 定义了工作负载副本数的上下限,防止无限伸缩或缩到零导致服务不可用。

  • minReplicaCount:默认值为 1。设置为 0 时,允许在无事件时缩到零 Pod(需要配合 scaleTargetRef 支持)。适用于批处理任务或事件驱动型工作负载。
  • maxReplicaCount:默认值为 100。建议根据集群资源容量和业务峰值合理设置,避免资源耗尽。

以下是一个允许缩到零的配置示例:

spec:
  minReplicaCount: 0
  maxReplicaCount: 20
  scaleTargetRef:
    name: event-processor
    kind: Deployment
注意:当 minReplicaCount: 0 时,工作负载必须支持从零启动(例如使用 scaleToZero 特性),且需要确保触发器能处理空指标的情况。某些触发器(如 Prometheus)在无数据时可能返回空值,需要配置 unsafeSsl 或默认值处理。

3.4 Polling Interval 与 Cooldown Period:伸缩节奏控制

这两个参数控制 KEDA 检查指标和触发伸缩的频率,直接影响系统的响应速度和稳定性。

参数 默认值 作用 建议值
pollingInterval 30 秒 KEDA 从事件源拉取指标的间隔 10-60 秒(根据指标变化速度调整)
cooldownPeriod 300 秒 最后一次触发伸缩后,等待多久才允许缩容 120-600 秒(避免频繁缩容导致抖动)
  • pollingInterval:值越小,KEDA 对指标变化越敏感,但会增加事件源和 KEDA 自身的负载。对于快速变化的指标(如秒级 QPS),建议设为 10-15 秒;对于慢变指标(如小时级批处理),可设为 60 秒以上。
  • cooldownPeriod:防止指标短暂波动导致频繁缩容。例如在流量高峰过后,指标可能快速下降,但 cooldown 会强制等待一段时间再缩容,确保系统稳定。对于有状态服务或启动耗时较长的应用,建议设置较大的值(如 300-600 秒)。
ScaledObject 伸缩节奏流程图 事件源 (Prometheus/Kafka/…) pollingInterval (每 30s 拉取指标) KEDA 评估 (计算期望副本数) HPA 需要伸缩? 不操作 执行伸缩 (更新 Deployment 副本数) cooldownPeriod (等待 300s 再允许缩容) 说明: pollingInterval 控制指标采集频率,cooldownPeriod 控制缩容等待时间。两者配合可避免伸缩抖动。 扩容不受 cooldown 限制,仅缩容需要等待冷却期结束。

3.5 Advanced 配置:精细化伸缩行为

ScaledObject 的 advanced 字段提供了对 HPA 行为的精细控制,包括缩容稳定窗口、策略类型和恢复原始副本数等。

字段 默认值 说明
restoreToOriginalReplicaCount false 删除 ScaledObject 后,是否将工作负载副本数恢复到创建前的值
horizontalPodAutoscalerConfig.behavior.scaleDown.stabilizationWindowSeconds 300 缩容稳定窗口,在窗口期内取最大期望副本数,防止缩容抖动
horizontalPodAutoscalerConfig.behavior.scaleDown.policies 默认 HPA 策略 缩容策略,支持 Percent(百分比)和 Pods(固定数量)两种类型

以下是一个生产级 advanced 配置示例:

spec:
  advanced:
    restoreToOriginalReplicaCount: true
    horizontalPodAutoscalerConfig:
      behavior:
        scaleDown:
          stabilizationWindowSeconds: 120
          policies:
            - type: Percent
              value: 25
              periodSeconds: 60
        scaleUp:
          stabilizationWindowSeconds: 0
          policies:
            - type: Pods
              value: 4
              periodSeconds: 15
最佳实践:对于流量突增型业务,建议将 scaleUp 的 stabilizationWindowSeconds 设为 0,并允许快速扩容(如每次最多加 4 个 Pod);对于缩容,设置较长的稳定窗口(如 120-300 秒)和较保守的策略(如每次最多缩 25%),避免因短暂流量下降而过度缩容。

3.6 多触发器与指标聚合

当 ScaledObject 配置了多个触发器时,KEDA 会为每个触发器独立计算期望副本数,然后取其中的最大值作为最终目标。这种设计确保了最紧张的指标优先驱动伸缩行为。

多触发器指标聚合示意图 触发器1: Prometheus 期望副本数: 8 触发器2: Kafka 期望副本数: 5 触发器3: Cron 期望副本数: 3 聚合器 取最大值: max(8,5,3)=8 最终目标副本数 8
设计建议:当使用多触发器时,注意各触发器的 threshold 应保持一致的语义。例如 Prometheus 的 threshold 代表每个 Pod 的目标 QPS,Kafka 的 lagThreshold 代表每个 Pod 能处理的最大堆积数。KEDA 会自动将指标值除以当前副本数来计算每个 Pod 的负载。

3.7 常见配置陷阱与排查

  • 陷阱1:pollingInterval 过小导致事件源压力大。 对于 Prometheus 等高频查询,建议不低于 15 秒,并考虑使用 Recording Rules 预聚合。
  • 陷阱2:cooldownPeriod 过短导致频繁缩容。 如果应用启动时间超过 30 秒,建议 cooldown 至少设为 120 秒以上。
  • 陷阱3:minReplicaCount 设为 0 但工作负载不支持从零启动。 确保 Deployment 的 replicas 初始值不为 0,或使用 scaleToZero 特性。
  • 陷阱4:多触发器时某个触发器返回空值。 某些触发器在无数据时可能返回空,导致 KEDA 无法计算期望副本数。建议在 metadata 中配置默认值或使用 unsafeSsl 处理。
排查命令:使用 kubectl get scaledobject -n <namespace> 查看 ScaledObject 状态;使用 kubectl describe scaledobject <name> -n <namespace> 查看事件和错误信息;使用 kubectl get hpa -n <namespace> 查看 KEDA 创建的 HPA 对象。