scrun

部分:Slurm 命令 (1)
更新:Slurm 命令
索引

 

名称

scrun - Slurm 的 OCI 运行时代理。

 

概要

 

创建操作

scrun [全局选项...] create [创建选项] <container-id>
在当前工作目录中准备一个新的容器,容器 ID 为 container-id。

 

启动操作

scrun [全局选项...] start <container-id>
请求启动并运行容器。

 

查询状态操作

scrun [全局选项...] state <container-id>
输出 OCI 定义的容器 JSON 状态。

 

杀死操作

scrun [全局选项...] kill <container-id> [signal]
向容器发送信号(默认:SIGTERM)。

 

删除操作

scrun [全局选项...] delete [删除选项] <container-id>
释放容器在本地和远程持有的任何资源。

根据以下内容对container-id执行 OCI 运行时操作:
https://github.com/opencontainers/runtime-spec/blob/main/runtime.md

scrun 尝试尽可能模仿crunrunc 的命令行行为,以保持与DOCKERpodman 的就地替换兼容性。所有crunrunc 的命令行参数都将被接受以保持兼容性,但可能会根据其适用性被忽略。

 

描述

scrun 是 Slurm 的 OCI 运行时代理。它充当与DOCKERpodman 的公共接口,以允许在 Slurm 下作为作业执行容器操作。scrun 将接受所有作为 OCI 兼容运行时的命令,但会将容器及其所有 STDIO 代理到 Slurm 进行调度和执行。容器将根据oci.conf(5) 中的设置在 Slurm 计算节点上远程执行。

scrun 要求所有容器符合 OCI 镜像标准:
https://github.com/opencontainers/image-spec/blob/main/spec.md

 

返回值

在操作成功时,scrun 将返回 0。对于任何其他情况,scrun 将返回任何非零数字以表示错误。

 

全局选项

--cgroup-manager
被忽略。

--debug
激活调试级别日志记录。

-f <slurm_conf_path>
使用指定的 slurm.conf 进行配置。
默认:在编译期间从configure获取的 sysconfdir

--usage
显示关于如何调用scrun的快速帮助

--log-format=<json|text>
可选选择日志记录格式。可以是“json”或“text”。
默认:文本

--root=<root_path>
用于通信套接字和临时目录及文件的存储目录路径。此路径应为 tmpfs,并应在重启时清除。
默认:/run/user/{user_id}/scrun/

--rootless
被忽略。所有scrun命令始终是无根的。

--systemd-cgroup
被忽略。

-v
增加日志记录详细程度。多个 -v 会增加详细程度。

-V, --version
打印版本信息并退出。

 

创建选项

-b <bundle_path>, --bundle=<bundle_path>
指向捆绑目录的根路径。
默认:调用者的工作目录

--console-socket=<console_socket_path>
可选路径,指向一个 AF_UNIX 套接字,该套接字将接收一个引用控制台伪终端主端的文件描述符。
默认:被忽略

--no-pivot
被忽略。

--no-new-keyring
被忽略。

--pid-file=<pid_file_path>
指定要锁定并填充进程 ID 的文件。
默认:被忽略

--preserve-fds
被忽略。

 

删除选项

--force
被忽略。所有删除请求都是强制的,并将终止任何正在运行的作业。

 

输入环境变量

SCRUN_DEBUG=<quiet|fatal|error|info|verbose|debug|debug2|debug3|debug4|debug5>
设置日志记录级别。

SCRUN_STDERR_DEBUG=<quiet|fatal|error|info|verbose|debug|debug2|debug3|debug4|debug5>
仅为标准错误输出设置日志记录级别。

SCRUN_SYSLOG_DEBUG=<quiet|fatal|error|info|verbose|debug|debug2|debug3|debug4|debug5>
仅为系统日志记录设置日志记录级别。

SCRUN_FILE_DEBUG=<quiet|fatal|error|info|verbose|debug|debug2|debug3|debug4|debug5>
仅为日志文件设置日志记录级别。

 

作业输入环境变量

SCRUN_ACCOUNT
参见SLURM_ACCOUNT,来自srun(1)。

