Cluster Validation Suite (CVS) cluster file: configuration and backend selection#
2026-10-27
13 min read time
In SSH mode, each cvs run invocation is pointed at a cluster file using --cluster_file <path>. The cluster file declares the SSH credentials, the node list, and an orchestrator value. Which suites follow that value is in the scope table below.
Note
Under a Slurm or SPUR job step --cluster_file is optional. See Run Cluster Validation Suite (CVS) on managed compute.
CVS ships two starter templates for the cluster file.
Template |
Backend |
Use when |
|---|---|---|
|
|
ROCm, RVS, RCCL, and other workload binaries are installed on the host filesystem. |
|
|
A suite that runs its workload in a per-host container. The host needs Docker, GPUs, and SSH. |
Copy the template that matches the suite you are running, edit the placeholders, and pass it to cvs run. cvs exec and cvs scp read the same file for hosts and SSH credentials and ignore orchestrator.
For SSH-mode runs, configure Set up passwordless SSH for Cluster Validation Suite (CVS) cluster nodes before running CVS against the cluster.
Prerequisites on each cluster node#
Every cluster node must meet the following requirements before using the container backend.
Requirement |
Details |
|---|---|
Docker installed |
The SSH user needs passwordless |
Host ROCm driver loaded |
|
SSH directory accessible |
Required only when the suite starts in-container sshd. CVS mounts
|
Container image available |
The image must be pre-loaded on each node, provided as |
Backends#
--cluster_file carries orchestrator (baremetal or container). Write those values in lowercase. The factory accepts any case, and the fixtures that start a container compare against the lowercase string container.
Suites do not all follow the key.
What the suite does |
Suites |
|---|---|
Honors the cluster key. With |
|
Honors the key and starts that same container (and sshd on more than one node), then runs its own checks on the host. |
|
Honors the key and skips the suite when the value is |
|
Honors the cluster key unless the MORI config sets |
|
Honors the cluster key. A first test step starts the container; GPU and NIC discovery, the perftest build and perftest then run inside it. sshd is not started. Dmesg and AFM vPOD discovery stay on the host. |
|
Forces |
|
Ignores |
|
Baremetal#
Baremetal is the default when a suite honors orchestrator and you leave the key unset. Commands go over SSH and run on the host filesystem.
Container#
When a suite runs a container, CVS reaches each node and starts one container there. In SSH mode that reachability is SSH. On a Slurm or SPUR job step it is the per-node HTTP agent (see Run Cluster Validation Suite (CVS) on managed compute). Later workload commands are docker exec into that container (docker exec <name> bash -c <cmd>). per_run, the default container.lifetime, starts the container at setup and removes it at teardown.
docker exec does not use port 2224. CVS starts sshd inside the container on port 2224 only so mpirun can SSH to peer containers (-p 2224). That step copies /host_ssh to /root/.ssh and runs /usr/sbin/sshd -p2224. It is skipped on a single node, and on a Slurm or SPUR job step. The health suites, RCCL, host_configs_cvs, and install_ompi use the shared fixture, which calls this step. preflight_checks has its own fixture that does the same. ATOM calls it. vLLM skips it. Aorta, SGLang, xDiT, megatron_single, megatron_distributed, TorchTitan, JAX MaxText, and MORI launch a container without calling it.
Cluster file shape#
Both templates share the same top-level shape.
Note
{user-id} is expanded to the user running CVS (USER, then LOGNAME, then USERNAME, then root) when a suite loads the cluster file, and when you run cvs monitor check_cluster_health. cvs exec and cvs scp leave the characters {user-id} as the SSH user and key path. Put a literal username in a file you pass to those two commands. The placeholders {xx.xx.xx.xx|hostname-N} are examples for real IPs or hostnames.
cluster_container.json
{
"orchestrator": "container",
"username": "{user-id}",
"priv_key_file": "/home/{user-id}/.ssh/id_rsa",
"head_node_dict": {
"mgmt_ip": "{xx.xx.xx.xx|hostname-1}"
},
"env_vars": {},
"node_dict": {
"{xx.xx.xx.xx|hostname-1}": {
"bmc_ip": "NA",
"vpc_ip": "{xx.xx.xx.xx|hostname-1}"
},
"{xx.xx.xx.xx|hostname-2}": {
"bmc_ip": "NA",
"vpc_ip": "{xx.xx.xx.xx|hostname-2}"
}
},
"container": {
"lifetime": "per_run",
"image": "rocm/cvs:latest",
"name": "cvs_container",
"runtime": {
"name": "docker",
"args": {
"network": "host",
"ipc": "host",
"privileged": true
}
}
}
}
Top-level parameters#
The following table describes every key accepted at the top level of the cluster file.
Configuration parameter |
Default value |
Description |
|---|---|---|
|
|
|
|
|
SSH username for all hosts. Expanded for |
|
|
Absolute path to the SSH private key used for every host. The same |
|
(optional) |
Stored and schema-checked. The orchestrator does not SSH here. See “Which host is the head” below. |
|
|
Shell |
|
(required) |
Cluster member nodes keyed by public IP or hostname. Each value is |
|
(generated) |
Written by CVS in scheduler-managed runs only; path to the agent bearer token. Do not set by hand. |
|
|
Container backend configuration. Required when a suite builds a container orchestrator. See the next section. |
Which host is the head#
CVS uses three different hosts. Setting one does not change the others.
Host |
What it is |
|---|---|
Launch host |
The machine where you run the |
Orchestrator head |
The first |
|
Optional field stored on the config. The orchestrator does not select its SSH head from it. Some suites overwrite it so it matches the host they already chose as the first |
CVS’s own privileged commands — the Docker CLI calls (docker run, exec, rm, ps, load, pull, login) and the MPI hostfile write — probe sudo -n true once per orchestrator. The cached answer is the orchestrator head’s result, and CVS prefixes every later privileged command on every host with ``sudo -n `` or with nothing. If the nodes disagree, CVS logs a warning and still uses the head’s answer. No cluster-file key controls this.
Container block#
The container block configures the container backend. It is consumed by the ContainerOrchestrator defined in cvs/core/orchestrators/container.py.
The following table describes each key in the container block.
Configuration parameter |
Default value |
Description |
|---|---|---|
|
|
Container lifecycle policy: |
|
(required) |
Image tag. Setup fails when this is missing. If any host does not already have |
|
|
Optional. Omit it and CVS builds the name from the user running |
|
|
Environment inside the container ( |
|
(unset) |
Path on each node. When set and any host lacks |
|
|
Container runtime. |
|
|
Backend-specific runtime arguments (see the next section). |
Docker runtime.args reference#
When runtime.name is docker, the keys below configure the underlying docker run command. Defaults are merged from DEFAULT_CONTAINER_ARGS in cvs/core/orchestrators/container.py:
List arguments (
volumes,devices,cap_add,security_opt,group_add,ulimit) append to the baked-in defaults.Scalar arguments (
network,ipc,privileged) override the default when set, otherwise inherit it.envis a map of extradocker -eflags, applied aftercontainer.env.registryis not adocker runflag. Whenimage_taris unset andregistryis set, CVS runsdocker loginon every node before the pull.usernameandpassword_fileare required;password_fileis a path on each node;serveris optional.An empty
args: {}already yields a working RDMA-ready container. The keys below are only needed to extend or override.
The following table lists the supported runtime.args keys and their defaults.
Argument |
Default value |
Description |
|---|---|---|
|
|
|
|
|
|
|
|
|
|
Appended |
List of |
|
|
Device passthroughs. CVS also passes through each device node under |
|
|
Linux capabilities. |
|
|
Security profile relaxations needed for RDMA and ptrace. |
|
|
Supplementary groups inside the container. |
|
|
Per-process resource limits. |
|
(unset) |
Extra |
|
(unset) |
|
|
(unset) |
|
|
(unset) |
|
lifetime truth table#
setup_containers and teardown_containers branch on container.lifetime. The behavior below is pinned by the per-lifetime unit tests in cvs/core/orchestrators/unittests/test_container.py.
The following table shows what each lifetime value does during setup and teardown.
|
|
|
|---|---|---|
|
Verify a container with the configured name is already running on every host; set |
No-op. CVS does not own a container it did not launch. |
|
Start a fresh container on every host (force-removing any stale same-named container first). |
Force-remove the container CVS started. |
|
Attach if the container is already running on every host. Start fresh only if it is running on no host. Running on some hosts but not all is a hard error (CVS will not force-remove the still-running hosts and destroy their overlay). Idempotent across runs. |
No-op. The container is left running for the next run; remove it yourself when done. |
Note
With lifetime: persistent, pin container.name. The default name is the user running cvs, then _, then the image with characters outside [A-Za-z0-9_] replaced by _. That name changes when you change the image tag, and the previous container’s overlay is left behind.