Soperator (Slurm-on-Kubernetes)
SkillCloud & infraUse to deploy or operate a Nebius soperator (Slurm-on-Kubernetes) cluster from npa — the npa.soperator/v0.0.1 spec, multi-preset worker pools, per-pool Docker/Enroot image cache, quota preflight, and post-deploy fixes.
Available today. Use it from your connected AI after setup.
No other account needed.
Connect ahel once, and every AI you use reads what you have installed.
Then ask your AI: use the Soperator (Slurm-on-Kubernetes) skill
What this skill tells your AI
The instructions your AI receives, as published by nebius/nebius-physical-ai in skills/tools/soperator/SKILL.md and read by ahel’s review.
When To Use
Use when a customer wants a managed Slurm cluster on Nebius (foundation-model
pretraining, large eval sweeps, HPC batch) instead of, or alongside, SkyPilot —
and wants npa to drive it. npa soperator deploy wraps the public
nebius/nebius-solutions-library soperator Terraform recipe from a compact
declarative spec, so customers get a working Slurm cluster without hand-editing
the recipe's large tfvars.
Three-tier contract:
- CLI:
npa soperator plan|deploy --spec <cluster.yaml>,npa soperator status --name <n>,npa soperator destroy --name <n>. - SDK:
npa.sdk.soperator.plan(spec)/deploy(spec)/destroy(name)withSoperatorSpec/WorkerPoolSpec. - YAML / agent:
apiVersion: npa.soperator/v0.0.1spec; workflowtoolRef: infra.soperator.deploy. - Fleet:
npa.fleet/v0.0.1targets may selectbackend: soperatorand embed this same spec undersoperator:. Standalone, SDK, and fleet call the same backend lifecycle; fleet remains responsible for identity, selection, concurrency, inventory, and shared-network ownership. Soperator names are fleet-wide physical/context identities and therefore must be unique even when targets belong to different projects.
Spec (npa.soperator/v0.0.1)
Multiple worker pools with different presets are first-class; each pool can
enable a node-local Docker/Enroot image cache disk (NETWORK_SSD_IO_M3) so
large GPU tool images don't thrash the boot disk.
apiVersion: npa.soperator/v0.0.1
name: npasop # company_name; kube context = nebius-<name>-slurm
region: us-central1 # or resolved from ~/.npa config
control_plane:
system: { min_size: 3, max_size: 24 } # preset omitted: derive XS..XL upstream
controller: {} # preset omitted: derive with same tier
login: { preset: 16vcpu-64gb } # login needs >= 16vcpu (sufficiency)
workers:
- name: cpu8
platform: cpu-d3
preset: 8vcpu-32gb
docker_cache: true # node-local IO_M3 image cache
docker_cache_gib: 930 # divisible by 93
- name: gpu
platform: gpu-b200-sxm
preset: 8gpu-160vcpu-1792gb # GPU workers must be fabric-capable (8-GPU SXM)
size: 2
fabric: us-central1-b # required for GPU presets; 1-GPU can't cluster
preemptible: true # on-demand GPU quota is often 0; preemptible works
# For reserved capacity, set preemptible: false and exactly one runtime
# selector. Never commit a live ID/name:
# capacity_block_group: <capacity-block-group-id>
# capacity_block_group_name: <unique-capacity-block-group-name>
docker_cache: true
accounting: false
# omitted REST preserves the legacy default (follows accounting); GPU checks still run directly
slurm_operator_version: "4.1.6"
k8s_version: "1.34"
node_group_version: "72"
Procedure
- Keep committed files public-safe: never hardcode project/tenant/registry IDs
or SSH keys in the skill or spec templates. The spec resolves region/tenant/
project from
~/.npa/config.yamlwhen its fields are empty. Login access is deliberately named as a root grant: oneroot_login_ssh_public_keyrecord,--root-login-ssh-public-key-file,NPA_SOPERATOR_ROOT_LOGIN_SSH_PUBLIC_KEY[_FILE], the compatibleNPA_SSH_PUBLIC_KEYpath, then~/.ssh/id_ed25519.pub/id_rsa.pub/id_ecdsa.pub. NPA validates one OpenSSH record and logs only its source and SHA256 fingerprint. The legacy one-elementssh_public_keyslist remains accepted; multiple records fail early. - Plan with
npa soperator plan --spec cluster.yaml. The public-safe output labels every worker pool ason-demand,preemptible, orreservedwithout echoing reservation selectors. Appliedstatusoutput reads local Terraform state and reports the same capacity modes. - Preflight quotas (the deploy hits these in order; raise before applying):
compute.instance.count— ~7 instances for a 2-pool cluster.compute.instance.non-gpu.vcpu— sum of all node vCPUs.compute.disk.count— boot disks + one IO_M3 cache disk per docker-cache pool + NFS PVC (~10).compute.disk.size.network-ssd-io-m3— NFS PVC + docker-cache disks.- GPU on-demand quota is commonly 0; use
preemptible: truefor GPU pools. Read withnebius quotas quota-allowance get-by-name --parent-id <tenant> --region <region> --name <quota>.
- Bind reserved B200 capacity explicitly when required. Set exactly one
per-pool selector:
capacity_block_groupfor an immutable ID (fleet-compatible) orcapacity_block_group_namefor an exact tenant-scoped name. Reserved pools must be GPU pools withpreemptible: false. Before Terraform rendering, deploy verifies the selected project belongs to the selected tenant/region, resolves names uniquely, and requires the group to be tenant-owned, active, region/platform/fabric-compatible, and large enough for the additional GPUs. Existing applied STRICT workers are credited so idempotent reconciles do not demand duplicate capacity. Missing, cross-tenant, inactive, ambiguous, incompatible, unreadable, or insufficient reservations fail before provider mutation. The renderer passes the exact upstream contract:reservation_policy = { policy = "STRICT", reservation_ids = [...] }and never combines it withpreemptible.AUTOis not accepted because it can fall back to on-demand capacity. - Deploy:
npa soperator deploy --spec cluster.yaml --terraform-dir <solutions-lib>/soperator(omit--terraform-dirto clone the library). The default source is immutable solutions-library commit7046fb3c68314a940cdb47ff5c4fd23c01a6711e, not movingmain;--refaccepts only a full commit SHA. Before any provider mutation NPA verifies the checkout SHA, sizing thresholds, REST/accounting inputs, template patch targets, example Slurm chart4.1.6, Kubernetes1.34, and node bundle72. Requires terraform >= 1.12 (setNPA_TERRAFORM_BINif the system terraform is older). Existing default checkouts, including legacy shallow clones on movingmain, are reconciled in place under a filesystem lock: NPA fetches the exact missing commit and checks it out detached while preserving untracked installations, Terraform state, and operator-owned files. Tracked changes or conflicting untracked paths fail with recovery guidance; NPA never deletes or recreates an installation to repair source. Destroy uses the same resolver.deploy --source-preflight-onlyanddestroy --source-preflight-onlyexercise their real source/install boundaries without Terraform initialization or provider mutation/deletion. For an existing installation, its owner-only environment sidecar is the authoritative project/tenant/region/subnet identity; an ambient default can never override it, and an incomplete/corrupt sidecar fails closed. Sidecar replacement is atomic. Before each deploy apply, NPA saves a Terraform plan, inspects its machine-readable actions, refuses every provider replacement, pure delete, and unexpected destructive action, and applies only that exact inspected plan. The immutable source patch stabilizes the cluster-context and login-IP triggers. During its one-time migration, only the three exact audited local-only refresh resources may replace; subsequent plans contain zero replacements. The sidecar is checkpointed only after the guard passes and immediately before provider mutation. - Control-plane sizing follows the pinned upstream worker-count tiers:
XS
<10, S<100, M<500, L<2000, XL>=2000. Omitted system, controller, and accounting presets inherit the tier. Explicit presets remain compatible when large enough; NPA rejects component-specific undersizing before clone/apply (system minimums: 16/16/16/32/64 vCPU across XS..XL). The system nodeset defaults to autoscaling frommin_sizethrough 24. - REST and accounting are explicit but the verified runtime has an important
boundary: although the pinned Terraform module accepts the switches
independently, the exact Slurm operator
4.1.6implementation skips REST reconciliation without an accounting database. Omitted REST therefore keeps the compatible legacy default (it follows accounting), explicitslurm_rest_enabled: falseis accepted, and explicit REST-on/accounting-off fails before mutation with an actionable error. This does not remove GPU creation validation: after every deploy NPA submits an exclusive Slurm step through the login-node jail on every GPU worker, allocates every GPU, and requiresdeviceQuery,vectorAdd,simpleMultiGPU, andp2pBandwidthLatencyTestto reportPASS. Accounting+REST GPU specs may also use the upstreamdevActiveChecks; all other specs useessential. --apply-fixes(default) applies the pinned-contract fixes: themonitoring-systemnamespace and prometheus-operator CRDs (charts need both even with telemetry off), recovery for a dashboards HelmRelease whose remediation retries were exhausted before those prerequisites existed, theplugStackConfig.ncclInspectorPreConfCRD preserve-unknown-fields patch, and the cluster-name-prefixed<ns>-slurm-scriptsconfigmap. If a previous ActiveChecks Helm generation is demonstrably still Progressing while a newer generation is pending, NPA removes only the superseded Helm-owned wait hook and requests reconciliation; current-generation installs are never interrupted. For the default unconfined worker profile, NPA also extends the node configurator's sysctls so Ubuntu's AppArmor user-namespace gate does not block Enroot/Pyxis jobs. The template mutation is indentation-bounded tonodeConfigurator.valuesand is tied to the verified chart contract. Post-apply monitoring repair is best-effort: RBAC/transient failures are returned as diagnostics and do not turn an otherwise healthy Terraform reconciliation into a failed deploy. The direct GPU creation check is a required validation, not a best-effort repair; it still runs with--skip-fixes, and a missing node/GPU or failed CUDA result fails deployment. Its independent--gpu-creation-check-timeoutdefaults to 1,800 seconds and bounds the whole gate, Slurm queue wait (srun --immediate), Slurm wall time, and the local kubectl process. The deploy--timeoutremains Terraform-only and is never silently reused for GPU validation. Timed-out/failed gate jobs are cancelled by a unique name and verified absent fromsqueue. If the Terraform apply created/reconciled the cluster but this gate fails, the SDK raisesSoperatorDeploymentValidationErrorwith a public-saferesult; text/JSON CLI output retains the install directory, kube context, and pool metadata, reportsdegraded-validation, and exits nonzero.- Verify:
npa soperator status --name <name>runssinfoon the controller and reports each applied worker pool's capacity mode without reservation IDs. Destroy requires the exact persisted cluster ID and treats only provider NotFound as absence; unreadable provider evidence retains local recovery state.
Compatibility and migration
- Slurm operator 4.1.0: this former default is rejected because it is not in
the verified runtime contract. Replace it with
4.1.6for the default unconfined Enroot/Pyxis setup.4.1.7is accepted only withuse_default_apparmor_profile: trueafter separately validating that loaded profile on the nodes. Do not re-enable4.1.0. - System autoscaling ceiling: older NPA output fixed
control_plane.system.max_sizetomin_size. Omission now renders the pinned upstream maximum of 24 (ormin_sizewhen it is greater than 24), which can increase capacity and cost if autoscaling is exercised. Set an explicitcontrol_plane.system.max_sizeto retain a reviewed lower ceiling, provided it is at leastmin_size. Rendered tfvars, deploy results, and agent validation/dry-run output expose the effective numeric maximum. - Immutable source migration: default legacy clones are upgraded in place;
preserve a clean tracked checkout and keep installations/state untracked.
Offline migration works once the pinned object has been fetched. If it is
missing, restore access to the checkout's
originand retry.
Gotchas
- AppArmor: the custom localhost profile is not loaded by the verified chart;
the spec defaults
use_default_apparmor_profile: false(unconfined) so login/worker sshd start. Non-default chart versions are permitted only when the userns override is not needed (use_default_apparmor_profile: true); the explicit override allowlist is currently4.1.6and4.1.7. - Worker registration can race readiness. Post-deploy
repair sets the nodeset-service FQDN and resumes down nodes. If diagnosing by
hand, the equivalent is
scontrol update NodeName=<w> NodeAddr=<w>.soperator-nodeset-svc.soperator.svc.cluster.local State=RESUME. - Region domain: the recipe hardcodes the EU API domain; the deploy patches
it to
api.nebius.cloudfor non-EU regions automatically. - Job I/O: submit from the login node chrooted into
/mnt/jail; write batch--outputto a shared jail path (e.g./root/...), not node-local/tmp. - GPU workers: only 8-GPU SXM presets are fabric-capable; 1-GPU SXM presets return "does not support GPU clustering" and cannot be soperator GPU workers.
Verify
npa soperator plan --help
npa soperator deploy --help
npa/.venv/bin/python -m pytest npa/tests/unit/test_soperator_cli.py -q
Signals
- GitHub stars
- 28
- Forks
- 15
- Last commit
- Sep 2026
Advanced
- Catalog kind
- skill
- Gateway key
soperator- Source
- github.com/nebius/nebius-physical-ai