SCRUN_ACCTG_FREQ
参见SLURM_ACCTG_FREQ,来自srun(1)。

SCRUN_BURST_BUFFER
参见SLURM_BURST_BUFFER,来自srun(1)。

SCRUN_CLUSTER_CONSTRAINT
参见SLURM_CLUSTER_CONSTRAINT,来自srun(1)。

SCRUN_CLUSTERS
参见SLURM_CLUSTERS,来自srun(1)。

SCRUN_CONSTRAINT
参见SLURM_CONSTRAINT,来自srun(1)。

SLURM_CORE_SPEC
参见SLURM_ACCOUNT,来自srun(1)。

SCRUN_CPU_BIND
参见SLURM_CPU_BIND,来自srun(1)。

SCRUN_CPU_FREQ_REQ
参见SLURM_CPU_FREQ_REQ,来自srun(1)。

SCRUN_CPUS_PER_GPU
参见SLURM_CPUS_PER_GPU,来自srun(1)。

SCRUN_CPUS_PER_TASK
参见SRUN_CPUS_PER_TASK,来自srun(1)。

SCRUN_DELAY_BOOT
参见SLURM_DELAY_BOOT,来自srun(1)。

SCRUN_DEPENDENCY
参见SLURM_DEPENDENCY,来自srun(1)。

SCRUN_DISTRIBUTION
参见SLURM_DISTRIBUTION,来自srun(1)。

SCRUN_EPILOG
参见SLURM_EPILOG,来自srun(1)。

SCRUN_EXACT
参见SLURM_EXACT,来自srun(1)。

SCRUN_EXCLUSIVE
参见SLURM_EXCLUSIVE,来自srun(1)。

SCRUN_GPU_BIND
参见SLURM_GPU_BIND,来自srun(1)。

SCRUN_GPU_FREQ
参见SLURM_GPU_FREQ,来自srun(1)。

SCRUN_GPUS
参见SLURM_GPUS,来自srun(1)。

SCRUN_GPUS_PER_NODE
参见SLURM_GPUS_PER_NODE,来自srun(1)。

SCRUN_GPUS_PER_SOCKET
参见SLURM_GPUS_PER_SOCKET,来自salloc(1)。

SCRUN_GPUS_PER_TASK
参见SLURM_GPUS_PER_TASK,来自srun(1)。

SCRUN_GRES_FLAGS
参见SLURM_GRES_FLAGS,来自srun(1)。

SCRUN_GRES
参见SLURM_GRES,来自srun(1)。

SCRUN_HINT
参见SLURM_HIST,来自srun(1)。

SCRUN_JOB_NAME
参见SLURM_JOB_NAME,来自srun(1)。

SCRUN_JOB_NODELIST
参见SLURM_JOB_NODELIST,来自srun(1)。

SCRUN_JOB_NUM_NODES
参见SLURM_JOB_NUM_NODES,来自srun(1)。

SCRUN_LABELIO
参见SLURM_LABELIO,来自srun(1)。

SCRUN_MEM_BIND
参见SLURM_MEM_BIND,来自srun(1)。

SCRUN_MEM_PER_CPU
参见SLURM_MEM_PER_CPU,来自srun(1)。

SCRUN_MEM_PER_GPU
参见SLURM_MEM_PER_GPU,来自srun(1)。

SCRUN_MEM_PER_NODE
参见SLURM_MEM_PER_NODE,来自srun(1)。

SCRUN_MPI_TYPE
参见SLURM_MPI_TYPE,来自srun(1)。

SCRUN_NCORES_PER_SOCKET
参见SLURM_NCORES_PER_SOCKET,来自srun(1)。

SCRUN_NETWORK
参见SLURM_NETWORK,来自srun(1)。

SCRUN_NSOCKETS_PER_NODE
参见SLURM_NSOCKETS_PER_NODE,来自srun(1)。

SCRUN_NTASKS
参见SLURM_NTASKS,来自srun(1)。

SCRUN_NTASKS_PER_CORE
参见SLURM_NTASKS_PER_CORE,来自srun(1)。

