4. ScaledJob 详解:CRD 定义、与 ScaledObject 的区别、Job 触发模式与失败重试策略
在 KEDA 生态中,ScaledJob 是专门为 批处理任务(Batch Job) 设计的事件驱动伸缩原语。与 ScaledObject 管理 Deployment/StatefulSet 的 Pod 副本数不同,ScaledJob 根据事件源水位动态创建 Kubernetes Job 对象,每个 Job 执行一次即完成。本章将深入 ScaledJob 的 CRD 结构、与 ScaledObject 的核心差异、触发模式以及生产级失败重试策略。
4.1 ScaledJob CRD 定义
ScaledJob 的 CRD 定义在 keda.sh/v1alpha1 API 版本下,其核心结构包含 jobTargetRef(Job 模板)、triggers(事件源)、scalingStrategy(伸缩策略)和 failedJobsHistoryLimit(失败历史限制)。以下是一个完整的 YAML 示例:
apiVersion: keda.sh/v1alpha1
kind: ScaledJob
metadata:
name: sqs-job-scaler
namespace: default
spec:
# Job 模板:定义每次创建的 Job 规格
jobTargetRef:
template:
spec:
containers:
- name: worker
image: myregistry/worker:1.0
command: ["python", "process_messages.py"]
env:
- name: QUEUE_URL
value: "https://sqs.us-east-1.amazonaws.com/123456789/myqueue"
resources:
requests:
memory: "256Mi"
cpu: "250m"
limits:
memory: "512Mi"
cpu: "500m"
restartPolicy: Never
backoffLimit: 4 # Job 内部重试次数
ttlSecondsAfterFinished: 300 # Job 完成后 5 分钟自动清理
# 事件源触发器
triggers:
- type: aws-sqs-queue
metadata:
queueURL: "https://sqs.us-east-1.amazonaws.com/123456789/myqueue"
queueLength: "5" # 目标队列长度
awsRegion: "us-east-1"
activationQueueLength: "0" # 激活阈值
# 伸缩策略
scalingStrategy:
strategy: "default" # 可选:default, accurate, eager
maxScale: 10 # 最大并发 Job 数
pollingInterval: 10 # 轮询间隔(秒)
cooldownPeriod: 30 # 冷却期(秒)
# 失败历史限制
failedJobsHistoryLimit: 5
successfulJobsHistoryLimit: 3
jobTargetRef:与原生 Kubernetes Job 的spec结构一致,但不需要spec.parallelism和spec.completions,因为 KEDA 会动态控制并发 Job 数量。scalingStrategy.strategy:决定 KEDA 如何计算需要创建的 Job 数量。默认策略基于事件源水位与目标值的比值。failedJobsHistoryLimit:保留最近 N 个失败 Job 的记录,用于审计和调试。
4.2 ScaledJob 与 ScaledObject 的核心区别
虽然 ScaledJob 和 ScaledObject 都使用相同的触发器机制,但它们的伸缩对象、生命周期和适用场景有本质区别。下表从 6 个维度进行对比:
| 对比维度 | ScaledObject | ScaledJob |
|---|---|---|
| 伸缩目标 | Deployment / StatefulSet / Custom Resource | Kubernetes Job(一次性 Pod) |
| Pod 生命周期 | 长期运行,持续处理请求 | 执行完成后自动退出 |
| 伸缩方向 | 水平扩缩容(增加/减少副本数) | 垂直创建(增加 Job 实例数) |
| 适用场景 | Web 服务、API 网关、实时流处理 | 消息队列消费、批量数据处理、ETL 任务 |
| 失败处理 | 依赖 Deployment 的滚动更新和就绪探针 | 依赖 Job 的 backoffLimit + ScaledJob 重试策略 |
| 资源清理 | 缩容时自动删除 Pod | 通过 ttlSecondsAfterFinished 或历史限制清理 |
4.3 Job 触发模式
ScaledJob 支持三种触发模式,通过 scalingStrategy.strategy 字段控制。不同模式决定了 KEDA 如何根据事件源水位计算需要创建的 Job 数量。
4.3.1 默认模式(default)
KEDA 将事件源当前值除以目标值,向上取整得到 Job 数量。例如:SQS 队列有 23 条消息,目标值 queueLength: 5,则创建 ceil(23/5) = 5 个 Job。每个 Job 处理约 5 条消息。
4.3.2 精确模式(accurate)
KEDA 会跟踪当前正在运行的 Job 数量,并考虑它们可能处理的消息量。如果已有 3 个 Job 正在运行(每个预期处理 5 条),队列剩余 8 条,则只创建 ceil(8/5) = 2 个新 Job。此模式可避免过度创建。
4.3.3 积极模式(eager)
KEDA 会立即为队列中每条消息创建一个 Job(1:1 映射)。适用于每条消息处理时间差异大、需要最大并行度的场景。注意:此模式可能创建大量 Job,需配合 maxScale 限制。
| 模式 | 计算公式 | 适用场景 | 风险 |
|---|---|---|---|
| default | ceil(当前值 / 目标值) | 消息处理时间均匀,每个 Job 处理固定数量 | 可能创建过多 Job |
| accurate | ceil((当前值 - 运行中 Job 预期处理量) / 目标值) | 消息处理时间长,需要精确控制并发 | 计算略复杂,需监控运行中 Job |
| eager | 当前值(每条消息一个 Job) | 消息处理时间差异大,需要最大并行度 | 可能创建大量 Job,需设置 maxScale |
accurate 模式。它能在保证处理速度的同时,避免资源浪费。对于消息量波动剧烈的场景,配合 pollingInterval: 5 缩短轮询间隔,提高响应速度。
4.4 失败重试策略
ScaledJob 的失败重试分为两个层级:Job 内部重试和ScaledJob 级别重试。两者协同工作,确保批处理任务的可靠性。
4.4.1 Job 内部重试(backoffLimit)
在 jobTargetRef 中设置 backoffLimit,控制单个 Job 的 Pod 重启次数。默认值为 6。如果 Pod 退出码非零,Kubernetes 会重新创建 Pod,直到达到 backoffLimit 或 Job 成功。
jobTargetRef:
backoffLimit: 4 # 最多重试 4 次(总共执行 5 次)
4.4.2 ScaledJob 级别重试(failedJobsHistoryLimit + 重新入队)
当 Job 内部重试耗尽后,Job 标记为失败。ScaledJob 通过 failedJobsHistoryLimit 保留失败记录,但不会自动重新创建失败的 Job。真正的重试逻辑需要业务层配合:
- 消息重新入队: 如果 Job 处理失败,应将消息重新放回队列(如 SQS 的 visibility timeout 超时后自动重新可见)。
- 死信队列(DLQ): 超过最大重试次数的消息转入 DLQ,由人工或独立消费者处理。
- 监控告警: 通过
failedJobsHistoryLimit监控失败 Job 数量,触发告警。
failedJobsHistoryLimit 只是历史记录保留,不是自动重试机制。如果希望失败后重新创建 Job,需要在应用层实现消息重新入队逻辑,或使用 KEDA 的 scaleTriggers 配合死信队列指标。
4.5 生产配置最佳实践
基于以上分析,总结 ScaledJob 在生产环境中的推荐配置:
- 始终设置
maxScale:防止事件源突发高峰导致创建数千个 Job,耗尽集群资源。建议根据集群容量和任务资源需求计算上限。 - 合理设置
pollingInterval:对于延迟敏感场景设为 5-10 秒;对于批量处理场景设为 30-60 秒,减少 KEDA 自身负载。 - 启用
ttlSecondsAfterFinished:自动清理已完成 Job,避免 etcd 存储压力。建议设为 300-600 秒。 - 结合 HPA 与 ScaledJob:对于混合负载(如 Web 服务 + 后台批处理),使用 ScaledObject 管理 Web 层,ScaledJob 管理批处理层,互不干扰。
- 监控失败率:通过 Prometheus 监控
keda_scaledjob_failed_total指标,设置告警阈值(如 5% 失败率)。
strategy: accurate、maxScale: 20、pollingInterval: 10。高峰期每秒处理 500 条超时订单,Job 平均执行时间 2 秒,系统稳定运行无积压。