Container Service for Kubernetes (ACK) provides ack-slurm-operator to deploy and manage Slurm on ACK clusters for high-performance computing (HPC) and large-scale AI/ML workloads.
Slurm
Slurm is an open-source cluster resource management and job scheduling platform for supercomputers and large compute clusters. The following figure shows how Slurm works.
-
slurmctld (Slurm Control Daemon): The central controller that monitors resources, schedules jobs, and manages cluster state. Configure a standby slurmctld for high availability.
-
slurmd (Slurm Node Daemon): Runs on each compute node to receive instructions from slurmctld, execute jobs, and report status.
-
slurmdbd (Slurm Database Daemon): An optional component that maintains a centralized database for job history and accounting. Supports data aggregation across multiple Slurm-managed clusters.
-
SlurmCLI: Command-line tools for job management and system monitoring:
-
scontrol: Manages cluster configuration and state.
-
squeue: Queries the status of the job queue.
-
srun: Submits and manages jobs.
-
sbatch: Submits a batch job.
-
sinfo: Displays cluster state and node availability.
-
Slurm on ACK
The Slurm Operator uses the SlurmCluster CustomResource (CR) to deploy and manage Slurm clusters. An administrator creates a SlurmCluster object, and the operator provisions the control plane components. Mount configuration files through shared storage or a ConfigMap. The following figure shows the architecture of Slurm on ACK.
Prerequisites
You need an ACK cluster running Kubernetes 1.22 or later with at least one GPU-accelerated node. See Add GPU-accelerated nodes to a cluster and Update clusters.
Step 1: Install the ack-slurm-operator
Log on to the ACK console. In the left navigation pane, click .
-
On the Marketplace page, search for and click the ack-slurm-operator card. On the ack-slurm-operator details page, click Deploy and follow the prompts to configure the component.
Select a target cluster. Keep all other parameters at their defaults.
-
Click OK.
Step 2: Create a SlurmCluster
Create manually
-
Create a Secret in your ACK cluster for MUNGE-based authentication.
-
Generate a MUNGE authentication key with OpenSSL.
openssl rand -base64 512 | tr -d '\r\n' -
Create a Secret to store the generated MUNGE key.
kubectl create secret generic <$MungeKeyName> --from-literal=munge.key=<$MungeKey>-
Replace
<$MungeKeyName>with a custom name for your key, such asmungekey. -
Replace
<$MungeKey>with the key string that you generated in the previous step.
-
Configure the SlurmCluster resource to use this Secret for MUNGE-based authentication.
-
-
Create the ConfigMap required by the SlurmCluster resource.
Specifying
slurmConfPathin the CR mounts the ConfigMap to pods, ensuring automatic restoration if a pod is recreated.The
dataparameter contains a sample configuration. Generate configurations with the Easy Configurator or Full Configurator.Expected output:
configmap/slurm-test createdThe ConfigMap was created.
-
Submit the SlurmCluster CR.
-
Create a file named slurmcluster.yaml and copy the following content into it.
NoteThis example uses an Ubuntu-based image with CUDA 11.4, Slurm 23.06, and a Cloud Node auto scaling component. To use a custom image, create and upload it yourself.
This CR creates a Slurm-managed cluster with one head node and four worker nodes running as pods. The
mungeConfPathandslurmConfPathmust match the mount paths in theslurmctldandworkerGroupSpecstemplates. -
Deploy slurmcluster.yaml to the cluster:
kubectl apply -f slurmcluster.yamlExpected output:
slurmcluster.kai.alibabacloud.com/slurm-job-demo created -
Check the SlurmCluster status.
kubectl get slurmclusterExpected output:
NAME AVAILABLE WORKERS STATUS AGE slurm-job-demo 5 ready 14mThe Slurm-managed cluster is deployed with all 5 nodes in Ready state.
-
Verify that the
slurm-job-democluster pods are running.kubectl get podExpected output:
NAME READY STATUS RESTARTS AGE slurm-job-demo-head-x9sgs 1/1 Running 0 14m slurm-job-demo-worker-cpu-0 1/1 Running 0 14m slurm-job-demo-worker-cpu-1 1/1 Running 0 14m slurm-job-demo-worker-cpu1-0 1/1 Running 0 14m slurm-job-demo-worker-cpu1-1 1/1 Running 0 14mThe head node and four worker nodes are running.
-
Create with Helm
The Alibaba Cloud SlurmCluster Helm chart simplifies deployment by creating the required resources, such as RBAC permissions, a ConfigMap, a Secret, and the SlurmCluster CR.
The chart includes these resources:
|
Resource type |
Resource name |
Description |
|
ConfigMap |
{{ .Values.slurmConfigs.configMapName }} |
Created when |
|
ServiceAccount |
{{ .Release.Namespace }}/{{ .Values.clusterName }} |
Grants |
|
Role |
{{ .Release.Namespace }}/{{ .Values.clusterName }} |
Grants |
|
RoleBinding |
{{ .Release.Namespace }}/{{ .Values.clusterName }} |
Grants |
|
Role |
{{ .Values.slurmOperatorNamespace }}/{{ .Values.clusterName }} |
Grants |
|
RoleBinding |
{{ .Values.slurmOperatorNamespace }}/{{ .Values.clusterName }} |
Grants |
|
Secret |
{{ .Values.mungeConfigs.secretName }} |
Authenticates communications between Slurm components. Created when |
|
SlurmCluster |
The rendered SlurmCluster CR. |
The following table describes the parameters.
|
Parameter |
Sample value |
Description |
|
clusterName |
"" |
The cluster name, used to generate resources like Secrets and Roles. Must match |
|
headNodeConfig |
None |
Required. Defines the pod configuration for |
|
workerNodesConfig |
None |
Defines the pod configuration for |
|
workerNodesConfig.deleteSelfBeforeSuspend |
true |
When |
|
slurmdbdConfigs |
None |
Defines the |
|
slurmrestdConfigs |
None |
Defines the |
|
headNodeConfig.hostNetwork slurmdbdConfigs.hostNetwork slurmrestdConfigs.hostNetwork workerNodesConfig.workerGroups[].hostNetwork |
false |
Sets the |
|
headNodeConfig.setHostnameAsFQDN slurmdbdConfigs.setHostnameAsFQDN slurmrestdConfigs.setHostnameAsFQDN workerNodesConfig.workerGroups[].setHostnameAsFQDN |
false |
Sets the |
|
headNodeConfig.nodeSelector slurmdbdConfigs.nodeSelector slurmrestdConfigs.nodeSelector workerNodesConfig.workerGroups[].nodeSelector |
|
Sets the |
|
headNodeConfig.tolerations slurmdbdConfigs.tolerations slurmrestdConfigs.tolerations workerNodesConfig.workerGroups[].tolerations |
|
Sets the |
|
headNodeConfig.affinity slurmdbdConfigs.affinity slurmrestdConfigs.affinity workerNodesConfig.workerGroups[].affinity |
|
Sets the |
|
headNodeConfig.resources slurmdbdConfigs.resources slurmrestdConfigs.resources workerNodesConfig.workerGroups[].resources |
|
Resources for the main container. In worker pods, the main container's resource limits determine the Slurm node capacity. |
|
headNodeConfig.image slurmdbdConfigs.image slurmrestdConfigs.image workerNodesConfig.workerGroups[].image |
"registry-cn-hangzhou.ack.aliyuncs.com/acs/slurm:23.06-1.6-aliyun-49259f59" |
The container image for the main container. For custom images, see ai-models-on-ack/framework/slurm/building-slurm-image at main · AliyunContainerService/ai-models-on-ack (github.com). |
|
headNodeConfig.imagePullSecrets slurmdbdConfigs.imagePullSecrets slurmrestdConfigs.imagePullSecrets workerNodesConfig.workerGroups[].imagePullSecrets |
|
Sets the image pull secret for the corresponding pod(s). |
|
headNodeConfig.podSecurityContext slurmdbdConfigs.podSecurityContext slurmrestdConfigs.podSecurityContext workerNodesConfig.workerGroups[].podSecurityContext |
|
Sets the |
|
headNodeConfig.securityContext slurmdbdConfigs.securityContext slurmrestdConfigs.securityContext workerNodesConfig.workerGroups[].securityContext |
|
Sets the security context for the main container of the corresponding pod(s). |
|
headNodeConfig.volumeMounts slurmdbdConfigs.volumeMounts slurmrestdConfigs.volumeMounts workerNodesConfig.workerGroups[].volumeMounts |
None |
Sets the volume mounts for the main container of the corresponding pod(s). |
|
headNodeConfig.volumes slurmdbdConfigs.volumes slurmrestdConfigs.volumes workerNodesConfig.workerGroups[].volumes |
None |
Sets the volumes for the corresponding pod(s). |
|
slurmConfigs.slurmConfigPathInPod |
"" |
Mount path for Slurm configurations in the pod. Declare the |
|
slurmConfigs.createConfigsByConfigMap |
true |
Whether to auto-create a ConfigMap for Slurm configuration files. |
|
slurmConfigs.configMapName |
"" |
The name of the ConfigMap that stores the Slurm configuration files. |
|
slurmConfigs.filesInConfigMap |
"" |
Configuration file content when the ConfigMap is auto-created. |
|
mungeConfigs.mungeConfigPathInPod |
None |
Mount path for MUNGE configurations in the pod. Declare the |
|
mungeConfigs.createConfigsBySecret |
None |
Whether to auto-create a Secret for the MUNGE configuration file. |
|
mungeConfigs.secretName |
None |
The name of the Secret when it is automatically created. |
|
mungeConfigs.content |
None |
MUNGE configuration content when the Secret is auto-created. |
See the Slurm System Configuration Tool for slurmConfigs.filesInConfigMap options.
If you modify slurmConfigs.filesInConfigMap after pods start, recreate the pods for changes to take effect. Confirm file content before installation.
To install the chart:
-
Add the Alibaba Cloud chart repository to your local Helm client.
helm repo add aliyun https://aliacs-app-catalog.oss-cn-hangzhou.aliyuncs.com/charts-incubator/This adds access to Alibaba Cloud charts, including the Slurm chart.
-
Pull and extract the Helm chart.
helm pull aliyun/ack-slurm-cluster --untar=trueThis creates an
ack-slurm-clusterdirectory containing the chart files and templates. -
Modify the chart parameters in the values.yaml file.
Edit
values.yamlto customize the Slurm configuration, resource requests, and storage options.cd ack-slurm-cluster vi values.yaml -
Install the chart.
cd .. helm install my-slurm-cluster ack-slurm-cluster # You can replace my-slurm-cluster with a custom release name.This deploys the Slurm-managed cluster.
-
Verify the deployment
Use
kubectlto verify that the Slurm cluster pods are running.kubectl get pods -l app.kubernetes.io/name=slurm-cluster
Step 3: Log on to the Slurm cluster
For Kubernetes cluster administrators
Kubernetes cluster administrators can use kubectl to log on to any pod in the Slurm-managed cluster, which grants root permissions within Slurm.
Log on to any pod of the Slurm-managed cluster.
# Replace slurm-job-demo-xxxxx with the name of a specific pod in your cluster.
kubectl exec -it slurm-job-demo-xxxxx -- bash
For regular Slurm cluster users
Users without kubectl exec permissions must log on to the Slurm-managed cluster through SSH.
-
A Service external IP provides persistent access through a load balancer, accessible from anywhere within your internal network.
-
Port forwarding is a temporary solution for debugging, as
kubectl port-forwardmust run continuously.
Use an external IP
-
Create a
LoadBalancerService to expose internal services. See Use an existing Server Load Balancer instance to expose an application or Expose an application by using an automatically created LoadBalancer Service.-
Use an internal-facing Classic Load Balancer (CLB) instance.
-
Add the
kai.alibabacloud.com/slurm-cluster: ack-slurm-cluster-1andkai.alibabacloud.com/slurm-node-type: headlabels to route requests to the correct pod.
-
-
Obtain the external IP address of the
LoadBalancerService.kubectl get svc -
Log on to the head pod with SSH.
# Replace $YOURUSER with the username in the pod and $EXTERNAL_IP with the external IP address obtained from the Service. ssh $YOURUSER@$EXTERNAL_IP
Use port forwarding
Port forwarding requires saving the KubeConfig file locally, which poses a security risk. Do not use in production.
-
Start port forwarding on your local machine. This maps local port
$LOCALPORTto port 22 (SSH) of the slurmctld pod.# Replace $NAMESPACE, $CLUSTERNAME, and $LOCALPORT with their actual values. kubectl port-forward -n $NAMESPACE svc/$CLUSTERNAME $LOCALPORT:22 -
While
port-forwardis running, log on to the cluster and submit jobs.# $YOURUSER is the username to use when logging on to the pod. ssh -p $LOCALPORT $YOURUSER@localhost
Step 4: Use SlurmCluster
Configure user synchronization, shared logging, and auto scaling for your SlurmCluster.
User synchronization across nodes
Slurm lacks built-in centralized user authentication. Jobs submitted with sbatch fail if the user account does not exist on the target node. Configure LDAP as a centralized authentication backend to resolve this.
-
Create a file named
ldap.yamlwith the following content to deploy a basic LDAP service.The
ldap.yamlfile defines a pod for the LDAP service and a Service to expose it. -
Deploy the LDAP backend service:
kubectl apply -f ldap.yamlExpected output:
deployment.apps/ldap created service/ldap-service created secret/ldap-secret created -
(Optional) Deploy a frontend interface for improved management. Create a file named
phpldapadmin.yamlwith the following content.Deploy the LDAP frontend service:
kubectl apply -f phpldapadmin.yaml -
Log on to a SlurmCluster pod as described in Step 3, then install the LDAP client package:
apt update apt install libnss-ldapd -
After installing
libnss-ldapd, configure the network authentication service from within the pod.-
Install Vim for editing scripts and files:
apt update apt install vim -
Configure the LDAP client in
/etc/ldap/ldap.conf:... BASE dc=example,dc=org # Replace this with the base DN of your LDAP directory. URI ldap://ldap-service # Replace this with the address of your LDAP server. ... -
Define the LDAP server connection in
/etc/nslcd.conf:... uri ldap://ldap-service # Replace this with the address of your LDAP server. base dc=example,dc=org # Set this based on your LDAP directory structure. ... tls_cacertfile /etc/ssl/certs/ca-certificates.crt # Specifies the path to the CA certificate file used to verify the LDAP server certificate. ...
-
Log sharing and access
By default, sbatch job logs are stored on the node where the job runs. Create a NAS file system to centralize log storage across all nodes.
-
Create a NAS file system to store and share logs from all nodes.
-
Log on to the ACK console and create a PV and PVC for the NAS file system. See Use a statically provisioned NAS volume.
-
Modify the SlurmCluster CR.
Add
volumeMountsandvolumestoheadGroupSpecand eachworkerGroupSpecto mount the PVC to /home:headGroupSpec: ... # Add a volume mount for /home. volumeMounts: - mountPath: /home name: test # The name of the volume that references the PVC. volumes: # Add the PVC definition. - name: test # This must match the name in volumeMounts. persistentVolumeClaim: claimName: test # Replace this with the name of your PVC. ... workerGroupSpecs: # ... Repeat the preceding volume and volumeMounts configuration for each workerGroupSpec. -
Apply the changes to the SlurmCluster CR:
ImportantIf the SlurmCluster CR fails to deploy, delete it with
kubectl delete slurmcluster slurm-job-demoand redeploy.kubectl apply -f slurmcluster.yamlAll worker nodes now share the same file system.
Auto scaling
The default Slurm image includes slurm-resume.sh, slurm-suspend.sh, and slurmctld-copilot in the root directory. These scripts interact with slurmctld to manage cluster scaling.
Slurm auto scaling with cloud nodes
-
local node: A physical compute node that is directly connected to the cluster manager.
-
cloud node: A logical node that represents a VM instance that can be created and terminated on demand by a cloud provider.
Auto scaling in Slurm on ACK
Procedure
-
Configure permissions for auto scaling. If you installed with Helm, skip this step — permissions are already created.
Auto scaling requires the head pod to access and update the SlurmCluster CR. Grant permissions with RBAC.
Create the ServiceAccount, Role, and RoleBinding required by slurmctld. For a SlurmCluster named
slurm-job-demoin thedefaultnamespace, save the following torbac.yaml:apiVersion: v1 kind: ServiceAccount metadata: name: slurm-job-demo --- apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: name: slurm-job-demo rules: - apiGroups: ["kai.alibabacloud.com"] resources: ["slurmclusters"] verbs: ["get", "watch", "list", "update", "patch"] resourceNames: ["slurm-job-demo"] --- apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: name: slurm-job-demo subjects: - kind: ServiceAccount name: slurm-job-demo roleRef: kind: Role name: slurm-job-demo apiGroup: rbac.authorization.k8s.ioApply the manifest with
kubectl apply -f rbac.yaml.Assign permissions to the
slurmctldpod. Runkubectl edit slurmcluster slurm-job-demoand set.spec.slurmctld.template.spec.serviceAccountNameto the ServiceAccount you created.apiVersion: kai.alibabacloud.com/v1 kind: SlurmCluster ... spec: slurmctld: template: spec: serviceAccountName: slurm-job-demo ...Recreate the slurmctld StatefulSet to apply changes. View it with
kubectl get sts slurm-job-demoand delete it withkubectl delete sts slurm-job-demo. The operator recreates the StatefulSet with the new configuration. -
Configure auto scaling in the
/etc/slurm/slurm.conffile.Shared file system
# The following settings are required when using cloud nodes. # SuspendProgram and ResumeProgram are custom-developed features. SuspendTimeout=600 ResumeTimeout=600 # The interval after which an idle node is automatically suspended. SuspendTime=600 # The number of nodes that can be scaled out or in per minute. ResumeRate=1 SuspendRate=1 # The NodeName format must be ${cluster_name}-worker-${group_name}-. You must declare the node's resources in this line. # Otherwise, slurmctld treats the node as having only 1 CPU core. # To avoid resource waste, ensure that the resources declared here match the resources specified in the workerGroup. NodeName=slurm-job-demo-worker-cpu-[0-10] Feature=cloud State=CLOUD # The following settings are fixed and should not be changed. CommunicationParameters=NoAddrCache ReconfigFlags=KeepPowerSaveSettings SuspendProgram="/slurm-suspend.sh" ResumeProgram="/slurm-resume.sh"ConfigMap
If
slurm.confis in theslurm-configConfigMap, runkubectl edit slurm-configto add the following:slurm.conf: ... # The following settings are required when using cloud nodes. # SuspendProgram and ResumeProgram are custom-developed features. SuspendTimeout=600 ResumeTimeout=600 # The interval after which an idle node is automatically suspended. SuspendTime=600 # The number of nodes that can be scaled out or in per minute. ResumeRate=1 SuspendRate=1 # The NodeName format must be ${cluster_name}-worker-${group_name}-. You must declare the node's resources in this line. # Otherwise, slurmctld treats the node as having only 1 CPU core. # To avoid resource waste, ensure that the resources declared here match the resources specified in the workerGroup. NodeName=slurm-job-demo-worker-cpu-[0-10] Feature=cloud State=CLOUD # The following settings are fixed and should not be changed. CommunicationParameters=NoAddrCache ReconfigFlags=KeepPowerSaveSettings SuspendProgram="/slurm-suspend.sh" ResumeProgram="/slurm-resume.sh"Helm
-
Add the following to
values.yaml:slurm.conf: ... # The following settings are required when using cloud nodes. # SuspendProgram and ResumeProgram are custom-developed features. SuspendTimeout=600 ResumeTimeout=600 # The interval after which an idle node is automatically suspended. SuspendTime=600 # The number of nodes that can be scaled out or in per minute. ResumeRate=1 SuspendRate=1 # The NodeName format must be ${cluster_name}-worker-${group_name}-. You must declare the node's resources in this line. # Otherwise, slurmctld treats the node as having only 1 CPU core. # To avoid resource waste, ensure that the resources declared here match the resources specified in the workerGroup. NodeName=slurm-job-demo-worker-cpu-[0-10] Feature=cloud State=CLOUD # The following settings are fixed and should not be changed. CommunicationParameters=NoAddrCache ReconfigFlags=KeepPowerSaveSettings SuspendProgram="/slurm-suspend.sh" ResumeProgram="/slurm-resume.sh" -
Run
helm upgradeto update the Slurm configuration.
-
-
Apply the new configuration.
For a SlurmCluster named
slurm-job-demo, runkubectl delete sts slurm-job-demoto apply the new configuration to theslurmctldpod. -
Set the worker node replica count to 0 to observe auto scaling from the beginning.
Manual
For a SlurmCluster named
slurm-job-demo, runkubectl edit slurmcluster slurm-job-demoand setworkerCountto 0 in theworkerGroup.Helm
In
values.yaml, set.Values.workerGroup[].workerCountto 0, then runhelm upgrade slurm-job-demo .to apply. -
Submit an sbatch job.
-
Create a shell script:
cat << EOF > cloudnodedemo.shEnter the following:
#!/bin/bash srun hostname EOF -
Verify the script content:
cat cloudnodedemo.shExpected output:
#!/bin/bash srun hostnameThe script output is correct.
-
Submit the script to the SlurmCluster.
sbatch cloudnodedemo.shExpected output:
Submitted batch job 1The job was submitted and assigned a job ID.
-
-
View the cluster scaling status.
-
View the SlurmCluster scaling logs.
cat /var/log/slurm-resume.logExpected output:
namespace: default cluster: slurm-demo resume called, args [slurm-demo-worker-cpu-0] slurm cluster metadata: default slurm-demo get SlurmCluster CR slurm-demo succeed hostlists: [slurm-demo-worker-cpu-0] resume node slurm-demo-worker-cpu-0 resume worker -cpu-0 resume node -cpu-0 endThe SlurmCluster automatically added a compute node to meet job demand.
-
View the pod status in the cluster.
kubectl get podExpected output:
NAME READY STATUS RESTARTS AGE slurm-demo-head-9hn67 1/1 Running 0 21m slurm-demo-worker-cpu-0 1/1 Running 0 43sslurm-demo-worker-cpu-0 is the new pod, indicating the job triggered scale-out.
-
View the cluster node information.
sinfoExpected output:
PARTITION AVAIL TIMELIMIT NODES STATE NODELIST debug* up infinite 10 idle~ slurm-job-demo-worker-cpu-[2-10] debug* up infinite 1 idle slurm-job-demo-worker-cpu-[0-1]slurm-demo-worker-cpu-0 is the newly launched node. 10 additional nodes (1-10) are available for scaling out.
-
View the completed job information.
scontrol show job 1Expected output:
JobId=1 JobName=cloudnodedemo.sh UserId=root(0) GroupId=root(0) MCS_label=N/A Priority=4294901757 Nice=0 Account=(null) QOS=(null) JobState=COMPLETED Reason=None Dependency=(null) Requeue=1 Restarts=0 BatchFlag=1 Reboot=0 ExitCode=0:0 RunTime=00:00:00 TimeLimit=UNLIMITED TimeMin=N/A SubmitTime=2024-05-28T11:37:36 EligibleTime=2024-05-28T11:37:36 AccrueTime=2024-05-28T11:37:36 StartTime=2024-05-28T11:37:36 EndTime=2024-05-28T11:37:36 Deadline=N/A SuspendTime=None SecsPreSuspend=0 LastSchedEval=2024-05-28T11:37:36 Scheduler=Main Partition=debug AllocNode:Sid=slurm-job-demo:93 ReqNodeList=(null) ExcNodeList=(null) NodeList=slurm-job-demo-worker-cpu-0 BatchHost=slurm-job-demo-worker-cpu-0 NumNodes=1 NumCPUs=1 NumTasks=1 CPUs/Task=1 ReqB:S:C:T=0:0:*:* ReqTRES=cpu=1,mem=1M,node=1,billing=1 AllocTRES=cpu=1,mem=1M,node=1,billing=1 Socks/Node=* NtasksPerN:B:S:C=0:0:*:* CoreSpec=* MinCPUsNode=1 MinMemoryNode=0 MinTmpDiskNode=0 Features=(null) DelayBoot=00:00:00 OverSubscribe=OK Contiguous=0 Licenses=(null) Network=(null) Command=//cloudnodedemo.sh WorkDir=/ StdErr=//slurm-1.out StdIn=/dev/null StdOut=//slurm-1.out Power=NodeList=slurm-demo-worker-cpu-0 indicates the job ran on the newly added node.
-
After a while, view the node scale-in information.
sinfoExpected output:
PARTITION AVAIL TIMELIMIT NODES STATE NODELIST debug* up infinite 11 idle~ slurm-demo-worker-cpu-[0-10]Nodes 0-10 are available again, indicating automatic scale-in is complete.
-