Free · runs in the browser

One cluster.
Three tools.

A login node and twenty-one compute nodes, with a scheduler that really allocates them. Submit a job and it lands on named hardware; drain a node and the queue notices. Slurm, Spack and Apptainer on the same machines, because that is where you meet them.

user@login-01: ~
$ sbatch --nodes=4 mpi_job.sh
Submitted batch job 4821100
 
$ squeue --me
JOBID PARTITION NAME ST TIME NODES NODELIST(REASON)
4821100 compute mpi_job PD 0:00 4 (Resources)
 
$ sinfo -R
REASON USER TIMESTAMP NODELIST
maintenance root 2026-08-09T14:02:11 node007
 
$ scontrol update NodeName=node007 State=RESUME
(no output — scontrol is silent on success)
 
$ squeue --me
JOBID PARTITION NAME ST TIME NODES NODELIST(REASON)
4821100 compute mpi_job R 0:02 4 node[005-008]
 
$
21
Nodes
6
Partitions
3
Tool tracks
0
Queue time

Three tools, one set of machines

On a real cluster these are not separate subjects. You build software with Spack, wrap it with Apptainer, and run it through Slurm — and the interesting failures happen where they meet. So they share a cluster here too.

A command has to change something

The cluster keeps one record of which job holds which cores. Every view — squeue, sinfo, scontrol show node — is computed from it, so they cannot disagree. Nothing prints a success it did not perform.

▤
The scheduler schedules

--nodes=4 takes four nodes, or waits. Ask for more cores than the partition has and it stays pending with the reason a real controller would give. Cancel it and the cores come back.

⌗
It shows up in the logs

Submitting writes to slurmctld.log. Starting writes to the slurmd log on each allocated node. You can grep for your own job ID and watch the allocation happen.

⌸
It is a real shell

Pipes, redirects, command substitution, separate stdout and stderr, vim and nano, ssh between nodes, a filesystem with permissions. The scheduler is the new part; the machine underneath is not.