SCRUN_NTASKS_PER_GPU
参见SLURM_NTASKS_PER_GPU,来自srun(1)。

SCRUN_NTASKS_PER_NODE
参见SLURM_NTASKS_PER_NODE,来自srun(1)。

SCRUN_NTASKS_PER_TRES
参见SLURM_NTASKS_PER_TRES,来自srun(1)。

SCRUN_OPEN_MODE
参见SLURM_MODE,来自srun(1)。

SCRUN_OVERCOMMIT
参见SLURM_OVERCOMMIT,来自srun(1)。

SCRUN_OVERLAP
参见SLURM_OVERLAP,来自srun(1)。

SCRUN_PARTITION
参见SLURM_PARTITION,来自srun(1)。

SCRUN_POWER
参见SLURM_POWER,来自srun(1)。

SCRUN_PROFILE
参见SLURM_PROFILE,来自srun(1)。

SCRUN_PROLOG
参见SLURM_PROLOG,来自srun(1)。

SCRUN_QOS
参见SLURM_QOS,来自srun(1)。

SCRUN_REMOTE_CWD
参见SLURM_REMOTE_CWD,来自srun(1)。

SCRUN_REQ_SWITCH
参见SLURM_REQ_SWITCH,来自srun(1)。

SCRUN_RESERVATION
参见SLURM_RESERVATION,来自srun(1)。

SCRUN_SIGNAL
参见SLURM_SIGNAL,来自srun(1)。

SCRUN_SLURMD_DEBUG
参见SLURMD_DEBUG,来自srun(1)。

SCRUN_SPREAD_JOB
参见SLURM_SPREAD_JOB,来自srun(1)。

SCRUN_TASK_EPILOG
参见SLURM_TASK_EPILOG,来自srun(1)。

SCRUN_TASK_PROLOG
参见SLURM_TASK_PROLOG,来自srun(1)。

SCRUN_THREAD_SPEC
参见SLURM_THREAD_SPEC,来自srun(1)。

SCRUN_THREADS_PER_CORE
参见SLURM_THREADS_PER_CORE,来自srun(1)。

SCRUN_THREADS
参见SLURM_THREADS,来自srun(1)。

SCRUN_TIMELIMIT
参见SLURM_TIMELIMIT,来自srun(1)。

SCRUN_TRES_BIND
--tres-bind相同

SCRUN_TRES_PER_TASK
参见SLURM_TRES_PER_TASK,来自srun(1)。

SCRUN_UNBUFFEREDIO
参见SLURM_UNBUFFEREDIO,来自srun(1)。

SCRUN_USE_MIN_NODES
参见SLURM_USE_MIN_NODES,来自srun(1)。

SCRUN_WAIT4SWITCH
参见SLURM_WAIT4SWITCH,来自srun(1)。

SCRUN_WCKEY
参见SLURM_WCKEY,来自srun(1)。

SCRUN_WORKING_DIR
参见SLURM_WORKING_DIR,来自srun(1)。

 

输出环境变量

SCRUN_OCI_VERSION
容器的 OCI 合规性广告版本。

SCRUN_CONTAINER_ID
在创建操作期间基于container_id的值。

SCRUN_PID
用于监控和控制分配节点上容器的进程 PID。

SCRUN_BUNDLE
指向容器捆绑目录的路径。

SCRUN_SUBMISSION_BUNDLE
在 Lua 脚本修改之前指向容器捆绑目录的路径。

SCRUN_ANNOTATION_*
来自容器的 config.json 的注释列表。

SCRUN_PID_FILE
指向 PID 文件的路径,该文件被锁定并填充 scrun 的 PID。

SCRUN_SOCKET
指向 scrun 控制套接字的路径。
" href="#OPT_SCRUN_SUBMISSION_CONFIG_FILE">
提交时容器的 config.json 文件路径。

SCRUN_USER
调用创建操作的用户名称。

SCRUN_USER_ID
调用创建操作的用户的数字 ID。

SCRUN_GROUP
调用创建操作的用户的主要组名称。

