JuniorTree

Back

把云原生带入生物信息学Blur image

什么是云原生#

在正式进入生物信息学的科研训练之前,我对云原生(Cloud Native)充满兴趣,云原生指的并不是一个具体的产品,而是一套思想和方法,它的核心思想就是:应用从设计之初,就假设它会运行在“云”这种动态、分布式的环境中

“云原生”这个词现在非常火,但确实很容易让人“不明觉厉”,我来举出一个简单的例子

比如说你要做一个雕塑,传统的方法,你找来一整块巨大的石头,在上面精心雕刻出城堡的每一个部分——城墙、塔楼、吊桥… 最终,你得到一个完美的、连成一体的“城堡”雕塑

这种方法的优点是很坚固,一体性强,但当你要对其中的局部进行修改,比如你不喜欢这个塔楼,你可能得把整个雕塑砸掉重来,或者费巨大力气去“凿”,而且如果吊桥塌了,有可能会影响到整个雕塑

云原生的方法更像是用“乐高”去搭建整个雕塑,你不用一整块石头,而是用一堆标准化的“乐高积木”来搭建,“城墙”是一块积木(一个服务),“塔楼”是另一块积木(另一个服务),吊桥”又是另一块积木(再一个服务)

你把这些积木(微服务)都放进一个个透明的小盒子里(容器,比如 Docker),再把这些盒子交给一个“超级管家”(编排系统,比如 Kubernetes)来管理

云原生的方式有几个优点,第一个是快速迭代,比如说你要是不喜欢这个塔楼,你只要把塔楼的“乐高积木”给换掉即可,完全不影响“城墙”和“吊桥”,可以迅速开发

第二个是高可用性,如果吊桥塌掉了,“超级管家”会自动丢弃掉这个积木,并且迅速替换一个新的上去,在这个过程中,其他部件的功能完全不受影响

第三个是弹性伸缩,如果某天来参观你的雕塑的人非常多,“超级管家”会立刻自动复制 100 个“城堡”盒子(容器),游客一走,再把多余的盒子收回来

普通人接触到的不是“云原生技术”,而是“云原生体验”,最相关的体验就是:那些“理所当然”的丝滑和便捷

最典型的例子就是“双十一”抢购,会有几亿人同时涌入淘宝或京东,云原生系统(那个“超级管家”)检测到史无前例的访问量,它会在几分钟甚至几秒钟内,自动把“支付服务”、“订单服务”这些“乐高盒子”复制成千上万份,分布到全国的服务器上,几小时后,高峰过去,“超级管家”又会自动把多余的几万个“盒子”收回(省钱),这种“需要时无限变多,不需要时立刻消失”的超能力,就是云原生追求的弹性伸缩 (Scalability)

云原生能给生物信息学带来什么#

「一次编译、到处运行」#

我想,现在其实接触到云原生技术的同行其实非常多,基本上每台集群上都装的有 Singularity(现在改名叫 Apptainer)

就我自己而言,我跑流程非常讨厌配环境,尤其是我本地的开发环境是 macOS/Ubuntu,集群上使用比较“稳定”(老)的 CentOS,经常是写代码半天,配环境两天,尤其是碰到一些由 C/C++写的“金标准”软件,我们必须要在本地进行手动编译,这下更麻烦啦

但如果我们使用 Docker,这个问题将非常容易解决,我们可以将这些软件封装到容器中,就可以实现“一次编译,到处运行”的效果

比如说我这几天在折腾一个生成残基图的工具—— ERRAT1,这个工具是 C++写的,意味着它依赖底层的 C/C++ 库 (like libstdc++),而且你必须配置好完整等构建工具链

结果就是,在本地 (macOS/Ubuntu) 辛辛苦苦编译通过了,一拿到集群 (CentOS) 上,要么是动态链接库(.so 文件)缺失,要么是 glibc 版本太低,要么是 CPU 架构不匹配……总之就是跑不起来

很容易就想到用容器的方法,我们可以尝试在容器内对 ERRAT 进行编译,在这里使用了一种常见的优化容器体积的方法,多阶段编译,第一阶段因为安装了一些编译工具,导致容器的体积比较大;在第二阶段只有 ERRAT 的运行时,所以容器体积非常小

