抱歉,您的浏览器无法访问本站
本页面需要浏览器支持(启用)JavaScript
了解详情 >

在做生信分析的时候,难免会遇到一个pipeline上的软件存在冲突的情况,一般的解决方法是创建不同的conda环境,然后分别在不同的环境下跑不同的软件。这种操作可以解决环境冲突的问题但不适合写流程化的脚本,同时又非常占用空间。有的软件整合了pipeline流程的所有软件,按照顺序进行调用,这种软件虽然可以节省时间实现自动化分析,但是环境依赖的问题更加复杂,因此这一类的软件也往往提供容器来方便人们在一个封闭的环境中使用。

这篇博客主要讲一讲关于容器的一些基本常识,以及记录下学校集群中singularity的使用方法。

1. 容器(Container)

前面说到为了规避软件与现有环境依赖冲突,我们往往会把一个pipeline的软件封装到一个容器中。容器是一种在Linux系统上广泛采用的应用封装技术,它将可执行程序与依赖库打包成一个镜像文件,启动时与宿主节点共享操作系统内核。

镜像(Image):可执行的独立软件包,用于保存环境

实例(Instance):基于镜像启动的运行实例,运行实际任务,不同实例之间互相隔离

由于这个镜像文件自带了可执行文件和依赖库,因此不需要用到宿主机的依赖库,也就从源头上避免了环境冲突的情况。听起来这种实现方式类似于虚拟化技术,但还是有一些区别的:前面说过容器启动时与宿主机共享操作系统内核,没有运行独立的操作系统任务,在资源的占用上明显低于虚拟机。虚拟化可以认为它更全面和彻底一些,每个虚拟机从宿主机的物理框架中分割出来,有自己的一整套操作系统,会运行各种独立的操作系统任务,即使没有运行程序也会消耗内存和系统资源。

上图来自Microsoft Azure容器与虚拟机的比较。总结来说,在安全性和隔离性上虚拟机优于容器,在资源占用、可移植性和运行速度上,容器优于虚拟机。

现有的容器软件比较多,Docker(5.8k star)是代表性的软件之一,其他开源容器化工具还有Podman(17.4k star,无守护进程的容器技术,无需root权限)、LXD(3.8k star,可运行多个进程)、Apptainer(以前叫singularity,2.4k star,无需root权限)、Containerd(13.5k star)和RunC(10.1k star)等。

这些开源的容器化技术软件各有其特点,详情可以点各自的链接了解,这里就不过多介绍了。主要说下塔大集群部署的singularity(现在已改名为Apptainer,很多人不知道改名了,两个名字就放一块儿说)的使用方法。

2. Apptainer/Singularity

首先还是要说明以一下什么时候选择用容器,并不是说每一个软件都要用容器封装——反而这样是对系统资源的浪费。一般是在需要批量部署环境、或者快速部署一个pipeline环境的时候选择用容器。在HPC上进行大规模计算的时候,一般考虑安全性不会用Docker(需要root权限),Apptainer/Singularity这种无需root权限的容器工具是最好的选择。

需要说明一下,两年前Singularity改名为Apptainer,并且整个项目已经转移成为了Linux Foundation的一部分。Apptainer用法和Singularity几乎一模一样,可以参考
https://apptainer.org/docs/user/latest/quick_start.html
https://docs.sylabs.io/guides/latest/user-guide/quick_start.html#
两个官方手册。因为塔大超算预装了singularity,以下统一用Singularity命令来讲解。

Singularity的镜像文件以.sif为后缀(Singularity Image File, SIF),且该文件是只读的,这和Docker镜像文件有本质上的区别。

2.1 使用镜像库获取镜像文件

Singularity image文件是基于Docker image创建的:

1
2
3
4
5
6
7
singularity -d build braker3.sif docker://teambraker/braker3:latest
# 可以获取的镜像文件库(云平台)有以下几种
# Sylabs cloud library library://
# Docker docker://
# Shub shub://
# OCI registry oras://
# 创建之后的文件名为braker3.sif

build/pull 这两个命令都可以拉取镜像文件并创建为singularity的sif文件

创建的image路径、名字都可以在-d参数后根据需要自己改

当一个软件提供docker镜像,我们就可以通过上面的方法下载并创建一个singularity镜像,需要注意这个镜像文件是只读的

2.2 创建自定义镜像文件

这里顺带提一下如何制作自定义的SIF镜像文件:

1
2
3
4
5
6
7
8
singularity -d build --sandbox ubuntu/ docker://ubuntu
# 以沙盒的形式创建一个空的操作系统,放在ubuntu这个文件夹中

