Config Init and Manifest Generation
AIPerf ships two offline commands that let you author benchmarks as files before touching a cluster:
aiperf kube init— scaffold a starter YAML config (anAIPerfJobCR template) that you can edit by hand.aiperf kube generate— render the finished Kubernetes manifests (either anAIPerfJobCR or a rawNamespace + RBAC + ConfigMap + JobSetbundle) to stdout or a file, with no cluster calls.
Both commands are the foundation of a GitOps workflow: you commit the
rendered YAML to a repo, open a PR for review, and then kubectl apply
the reviewed file. No cluster access is required to run either command.
aiperf kube init
Purpose
init renders one of the bundled AIPerf config templates
(src/aiperf/config/templates/, the same library aiperf config init
uses), wraps it in an AIPerfJob CR shell, and writes the result to
stdout (or to a file with --output). The default template
(minimal) covers only the required fields; commented-out blocks for
deployment options, pod customization, and Kueue scheduling are
appended to every template so you can uncomment what you need.
CLI reference
With no arguments, init renders the minimal template (bundled in
src/aiperf/config/templates/) wrapped in an AIPerfJob CR shell. Use
--list / --search / --category to browse the other bundled templates
and --template to pick one.
Examples
Template walkthrough
The scaffold is an AIPerfJob CR. Below is the template as emitted by
init; usage comments at the top are substituted with the filename
you wrote to (defaulting to benchmark.yaml).
The minimal template uses AIPerf’s shorthand forms — model: (scalar),
endpoint.url:, dataset: (singular), and a flat phases: block — which
AIPerf auto-expands to their canonical list forms at load time. Point
model: and endpoint.url: at your real model and server before running
anything else. A realistic edit looks like:
To scaffold a different starting point (goodput SLOs, multi-phase load,
etc.), pick another bundled template with aiperf kube init --list and
--template <name>.
Relationship with other commands
The file init writes is the same format accepted by every other
config-consuming command:
aiperf kube preflight is deliberately absent from that table: it does
not read a config file at all. It takes --image, --image-pull-secrets,
--secrets, --endpoint-url, --workers, and --output (plus the shared
namespace/kubeconfig flags) and probes the cluster with them.
When invoking profile or generate, CLI flags for Kubernetes
settings (--image, --namespace, --total-workers, etc.) still
overlay the CR — the file owns the benchmark config, the flags own the
deployment shape.
aiperf kube generate
Purpose
generate renders the YAML that would otherwise be submitted by
profile, and writes it to stdout. It does not connect to a cluster
and does not require the AIPerf operator to be installed.
It has two mutually exclusive modes:
--operator— emits oneAIPerfJobCR document for a single run, or oneAIPerfSweepCR document when the config hassweep:or requests multiple trials throughmultiRun.numRuns > 1/multiRun.convergence. Requires the AIPerf operator to be installed on the target cluster forkubectl applyto do anything useful.--no-operator— emits multiple documents separated by---:Namespace,Role,RoleBinding,ConfigMap, andJobSet. Works on any cluster with the JobSet controller (no operator required). This mode executes exactly one benchmark run; configs withsweep:or multi-run orchestration must use--operatororaiperf kube sweep.
One of the two flags must be specified; the command exits with an error if neither (or both) is given.
CLI reference
generate accepts the full set of aiperf benchmark flags plus the
Kubernetes / KubeOptions group. The mode flags are:
Relevant KubeOptions flags that shape the rendered manifests:
Output always goes to stdout. Redirect it to capture to a file; a memory-usage estimate is printed to stderr so it does not contaminate the YAML stream.
Examples
What’s in the rendered manifest
Operator mode (--operator) emits one document:
aiperf.nvidia.com/v1alpha1AIPerfJob— for a single-run config, withspec.benchmarkholding the benchmark body and deployment fields (image,podTemplate,scheduling,connectionsPerWorker, etc.) at the top ofspec.aiperf.nvidia.com/v1alpha1AIPerfSweep— when the resolved config has a parametersweep:or needs multiple trials. A multi-run-only config receives a one-cellbasescenario so the sweep controller executes the canonical trial plan without inventing a parameter dimension.
Direct mode (--no-operator) emits, in order:
Direct mode accepts only a single-run config. It fails before writing manifests when the resolved config requires parameter-sweep or multi-run orchestration, because a raw JobSet has no sweep-controller owner and would otherwise execute only the base cell.
The target namespace is not emitted — it must already exist. Creating it would demand cluster-scoped namespace-create rights that most benchmark runners do not have.
rbac.authorization.k8s.io/v1Role— grants the benchmark pods get/list/watch onconfigmaps,services,endpoints,events,pods,pods/log,jobs, andjobsets/status, plus get/list/watch/patch onjobsetsand onaiperfjobs/aiperfjobs/status.patchis the only write verb; the pods share one ServiceAccount, so nothing here can create, replace, or delete an object.rbac.authorization.k8s.io/v1RoleBinding— binds the Role to the pods’ ServiceAccount (default:default).v1ConfigMapnamedaiperf-<job_id>-config, containing a single keyrun_config.jsonwith the fully materializedBenchmarkRun(1 MiB hard cap —generatevalidates this before emitting).jobset.x-k8s.io/v1alpha2JobSetnamedaiperf-<job_id>— two replicated jobs, onecontrollerpod and Nworkerspods. GPU telemetry and server metrics are optional extra containers inside the controller pod, not separate pods.
Worker count is derived from the max phase concurrency and
connections_per_worker; generate runs the same
apply_k8s_runtime_config + apply_worker_config passes that
profile uses, so the rendered JobSet has the correct number of
replicas baked in.
GitOps recipe
The source config and the rendered manifest are both tracked; the rendered file is the one the cluster sees, so reviewers can inspect the exact JobSet spec, RBAC rules, and ConfigMap payload that will be applied.
Preview vs. profile --dry-run
Both generate and profile --dry-run run entirely offline and
neither submits anything to the cluster. The difference is output:
Both commands keep stdout machine-readable and safe to pipe: the payload is
written verbatim, so a long image reference or endpoint URL is never wrapped
into an invalid document when stdout is a pipe or file. Use generate when the
YAML itself is the stable artifact you want to commit or diff. Use
profile --dry-run to preview the exact operator or direct deployment path
without actually running it.
Validation chain
The typical end-to-end flow is:
Each step is independent and idempotent:
initwrites the starter file.- Edit — adjust models, endpoint, phases, pod template.
validate— schema-check the file; purely offline.preflight— verify cluster reachability and endpoint health. 5a. GitOps path:generate→ commit →kubectl apply. 5b. CLI path:profile— deploy and stream progress directly.
For long-lived recurring benchmarks that are reviewed and versioned,
prefer the GitOps path. For ad-hoc experiments, run profile
directly — it performs the same manifest generation under the hood.