Apptainer installed only on the head node; containerized sbatch jobs fail on compute¶
Date: 2026-04-13. Impact: harness.
← back to the Exercise Validation summary
What happened¶
user/containers.md exercise 2 submits a containerized batch
job that the compute node has to execute. The Ansible
setup-software.yml playbook installs Apptainer via dnf (with
an upstream EPEL-9 RPM fallback), but only targets the head
node. pcluster compute nodes boot from a stock AL2023 AMI
which does NOT ship Apptainer, so apptainer exec fails with
command not found on any compute-bound job.
Four workable fix paths, in roughly increasing order of one-time setup effort:
-
Apptainer built from source into
/shared/apptainer/(EBS, visible on all nodes). Apptainer's./mconfig --prefix=/shared/apptainer/ && make && make installproduces a fully relocatable install. ~10-20 minutes of build time using a compute node's Go toolchain, then every compute node reaches apptainer at/shared/apptainer/bin/apptainer. Add the prefix to each job script's PATH (or ship an Lmod modulefile:/shared/modulefiles/apptainer/1.3.6.lua) and training users follow the samemodule load apptainerpattern they already know from Lmod. Most pcluster-idiomatic per the surrounding training content; also works on PCS with zero config change. -
CustomActions.OnNodeConfiguredruns a script at node boot. The scriptdnf install -y <apptainer-rpm-url>. Cleanest from pcluster's perspective but requires a cluster-config update and a cluster restart. MUST handle package-manager contention on freshly-booted nodes — cloud-init, dnf-automatic, unattended-upgrades can all be mid-operation. Recommended script skeleton:
#!/bin/bash
set -e
# Wait for any concurrent package-manager work to drain.
for i in $(seq 1 60); do
fuser /var/cache/dnf/metadata_lock.pid \
/var/lib/rpm/.rpm.lock \
/var/lib/dnf/rpmdb_lock.pid 2>/dev/null || break
echo "Waiting for dnf lock (${i}/60)" ; sleep 5
done
# Retry with backoff — DNS warmup and mirror flakes are common.
for attempt in 1 2 3; do
dnf install -y \
https://github.com/apptainer/apptainer/releases/download/v1.3.6/apptainer-1.3.6-1.x86_64.rpm \
&& exit 0
sleep $(( attempt * 10 ))
done
exit 1
-
Custom AMI with Apptainer pre-baked, referenced via
Image.CustomAmiin the pcluster config. Fastest compute- node boot time (no per-boot install step), most effort up-front (image-build pipeline). -
RPM extracted + relocated into
/shared/apptainer/. Fragile — apptainer's binaries have compiled-in paths for/usr/libexec/apptainer/,/etc/apptainer/, etc. Requires wrapper scripts with environment overrides for every invocation. Not recommended.
Until one of these lands, the containers ex2 test detects the missing binary on compute and skips with a clear message. Containers ex1 (the head-node apptainer pull) still runs.
Fix commits¶
slurm-training-validation@pending— containers.bats ex2 skips when apptainer is absent on compute