介绍
Singularity是和docker相似的容器化软件。由于在部署Cromwell调度WDL流程时,运行docker失败。看了下文档说是集群无法支持docker,需要使用singularity。
Singularity的sif格式支持直接从docker image中转换过来,因此流程的迁移还是比较方便的。考虑到学习成本,我大概还是只会使用docker来build镜像,再用singularity来部署。在集群中使用singularity,日常普通任务时使用docker。
安装singularity
使用root权限安装,安装文档参阅。
安装依赖,我用的是centos,如果没有找到就先使用国内的源进行更新。
# yum clean all && yum makecache
yum groupinstall -y 'Development Tools'
yum install -y epel-release
yum install -y golang libseccomp-devel squashfs-tools cryptsetup
然后使用rpm安装,安装时由于国内网络原因,无法连接GO服务器进行校对,会报超时错误,但是貌似没有影响。
yum install -y rpm-build
export VERSION=3.8.0
wget https://github.com/hpcng/singularity/releases/download/v${VERSION}/singularity-${VERSION}.tar.gz
rpmbuild -tb singularity-${VERSION}.tar.gz
rpm -ivh ~/rpmbuild/RPMS/x86_64/singularity-${VERSION}-1.el7.x86_64.rpm
rm -rf ~/rpmbuild singularity-${VERSION}*.tar.gz
使用singularity
创建镜像
singularity -d build ubuntu.sif docker://ubuntu:latest
拉取镜像
singularity pull sub://ubuntu:latest
# 从docker hub中pull
singularity pull docker://ubuntu:latest
# pull并保存镜像文件
singularity pull ubuntu.latest.sif sub://ubuntu:latest
使用镜像
# shell方法
singularity shell ubuntu.latest.sif
# -B 参数与docker run的-v参数类似
singularity shell -B /data:/data ubuntu.latest.sif
# run方法
singularity run ubuntu.latest.sif
# exec方法
singularity exec --containall --bind ${cwd}:${docker_cwd} ubuntu.latest.sif /bin/bash script.sh
singularity shell的一个特点是从什么用户进去,外部权限就会是什么用户的,也就是说,在container内新建一个文件夹,对应的外部文件夹权限是属于当时创建container的外部用户的。另外,shell方法只要使用了exit,container就会退出且删除,相当于docker的run –rm。使用-B绑定多个目录时,可用”,”分隔。
查看运行的container,相当于docker ps -l。另外,如果使用分别用普通用户和root用户的instance start创建,在查询list时也是分开的,就是说普通用户instance list是查不到root用户的instance list的。
singularity instance list
singularity instance start <name>
singularity instance stop <name>
Cromwell config
cromwell的config文件中,对于singularity配置的简单写法如下
include required(classpath("application"))
backend {
default: singularity
providers: {
singularity {
actor-factory = "cromwell.backend.impl.sfs.config.ConfigBackendLifecycleActorFactory"
config {
run-in-background = true
runtime-attributes = """
String? docker
"""
submit-docker = """
singularity exec --containall --bind ${cwd}:${docker_cwd} docker://${docker} ${job_shell} ${docker_script}
"""
}
}
}
}
合并slurm集群的配置可看Cromwell的文档。不要参考Cromwell的github仓库中的例子,那个例子有问题。
由于我将所有docker image都通过singularity转格为sif保存,我是这样改的
backend {
default = slurm
providers {
slurm {
actor-factory = "cromwell.backend.impl.sfs.config.ConfigBackendLifecycleActorFactory"
config {
runtime-attributes = """
Int runtime_minutes = 600
Int cpus = 2
Int requested_memory_mb_per_core = 8000
String? docker
"""
submit = """
sbatch --wait \
-J ${job_name} \
-D ${cwd} \
-o ${out} \
-e ${err} \
-t ${runtime_minutes} \
${"-c " + cpus} \
--mem-per-cpu=${requested_memory_mb_per_core} \
--wrap "/bin/bash ${script}"
"""
submit-docker = """
export SINGULARITY_CACHEDIR=/path/to/your/singularity_cache
CACHE_DIR=$SINGULARITY_CACHEDIR
DOCKER_NAME=$(sed -e 's/[^A-Za-z0-9._-]/_/g' <<< ${docker})
IMAGE=$CACHE_DIR/$DOCKER_NAME.sif
if [ ! -f $IMAGE ]; then
singularity pull $IMAGE docker://${docker}
fi
sbatch \
--wait \
-J ${job_name} \
-D ${cwd} \
-o ${cwd}/execution/stdout \
-e ${cwd}/execution/stderr \
-t ${runtime_minutes} \
${"-c " + cpus} \
--mem-per-cpu=${requested_memory_mb_per_core} \
--wrap "singularity exec --containall --bind ${cwd}:${docker_cwd} $IMAGE ${job_shell} ${docker_script}"
"""
kill = "scancel ${job_id}"
check-alive = "squeue -j ${job_id}"
job-id-regex = "Submitted batch job (\\d+).*"
}
}
}
}