为什么HPC环境更推荐Singularity而非Docker?CentOS7.9实战安装教程
为什么HPC环境更推荐Singularity而非Docker?CentOS7.9实战安装教程
如果你在高校的计算中心、研究所的集群或者任何高性能计算(HPC)环境中工作过,大概率会听过一个共同的抱怨:“为什么Docker在这里用起来这么别扭?” 这背后不是Docker技术本身的问题,而是HPC独特的管理模式和安全边界,与Docker的设计哲学产生了根本性的碰撞。对于需要处理基因组数据、气候模拟或者高能物理实验的研究人员来说,一个既能让用户自由携带软件环境,又不会让系统管理员夜不能寐的容器方案,才是真正的刚需。这正是Singularity(及其社区版SingularityCE)脱颖而出的地方。它不是要取代Docker,而是在一个特定的、要求严苛的领域——HPC——提供了一个更贴合的解决方案。今天,我们就来深入聊聊这背后的技术选型逻辑,并手把手带你在一台经典的CentOS 7.9系统上,从零开始部署Singularity。
1. 理解HPC的独特生态:为何Docker在此“水土不服”
在谈论具体技术之前,我们必须先理解HPC环境的运行规则。它不像我们个人开发的云服务器,更像一个高度协同、资源共享且安全隔离严密的“数字实验室”。
核心矛盾点在于权限模型。Docker的守护进程(dockerd)默认需要root权限运行。这意味着,普通用户想要启动一个容器,实际上是通过与root权限的守护进程通信来完成的。在HPC集群中,将root权限开放给用户(哪怕是间接通过守护进程)是系统管理员的大忌。这直接带来了几个无法回避的问题:
- 安全风险:用户容器内的进程理论上可以逃逸并获取宿主机
root权限,这对于存放着未发表科研数据、珍贵实验结果的集群来说是致命威胁。 - 权限冲突:HPC作业调度系统(如Slurm、PBS)以用户身份提交和运行任务。Docker容器默认以
root内部身份运行,这会导致容器内生成的文件所有权是root:root,与调度系统期望的用户身份不符,造成后续文件访问和清理的混乱。 - 资源管理脱节:HPC调度器精细地管理着CPU、内存、GPU等资源。Docker容器自己有一套资源限制机制(
--cpus,--memory),两者容易产生冲突或管理盲区,可能导致单个任务耗尽节点资源,影响其他用户。
注意:这并不是说Docker不安全,而是在多租户、强隔离、共享资源的HPC场景下,其基于守护进程的架构引入了不必要的复杂性和风险面。
相比之下,Singularity从设计之初就瞄准了这些痛点。它的运行不需要任何守护进程,用户直接以自身身份执行容器镜像。你可以把它理解为一个特殊的、封装了完整环境的可执行文件。这个设计带来了几个立竿见影的好处:
- 用户级运行:用户
alice运行Singularity容器,容器内的进程在宿主机上看到的UID/GID就是alice。文件权限问题迎刃而解。 - 无缝集成调度器:Slurm脚本中直接调用
singularity exec,就像调用python或mpirun一样自然,所有资源都由调度器统一管理。 - 安全性提升:容器默认以非特权模式运行,且提供了多种安全选项(如
--containall,--fakeroot),在便利和安全之间提供了灵活的选择。
为了更直观地对比两者在HPC语境下的关键差异,可以参考下表:
| 特性维度 | Docker | Singularity | HPC场景影响分析 |
|---|---|---|---|
| 运行权限 | 需要root权限的守护进程 | 直接以用户身份运行 | Singularity避免了特权提升风险,符合HPC最小权限原则。 |
| 文件系统集成 | 默认隔离,需显式挂载卷 | 默认挂载用户家目录、临时目录等 | Singularity默认行为更符合科研人员交互式使用习惯,数据访问更便捷。 |
| 与调度器集成 | 复杂,通常需要额外封装或插件 | 简单,可直接嵌入作业脚本 | Singularity大大降低了在Slurm/PBS中使用容器的门槛。 |
| 镜像格式 | Docker镜像(OCI标准) | SIF(Singularity Image Format) | Singularity可直接拉取Docker镜像并转换为SIF,兼容性好。SIF是单文件,易于分发和校验。 |
| 主要设计目标 | 微服务、开发运维 | 科学计算、可重复性研究 | 目标不同导致架构取舍不同,Singularity更贴合科研工作流。 |
理解了“为什么选Singularity”,接下来我们就进入实战环节。CentOS 7.9作为一款依然广泛存在于科研机构中的稳定系统,是部署Singularity的典型环境。
2. 实战准备:CentOS 7.9基础环境配置
在开始编译安装Singularity之前,我们需要一个“干净”且具备编译能力的系统环境。假设你已经拥有一台安装了CentOS 7.9的服务器或虚拟机,并以root用户登录。以下步骤将为你搭建好编译舞台。
首先,更新系统并安装核心的开发工具集。这一步确保了我们有最新的软件包和完整的编译链(如gcc, make, autoconf等)。
yum update -y
yum groupinstall -y 'Development Tools'
接下来,安装Singularity编译和运行时所需的特定依赖库。这些库涵盖了从加密、UUID生成到安全容器(seccomp)和镜像文件系统(squashfs)的各个方面。
yum install -y openssl-devel \
libuuid-devel \
libseccomp-devel \
wget \
squashfs-tools \
cryptsetup
- openssl-devel: 提供加密和证书相关功能支持。
- libuuid-devel: 用于生成唯一标识符。
- libseccomp-devel: 关键的安全组件,允许程序限制可用的系统调用,是容器安全的基础。
- squashfs-tools: 用于处理SIF镜像内部使用的squashfs文件系统。
- cryptsetup: 为容器加密功能提供支持(如果未来需要)。
完成上述步骤后,你的系统就已经具备了编译Singularity的所有底层依赖。我们可以进入下一个关键环节:配置Go语言环境。
3. 搭建构建引擎:安装Go语言环境
Singularity是用Go语言编写的,因此我们需要Go编译器来从源码构建它。这里我们选择手动安装特定版本的Go,以获得更好的版本控制。
第一步:下载和解压Go
访问Go官方下载页面(例如 https://go.dev/dl/),根据你的系统架构选择对应的版本。对于x86_64架构的CentOS 7.9,我们通常选择类似 go1.24.2.linux-amd64.tar.gz 的版本。你可以直接在服务器上用wget下载,如果网络不稳定,也可以先下载到本地再上传。
# 假设你将安装包上传到了 /root 目录
cd /root
tar -zxvf go1.24.2.linux-amd64.tar.gz -C /usr/local
这里我们将Go解压到了/usr/local目录下,解压后会生成一个go文件夹。
第二步:配置环境变量
为了让系统识别go命令,需要将Go的二进制文件路径添加到系统的PATH环境变量中,同时设置GOROOT。编辑/etc/profile文件(对所有用户生效)或~/.bashrc文件(对当前用户生效),这里我们以/etc/profile为例:
echo 'export GOROOT=/usr/local/go' >> /etc/profile
echo 'export PATH=$GOROOT/bin:$PATH' >> /etc/profile
然后让配置立即生效:
source /etc/profile
第三步:验证安装 执行以下命令,检查Go是否安装成功:
go version
如果安装正确,你会看到类似 go version go1.24.2 linux/amd64 的输出。至此,我们的“构建引擎”就准备就绪了。
4. 从源码编译与安装SingularityCE
我们选择从GitHub发布页下载SingularityCE(Community Edition)的源码进行编译,这样可以确保获得特定版本,并且过程透明可控。
第一步:下载源码
前往SingularityCE的GitHub Release页面(例如 https://github.com/sylabs/singularity/releases),找到你想要的稳定版本。例如,我们选择 singularity-ce-4.3.0.tar.gz。同样,下载并上传到服务器。
cd /root
tar -zxvf singularity-ce-4.3.0.tar.gz
cd singularity-ce-4.3.0
第二步:配置编译选项
Singularity提供了一个灵活的配置脚本 ./mconfig。对于大多数HPC环境,我们采用一个比较标准的配置。--without-libsubid 选项表示不编译需要较新内核支持的子UID/GID映射功能,在CentOS 7.9的内核上通常更稳定。
./mconfig --prefix=/usr/local --without-libsubid
--prefix=/usr/local: 指定安装目录为/usr/local,这是类Unix系统安装本地软件的常见位置。- 执行
./mconfig后,它会在当前目录下生成一个builddir目录,里面包含了定制化的Makefile。
第三步:编译与安装 这是一个需要一些时间的步骤,具体取决于你的服务器CPU性能。
make -C builddir
make -C builddir install
make -C builddir 会启动编译过程。完成后,make -C builddir install 会将编译好的二进制文件、库文件和手册页安装到/usr/local指定的目录下。
第四步:验证安装并尝试运行 安装完成后,验证一下:
singularity --version
如果成功,你会看到 singularity-ce version 4.3.0。现在,你可以尝试拉取一个简单的Docker镜像来测试功能。例如,拉取一个Alpine Linux的镜像并运行一个简单的命令:
# 拉取Docker Hub上的alpine镜像并转换为SIF格式
singularity pull docker://alpine:latest
# 运行容器,执行`cat /etc/os-release`命令
singularity exec alpine_latest.sif cat /etc/os-release
如果一切顺利,你将看到Alpine Linux的系统信息。这表明你的Singularity已经可以正常工作,并且能够无缝使用庞大的Docker镜像生态。
5. 超越安装:HPC中的典型工作流与进阶配置
安装只是第一步。要让Singularity真正在HPC环境中发挥作用,我们需要了解如何将其融入日常科研工作流。
与Slurm调度器的集成 这是最常见的场景。你的作业脚本(submit.sh)可能会是这样:
#!/bin/bash
#SBATCH --job-name=my_singularity_job
#SBATCH --nodes=1
#SBATCH --ntasks-per-node=4
#SBATCH --time=01:00:00
# 加载必要的环境模块(如果有)
# module load singularity/4.3.0
# 定义容器镜像路径(假设已提前下载到共享存储)
SIF_FILE="/shared/containers/my_pytorch.sif"
# 运行容器内的Python脚本,使用所有分配的CPU
srun singularity exec --nv $SIF_FILE python /path/to/your/script.py
--nv参数用于在容器内启用NVIDIA GPU支持,如果你的计算涉及GPU加速,这个参数至关重要。srun是Slurm的命令,用于在分配的节点和核心上并行执行任务。Singularity命令作为其参数,实现了完美的资源绑定。
构建自定义镜像 虽然可以直接使用Docker镜像,但为特定科学计算任务构建优化的SIF镜像也是常事。你有几种方式:
-
使用Definition File(推荐):创建一个名为
myimage.def的文本文件来定义镜像内容,然后构建。Bootstrap: docker From: ubuntu:22.04 %post apt-get update && apt-get install -y python3 python3-pip pip3 install numpy scipy pandas %runscript exec python3 "$@" # 构建镜像 sudo singularity build myimage.sif myimage.def注意,构建最终镜像(
build命令)通常需要sudo权限,因为这涉及挂载循环设备等操作。但构建完成后,普通用户就可以无特权运行这个.sif文件。 -
交互式沙盒开发:对于复杂的、需要反复调试的镜像,可以创建一个可写的沙盒目录进行交互式修改,最后再编译成不可变的SIF文件。
# 从Docker镜像创建一个沙盒目录 sudo singularity build --sandbox ./my_sandbox docker://centos:7 # 以可写模式进入沙盒(需要sudo) sudo singularity shell --writable ./my_sandbox # 在沙盒内进行各种安装配置... # 退出后,将沙盒构建为最终的SIF镜像 sudo singularity build final_image.sif ./my_sandbox
性能与存储考量
在HPC中,容器镜像的存储位置很有讲究。将常用的、较大的SIF文件放在全局共享的并行文件系统(如Lustre, GPFS)上,可以让所有计算节点快速访问,避免每个节点重复下载。但同时要注意,大量小文件IO可能会对元数据服务器造成压力。一个最佳实践是,对于极度追求IO性能的应用,可以考虑在作业开始时,将SIF文件从共享存储复制到计算节点的本地SSD(通过$SLURM_TMPDIR),然后在本地运行。
最后,记得查阅官方文档来探索更多强大功能,例如使用singularity cache管理本地缓存来节省磁盘空间,或者利用singularity instance来启动长期运行的服务型容器。Singularity的生态正在不断成熟,它已经成为连接科学软件复杂依赖与HPC严谨管理环境之间那座最可靠的桥梁。当你第一次在Slurm作业中轻松跑起一个曾经需要折腾半天环境依赖的软件时,就会明白这种选择的价值所在。
更多推荐



所有评论(0)