Slurm作业调度系统在容器中的应用

内容:

● 在容器中的Slurm
● Slurm容器支持
○ sbatch/salloc/srun --container
● scrun
○ 容器运行时可以通过scrun向Slurm提交作业
■ 用户无法直接看到Slurm
○ 使用Docker的示例
○ 使用Podman的示例

Slurmd守护进程可以在容器中运行 

● slurmctld、slurmdbd和mysql已经能够在容器中运行
● slurmd现在可以在容器中运行(23.02)
○ 需要cgroup v2
○ 在特权模式下对cgroup v1的支持有限(并不理想)

Slurm如何运行容器:sbatch/salloc/srun --container

Slurm容器支持

● 添加了‘--container’(21.08)支持,用于以下命令:
○ srun
○ salloc
○ sbatch

● 添加了查看作业容器[包路径](21.08)和容器ID(23.02)功能,适用于以下命令:
○ scontrol show jobs
○ scontrol show steps
○ sacct
■ 如果作为“--format”参数的一部分传递,使用“Container”
○ slurmd、slurmstepd、slurmdbd和slurmctld的日志(太多地方无法一一列举)

 srun示例

 $ srun --container=/tmp/centos grep ^NAME /etc/os-release
 NAME="CentOS Linux"

 salloc示例

$ salloc --container=/tmp/centos grep ^NAME /etc/os-release
 salloc: Granted job allocation 65
 NAME="CentOS Linux"
 salloc: Relinquishing job allocation 65

sbatch示例

 $ sbatch --container=/tmp/centos --wrap 'grep ^NAME /etc/os-release'
 Submitted batch job 24419
 $ cat slurm-24419.out
 NAME="CentOS Linux"
 $srun --container ~/oci_images/alpine/ uptime
 srun: job 13772 queued and waiting for resources
 srun: job 13772 has been allocated resources
 17:12:33 up 2 days, 20:27,  0 users,  load average: 1.78, 3.42, 3.44
$sacct --format=jobid,container%40
 13772                    /home/scott/oci_images/alpine/ 
13772.extern                                          
13772.0                /home/scott/oci_images/alpine/
 $scontrol show jobs | grep -i -E 'container|jobid'
 JobId=13772 JobName=uptime
 Container=/home/scott/oci_images/alpine/ ContainerID=(null)

● 如果在容器外部能够正常运行,则在容器内部也应该能够正常运行
○ Slurm的cgroups功能适用于容器
○ 目前Slurm只支持非特权容器
○ 容器必须能够在现有主机网络中正常运行

● 通过/etc/slurm/中的‘oci.conf’进行每个主机的配置
○ slurm.schedmd.com/oci.conf.html

● 环境变量SLURM_CONTAINER(22.05)和SLURM_CONTAINER_ID(23.02)将始终设置一个值(如果存在)

容器运行时如何向Slurm提交作业:scrun

使用Slurm用户命令前端

OCI运行时代理 - scrun

● scrun的目标是使Slurm对运行Docker/Podman的用户透明
○ 用户直接与OCI运行时客户端(Docker、Podman、Podman-HPC等)接口
○ 更容易让已经熟悉Docker/Podman的用户上手
○ 站点管理员需要对配置进行设置和维护

● 利用Slurm现有基础设施在计算节点上运行容器
● 允许用户使用他们想要的工具,同时在Slurm集群上运行工作
● scrun是一个新的CLI命令,加入了srun、sbatch和salloc,但用户应该永远不需要直接调用它,甚至不需要真正意识到它的存在
○ scrun仍然相对较新,我们欢迎提交关于增强功能的请求和特别是错误报告的工单
● 结束了用户在计算节点上手动准备镜像的要求
○ 我们建议使用网络文件系统
○ 我们还可以选择实现容器的自动装入和卸载
■ Lua
■ SPANK
● scrun并不打算直接由用户调用

 通过无根(Rootless)Docker(23.02)的scrun

