Certification
Certification is the top-level resource that defines a suite of certification categories to run against a GPU node pool.
Example
Spec fields
Fields documented so far:
Like the rest of spec, gangScheduler is immutable after the Certification is created.
When gangScheduler is set, its resolved queue is also placed on each category’s generated workload object (the TrainJob), under gangScheduler.queueLabelKey, in addition to the runtime Job- and pod-template placement described above. See Workload object labels.
Workload object labels
workloadMetadata sets labels on the workload object each category’s Job creates — today a Kubeflow TrainJob. That object’s own metadata.labels is where Kueue selects a local queue and where Kubeflow’s KAI Scheduler guide documents the queue label, both read before any workload pod exists.
Because CertificationSpec inlines the shared category options, the one field is read at two paths: globally at spec.workloadMetadata and per category at spec.categories[].options.workloadMetadata.
That nccl-all-reduce category’s TrainJob receives both environment: burn-in and kueue.x-k8s.io/queue-name: nccl-queue.
These labels are not pod labels. See Job workload object labels for the full contract, reserved keys, limits, and immutability rules.
Precedence
Unlike the other maps, slices, and pointers in category options — thresholds, resources, imagePullSecrets — workload labels merge per key rather than replacing the whole value. The order is:
- labels already present in the resolved catalog job spec,
- global
spec.workloadMetadata.labels, - per-category
options.workloadMetadata.labels, and - the resolved
gangSchedulerqueue label.
Steps 2 and 3 replace earlier values by key. Step 4 does not overwrite: a missing key is inserted, the same value is accepted, and a different value fails.
The consequence of merging is that a category can change or add a key but cannot remove a global one — there is no deletion syntax, and an empty string is a real label value. A category needing a wholly different map should not set those keys globally.
Per-category queue conflicts
spec.gangScheduler is global, so every category receives the same resolved queue, including the default-queue default. A category that sets that same KAI or Run:ai key to a different value fails, naming the key, both values, and the field path. Per-category Kueue queues remain independent, because kueue.x-k8s.io/queue-name is a different key.
<Note>
A Certification that sets gangScheduler and no workloadMetadata now emits the resolved queue label — the explicit queue, or default-queue when omitted — on every category’s TrainJob as well as on the runtime templates. This is an intended behavior change that aligns the submitted object with Kubeflow’s documented KAI placement.
</Note>
Category options
spec embeds a set of workload options that apply to every category, and each spec.categories[] entry can override them via options; the per-category value wins. Options documented so far:
Spec immutability
<Warning>
The entire spec is immutable after the Certification is created (a self == oldSelf transition rule on the CRD rejects every update with spec is immutable after creation). The controller never applies edits to an active run, so mutable fields would either be silently ignored or applied only to later categories. To run with different inputs, delete the Certification and create a new one. The minimum is 1 category.
</Warning>
Status fields
Each categoryStatuses entry includes a failedNodesRef — a TypedLocalObjectReference pointing to a ConfigMap that stores the failed-node list (name, reason, message) for that category. To read the failed nodes:
Lifecycle
- Controller creates one
Workflowper entry inspec.categories. The spec cannot be changed after creation — delete and recreate to modify it. - Workflows run sequentially — the controller processes one category at a time.
maxConcurrentcontrols job/group parallelism within a single Workflow (how many node groups run at once), not across categories. - When all Workflows complete, Certification is marked
SucceededorFailed. - Failed nodes are recorded in ConfigMaps referenced by
status.categoryStatuses[].failedNodesRef. NVCRE does not taint or cordon nodes.