|
| 1 | +# 【小记】在 Google Colab 上基于 Apptainer 运行 GPU 容器 |
| 2 | + |
| 3 | +最近想到了可能的创新点,准备开始做实验了。在前期我准备先薅一波提供免费 GPU 运算资源的平台的羊毛,但这些平台提供的免费时长并不多,可能这家配额跑完了就要换下家,如果每次都要重新搭建环境多少有些不方便。 |
| 4 | + |
| 5 | + |
| 6 | + |
| 7 | +那咱用容器化技术不就行啦!直接把环境打包成镜像,哪个平台都能跑。 |
| 8 | + |
| 9 | +比起 Docker,这回咱决定采用**更为轻量的** Apptainer(前身为 Singularity): |
| 10 | + |
| 11 | +* Apptainer 默认以普通用户的身份运行容器,无需类似于 root 用户的特权,不像 Docker Daemon 那样必须要运行在特权用户下。(因而更安全,也更容易安装部署,不会有什么权限问题) |
| 12 | +* Apptainer 针对高性能计算(HPC)这种并行场景进行了优化(虽然我还不太用得上)。 |
| 13 | +* Apptainer 支持 Docker 镜像,体验上近乎无缝(这个是最爽滴)。 |
| 14 | + |
| 15 | +这篇笔记主要记录一下咱在 Google Colab 上基于 Apptainer 运行 GPU 容器时的踩坑和爬出坑的过程。 |
| 16 | + |
| 17 | +## 1. 安装 Apptainer |
| 18 | + |
| 19 | +这里不多赘述,图快的话咱主要推荐以下两种安装方式: |
| 20 | + |
| 21 | +### 1.1. 利用官方脚本安装 |
| 22 | + |
| 23 | +* [官方文档](https://apptainer.org/docs/admin/1.3/installation.html#install-unprivileged-from-pre-built-binaries) |
| 24 | + |
| 25 | +注:文档中提到在执行脚本前可能需要安装 `curl`, `cpio`, `rpm2cpio` 等必要的工具: |
| 26 | + |
| 27 | +```bash |
| 28 | +sudo apt-get update |
| 29 | +# rpm2cpio 是 rpm 包的工具 |
| 30 | +sudo apt-get install -y curl cpio rpm |
| 31 | +``` |
| 32 | + |
| 33 | + |
| 34 | +### 1.2. 利用包管理器安装 |
| 35 | + |
| 36 | +* [官方文档](https://apptainer.org/docs/admin/1.3/installation.html#install-ubuntu-packages) |
| 37 | + |
| 38 | +Colab 默认是 Ubuntu 系统,copy 官方文档中的命令就能顺利安装了~ |
| 39 | + |
| 40 | +## 2. 尝试跑一下 hello-world 镜像 |
| 41 | + |
| 42 | +### 2.1. 构建 .sif 文件 |
| 43 | + |
| 44 | +Apptainer 可以直接拉取 Docker Hub 上的镜像并构建成 `.sif` 单文件: |
| 45 | + |
| 46 | +```bash |
| 47 | +apptainer build hello.sif docker://hello-world |
| 48 | +``` |
| 49 | + |
| 50 | + |
| 51 | + |
| 52 | +### 2.2. 建立普通用户 |
| 53 | + |
| 54 | +Colab 默认在 root 用户下执行命令,这里建立一个普通用户 `somebottle` : |
| 55 | + |
| 56 | +```bash |
| 57 | +adduser --home /home/somebottle --gecos "" --shell /bin/bash --disabled-password somebottle |
| 58 | +``` |
| 59 | + |
| 60 | +* root 用户当然是可以运行 Apptainer 容器的,但为了安全起见,咱接下来会尝试用普通用户来运行容器。 |
| 61 | + |
| 62 | +### 2.3. 启动容器 |
| 63 | + |
| 64 | +Colab **对 root 用户的权限有所限制**,如果直接尝试启动容器会出现挂载问题: |
| 65 | + |
| 66 | +```bash |
| 67 | +apptainer run hello.sif |
| 68 | +# >> FATAL: container creation failed: mount hook function failure: mount overlay->/var/lib/apptainer/mnt/session/final error: while mounting overlay: can't mount overlay filesystem to /var/lib/apptainer/mnt/session/final: while setting effective capabilities: CAP_DAC_READ_SEARCH is not in the permitted capability set |
| 69 | +``` |
| 70 | + |
| 71 | +* 相关 issue:https://github.com/apptainer/apptainer/issues/1041 |
| 72 | + |
| 73 | +利用 `setcap` 进行权限设定还是麻烦了,这里我根据 issue 中的指引,直接在一个新的**命名空间**下运行了容器: |
| 74 | + |
| 75 | +```bash |
| 76 | +# 在 root 用户下执行这条命令,容器内用户为 root |
| 77 | +unshare -r apptainer run hello.sif |
| 78 | +``` |
| 79 | +> `unshare -r` 建立一个新的**用户命名空间**,并把当前用户映射为命名空间内的 root 用户,这个命名空间内的进程将会默认拥有完整的 capabilities 权限集。 |
| 80 | +
|
| 81 | +* 💡 注:如果在 root 用户下执行上面这条命令,其实仍然相当于在特权用户下启动了容器。 |
| 82 | + |
| 83 | +--- |
| 84 | + |
| 85 | +✨ 或者**以普通用户的身份**运行容器: |
| 86 | + |
| 87 | +```bash |
| 88 | +# 以 somebottle 身份启动容器,容器内用户为 somebottle |
| 89 | +sudo -u somebottle apptainer run hello.sif |
| 90 | +``` |
| 91 | + |
| 92 | +> Apptainer 默认借助用户命名空间来运行容器,系统应支持以非特权方式建立用户命名空间,经测试 Colab 已经满足了这点。具体要求可查看[文档](https://apptainer.org/docs/admin/1.3/user_namespace.html)。 |
| 93 | +
|
| 94 | +--- |
| 95 | + |
| 96 | +✨ 为了能**让普通用户在容器内以 root 用户的身份运行**,可以加上 `--fakeroot` 选项: |
| 97 | + |
| 98 | +```bash |
| 99 | +# 以 somebottle 身份启动容器,容器内用户为 root |
| 100 | +sudo -u somebottle apptainer run --fakeroot hello.sif |
| 101 | +``` |
| 102 | + |
| 103 | +具体行为可见[官方文档](https://apptainer.org/docs/user/1.3/fakeroot.html)说明。 |
| 104 | + |
| 105 | + |
| 106 | + |
| 107 | + |
| 108 | +TODO: sudo -E -u somebottle <command> ,这里 -E 的作用是否需要阐释。注:新的用户命名空间建立时默认会**继承**当前进程的环境变量。 |
| 109 | + |
| 110 | + |
| 111 | + |
| 112 | + |
| 113 | + |
| 114 | + |
| 115 | + |
| 116 | + |
0 commit comments