例如:

 $ export DOCKER_HOST=unix://$XDG_RUNTIME_DIR/docker.sock
 $ export DOCKER_SECURITY=”--security-opt label:disable --security-opt 
seccomp=unconfined  --security-opt apparmor=unconfined --net=none”
 $ docker run $DOCKER_SECURITY -i ubuntu /bin/sh -c 'grep ^NAME /etc/os-release'
 NAME="Ubuntu"
 $ docker run $DOCKER_SECURITY -i centos /bin/sh -c 'grep ^NAME /etc/os-release'
 NAME="CentOS Linux"

无根(Rootless)Docker进程树

 无根(Rootless)Docker配置(23.02)

 ~/.config/docker/daemon.json
 {
  "default-runtime": "slurm",
  "runtimes": {
    "slurm": {
      "path": "/usr/local/slurm/sbin/scrun"
    }
  },
 "experimental": true,
  "iptables": false,
  "bridge": "none",
  "no-new-privileges": true,
  "rootless": true,
  "selinux-enabled": false
 }

通过无根(Rootless)Podman的scrun(23.02)

例如:

 $ podman run ubuntu /bin/sh -c 'grep ^NAME /etc/os-release'
 NAME="Ubuntu"
 $ podman run centos /bin/sh -c 'grep ^NAME /etc/os-release'
 NAME="CentOS Linux"
 $ podman run centos /bin/sh -c 'printenv SLURM_JOB_ID'
 77
 $ podman run centos /bin/sh -c 'printenv SLURM_JOB_ID'
 78

Podman进程树

 用于scrun的Podman配置(23.02)

 ~/.config/containers/containers.conf:
 [containers]
 apparmor_profile = "unconfined"
 cgroupns = "host"
 cgroups = "enabled"
 default_sysctls = []
 label = false
 netns = "host"
 no_hosts = true
 pidns = "host"
 utsns = "host"
 userns = "host"
 [engine]
 runtime = "slurm"
 runtime_supports_nocgroups = [ "slurm" ]
 runtime_supports_json = [ "slurm" ]
 remote = false
 [engine.runtimes]
 slurm = [ "/usr/local/slurm/sbin/scrun" ]

Questions?

● Documentation: ○ https://slurm.schedmd.com/containers.html

附录1:scrun的限制 

scrun - 限制(23.02)

● 完全支持在 scrun 中使用注释 ○ 注释不会记录在 Slurm 的会计中 - 在 sacct/sreport 中不会显示 ○ 注释不被 slurmctld 识别 - 在使用 scontrol 显示作业/步骤时不会显示

● slurm-23.02 中不支持网络命名空间 ○ 所有容器必须在主机网络下运行 ○ Slurm 没有与网络命名空间相关的设计限制。这只是尚未实施的功能。

■ 欢迎用户提交 RFE(功能请求)以开始关于添加此功能的讨论。

● Kubernetes 操作员和 Kubernetes CNI 支持也未实施。 ○ 这只是尚未实施的功能。

■ 欢迎用户提交 RFE 以开始关于添加此功能的讨论。

● 登录节点上的无根 Docker/Podman 不应启用 cgroup/apparmor/selinux 支持

● 在大多数情况下,这些限制/系统在 Docker/Podman 的无根模式下是无效的,无论是否使用 Slurm。它们在使用用户命名空间时不适用。

● 所有容器都是远程执行的,因此本地系统的安全系统对容器来说是无关紧要的。Slurm 将对在 scrun 下运行的容器强制执行为 Slurm 集群定义的现有限制。

● 如果 Docker/Podman 在任何 selinux 标记下运行,则该标记将在阶段操作期间由 scrun 自动继承。结果作业需要由 Slurm 中现有的 selinux 支持应用这些标签。

● Podman 允许轻松配置禁用,而 Docker 需要命令行参数(在撰写本文时)。

● 目前尚未实现自动资源选择

