一、Cromwell简介:我们先聊聊它是什么

说白了,Cromwell 就是一个工作流管理系统。你可能会问:工作流管理系统多了去了,为什么偏要用它?

我个人习惯把 Cromwell 比作一个“流水线调度员”。你写好一份工作流脚本(通常是 WDL),告诉它“先做 A,再做 B,如果 A 失败了就跑 C”。剩下的活儿——比如在哪台机器上跑、怎么分配资源、怎么传数据——全都交给 Cromwell 去操心。

我在项目中遇到过不少类似的工具,有些太重,有些又太死板。Cromwell 不一样的地方在于——它对底层计算环境没有偏见。本地跑可以,上云也可以,混合着来照样行。嗯,这一点在混合云迁移的场景里特别关键。

核心概念:你得先搞懂这几个东西

刚接触 Cromwell 时,我建议你先抓住三个核心概念。其他的都是锦上添花。

  • Workflow(工作流):整个任务的蓝图。它定义了一系列步骤和它们之间的依赖关系。
  • Task(任务):工作流里的最小执行单元。一个 Task 做一件事,比如“比对基因序列”或“转换文件格式”。
  • Call(调用):在工作流中真正去执行某个 Task 的动作。你可以多次调用同一个 Task,传入不同的参数。

打个比方吧:Workflow 是菜谱,Task 是具体的烹饪步骤(切菜、炒菜、装盘),Call 就是你真的拿起锅铲去做的那一下。

概念 类比 我的理解
Workflow 菜谱 定义了“做什么”和“按什么顺序做”
Task 烹饪步骤 一个不可再拆分的原子操作
Call 实际操作 把步骤真正执行一遍,可能执行多次
避坑指南:我曾经把 Workflow 和 Task 的边界搞混,把一个复杂逻辑写进 Task 里。结果调试起来非常痛苦。记住——Task 要足够小,小到只做一件事。

WDL 介绍:工作流描述语言长什么样

WDL 是 Cromwell 的“母语”。你不用学太多,掌握几个基本语法就能上手。

来看一个最简单的例子。下面这个 WDL 脚本定义了一个工作流,它调用一个 Task 来打印 “Hello World”:

workflow my_workflow {
  call my_task
}

task my_task {
  command {
    echo "Hello World"
  }
  output {
    String out = read_string(stdout())
  }
  runtime {
    docker: "ubuntu:latest"
  }
}

你发现了吗?结构非常清晰:

  • workflow 块定义一个工作流
  • task 块定义一个任务
  • command 是你真正要执行的 shell 命令
  • output 定义怎么从执行结果里提取数据
  • runtime 指定运行环境,比如 Docker 镜像
我的习惯:每写一个 Task,我都会先用 runtime 指定 Docker 镜像。这能保证任务在任何环境下的行为是一致的。云上云下跑出来的结果不会打架。

WDL 还支持变量、条件判断、循环、以及更复杂的输入输出定义。你想想看,如果只用 shell 脚本去管理这些,早乱成一锅粥了。

workflow simple_math {
  File input_file
  
  call add_one { input: num = read_int(input_file) }
  call multiply_two { input: num = add_one.result }
  
  output {
    Int final_result = multiply_two.result
  }
}

task add_one {
  Int num
  
  command {
    echo $((num + 1))
  }
  output {
    Int result = read_int(stdout())
  }
}

task multiply_two {
  Int num
  
  command {
    echo $((num * 2))
  }
  output {
    Int result = read_int(stdout())
  }
}

这段代码展示了一个典型的数据依赖链:先加一,再乘二。Cromwell 会自动解析这些依赖关系,保证 multiply_two 在 add_one 完成后才启动。你完全不用操心调度顺序。

Cromwell 工作流系统核心架构 WDL 工作流定义 Cromwell 引擎(调度与状态管理) 解析 WDL → 构建依赖图 → 管理执行 本地后端 Linux/Mac HPC / 集群 SLURM / SGE 云后端 AWS / GCP / Azure 执行结果与输出文件 核心能力 一次编写,多地运行 混合云关键 后端可插拔,配置即切换

这张图展示了我对 Cromwell 架构的理解。你从顶层塞进去一个 WDL 脚本,中间层是 Cromwell 引擎——它负责解析、调度、追踪状态。最下层是各种后端适配器。Cromwell 之所以适合混合云,就是因为它允许你在同一套工作流里,把不同任务分发给不同的后端。

举个例子,你可以让数据预处理跑在本地集群,而计算密集型的分析任务自动提交到云上的大规模计算集群。配置改一行就能切换,工作流本身不用动。

一句话总结:Cromwell = WDL(你描述想做什么) + 可插拔后端(你决定在哪儿做)。理解了这个组合,你就掌握了 Cromwell 的精髓。