singularity shell --writable ubuntu
# --writable或者-w以可修改模式进入沙盒。也可以不用这种方法进入,直接进入对应的文件位置修改即可

singularity build name.sif ubuntu
# 创建sif镜像文件

进入沙盒,就可以和正常的linux操作系统一样进行安装软件,最后build制作成名为name.sif的singularity镜像,和2.1从镜像库拉取创建的镜像后续是一样的用法。

第二步以可修改模式进入沙盒时可能会有如下提示:

1
2
WARNING: By using --writable, Singularity can't create /public destination automatically without overlay or underlay
FATAL: container creation failed: mount /var/singularity/mnt/session/public->/public error: while mounting /var/singularity/mnt/session/public: destination /public doesn't exist in container

无法自动创建public这个文件夹,并且进入/var/singularity/mnt/session/这个文件夹下你会发现是空的,此时需要手动在你创建ubuntu的文件夹中创建public文件夹 mkdir public,提示缺少其他文件也是一样的处理方法,缺啥创建啥,就可以正常进入了。

需要注意,塔大集群无法制作sif镜像文件!!!会在最后一步build的时候提示permission denied,因此,创建自定义镜像文件要在自己的计算机上(拥有root权限),制作完成之后的sif镜像文件可以上传到集群中再运行。

2.3 运行镜像文件

singularity主要有两种运行方式,一种是执行镜像文件中的命令 singularity exec;一种是进入交互模式singularity shell

1
2
3
4
5
singularity exec name.sif test/test.pl 
# 运行name.sif镜像文件中test文件夹下的test.pl程序

singularity shell name.sif
# 以交互模式进入name.sif镜像文件

需要注意,运行镜像文件后,singularity会自动挂载当前目录$PWD、用户家目录$HOME和宿主机的/tmp目录,对这些目录的文件进行修改会影响到原文件。对于一般的程序来说已经足够了,如果需要访问宿主机的其他目录,需要用--bind将宿主机目录映射到容器内。

1
2
3
4
5
singularity exec --bind /pub/software:/mnt name.sif python test.py
# --bind挂载宿主机的文件夹,冒号前为宿主机的路径,冒号后为容器中的路径。内容挂载到/mnt中

singularity exec --bind /pub/software name.sif python test.py
# 不写挂载点,则与宿主机的目录一致。内容挂载到/pub/software中

2.4 在集群中提交singularity作业

一般来说登录节点预装了singularity,计算节点也会装singularity才对,但是无论我直接用singularity命令还是指定singularity命令的绝对路径,在sbatch提交作业后都是提示该命令不存在。很疑惑,又去查了一些资料,发现有的平台需要在作业里module load singularity之后才可以加载,但是塔大集群用这个指令仍然行不通,只有本地(登录节点)才可以使用该命令。

百思不得其解,询问集群管理员暂时没有答复,后续有新消息会更新。这里说一下我的解决方法:

既然可以在本地运行singularity,那就可以用salloc申请计算资源,在本地跑程序。但是我又不可能一直坐在电脑跟前,因此需要用到screen这个工具维持当前会话。

1
2
3
4
5
6
7
8
9
10
11
screen -S test
# 创建名为test的session对象

salloc -n 50 -t 7200
# 申请50核的计算资源

export BRAKER_SIF=\$PWD/braker3.sif
# 给host添加环境变量(非必须,打个比方)

singularity esec braker3.sif braker.pl
# 运行容器中的程序

运行之后就可以双手离开键盘,关上电脑,等待第二天程序运行结束了。

再次打开session的时候只需要运行如下命令:

1
2
3
4
5
6
7
8
screen -r test
# 再次打开session

exit
# 退出session

exit
# 释放计算资源

注意需要两次exit之后才会回到原来的登录节点。

singularity还有很多其他参数,对我而言暂时用不到,需要用的时候再更新。

可以参考武大超算中心的文档运行 Singularity · GitBook (whu.edu.cn)和北鲲云的介绍文档https://www.cloudam.cn/helpce/docs/2030/about2/。
(可恶,我们学校集群什么时候能出一个详细的文档啊。好想吐槽,slurm调度系统和各种软件都要自己学,功能还不一定全,也不知道到底预装了哪些东西,以后要是我来管理集群一定会做详细的文档介绍所有花里胡哨的功能,而不是藏着不告诉用户)

2023.3.29更新

破案了,计算节点确实没装singularity(噎住.jpg)

欢迎小伙伴们留言评论~