我自测第一阶段容器有 200 多 MB,实际编译出来的运行时只有 30 多MB

# ====================================================================
# ERRAT-CLI 容器化
# 轻量级容器,仅包含 ERRAT-CLI 工具和必要依赖
# 使用多阶段构建优化镜像大小
# ====================================================================

# ====================================================================
# 第一阶段:构建阶段(Builder Stage)
# 安装编译工具并编译 ERRAT-CLI
# ====================================================================
FROM debian:12-slim AS builder

LABEL maintainer="Protein Analysis Pipeline Team"
LABEL version="1.0"
LABEL description="Builder stage for ERRAT-CLI"

# 设置非交互式安装
ENV DEBIAN_FRONTEND=noninteractive

# 配置 APT 使用清华源(可选,提高国内构建速度)
RUN sed -i 's/deb.debian.org/mirrors.tuna.tsinghua.edu.cn/g' /etc/apt/sources.list.d/debian.sources 2>/dev/null || \
    sed -i 's/deb.debian.org/mirrors.tuna.tsinghua.edu.cn/g' /etc/apt/sources.list 2>/dev/null || true

# 安装编译工具
RUN apt-get update && apt-get install -y --no-install-recommends \
    build-essential \
    g++ \
    make \
    ca-certificates \
    && rm -rf /var/lib/apt/lists/*

# 设置工作目录
WORKDIR /workspace

# 复制 ERRAT-CLI 源代码
COPY ERRAT-CLI /workspace/ERRAT-CLI

# 编译 ERRAT-CLI
RUN if [ -d "/workspace/ERRAT-CLI" ] && [ -f "/workspace/ERRAT-CLI/src/errat.cpp" ]; then \
        cd /workspace/ERRAT-CLI && \
        mkdir -p bin && \
        g++ -o bin/errat_cli src/errat.cpp -lm -O3 && \
        chmod +x bin/errat_cli && \
        echo "✓ ERRAT-CLI compiled successfully"; \
    else \
        echo "✗ ERRAT-CLI source not found"; \
        exit 1; \
    fi

# ====================================================================
# 第二阶段:运行阶段(Runtime Stage)
# 只复制编译好的二进制文件,不包含编译工具
# ====================================================================
FROM debian:12-slim

LABEL maintainer="Protein Analysis Pipeline Team"
LABEL version="1.0"
LABEL description="Lightweight container for ERRAT-CLI protein structure analysis tool"

# 设置非交互式安装
ENV DEBIAN_FRONTEND=noninteractive
ENV LANG=C.UTF-8
ENV LC_ALL=C.UTF-8

# 配置 APT 使用清华源
RUN sed -i 's/deb.debian.org/mirrors.tuna.tsinghua.edu.cn/g' /etc/apt/sources.list.d/debian.sources 2>/dev/null || \
    sed -i 's/deb.debian.org/mirrors.tuna.tsinghua.edu.cn/g' /etc/apt/sources.list 2>/dev/null || true

# 只安装运行时依赖(C++ 标准库等)
# libstdc++6 是 C++ 运行时库,libgcc-s1 是 GCC 运行时库
RUN apt-get update && apt-get install -y --no-install-recommends \
    ca-certificates \
    libstdc++6 \
    libgcc-s1 \
    && rm -rf /var/lib/apt/lists/*

# 设置工作目录
WORKDIR /workspace

# 从构建阶段复制编译好的二进制文件
COPY --from=builder /workspace/ERRAT-CLI/bin/errat_cli /workspace/ERRAT-CLI/bin/errat_cli

# 设置 PATH 环境变量
ENV PATH="/workspace/ERRAT-CLI/bin:$PATH"

# 设置入口点
ENTRYPOINT ["/workspace/ERRAT-CLI/bin/errat_cli"]
CMD ["--help"]
plaintext

编译完成后,在本地的 macOS 上 docker run ... errat_image ...,完美运行;在集群上 singularity run ... docker://your_username/errat_image ...,也是完美运行

无论在哪里,ERRAT 感受到的都是它最“舒服”的、在编译时就固定下来的那个环境,它再也不用担心“水土不服”了

事实上生信就是有如此多的古董代码和软件,我刚开始的时候还尝试去手动修改里面的一些代码,使其能运行,后来越改越烦,这套方法论对于生物信息学这种重度依赖各种“祖传”编译工具的领域来说,简直是革命性的

事实上已经有生物信息学开发者这样干了,也就是 BioContainers2,但是我看仓库的提交记录都非常老,而且有些容器没有写好注释,我也不知道能不能用

一起来搭乐高(Workflows)#

上面我们尝试用 Docker/Singularity 造好了“塔楼” (ERRAT)、“城墙” (BWA)、“吊桥” (Samtools) 这些单个的积木

下一个问题是,要如何把这几十块积木按顺序拼成一个完整的“城堡”,即一个完整的生物信息分析流程

传统方法是,写一个巨大且复杂的 bash 脚本,这个脚本非常脆弱,中间任何一步(比如“吊桥”)塌了,都得手动去检查,然后从头再来,非常浪费时间和计算资源

在我刚开始接触 Pipeline 搭建的时候,我就在尝试用这种传统方法,我写了一个很长、很复杂的 Python 脚本,生物信息学的流程搭建通常会涉及到很多工具(调包),也并不所有的工具都给了 Python 的 SDK,比如说前面的 ERRAT,你必须使用 Python 里面的 subprocess 去调度

subprocess.Run (["errat", ...]) 来调用 ERRAT,如果 ERRAT 因为某种原因(比如输入文件格式不对)崩溃了,它会返回一个“非零退出码”,但是我的脚本对此一无所知,它会继续运行,直到下一个工具(比如 Ghostscript)拿到一个损坏的、不完整的 ERRAT 输出文件,然后再次崩溃

然后作为开发者,我只能看到 Ghostscript 报错,但真正的案发现场在 ERRAT,我必须手动去翻找日志,十分痛苦和恶心

这就是“传统脚本”最大的痛点,它没有“状态”

“拼装说明书” (Workflow) 如何解决?

Nextflow3Snakemake4,它们的核心思想就是来解决 subprocess 的这两个问题,它们不是“命令式”的(“第一步跑 A,第二步跑 B”),而是“声明式”的(“我想要 C,而 C 依赖 B,B 依赖 A”)

用 Snakemake 来写这个流程时,会这样写(一个“规则”):

# 这就是一个“乐高积木”的建造规则
rule run_errat:
    input:  "results/step3.bam"
    output: "results/errat.out"
    # 这里不再是脆弱的 subprocess
    # 而是被 Snakemake "管理" 起来的 shell 命令
    shell:
        """
        errat -i {input} -o {output}
        """
python

当运行 Snakemake 时,Snakemake 会主动检查 errat 命令的退出码,如果它失败了,Snakemake 会立刻停止,并明确告知“run_errat 这条规则(这个积木)塌掉了!” 错误定位非常清晰

并且它有“断点断续”,当修复了流程存在的问题,重新运行同一个 snakemake 命令,它会检查 results/step3.bam,如果发现文件存在且规则没有更改,就会跳过

我目前只用过 Snakemake,因为我是一个 Python 开发者,Snakemake 的上手比较友好(对于熟练 Python 的人),相较于 SnakemakeNextflow 的云原生更加彻底,等我用了再分析吧,目前似乎没有看到什么 based on Go 的流程编排系统

从本地迈向云(Beyond the Cloud)#

对于云这个概念,我们不必要特别强调是类似于阿里云、腾讯云或者 Azure 和 GCP 那种云服务商,本地的集群也可以当作云,一切我们接触不到的实体都可以称为“云”

集群调度#

对于比较有钱的组,通常自己会有裸金属或者集群,但是很多集群都没有专职的人来进行管理,就导致实际的有效计算时间并不长,也就是著名的“科研计算的公地悲剧”(Tragedy of the Commons in Research Computing)

Nextflow + Slurm 也许可以帮助解决此类问题

基础层:Slurm 的 QoS(服务质量)策略:

# /etc/slurm/slurm.conf
# 为每个学生创建独立账户
AccountStudent1=cpu=100,mem=200G  # 学生1最多用100核+200G内存
AccountStudent2=cpu=100,mem=200G
# ...

# 创建优先级队列
QosName=normal Priority=100 MaxJobs=5  # 普通任务,最多5个并行作业
QosName=urgent Priority=1000 MaxJobs=2 # 紧急任务,高优先级但限2个
bash

Nextflow 层:自动带上用户身份:

// 每个学生在~/.nextflow/config中配置自己的Slurm账户
process {
    executor = 'slurm'
    queue = 'main'
    clusterOptions = '-A student1 --qos=normal'  // 自动带上账户和QoS
}
groovy

执行流程:

# 学生1提交(占用8核)
nextflow run rnaseq.nf -profile slurm

# 学生2提交(占用32核)
nextflow run variant.nf -profile slurm

# Slurm自动截停:如果学生2的32核申请会超限,作业进入PENDING队列
# 学生1完成后,学生2自动启动
bash

Nextflow 本身提供了一些不依赖底层调度器的轻量级并发控制

全局并发限制(Global Concurrency),即使 8 个学生同时提交,Nextflow 会全局排队,避免集群瞬间过载

// 在集群登录节点的全局配置 /etc/nextflow/config
executor {
    queueSize = 100  // 整个集群最多100个任务同时运行
}

process {
    maxForks = 50    // 单个Nextflow实例最多50个并行任务
}
groovy

动态资源申请(避免僵尸),学生 A 的 10G 样本自动申请 20G 内存,学生 B 的 1G 样本只申请 2G,资源精确匹配需求,杜绝浪费

// 根据输入文件大小自动申请资源
process BWA_MEM {
    memory { 2.GB * fastq_file.sizeGb }  // 文件越大,内存越多
    cpus { fastq_file.sizeGb > 10 ? 16 : 8 } // 大文件用16核
    
    input:
    path fastq_file
    
    script:
    "bwa mem -t ${task.cpus} ref.fa $fastq_file"
}
groovy

如果是八个用户同时提交任务呢?实际的任务执行流程应该是这样的:

学生流程申请资源优先级Slurm处理
1RNA-seq (N=10)8核, 16Gnormal立即运行
2RNA-seq (N=50)32核, 64Gnormal排队(配额超限)
3RNA-seq (N=5)4核, 8Gurgent抢占学生1资源,立即运行
4Variant calling16核, 32Gnormal排队
5FastQC (N=100)2核, 4Gnormal立即运行
6Deep learning48核, 200Glow无限期等待(配额最低)
7RNA-seq (N=20)16核, 32Gnormal排队
8测试任务1核, 2Gnormal立即运行

Nextflow 不管调度,它只负责把任务翻译成 Slurm sbatch ,真正的调度是由 sbatch 来完成,确保了资源调度的公平,尽可能提高实际有效的集群使用实验

云计算#

有一些组可能本身不是做生物信息学的,但是在某个课题中需要用到一些高性能计算,他们可能会尝试去购买或者租赁高性能的计算服务器,这其实是不划算的

实际上,一些云服务商,国外的有 Azure CycleCloud5、AWS ParallelCluster6,Google Batch7;国内有阿里云的 E-HPC(弹性高性能计算)8、腾讯云的 THPC9,字节火山云似乎也在搞

它们的核心价值不是“提供一台服务器”,而是“一键部署一个临时的、弹性的 HPC 集群”

我们可以想象一个“优雅的”流程,看看它如何从根本上解决“不划算”的购买服务器问题

假设一个项目在第一天开始,一位以“湿实验”为主的博士生突然需要一个临时的高性能计算环境,来处理 1000 个蛋白质的结构预测。他无需填写冗长的采购申请,而是直接登录了 AWS、Azure 或阿里云,他使用了像 AWS ParallelCluster 或阿里云 E-HPC 这样的服务,仅凭一个简单的配置文件,点击“创建”

神奇的事情在 15 分钟后发生了:云服务商自动为他创建了一个完整、干净且功能齐备的 HPC 集群。这个集群包含了运行所需的一切:一个登录节点用于操作,一个预配置好的 Slurm 调度器(也就是提供 qstatsinfo 命令的队列系统),以及——在初始状态下——零个计算节点,因为现在还没有任务,所以完全不产生计算费用

到了第一天下午,这位博士生便通过 ssh 登录到这个临时的登录节点,他从 Git 仓库克隆下了一个标准化的 Snakemake 或 Nextflow 分析流程——这是一个可复现、容器化的“作战蓝图”,随后,他运行了一个简单的命令,比如 snakemake --profile slurm --use-singularitynextflow run ... -profile awsbatch

从这一刻起,“弹性”的魔力便开始显现,并在接下来的 72 小时内持续发挥作用

Snakemake 或 Nextflow 作为“总指挥”,开始读取作战计划,并向 Slurm 这支“执行部队”提交全部 1000 个计算任务。Slurm 的队列瞬间被任务填满。AWS ParallelCluster 这样的云平台检测到了队列中的等待任务,于是自动开始“创建”计算节点,它会根据任务需求,在几分钟内启动 1000 台服务器,让这 1000 个任务得以大规模并行计算

到了第四天,所有任务都已跑完,Snakemake 或 Nextflow 自动汇总了最终结果,此时,由于没有新任务,所有计算节点都已被自动销毁,这位博士生只需将 results/ 目录打包下载,然后回到云平台控制台,点击“删除”集群

这就是新旧模式的鲜明对比,旧模式是购买服务器:投入 20 万固定资产,每年还需支付 2 万电费和 N 小时的管理员维护时间(如果没人管,很快就沦为“公地悲剧”);为了跑 1000 个样本,可能要在这台机器上排队等待 1 个月

而新模式是云 HPC 加上“优雅的工作流”:成本是弹性的,假设总共花了 2 万块钱,这是按秒计费的实际用量,效率是惊人的,1 个月的计算量在 3 天内就完成了,最重要的是,维护成本为零,用完即走,不留下一片垃圾

这也是我为啥非常推崇“云”,它把 HPC 从一个“重资产”变成了一种像“自来水”一样的“服务”,而 Snakemake, Nextflow 和 Container,就是能让你拧开这个“水龙头”的完美工具

总结#

把云原生带入到生物信息学中,能让我们聚焦于算法和数据本身,而无需去关注基础设施本身,这对于我们来说,是一场根本性的变革

这意味着研究者终于可以从“环境配置工程师”、“集群管理员”和“软件打包工”的多重身份中解放出来

当基础设施(无论是你组里的“裸金属”集群,还是公有云)变成一个按需取用、用完即走的“插座”时,“可复现性”就从一个需要额外努力去达成的崇高理想,变成了我们工作流中一个自动实现的“副产品”

你不再需要花费数天时间去解决“conda 卡死”或“glibc 冲突”,而是通过 git push 自动构建一个干净、可控的环境

你不再受限于本地硬件的“天花板”,而是可以(通过云)将一个月的计算任务,弹性扩展到三天内并行完成

最终,这彻底拉平了科研的门槛,一个“湿实验”的课题组可以即时获得并运行一个世界级的计算流程,而一个“干实验”的开发者也能确保自己的分析方法,在五年后、在任何地方,都能被同行 100%地重现

Footnotes#

  1. Colovos, C., & Yeates, T. O. (1993). Verification of protein structures: Patterns of nonbonded atomic interactions. Protein Science, 2(9), 1511–1519. https://doi.org/10.1002/pro.5560020916

  2. BioContainer - GitHub

  3. Bal, H. E., Steiner, J. G., & Tanenbaum, A. S. (1989). Programming languages for distributed computing systems. ACM Computing Surveys, 21(3), 261–322. https://doi.org/10.1145/72551.72552

  4. Mölder, F., Jablonski, K. P., Letcher, B., Hall, M. B., Tomkins-Tinch, C. H., Sochat, V., Forster, J., Lee, S., Twardziok, S. O., Kanitz, A., Wilm, A., Holtgrewe, M., Rahmann, S., Nahnsen, S., & Köster, J. (2021). Sustainable data analysis with Snakemake. F1000Research, 10, 33. https://doi.org/10.12688/f1000research.29032.2

  5. Galaxy On Cyclecloud - Microsoft Azure

  6. Quickly build HPC compute environments on AWS - AWS ParallelCluster

  7. Batch - Google Cloud

  8. 弹性高性能计算E-HPC_超算云_高性能计算_弹性计算-阿里云

  9. 高性能计算平台简介_高性能计算平台购买指南_高性能计算平台操作指南-腾讯云

把云原生带入生物信息学
https://www.juniortree.com/blog/bring-cloud-native-into-bioinfo
Author liueic
Published at 2025年11月14日
Comment seems to stuck. Try to refresh?✨