SCRUN_GROUP_ID
调用创建操作的用户主要组的数字 ID。

SCRUN_ROOT
请参见 --root

SCRUN_ROOTFS_PATH
容器根目录的路径。

SCRUN_SUBMISSION_ROOTFS_PATH
提交时容器根目录的路径。

SCRUN_LOG_FILE
创建操作期间 scrun 的日志文件路径。

SCRUN_LOG_FORMAT
创建操作期间的日志格式类型。

 

作业输出环境变量

SLURM_*_HET_GROUP_#
对于异构作业分配,环境变量会为每个组件单独设置。

SLURM_CLUSTER_NAME
作业正在执行的集群名称。

SLURM_CONTAINER
作业的 OCI 包。

SLURM_CONTAINER_ID
作业的 OCI ID。

SLURM_CPUS_PER_GPU
每个分配的 GPU 请求的 CPU 数量。

SLURM_CPUS_PER_TASK
每个任务请求的 CPU 数量。

SLURM_DIST_PLANESIZE
平面分布大小。仅为平面分布设置。

SLURM_DISTRIBUTION
分配作业的分布类型。

SLURM_GPU_BIND
请求将任务绑定到 GPU。

SLURM_GPU_FREQ
请求的 GPU 频率。

SLURM_GPUS
请求的 GPU 数量。

SLURM_GPUS_PER_NODE
每个分配节点请求的 GPU 数量。

SLURM_GPUS_PER_SOCKET
每个分配插槽请求的 GPU 数量。

SLURM_GPUS_PER_TASK
每个分配任务请求的 GPU 数量。

SLURM_HET_SIZE
设置为异构作业中的组件数量。

SLURM_JOB_ACCOUNT
与作业分配相关联的账户名称。

SLURM_JOB_CPUS_PER_NODE
分配节点上可用于作业的 CPU 数量,使用格式 CPU_count[(xnumber_of_nodes)][,CPU_count[(xnumber_of_nodes)] ...]。 例如:SLURM_JOB_CPUS_PER_NODE='72(x2),36' 表示在第一个和第二个节点(如 SLURM_JOB_NODELIST 列出)上分配了 72 个 CPU,而第三个节点上有 36 个 CPU。 注意select/linear 插件将整个节点分配给作业,因此该值表示分配节点上 CPU 的总数。select/cons_tres 插件将单个 CPU 分配给作业,因此该数字表示分配给作业的 CPU 数量。

SLURM_JOB_END_TIME
作业预计结束时间的 UNIX 时间戳。

SLURM_JOB_GPUS
分配给该作业的 GPU 的全局 GPU ID。GPU ID 不相对于任何设备 cgroup,即使设备受到任务/cgroup 的约束。 仅在批处理和交互式作业中设置。

SLURM_JOB_ID
作业分配的 ID。

SLURM_JOB_NODELIST
分配给作业的节点列表。

SLURM_JOB_NUM_NODES
作业分配中的节点总数。

SLURM_JOB_PARTITION
作业正在运行的分区名称。

SLURM_JOB_QOS
作业分配的服务质量 (QOS)。

SLURM_JOB_RESERVATION
包含作业分配的高级预留(如果有)。

SLURM_JOB_START_TIME
作业开始时间的 UNIX 时间戳。

SLURM_MEM_BIND
将任务绑定到内存。

SLURM_MEM_BIND_LIST
设置为用于内存绑定的位掩码。

SLURM_MEM_BIND_PREFER
如果 SLURM_MEM_BIND 选项包括 prefer 选项,则设置为“prefer”。

SLURM_MEM_BIND_SORT
对空闲缓存页面进行排序(在 Intel KNL 节点上运行 zonesort)

SLURM_MEM_BIND_TYPE
设置为使用 SLURM_MEM_BIND 选项指定的内存绑定类型。 可能的值为“none”、“rank”、“map_map”、“mask_mem”和“local”。

SLURM_MEM_BIND_VERBOSE
如果 SLURM_MEM_BIND 选项包括详细选项,则设置为“verbose”。 否则设置为“quiet”。

