4. 任务编排基础:工作流、DAG、有状态任务与无状态任务
在构建多集群弹性伸缩运营系统时,任务编排是连接策略决策与底层执行的核心纽带。本章将系统梳理任务编排的四大基础概念:工作流、DAG(有向无环图)、有状态任务与无状态任务,并深入解析 Kubernetes 原生提供的 Job 与 CronJob 原语。理解这些基础是设计可靠、可观测、可恢复的自动化运维流水线的先决条件。
4.1 核心概念辨析
任务编排的本质是将一个复杂的运维目标(如“完成集群扩容并验证业务可用性”)拆解为多个可独立执行、可依赖、可重试的子步骤。下表从定义、特征与适用场景三个维度对比了四个核心概念:
| 概念 | 定义 | 核心特征 | 典型场景 |
|---|---|---|---|
| 工作流 (Workflow) | 一系列任务及其依赖关系的完整定义,包含执行顺序、条件分支、超时与重试策略。 | 可编排、可观测、可恢复;通常由工作流引擎驱动。 | 集群扩缩容流水线、CI/CD 发布、备份恢复流程。 |
| DAG (有向无环图) | 一种用图结构表示任务依赖关系的数学模型,节点代表任务,有向边代表依赖,且图中不存在循环。 | 无环、拓扑排序、并行度明确;天然适合表达“先 A 后 B,C 与 D 可并行”的逻辑。 | 数据管道、多阶段部署、并行测试执行。 |
| 有状态任务 | 执行过程中依赖或产生持久化数据(状态)的任务,重启后需恢复上下文。 | 需要存储(如 PVC、数据库)、幂等性设计复杂、故障恢复成本高。 | 数据库迁移、日志聚合、模型训练 checkpoint 保存。 |
| 无状态任务 | 执行不依赖本地持久化数据,所有输入通过参数或外部存储传递,任务实例可随时替换。 | 天然幂等、易于水平扩展、故障后直接重建即可。 | 健康检查、配置下发、镜像扫描、告警通知。 |
4.2 工作流与 DAG 的关系
工作流是 DAG 的一种具体实现载体。DAG 提供了数学层面的依赖约束,而工作流引擎(如 Argo Workflows、Apache Airflow、Temporal)将 DAG 转化为可执行的流水线。下图展示了一个典型的集群弹性伸缩工作流 DAG:
上图展示了 DAG 的三个关键特性:无环(不存在循环依赖)、并行性(扩容评估、预热、配置下发可同时执行)、条件分支(健康检查结果决定进入完成或回滚路径)。工作流引擎通过拓扑排序确定执行顺序,并维护每个节点的状态(Pending、Running、Succeeded、Failed)。
4.3 有状态任务 vs 无状态任务:设计取舍
在 Kubernetes 环境中,任务的状态管理直接决定了其故障恢复模型与资源开销。下表从多个维度进行对比:
| 维度 | 无状态任务 | 有状态任务 |
|---|---|---|
| 存储依赖 | 无本地持久化,数据通过 ConfigMap、Secret、API 调用传递 | 依赖 PVC、数据库、对象存储等持久化后端 |
| Pod 标识 | 随机名称,重建后完全替换 | 需要稳定的网络标识(如 StatefulSet 的序号) |
| 扩缩容 | 快速水平扩展,无冷启动延迟 | 扩展受限于数据分片或锁机制,速度较慢 |
| 故障恢复 | 直接删除并重建 Pod,无需数据迁移 | 需检测数据一致性,可能需手动干预 |
| 幂等性 | 天然幂等(输入不变则输出不变) | 需业务层实现幂等(如去重表、版本号) |
| Kubernetes 原语 | Job、CronJob、Deployment | StatefulSet、Operator(如 TiDB Operator) |
4.4 Kubernetes Job 原语详解
Job 是 Kubernetes 中最基础的任务执行原语,用于运行一个或多个 Pod 直至成功终止。它天然适合无状态、批处理类型的任务。
4.4.1 Job 的核心行为模式
- 非并行 Job: 只启动一个 Pod,Pod 成功退出后 Job 标记为 Completed。
- 固定完成次数的并行 Job: 设置
.spec.completions和.spec.parallelism,启动多个 Pod 并行执行,直到成功次数达到 completions 值。 - 工作队列 Job: 不设置 completions,Pod 从外部队列消费任务,直到所有任务完成且无新任务。
apiVersion: batch/v1
kind: Job
metadata:
name: cluster-scale-check
spec:
completions: 3 # 总共需要成功 3 次
parallelism: 2 # 最多同时运行 2 个 Pod
backoffLimit: 4 # 失败重试次数上限
activeDeadlineSeconds: 300 # 任务最长执行时间
template:
spec:
restartPolicy: Never
containers:
- name: checker
image: registry.example.com/scale-checker:1.0
args: ["--cluster", "$(CLUSTER_NAME)"]
env:
- name: CLUSTER_NAME
value: "prod-cluster-01"
4.4.2 Job 的失败处理策略
| 参数 | 说明 | 推荐值 |
|---|---|---|
backoffLimit |
Pod 失败后的重试次数,超过后 Job 标记为 Failed | 4-6(根据任务稳定性调整) |
activeDeadlineSeconds |
Job 整体超时时间,超时后强制终止所有 Pod | 任务预估时间的 1.5-2 倍 |
ttlSecondsAfterFinished |
Job 完成后自动清理的等待时间 | 3600(1 小时) |
4.5 Kubernetes CronJob 原语详解
CronJob 在 Job 之上增加了时间调度能力,使用标准的 Cron 表达式定义执行周期。它是实现定时弹性伸缩、周期性健康检查、日志轮转等场景的首选原语。
4.5.1 CronJob 的关键字段
apiVersion: batch/v1
kind: CronJob
metadata:
name: hourly-scale-check
spec:
schedule: "0 * * * *" # 每小时执行一次
startingDeadlineSeconds: 120 # 调度延迟超过 120 秒则跳过本次执行
concurrencyPolicy: Forbid # 禁止并发:上次未完成则跳过本次
successfulJobsHistoryLimit: 3 # 保留最近 3 个成功的 Job 记录
failedJobsHistoryLimit: 1 # 保留最近 1 个失败的 Job 记录
jobTemplate:
spec:
template:
spec:
containers:
- name: scaler
image: registry.example.com/auto-scaler:2.0
restartPolicy: Never
4.5.2 并发策略选择
| 策略 | 行为 | 适用场景 |
|---|---|---|
Allow |
允许新的 Job 与正在运行的 Job 并发执行 | 只读检查、数据采集(无副作用) |
Forbid |
如果上次 Job 仍在运行,则跳过本次调度 | 集群扩缩容、配置变更(必须串行) |
Replace |
取消正在运行的 Job,启动新的 Job | 需要最新状态的轮询任务 |
startingDeadlineSeconds 可以避免堆积。
4.6 Job/CronJob 与工作流引擎的集成模式
在复杂的多集群编排场景中,单个 Job 或 CronJob 往往不足以表达完整的业务逻辑。下图展示了 Job 作为工作流引擎中的“任务节点”的集成架构:
这种集成模式的核心优势在于:工作流引擎负责 DAG 逻辑、状态持久化与用户界面,而每个任务节点实际由 Kubernetes Job 承载。Job 天然提供 Pod 级别的资源隔离、自动重试与超时控制,工作流引擎只需监控 Job 的完成状态即可驱动流程前进。
4.7 本章小结
- 工作流与 DAG 是任务编排的骨架,DAG 保证无环依赖,工作流引擎将其转化为可执行流水线。
- 无状态任务 是弹性伸缩场景的首选,故障恢复成本低,易于水平扩展;有状态任务 仅在必须持久化中间结果时使用。
- Kubernetes Job 提供并行执行、重试、超时等能力,适合批处理与一次性任务。
- CronJob 在 Job 基础上增加定时调度,通过
concurrencyPolicy控制并发行为,适合周期性运维任务。 - 在生产级编排中,工作流引擎 + Kubernetes Job 的组合模式兼顾了编排灵活性与执行可靠性。