3. Scaler 机制详解:Scaler 的分类与注册发现
Scaler(缩放器)是 KEDA 的核心抽象,负责连接外部事件源并返回事件指标数据,驱动 HPA 对工作负载进行弹性伸缩。理解 Scaler 的分类与注册发现机制,是正确配置事件源和构建流水线触发器的前提。
3.1 Scaler 的分类
KEDA 将 Scaler 分为两大类:内置 Scaler(Built-in Scaler)和外部 Scaler(External Scaler)。两者的核心区别在于实现方式、维护主体和部署形态。
| 对比维度 | 内置 Scaler(Built-in) | 外部 Scaler(External) |
|---|---|---|
| 实现方式 | KEDA 核心代码仓库内维护,Go 语言实现 | 独立 gRPC 服务,任何语言均可实现 |
| 维护主体 | KEDA 社区官方维护 | 第三方开发者或企业自行维护 |
| 部署形态 | 随 KEDA Operator 进程一起运行 | 独立 Deployment + Service,需额外部署 |
| 注册方式 | 编译时注册,启动时自动加载 | 通过 ClusterTriggerAuthentication 或 ScaledObject 中指定地址 |
| 典型场景 | Kafka、Prometheus、RabbitMQ、AWS SQS 等 | 自研监控系统、私有协议、遗留中间件 |
3.1.1 内置 Scaler
内置 Scaler 是 KEDA 官方提供的事件源适配器,覆盖了主流的消息队列、数据库、监控系统和云服务。截至 KEDA 2.14,官方已提供超过 50 种内置 Scaler。常见分类如下:
- 消息队列类:Apache Kafka、RabbitMQ、AWS SQS/SNS、Azure Service Bus、GCP Pub/Sub、NATS、Redis Streams
- 数据库类:PostgreSQL、MySQL、MongoDB、Redis、Cassandra、DynamoDB
- 监控与指标类:Prometheus、Datadog、New Relic、Azure Monitor、AWS CloudWatch
- CI/CD 与工作流类:Jenkins、GitHub Actions、GitLab CI、Argo Workflows
- HTTP 与自定义类:HTTP Add-on(基于请求速率)、Cron(定时伸缩)、Metrics API(自定义指标端点)
3.1.2 外部 Scaler
当内置 Scaler 无法满足需求时(例如对接自研监控系统、私有协议或遗留中间件),可以通过外部 Scaler 扩展 KEDA 的事件源能力。外部 Scaler 本质上是一个独立的 gRPC 服务,必须实现 KEDA 定义的 ExternalScaler 接口。
外部 Scaler 的 gRPC 接口定义如下(protobuf):
service ExternalScaler {
// 返回 Scaler 是否处于活动状态
rpc IsActive(ScaledObjectRef) returns (IsActiveResponse);
// 返回当前指标值,KEDA 据此计算目标副本数
rpc GetMetricSpec(ScaledObjectRef) returns (GetMetricSpecResponse);
// 返回指标快照值(可选,用于更精确的缩放决策)
rpc GetMetrics(GetMetricsRequest) returns (GetMetricsResponse);
// 关闭 Scaler 时的清理操作
rpc Close(ScaledObjectRef) returns (CloseResponse);
}
3.2 Scaler 注册与发现机制
KEDA 通过一套清晰的注册与发现流程,将 Scaler 与 ScaledObject 绑定,实现事件驱动的弹性伸缩。下图展示了 Scaler 从注册到被调用的完整链路。
3.2.1 内置 Scaler 的注册机制
内置 Scaler 采用编译时注册 + 启动时自动加载的模式。每个内置 Scaler 在 pkg/scalers/ 目录下独立实现,通过 init() 函数调用 Register() 方法将自身注册到全局的 scalerMap 中。
注册核心代码示例:
// pkg/scalers/kafka_scaler.go
func init() {
// 注册 Kafka Scaler,key 为 "kafka"
Register("kafka", func() Scaler {
return &kafkaScaler{}
})
}
// pkg/scalers/registry.go
var scalerMap = make(map[string]ScalerBuilder)
func Register(name string, builder ScalerBuilder) {
scalerMap[name] = builder
}
func GetScaler(name string) (Scaler, bool) {
s, ok := scalerMap[name]
return s, ok
}
当用户创建 ScaledObject 时,KEDA 的控制器会解析 spec.triggers[].type 字段,从 scalerMap 中查找对应的 Scaler 构建器,实例化后开始拉取指标。
3.2.2 外部 Scaler 的发现机制
外部 Scaler 采用运行时动态发现 + gRPC 连接的模式。KEDA 不预先注册外部 Scaler,而是在 ScaledObject 中通过 spec.triggers[].metadata.address 字段指定外部 Scaler 的 gRPC 服务地址。
外部 Scaler 的 ScaledObject 配置示例:
apiVersion: keda.sh/v1alpha1
kind: ScaledObject
metadata:
name: custom-scaledobject
spec:
scaleTargetRef:
name: my-deployment
triggers:
- type: external
metadata:
# 外部 Scaler 的 gRPC 服务地址
address: custom-scaler.namespace.svc.cluster.local:9090
# 传递给外部 Scaler 的自定义参数
topic: my-topic
threshold: "100"
authenticationRef:
name: custom-scaler-auth
type 字段直接使用 Scaler 名称(如 kafka、prometheus),而外部 Scaler 的 type 字段固定为 external,通过 address 元数据指定实际服务位置。
3.3 Scaler 生命周期管理
KEDA 对每个 Scaler 实例进行完整的生命周期管理,确保资源正确释放和指标持续可用。
| 阶段 | 内置 Scaler | 外部 Scaler |
|---|---|---|
| 初始化 | ScaledObject 创建时,从 scalerMap 构建实例 | ScaledObject 创建时,建立 gRPC 连接 |
| 指标拉取 | KEDA 定时调用 GetMetrics(),默认每 30 秒一次 | 通过 gRPC 流式或轮询调用 GetMetrics() |
| 健康检查 | 内置在 KEDA Operator 进程中,随进程存活 | KEDA 定期发送 gRPC 健康检查请求 |
| 销毁 | ScaledObject 删除时,调用 Close() 清理资源 | ScaledObject 删除时,关闭 gRPC 连接 |
3.4 选择 Scaler 类型的决策指南
在实际项目中,选择内置 Scaler 还是外部 Scaler,可以参考以下决策树:
1. 对接自研或私有化监控系统;
2. 需要自定义复杂的指标计算逻辑;
3. 内置 Scaler 无法满足性能或功能需求。
3.5 小结
Scaler 是 KEDA 事件驱动伸缩的核心抽象。内置 Scaler 通过编译时注册、启动时自动加载的方式提供官方事件源支持;外部 Scaler 通过 gRPC 接口实现运行时动态发现,扩展了 KEDA 的生态边界。理解两者的注册与发现机制,有助于在流水线构建触发器集成时正确选择 Scaler 类型,并合理配置 ScaledObject 的触发器参数。