○ 使用 Slurm 环境变量可以控制作业属性

○ scrun 当前将以请求的默认资源运行默认作业

● 容器失败可能需要检查 slurmd 日志和/或系统日志以确定根本原因

○ 这似乎是容器编排系统的一个常见问题,将来版本中可能有几种潜在的处理方法

● Lua 必须与 JSON 支持一起编译,或者必须安装库。

○ 在 Lua 安装 JSON 库后,可能需要重新编译 Slurm,以便能够使用它。

● 当前 scrun 不会在 Lua 脚本运行时终止或停止该脚本。

○ 如果 Lua 阶段脚本挂起,则作业时间限制可能会被触发并终止作业。

● scrun 具有相关的 SPANK 和 clifilter 支持。

○ 这些钩子不是安全设备,任何用户都可以像使用 srun/sbatch/salloc 一样覆盖它们。

○ scrun 使用标准 Slurm RPC 和用户权限。任何用户都可以修改或 ptrace 自己的进程。任何安全性必须在控制器上应用。

● 每个用户每个主机一个 podman/docker 实例

○ scrun 不提供其自身以外作业的信息

■ 作业将在 squeue/sacct/slurmrestd 中可见

○ docker/podman 对任何外部启动的容器将是盲目的

● MUNGE 身份验证 ○ scrun 目前仅通过 MUNGE 工作

○ 作业提交主机必须安装 Slurm 并位于 MUNGE 安全范围内

● JWT 身份验证

○ 当前未实施

● 容器 ID 必须对每个用户唯一

○ Docker 或 Podman 将逐字传递容器 ID 给 scrun。

○ 如果本地锚定进程已死,scrun 将尝试按 ID 搜索容器。

● 在 Slurm 中运行容器的所有现有限制仍然适用:

○ 容器必须安装兼容版本的 Slurm 以调用 Slurm 命令

○ 为使用基于 MUNGE 的身份验证,MUNGE 的套接字必须挂载在容器中

○ 从容器进行 JWT 身份验证是可能的,但目前没有可用的秘密功能。

■ 目前,Slurm 不支持通过 JWT 进行的步骤控制/命令。

● 用户环境必须显式设置

○ 在调用 docker/podman 时的环境不会被容器继承,除非 Docker/Podman 支持环境变量。

○ 任何环境变量必须进行设置:

■ 这可以通过在容器镜像中的 config.json 中设置环境变量来完成。

■ Docker 还支持在运行时设置环境变量的 ‘--env’,‘-e’ 和 ‘--env-file’。

● scrun 将创建一个本地进程,该进程必须在作业持续时间内保持活动

○ 如果本地进程被终止,则 Slurm 将终止作业。这与通过 srun 运行的任何作业是相同的要求。

○ scrun 可以从批处理作业启动,以避免提交主机的正常运行时间要求。

● Docker 当前使用基于事件和轮询的系统来确定容器是否存活

○ 这可能会导致运行 Docker 的主机上 CPU 使用率高于仅通过 srun 直接运行容器的情况。

○ 这属于 Docker 的设计,与 Slurm 无关。

○ 选择无根模式的登录节点将需要注意即使用户并不总是直接与 Docker 交互,也要考虑额外的 CPU 和内存使用。

● scrun 支持内置的 Docker/Podman 日志记录 ○ scrun 增加了对 Docker JSON 格式的日志文件输出的支持

■ Docker JSON 格式的日志包括元数据,以确定日志条目的来源

■ 作业输出到 stdout 和 stderr 将被注释(因此可以在 Docker 中轻松查询)

○ scrun 的日志将被标记为来自 stdout 源

■ 正常的 slurm 命令将继续根据日志的严重性将日志打印到 stdout 和 stderr。

● scrun 需要完全配置 oci.conf

○ 如果 oci.conf 未配置,则 scrun 将拒绝运行,并且将不支持容器。

● 提交主机的 I/O 限制和其他限制将影响容器的阶段进出

