4. Scaler 概念与分类

Scaler 是 KEDA 的核心抽象,负责从外部事件源(如 Kafka、RabbitMQ、Prometheus、AWS SQS 等)拉取指标数据,并基于这些数据计算出期望的副本数。KEDA 通过 Scaler 将事件驱动的弹性伸缩能力与 Kubernetes HPA 解耦,使得任何事件源都可以成为触发扩缩容的信号。

4.1 Scaler 的定义

在 KEDA 中,Scaler 是一个实现了特定接口的组件,它完成以下三项职责:

  • 指标获取:从外部系统(消息队列、数据库、监控系统等)拉取实时指标值。
  • 阈值比较:将当前指标值与用户定义的阈值(如 messageCount > 10)进行比较。
  • 副本计算:根据指标偏差量计算出 HPA 所需的 target 值,驱动 Kubernetes 调整 Pod 副本数。
关键概念:Scaler 不直接操作 Pod,它只负责生成指标数据。KEDA Operator 将这些指标注入到 Kubernetes 自定义指标 API 中,HPA 再根据这些指标执行实际的扩缩容动作。

4.2 内置 Scaler 列表

KEDA 官方维护了 50+ 个内置 Scaler,覆盖了主流的消息中间件、数据库、监控系统和云服务。下表列出了生产环境中使用频率最高的 12 个 Scaler:

Scaler 名称 事件源类型 典型指标 生产推荐度
Kafka 消息队列 lag(消费者滞后量) ★★★★★
RabbitMQ 消息队列 queueLength(队列长度) ★★★★★
Prometheus 监控系统 自定义 PromQL 查询结果 ★★★★★
AWS SQS 云服务 ApproximateNumberOfMessages ★★★★☆
Redis Lists 缓存/队列 listLength(列表长度) ★★★★☆
MySQL 数据库 自定义 SQL 查询结果 ★★★★☆
PostgreSQL 数据库 自定义 SQL 查询结果 ★★★★☆
Azure Service Bus 云服务 messageCount(消息数) ★★★★☆
GCP Pub/Sub 云服务 subscriptionSize(订阅积压量) ★★★★☆
HTTP 网络请求 并发请求数 / 请求速率 ★★★☆☆
Cron 时间调度 时间表达式匹配 ★★★☆☆
Elasticsearch 搜索引擎 文档数量 / 查询负载 ★★★☆☆
选型建议:消息队列类 Scaler(Kafka、RabbitMQ、SQS)是事件驱动架构的首选,因为它们能直接反映工作负载的积压情况。Prometheus Scaler 适合已有 Prometheus 监控体系且需要基于业务指标(如 QPS、错误率)做弹性伸缩的场景。

4.3 外部 Scaler 机制

当内置 Scaler 无法满足需求时,KEDA 提供了 外部 Scaler(External Scaler) 机制,允许用户通过 gRPC 协议自定义指标获取逻辑。外部 Scaler 是一个独立的 gRPC 服务,需要实现以下两个接口:

// 定义在 keda.sh/external-scaler 协议中
service ExternalScaler {
    // 返回 Scaler 的元数据(名称、支持的指标等)
    rpc GetMetricSpec(ScaledObjectRef) returns (MetricSpec);
    
    // 返回当前指标值,KEDA 会按 pollingInterval 周期调用
    rpc GetMetrics(MetricRequest) returns (MetricResult);
    
    // 可选:检查 Scaler 是否健康
    rpc IsActive(ScaledObjectRef) returns (IsActiveResult);
}

外部 Scaler 的工作流程如下:

  1. 用户编写一个 gRPC 服务,实现上述三个接口。
  2. 将该服务部署为 Kubernetes Deployment,并暴露 ClusterIP Service。
  3. 在 ScaledObject 中通过 external 类型引用该 Service 地址。
  4. KEDA Operator 通过 gRPC 调用外部 Scaler 获取指标,其余流程与内置 Scaler 一致。
生产注意事项:外部 Scaler 的稳定性直接影响整个弹性伸缩链路。建议为外部 Scaler 服务配置独立的资源限制、健康检查和监控告警。gRPC 调用超时时间默认 5 秒,如果指标获取耗时较长,需要在 ScaledObject 中调整 pollingInterval 和 cooldownPeriod。

4.4 Scaler 的工作原理

Scaler 在 KEDA 中的完整工作周期包含四个阶段:注册 → 轮询 → 计算 → 反馈。下图展示了这一流程:

Scaler 工作原理:四阶段周期 阶段 1:注册 ScaledObject 创建 阶段 2:轮询 GetMetrics 调用 阶段 3:计算 副本数推导 阶段 4:反馈 HPA 更新副本数 循环(pollingInterval) 各阶段详细说明 1. 注册:用户创建 ScaledObject CRD,指定 Scaler 类型和参数,KEDA Operator 初始化 Scaler 实例。 2. 轮询:按 pollingInterval(默认 30s)周期调用 Scaler.GetMetrics(),获取当前指标值。 3. 计算:将指标值与 targetValue/targetAverageValue 对比,计算期望副本数。 4. 反馈:将计算结果写入 HPA 的 target 字段,HPA 触发 Deployment/StatefulSet 的副本调整。 循环:只要 ScaledObject 未被删除,上述周期持续运行,实现动态弹性伸缩。

Scaler 在计算副本数时遵循以下公式:

期望副本数 = ceil( 当前指标值 / targetValue )

示例:
- Kafka 当前 lag = 1500
- targetValue = 500(每个 Pod 处理 500 条消息)
- 期望副本数 = ceil(1500 / 500) = 3 个 Pod
关键设计原则:Scaler 的计算结果始终是 向上取整 的整数,确保有足够的 Pod 处理积压。当指标值降为 0 时,Scaler 返回 0,HPA 会将副本数缩到 minReplicaCount(默认为 1)。如果希望缩到 0,需要启用 idleReplicaCount 特性。

4.5 Scaler 的配置示例

以下是一个使用 Kafka Scaler 的完整 ScaledObject 配置,展示了 Scaler 参数如何与工作原理对应:

apiVersion: keda.sh/v1alpha1
kind: ScaledObject
metadata:
  name: kafka-consumer-scaler
  namespace: production
spec:
  scaleTargetRef:
    name: kafka-consumer-deployment  # 目标 Deployment
  pollingInterval: 15                # 轮询间隔(秒),对应阶段 2
  cooldownPeriod: 60                 # 冷却时间(秒),防止频繁扩缩
  minReplicaCount: 1                 # 最小副本数
  maxReplicaCount: 20                # 最大副本数
  triggers:
  - type: kafka
    metadata:
      bootstrapServers: kafka-cluster:9092
      consumerGroup: my-consumer-group
      topic: orders
      lagThreshold: "100"            # 触发扩容的滞后阈值
      offsetResetPolicy: latest
      # targetValue 默认 = lagThreshold,每个 Pod 处理 100 条消息
参数调优建议:pollingInterval 不宜过短(建议 ≥10s),避免对事件源造成过大压力。cooldownPeriod 建议设置为指标采集周期的 2-3 倍,防止指标抖动导致频繁扩缩。