SLURM_MEM_PER_CPU
每个可用分配 CPU 所需的最小内存。

SLURM_MEM_PER_GPU
每个分配 GPU 请求的内存。

SLURM_MEM_PER_NODE
指定每个节点所需的实际内存。

SLURM_NTASKS
指定要运行的任务数量。

SLURM_NTASKS_PER_CORE
请求在每个核心上调用最大 ntasks

SLURM_NTASKS_PER_GPU
请求为每个 GPU 调用 ntasks 任务。

SLURM_NTASKS_PER_NODE
请求在每个节点上调用 ntasks

SLURM_NTASKS_PER_SOCKET
请求在每个插槽上调用最大 ntasks

SLURM_OVERCOMMIT
超额分配资源。

SLURM_PROFILE
通过 acct_gather_profile 插件启用详细数据收集。

SLURM_SHARDS_ON_NODE
此节点上可用于步骤的 GPU 分片数量。

SLURM_SUBMIT_HOST
从中调用 scrun 的计算机的主机名。

SLURM_TASKS_PER_NODE
每个节点上要启动的任务数量。值用逗号分隔,并与 SLURM_JOB_NODELIST 中的顺序相同。 如果两个或更多连续节点要具有相同的任务计数,则该计数后跟“(x#)”,其中“#”是重复计数。例如,“SLURM_TASKS_PER_NODE=2(x3),1”表示前 3 个节点将各自执行两个任务,而第四个节点将执行一个任务。

SLURM_THREADS_PER_CORE
仅在指定了 --threads-per-coreSCRUN_THREADS_PER_CORE 时设置。该值将设置为 --threads-per-coreSCRUN_THREADS_PER_CORE 指定的值。此值在作业分配中的后续 srun 调用中使用。

SLURM_TRES_PER_TASK
设置为 --tres-per-task 的值。如果指定了 --cpus-per-task--gpus-per-task,则它也会在 SLURM_TRES_PER_TASK 中设置,就像在 --tres-per-task 中指定的一样。

 

SCRUN.LUA

/etc/slurm/scrun.lua 必须存在于任何将调用 scrun 的节点上。scrun.lua 必须是合规的 lua 脚本。

 

必需的函数

以下函数必须被定义。

• function slurm_scrun_stage_in(id, bundle, spool_dir, config_file, job_id, user_id, group_id, job_env)
在作业分配后立即调用以将容器阶段放入作业节点。必须返回 SLURM.success,否则作业将被取消。要求该函数准备容器以便在作业节点上执行,按照 oci.conf(1) 中配置的要求。该函数可以阻塞,直到容器完全准备好(最长可达作业的最大墙时间)。
id
容器 ID
bundle
OCI 包路径
spool_dir
容器的临时工作目录
config_file
容器的 config.json 路径
job_id
jobid 的作业分配
user_id
作业分配的解析数字用户 ID。通常期望 lua 脚本将在以 root(0) 用户身份运行的用户命名空间内执行。
group_id
作业分配的解析数字组 ID。通常期望 lua 脚本将在以 root(0) 组身份运行的用户命名空间内执行。
job_env
每个环境变量的键=值或值的表。

• function slurm_scrun_stage_out(id, bundle, orig_bundle, root_path, orig_root_path, spool_dir, config_file, jobid, user_id, group_id)
在容器步骤完成后立即调用以将文件从作业节点阶段输出。必须返回 SLURM.success,否则作业将被取消。要求该函数将任何更改拉回并清理作业节点上的容器。该函数可以阻塞,直到容器完全准备好(最长可达作业的最大墙时间)。

id
容器 ID
bundle
OCI 包路径
orig_bundle
在被 set_bundle_path() 修改之前提交的原始 OCI 包路径。
root_path
容器内容的目录根路径。
orig_root_path
在被 set_root_path() 修改之前的容器内容的目录根路径。
spool_dir
容器的临时工作目录
config_file
容器的 config.json 路径
job_id
jobid 的作业分配
user_id
作业分配的解析数字用户 ID。通常期望 lua 脚本将在以 root(0) 用户身份运行的用户命名空间内执行。
group_id
作业分配的解析数字组 ID。通常期望 lua 脚本将在以 root(0) 组身份运行的用户命名空间内执行。

 

提供的函数

以下函数可供任何 Lua 函数根据需要调用。

slurm.set_bundle_path(PATH)
调用以通知 scrun 使用 PATH 作为新的 OCI 容器包路径。根据文件系统布局,可能需要克隆容器包以允许在作业节点上执行。

slurm.set_root_path(PATH)
调用以通知 scrun 使用 PATH 作为新的容器根文件系统路径。根据文件系统布局,可能需要克隆容器包以允许在作业节点上执行。脚本在更改根路径时还必须更新 config.json 中的 #/root/path。

STATUS,OUTPUT = slurm.remote_command(SCRIPT)
在所有作业节点的新作业步骤中运行 SCRIPT。返回数字作业状态作为 STATUS 和作业标准输入输出作为 OUTPUT。阻塞直到 SCRIPT 退出。

STATUS,OUTPUT = slurm.allocator_command(SCRIPT)
作为 scrun 的分叉子进程运行 SCRIPT。返回数字作业状态作为 STATUS 和作业标准输入输出作为 OUTPUT。阻塞直到 SCRIPT 退出。

slurm.log(MSG, LEVEL)
在日志 LEVEL 记录 MSGLEVEL 的有效值范围为 [0, 4]。

slurm.error(MSG)
记录错误 MSG

slurm.log_error(MSG)
记录错误 MSG

slurm.log_info(MSG)
在日志级别 INFO 记录 MSG

slurm.log_verbose(MSG)
在日志级别 VERBOSE 记录 MSG

slurm.log_verbose(MSG)
在日志级别 VERBOSE 记录 MSG

slurm.log_debug(MSG)
在日志级别 DEBUG 记录 MSG

slurm.log_debug2(MSG)
在日志级别 DEBUG2 记录 MSG

slurm.log_debug3(MSG)
在日志级别 DEBUG3 记录 MSG

slurm.log_debug4(MSG)
在日志级别 DEBUG4 记录 MSG

MINUTES = slurm.time_str2mins(TIME_STRING)
TIME_STRING 解析为分钟数 MINUTES。有效格式:
• days-[hours[:minutes[:seconds]]]
• hours:minutes:seconds
• minutes[:seconds]
• -1
• INFINITE
• UNLIMITED

 

示例 scrun.lua 脚本

使用 rsync 的完整容器阶段示例:
此完整示例将根据 dockerpodman 阶段一个容器。容器的 config.json 被修改以删除可能导致容器在 crunrunc 下运行的无用功能。 该脚本使用 rsync 将容器移动到 scratch_path 变量下的共享文件系统。

注意:在编译 Slurm 之前,必须通常安装 liblua 中对 JSON 的支持。通过直接使用 lua 调用脚本来测试 scrun.lua 的语法和加载 JSON 支持的能力。

local json = require 'json'
local open = io.open
local scratch_path = "/run/user/"

local function read_file(path)
        local file = open(path, "rb")
        if not file then return nil end
        local content = file:read "*all"
        file:close()
        return content
end

local function write_file(path, contents)
        local file = open(path, "wb")
        if not file then return nil end
        file:write(contents)
        file:close()
        return
end

function slurm_scrun_stage_in(id, bundle, spool_dir, config_file, job_id, user_id, group_id, job_env)
        slurm.log_debug(string.format("stage_in(%s, %s, %s, %s, %d, %d, %d)",
                       id, bundle, spool_dir, config_file, job_id, user_id, group_id))

        local status, output, user, rc
        local config = json.decode(read_file(config_file))
        local src_rootfs = config["root"]["path"]
        rc, user = slurm.allocator_command(string.format("id -un %d", user_id))
        user = string.gsub(user, "%s+", "")
        local root = scratch_path..math.floor(user_id).."/slurm/scrun/"
        local dst_bundle = root.."/"..id.."/"
        local dst_config = root.."/"..id.."/config.json"
        local dst_rootfs = root.."/"..id.."/rootfs/"

        if string.sub(src_rootfs, 1, 1) ~= "/"
        then
                -- 始终使用绝对路径
                src_rootfs = string.format("%s/%s", bundle, src_rootfs)
        end

        status, output = slurm.allocator_command("mkdir -p "..dst_rootfs)
        if (status ~= 0)
        then
                slurm.log_info(string.format("mkdir(%s) failed %u: %s",
                               dst_rootfs, status, output))
                return slurm.ERROR
        end

        status, output = slurm.allocator_command(string.format("/usr/bin/env rsync --exclude sys --exclude proc --numeric-ids --delete-after --ignore-errors --stats -a -- %s/ %s/", src_rootfs, dst_rootfs))
        if (status ~= 0)
        then
                -- rsync 可能由于权限问题而失败,但这可能无关紧要
                slurm.log_info(string.format("WARNING: rsync failed: %s", output))
        end

        slurm.set_bundle_path(dst_bundle)
        slurm.set_root_path(dst_rootfs)

        config["root"]["path"] = dst_rootfs

        -- 始终强制容器中的用户命名空间支持,否则 runc 将拒绝
        local process_user_id = 0
        local process_group_id = 0

        if ((config["process"] ~= nil) and (config["process"]["user"] ~= nil))
        then
                -- 在容器中解析用户
                if (config["process"]["user"]["uid"] ~= nil)
                then
                        process_user_id=config["process"]["user"]["uid"]
                else
                        process_user_id=0
                end

                -- 在容器中解析组
                if (config["process"]["user"]["gid"] ~= nil)
                then
                        process_group_id=config["process"]["user"]["gid"]
                else
                        process_group_id=0
                end

                -- 清除 additionalGids,因为它们在无根模式下不受支持
                if (config["process"]["user"]["additionalGids"] ~= nil)
                then
                        config["process"]["user"]["additionalGids"] = nil
                end
        end

        if (config["linux"] ~= nil)
        then
                -- 强制用户命名空间始终在无根模式下定义
                local found = false
                if (config["linux"]["namespaces"] == nil)
                then
                        config["linux"]["namespaces"] = {}
                else
                        for _, namespace in ipairs(config["linux"]["namespaces"]) do
                                if (namespace["type"] == "user")
                                then
                                        found=true
                                        break
                                end
                        end
                end
                if (found == false)
                then
                        table.insert(config["linux"]["namespaces"], {type= "user"})
                end

                -- 如果未提供,则提供默认用户映射为 root
                if (true or config["linux"]["uidMappings"] == nil)
                then
                        config["linux"]["uidMappings"] =
                                {{containerID=process_user_id, hostID=math.floor(user_id), size=1}}
                end

                -- 如果未提供,则提供默认组映射为 root
                -- 映射在构建时失败???
                if (true or config["linux"]["gidMappings"] == nil)
                then
                        config["linux"]["gidMappings"] =
                                {{containerID=process_group_id, hostID=math.floor(group_id), size=1}}
                end

                -- 禁用尝试使用特定 cgroup
                config["linux"]["cgroupsPath"] = nil
        end

        if (config["mounts"] ~= nil)
        then
                -- 查找并删除挂载中的任何用户/组设置
                for _, mount in ipairs(config["mounts"]) do
                        local opts = {}

                        if (mount["options"] ~= nil)
                        then
                                for _, opt in ipairs(mount["options"]) do
                                        if ((string.sub(opt, 1, 4) ~= "gid=") and (string.sub(opt, 1, 4) ~= "uid="))
                                        then
                                                table.insert(opts, opt)
                                        end
                                end
                        end

                        if (opts ~= nil and #opts > 0)
                        then
                                mount["options"] = opts
                        else
                                mount["options"] = nil
                        end
                end

                -- 通过将文件复制到 rootfs 来删除所有绑定挂载
                local mounts = {}
                for i, mount in ipairs(config["mounts"]) do
                        if ((mount["type"] ~= nil) and (mount["type"] == "bind") and (string.sub(mount["source"], 1, 4) ~= "/sys") and (string.sub(mount["source"], 1, 5) ~= "/proc"))
                        then
                                status, output = slurm.allocator_command(string.format("/usr/bin/env rsync --numeric-ids --ignore-errors --stats -a -- %s %s", mount["source"], dst_rootfs..mount["destination"]))
                                if (status ~= 0)
                                then
                                        -- rsync 可能由于权限问题而失败,但这可能无关紧要
                                        slurm.log_info("rsync failed")
                                end
                        else
                                table.insert(mounts, mount)
                        end
                end
                config["mounts"] = mounts
        end

        -- 强制版本与旧版 runc/crun 兼容,以防新功能静默失败
        config["ociVersion"] = "1.0.0"

        -- 将作业环境合并到容器中 -- 这是可选的!
        if (config["process"]["env"] == nil)
        then
                config["process"]["env"] = {}
        end
        for _, env in ipairs(job_env) do
                table.insert(config["process"]["env"], env)
        end

        -- 删除所有预启动钩子以压制任何网络尝试
        if ((config["hooks"] ~= nil) and (config["hooks"]["prestart"] ~= nil))
        then
                config["hooks"]["prestart"] = nil
        end

        -- 删除所有 rlimits
        if ((config["process"] ~= nil) and (config["process"]["rlimits"] ~= nil))
        then
                config["process"]["rlimits"] = nil
        end

        write_file(dst_config, json.encode(config))
        slurm.log_info("created: "..dst_config)

        return slurm.SUCCESS
end

function slurm_scrun_stage_out(id, bundle, orig_bundle, root_path, orig_root_path, spool_dir, config_file, jobid, user_id, group_id)
        if (root_path == nil)
        then
                root_path = ""
        end

        slurm.log_debug(string.format("stage_out(%s, %s, %s, %s, %s, %s, %s, %d, %d, %d)",
                       id, bundle, orig_bundle, root_path, orig_root_path, spool_dir, config_file, jobid, user_id, group_id))

        if (bundle == orig_bundle)
        then
                slurm.log_info(string.format("skipping stage_out as bundle=orig_bundle=%s", bundle))
                return slurm.SUCCESS
        end

        status, output = slurm.allocator_command(string.format("/usr/bin/env rsync --numeric-ids --delete-after --ignore-errors --stats -a -- %s/ %s/", root_path, orig_root_path))
        if (status ~= 0)
        then
                -- rsync 可能由于权限问题而失败,但这可能无关紧要
                slurm.log_info("rsync failed")
        else
                -- 在同步回源后清理临时文件
                slurm.allocator_command(string.format("/usr/bin/rm --preserve-root=all --one-file-system -dr -- %s", bundle))
        end

        return slurm.SUCCESS
end

slurm.log_info("initialized scrun.lua")

return slurm.SUCCESS

 

信号

SIGINT
尝试优雅地取消任何相关作业(如果有)并进行清理。

SIGCHLD
等待所有子进程,清理锚点并优雅地关闭。

 

版权

版权所有 (C) 2023 SchedMD LLC。

此文件是 Slurm 的一部分,资源管理程序。 有关详细信息,请参见 <https://slurm.schedmd.com/>。

Slurm 是自由软件;您可以根据自由软件基金会发布的 GNU 通用公共许可证的条款重新分发和/或修改它;许可证的第 2 版,或(根据您的选择)任何更高版本。

Slurm 的分发希望它能有用,但不提供任何担保;甚至没有适销性或适合特定目的的隐含担保。有关详细信息,请参阅 GNU 通用公共许可证。

 

另见

slurm(1), oci.conf(5), srun(1), crunruncDOCKERpodman


 

索引

名称
概要
创建操作
开始操作
查询状态操作
杀死操作
删除操作
描述
返回值
全局选项
创建选项
删除选项
输入环境变量
作业输入环境变量
输出环境变量
作业输出环境变量
SCRUN.LUA
必需的函数
提供的函数
示例 scrun.lua 脚本
信号
版权
另见

此文档由 man2html 使用手册页创建。
时间:2025年7月2日 13:21:56 GMT