● Slurm 无法控制 Docker/Podman ○ Docker 和 Podman 需要独立于 Slurm 配置

○ 仅支持无根 Docker/Podman

■ 无根 Docker 在旧内核上支持程度不一

■ 建议用户运行其发行版和 Docker 的最新版本,以避免问题 ○ Slurm(scrun)作为启动 Docker/Podman 中容器的最后一步之一来运行

● 目前尚未实现 Docker/Podman 的所有功能

● 在线镜像库独立于 Slurm 存在,并可能会适用带宽或使用限制 ○ 这些限制可能会错误地暗示 scrun(和 Slurm)运行缓慢

○ 建议用户在可能的情况下设置本地缓存代理

○ scrun 不缓存镜像

● scrun 不是安全解决方案、反病毒软件或新的安全层

○ 它不扫描或推理容器镜像的内容,仅执行对基本 OCI 镜像格式的强制

○ 它将图像推送到执行主机,在那里配置的和在 oci.conf 中的 OCI 运行时将被执行以启动容器

○ 用户有责任确保容器镜像遵循站点政策和程序,并且没有恶意代码

● scrun 仅在 POSIX 用户/组下运行,既不添加也不移除用户和容器进程的能力/权限

● 网站必须配置阶段进出 Lua 脚本,以清理缓存的镜像

○ 未能清理镜像可能会导致文件系统的巨大浪费。

● 网站必须配置 Docker/Podman 以独立于 Slurm 清理缓存的镜像

○ Docker 的构建缓存可能会变得非常大!

● 为了支持 docker build 或 podman build,容器的阶段进出必须完成,以将最终更改应用回容器的私有挂载空间

○ 这只会在单个计算节点上发生,因此不应出现跨节点同步更改的问题。

○ 残留的容器镜像文件树将减少同步调用,但最终清理必须在 scrun 外部进行。

● scrun exec 尚未实现

附录 2:通过 Scrun 的工作生命周期

容器创建流程 - Scrun

 

附录:3 Scrun 的容器暂存

Scrun - 容器暂存
● Scrun 在启动时需要将镜像暂存到远程宿主机
● Scrun 在作业结束时需要将镜像从远程宿主机中移除
● 由于每个站点具有不同的共享文件系统配置和数据进出规则,因此需要灵活性。
○ Scrun 尽量避免对请求主机与在 Slurm 中的执行主机之间的假设
○ 站点管理员必须配置镜像的存放位置和方式。

Scrun - 通过 Lua 进行容器暂存
● Scrun 的 Lua 暂存插件允许站点编写自定义和简单的脚本,以便将镜像移动到远程存储并返回。
● Scrun 的暂存 Lua 脚本位于:
○ /etc/slurm/scrun.lua
● Lua 脚本以用户身份运行,避免任何额外的提升权限风险
● Lua 通过库已经支持 JSON
● 如果需要,站点可以编写本地的 Slurm 插件,而不是使用 Lua 插件。

Scrun - Lua 容器暂存示例

简化的暂存到(常见共享文件系统)的钩子:

 function slurm_scrun_stage_in(id, bundle, spool_dir, config_file, job_id, user_id,
     group_id, job_env)
 os.execute(string.format("/usr/bin/env rsync --numeric-ids --delete-after  
     --ignore-errors -a -- %s/ %s/", rootfs, dstfs))
 slurm.set_bundle_path(p)
 slurm.set_root_path(p.."rootfs")
 write_file(jc, json.encode(c))
 return slurm.SUCCESS
 end

 Scrun - Lua 容器移除示例

简化的移除钩子:(此示例仅删除容器)

function slurm_scrun_stage_out(id, bundle, orig_bundle, root_path, orig_root_path,
        spool_dir, config_file, jobid, user_id, group_id)
 os.execute("rm --one-file-system --preserve-root=all -rf "..bundle)
 return slurm.SUCCESS
 end

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

技术瘾君子1573

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值