Helm Deployment¶
Use this page to deploy the Cosmos3 NIM on Kubernetes with the shared
nim-wfm Helm chart. Model selection, hardware floors, and verification are
the same as in Deployment.
For the experimental NVIDIA Dynamo stack for the Reasoner, refer to the Dynamo deployment guides. They provide separate plain YAML for regular Dynamo and Dynamo with streaming, and require the Dynamo operator.
Prerequisites¶
Before you start, make sure you have the following:
- A Kubernetes cluster with GPU nodes that match a row in the Support Matrix, with the NVIDIA GPU Operator installed.
- Helm and
kubectlaccess to the target namespace. The commands below use the default namespace. - A storage class for the persistent model cache.
NGC_API_KEYexported as described in Network and NGC Access.
Create Secrets¶
The chart needs an image pull secret and a generic secret with a key named
NGC_API_KEY:
kubectl create secret docker-registry ngc-secret \
--docker-server=nvcr.io \
--docker-username='$oauthtoken' \
--docker-password="$NGC_API_KEY"
kubectl create secret generic ngc-api \
--from-literal=NGC_API_KEY="$NGC_API_KEY"
Fetch the Chart¶
This page uses nim-wfm chart version 1.3.0:
export NIM_WFM_VERSION='1.3.0'
helm fetch "https://helm.ngc.nvidia.com/nim/charts/nim-wfm-${NIM_WFM_VERSION}.tgz" \
--username='$oauthtoken' \
--password="$NGC_API_KEY"
The chart README lists every value supported by that version:
helm show readme "nim-wfm-${NIM_WFM_VERSION}.tgz"
helm show values "nim-wfm-${NIM_WFM_VERSION}.tgz"
Configure Values¶
Save the following as cosmos3-values.yaml. It deploys the Nano Generator,
optimized for latency, on one GPU:
image:
repository: nvcr.io/nim/nvidia/cosmos3
tag: "2.1.0"
imagePullSecrets:
- name: ngc-secret
model:
ngcAPISecret: ngc-api
nimCache: /opt/nim/.cache
persistence:
enabled: true
size: 220Gi
sharedMemory:
sizeLimit: 16Gi
resources:
limits:
nvidia.com/gpu: 1
env:
- name: NIM_MODEL_TYPE
value: generator
- name: NIM_MODEL_VARIANT
value: nano
- name: NIM_PERF_PROFILE
value: latency
The chart also accepts these selectors as model.selection.type,
model.selection.variant, model.selection.precision, and
model.selection.performanceProfile values. Setting a selector both there and
in env fails the render. Chart 1.3.0's model.selection does not accept the
edge or edge-droid variants, so set those through env.
Adjust it for the chosen configuration:
- Model and GPUs: Change
NIM_MODEL_VARIANT,NIM_PERF_PROFILE, andnvidia.com/gputogether using the Generator Profiles. The GPU count does not select a GPU type. UsenodeSelectororaffinityto target eligible GPU nodes, andtolerationsif those nodes are tainted. On nodes with MIG enabled, request the MIG resource instead ofnvidia.com/gpu, for examplenvidia.com/mig-4g.24gb: 2. - Cache size:
220Giis a starting size for large model files. Setpersistence.storageClassif the cluster has no default storage class. - Memory: A pod memory limit counts as system memory during profile selection. Keep any limit at or above the system-memory floor of the selected row.
- Shared memory: The chart mounts a memory-backed
emptyDirat/dev/shmby default.sharedMemory.sizeLimit: 16Gimatches the 16 GiB that the Docker launch allocates. - Pod user: The chart runs the pod as UID and GID 1000 with
fsGroup: 1000(podSecurityContext). The cache volume must be writable by that user. Storage that ignoresfsGroup, such as some NFS exports andhostPathdirectories, needs matching ownership.
Set these through chart values rather than env:
| Chart Value | Replaces |
|---|---|
model.nimCache |
NIM_CACHE_PATH |
model.ngcAPISecret |
NGC_API_KEY |
model.apiPort |
NIM_HTTP_API_PORT |
model.jsonLogging |
NIM_LOGGING_JSONL |
model.logLevel |
NIM_LOG_LEVEL |
Add other Configuration variables to env.
To check profile compatibility before a cold download, run the Docker pre-download profile preflight on a host with the same GPUs and selectors.
Reasoner¶
For Reasoner, replace env with the Reasoner selectors and choose the GPU
count from the Reasoner Profiles.
Reasoner does not use NIM_PERF_PROFILE:
env:
- name: NIM_MODEL_TYPE
value: reasoner
- name: NIM_MODEL_VARIANT
value: nano
On NVIDIA DGX Spark/GB10 or Jetson AGX Thor nodes, the NIM defaults
NIM_GPU_MEMORY_UTILIZATION to 0.70. Set a lower value only from host
measurements. Refer to
Set the Reasoner Memory Share.
OpenTelemetry¶
To export traces and metrics over OTLP, add these entries to env. The
endpoint assumes an OpenTelemetry Collector DaemonSet that listens on host port
4318. Change OTEL_EXPORTER_OTLP_ENDPOINT for other collector layouts:
- name: NIM_ENABLE_OTEL
value: "1"
- name: OTEL_SERVICE_NAME
value: cosmos3
- name: OTEL_TRACES_EXPORTER
value: otlp
- name: OTEL_METRICS_EXPORTER
value: otlp
- name: HOST_IP
valueFrom:
fieldRef:
fieldPath: status.hostIP
- name: OTEL_EXPORTER_OTLP_ENDPOINT
value: "http://$(HOST_IP):4318"
HOST_IP must come before OTEL_EXPORTER_OTLP_ENDPOINT so that Kubernetes
can expand it.
Other Chart Features¶
The chart README documents the following optional features, which are all off by default:
- Prometheus metrics: Set
metrics.serviceMonitor.enabled: trueto create a Prometheus OperatorServiceMonitorthat scrapes/v1/metricson thehttp-apiport. Refer to Metrics. - Ingress:
ingress.enabled,ingress.className,ingress.hosts, andingress.tls. The NIM does not authenticate requests, so protect any ingress outside the cluster. - Autoscaling:
autoscaling.enabledwithminReplicas,maxReplicas, andmetrics. CPU and memory metrics are of limited use for scaling a NIM. Use custom metrics, for example throughprometheus-adapter. Each new replica must download or mount the model before it becomes ready. Refer to Storage and Scaling.
Install¶
Review the rendered manifests, then install the release:
helm template cosmos3 "nim-wfm-${NIM_WFM_VERSION}.tgz" -f cosmos3-values.yaml
helm install cosmos3 "nim-wfm-${NIM_WFM_VERSION}.tgz" -f cosmos3-values.yaml
kubectl get pods -w
Cold download, materialization, and model load can take much longer than pod
startup. Send requests only after the pod reports Ready. Kubernetes restarts
the container if it is not ready within startupProbe.initialDelaySeconds plus
startupProbe.failureThreshold × startupProbe.periodSeconds. Raise
failureThreshold for slow first downloads.
Verify¶
The chart creates a ClusterIP Service with no ingress, and the NIM does not
handle authentication. Port-forward the Service for testing:
kubectl port-forward service/cosmos3-nim-wfm 8000:http-api
In another terminal, check readiness and metadata:
export NIM_URL=http://localhost:8000
curl -fsS "$NIM_URL/v1/health/ready"
curl -fsS "$NIM_URL/v1/metadata" | python3 -m json.tool
Confirm that metadata reports generator and /v1/infer, or reasoner and
/v1/chat/completions. Then run a first request from
Use an Existing NIM Endpoint.
Storage and Scaling¶
The chart supports the following cache options. Use only one of them:
| Option | Values | Notes |
|---|---|---|
| StatefulSet volume claims | persistence.enabled: true with the default statefulSet.enabled: true |
Default. Each replica gets its own claim and downloads the model before it becomes ready |
| Shared volume claim | persistence.enabled: true, statefulSet.enabled: false, persistence.accessMode: ReadWriteMany |
One cache shared by all replicas; needs a ReadWriteMany storage class |
| Existing claim | persistence.enabled: true, persistence.existingClaim: <claim-name> |
Reuse a pre-filled cache. Run one replica unless the claim is ReadWriteMany |
| Direct NFS | nfs.enabled: true, nfs.server, nfs.path |
Mount options cannot be set per pod; an NFS-backed claim is usually a better choice |
hostPath |
hostPath.enabled: true, hostPath.path |
Ties pods to one node and has security implications |
Set replicaCount for a fixed number of replicas. With the default
StatefulSet, you can pre-populate caches by scaling up to the maximum replica
count once and then scaling down. The retained claims let later scale-ups
start without a new download.
With statefulSet.enabled: false and a ReadWriteOnce volume, scaling or
rolling upgrades beyond one pod are likely to fail. Use a ReadWriteMany
storage class or writable direct NFS. Without persistence, the cache is an
emptyDir and every pod start downloads the model again.
Troubleshooting¶
| Symptom | Check |
|---|---|
Pod stays Pending |
Run kubectl describe pod <pod> and check Events for insufficient GPUs, untolerated taints, or an unbound volume claim |
| Pod restarts while preparing the model workspace | The startup probe ran out before the download finished; increase startupProbe.failureThreshold |
Scaling or upgrade fails with statefulSet.enabled: false |
The cache volume is ReadWriteOnce; refer to Storage and Scaling |
| Profile selection fails | Compare GPU type, count, free memory, and pod memory limit with the Support Matrix; refer to Troubleshooting |
Remove the Deployment¶
helm uninstall cosmos3
kubectl get pvc
StatefulSet volume claims are retained by default and keep the model cache.
Delete them and the ngc-secret and ngc-api secrets only when they are no
longer needed.
Chart Parameters¶
These are the nim-wfm chart values used with the chart version pinned on this
page (1.3.0). For the authoritative list, run
helm show values "nim-wfm-${NIM_WFM_VERSION}.tgz".
Deployment Parameters¶
| Name | Description | Value |
|---|---|---|
affinity |
Affinity settings for deployment. | {} |
containerSecurityContext |
Sets privilege and access control settings for container (Only affects the main container, not pod-level). | {} |
customCommand |
Overrides command line options sent to the NIM with the array listed here. | [] |
customArgs |
Overrides command line arguments of the NIM container with the array listed here. | [] |
env |
Adds arbitrary environment variables to the main container. | [] |
extraEnvFrom |
Adds arbitrary ConfigMap or Secret sources to the main container environment. | [] |
extraVolumes |
Adds arbitrary additional volumes to the deployment set definition. | {} |
extraVolumeMounts |
Adds volume mounts to the main container from extraVolumes. |
{} |
sharedMemory.enabled |
Mounts a RAM-backed emptyDir at /dev/shm. |
true |
sharedMemory.sizeLimit |
Optional Kubernetes quantity limiting the shared-memory volume. | "" |
image.repository |
Specifies the NIM-WFM image to deploy. The chart default is another NIM; set nvcr.io/nim/nvidia/cosmos3 as in Configure Values. |
nvcr.io/nvidia/nemo-microservices/nemoretriever-parse |
image.tag |
Specifies the image tag or version. | "" |
image.pullPolicy |
Sets the image pull policy. | IfNotPresent |
imagePullSecrets |
Specifies a list of secret names that are needed for the main container and any init containers. | [{name: ngc-secret}] |
initContainers |
Specifies model init containers, if needed. | Refer to subkeys |
initContainers.extraInit |
Fully specify any additional init containers your use case requires. | [] |
nodeSelector |
Sets node selectors for the NIM—for example nvidia.com/gpu.present: "true". |
{} |
runtimeClassName |
Selects the container runtime class for workload pods. | "" |
priorityClassName |
Selects the Kubernetes priority class for workload pods. | "" |
topologySpreadConstraints |
Configures pod topology spreading. | [] |
podAnnotations |
Sets additional annotations on the main deployment pods. | {} |
podSecurityContext |
Specifies security context settings for pod. | Refer to subkeys |
podSecurityContext.runAsUser |
Specify user UID for pod. | 1000 |
podSecurityContext.runAsGroup |
Specify group ID for pod. | 1000 |
podSecurityContext.fsGroup |
Specify file system owner group id. | 1000 |
proxyCA |
Specify a certificate for a custom proxy. When proxyCA is set native TLS is used for downloading from NGC. |
Refer to subkeys |
proxyCA.enabled |
Specify true if NIM is run behind a proxy. | false |
proxyCA.secretName |
Specify a name of the Kubernetes secret containing the certificate. The secret is created before the deployment. Must be used together with proxyCA.keyName |
"" |
proxyCA.keyName |
Specify a name of the key inside the secret that contains the certificate. Must be used together with proxyCA.secretName |
"" |
terminationGracePeriodSeconds |
Seconds Kubernetes allows the NIM to terminate gracefully. | 60 |
replicaCount |
Specify static replica count for deployment. | 1 |
resources |
Specify resources limits and requests for the running service. | {limits: {nvidia.com/gpu: 1}} |
resources.limits.nvidia.com/gpu |
Specify number of GPUs to present to the running service. | 1 |
serviceAccount |
Options to specify service account for the deployment. | Refer to subkeys |
serviceAccount.create |
Specifies whether a service account should be created. | false |
serviceAccount.annotations |
Sets annotations to be added to the service account. | {} |
serviceAccount.name |
Specifies the name of the service account to use. If it is not set and create is true, a name is generated using a fullname template. |
"" |
statefulSet.enabled |
Enables statefulset deployment. Enabling statefulSet allows PVC templates for scaling. If using central PVC with RWX accessMode, this is not needed. |
true |
tolerations |
Specify tolerations for pod assignment. Allows the scheduler to schedule pods with matching taints. | [{key: nvidia.com/gpu, operator: Exists, effect: NoSchedule}] |
Autoscaling Parameters¶
Values used for creating a Horizontal Pod Autoscaler. If autoscaling is not
enabled, the rest are ignored. NVIDIA recommends usage of the custom metrics
API, commonly implemented with the Prometheus Adapter. Standard metrics of CPU
and memory are of limited use in scaling NIM.
| Name | Description | Value |
|---|---|---|
autoscaling.enabled |
Enables horizontal pod autoscaler. | false |
autoscaling.minReplicas |
Specify minimum replicas for autoscaling. | 1 |
autoscaling.maxReplicas |
Specify maximum replicas for autoscaling. | 10 |
autoscaling.metrics |
Array of metrics for autoscaling. | [] |
Ingress Parameters¶
| Name | Description | Value |
|---|---|---|
ingress.enabled |
Enables ingress. | false |
ingress.className |
Specify class name for Ingress. | "" |
ingress.annotations |
Specify additional annotations for ingress. | {} |
ingress.hosts |
Specify list of hosts each containing lists of paths. | Refer to subkeys |
ingress.hosts[0].host |
Specify name of host. | chart-example.local |
ingress.hosts[0].paths[0].path |
Specify ingress path. | / |
ingress.hosts[0].paths[0].pathType |
Specify path type. | ImplementationSpecific |
ingress.tls |
Specify list of pairs of TLS secretName and hosts. |
[] |
Probe Parameters¶
| Name | Description | Value |
|---|---|---|
livenessProbe.enabled |
Enables livenessProbe. |
true |
livenessProbe.method |
LivenessProbe http or script, but no script is currently provided. |
http |
livenessProbe.command |
LivenessProbe script command to use (unsupported at this time). |
["myscript.sh"] |
livenessProbe.path |
LivenessProbe endpoint path. |
/v1/health/live |
livenessProbe.initialDelaySeconds |
Initial delay seconds for livenessProbe. |
15 |
livenessProbe.timeoutSeconds |
Timeout seconds for livenessProbe. |
1 |
livenessProbe.periodSeconds |
Period seconds for livenessProbe. |
10 |
livenessProbe.successThreshold |
Success threshold for livenessProbe. |
1 |
livenessProbe.failureThreshold |
Failure threshold for livenessProbe. |
3 |
readinessProbe.enabled |
Enables readinessProbe. |
true |
readinessProbe.path |
Readiness Endpoint Path. | /v1/health/ready |
readinessProbe.initialDelaySeconds |
Initial delay seconds for readinessProbe. |
15 |
readinessProbe.timeoutSeconds |
Timeout seconds for readinessProbe. |
1 |
readinessProbe.periodSeconds |
Period seconds for readinessProbe. |
10 |
readinessProbe.successThreshold |
Success threshold for readinessProbe. |
1 |
readinessProbe.failureThreshold |
Failure threshold for readinessProbe. |
3 |
startupProbe.enabled |
Enables startupProbe. |
true |
startupProbe.path |
StartupProbe Endpoint Path. |
/v1/health/ready |
startupProbe.initialDelaySeconds |
Initial delay seconds for startupProbe. |
40 |
startupProbe.timeoutSeconds |
Timeout seconds for startupProbe. |
1 |
startupProbe.periodSeconds |
Period seconds for startupProbe. |
10 |
startupProbe.successThreshold |
Success threshold for startupProbe. |
1 |
startupProbe.failureThreshold |
Failure threshold for startupProbe. |
180 |
Helm Test Parameters¶
The readiness test always uses the HTTP management endpoint, including when
gRPC inference is selected. The inference test is opt-in because request
payloads are model-specific, and it is only rendered for
model.inferenceProtocol: http.
| Name | Description | Value |
|---|---|---|
tests.image.repository |
Container image repository used by Helm test pods. | curlimages/curl |
tests.image.tag |
Container image tag used by Helm test pods. | 8.6.0 |
tests.image.pullPolicy |
Container image pull policy used by Helm test pods. | IfNotPresent |
tests.readiness.enabled |
Enables the HTTP readiness Helm test. | true |
tests.readiness.path |
HTTP path used by the readiness Helm test. | /v1/health/ready |
tests.readiness.timeoutSeconds |
Timeout in seconds for the readiness request. | 30 |
tests.metadata.enabled |
Enables the runtime metadata Helm test. | false |
tests.metadata.path |
HTTP path used by the metadata Helm test. | /v1/metadata |
tests.metadata.timeoutSeconds |
Timeout in seconds for the metadata request. | 30 |
tests.metadata.expectedModelType |
Optional expected model_type value. |
"" |
tests.metadata.expectedInferenceEndpoint |
Optional expected inference_endpoint value. |
"" |
tests.inference.enabled |
Enables the HTTP inference Helm test. This test is only rendered when model.inferenceProtocol is http. |
false |
tests.inference.path |
HTTP path used by the inference Helm test. | /v1/infer |
tests.inference.timeoutSeconds |
Timeout in seconds for the inference request. | 300 |
tests.inference.expectedStatus |
Expected HTTP status code from the inference request. | 200 |
tests.inference.payload |
Request body sent by the inference Helm test. Required when the inference test is enabled. | "" |
tests.inference.expectedResponseField |
Optional response field required in the inference response. | "" |
Metrics Parameters¶
| Name | Description | Value |
|---|---|---|
metrics |
Configures Prometheus integration for the NIM HTTP metrics endpoint. | Refer to subkeys |
metrics.serviceMonitor |
Options for serviceMonitor to use the Prometheus Operator and the primary service object. |
Refer to subkeys |
metrics.serviceMonitor.enabled |
Enables serviceMonitor creation. |
false |
metrics.serviceMonitor.additionalLabels |
Specify additional labels for serviceMonitor. |
{} |
metrics.serviceMonitor.port |
Named Service port scraped by ServiceMonitor. | http-api |
metrics.serviceMonitor.path |
HTTP metrics path scraped by ServiceMonitor. | /v1/metrics |
metrics.serviceMonitor.interval |
Optional Prometheus scrape interval. | "" |
metrics.serviceMonitor.scrapeTimeout |
Optional Prometheus scrape timeout. | "" |
Models Parameters¶
| Name | Description | Value |
|---|---|---|
model.nimCache |
Path to mount writable storage or a pre-filled model cache for the NIM. | /model-store |
model.name |
Optional model name retained for compatibility with NIM-specific values files. | nvidia/Cosmos3-Nano |
model.ngcAPISecret |
Name of a secret containing NGC_API_KEY for model downloads. When model.ngcAPIKey is set, the chart generates this secret; leave the name empty to generate only the image pull secret. |
ngc-api |
model.ngcAPIKey |
NGC API key literal used to generate the image pull secret and, when model.ngcAPISecret is nonempty, the model-download secret. |
"" |
model.hfTokenSecret |
Name of a pre-existing secret with a key named HF_TOKEN for Hugging Face model downloads. |
"" |
model.apiPort |
Specifies the HTTP API and management port. | 8000 |
model.grpcPort |
Specifies the gRPC inference port. | 50051 |
model.inferenceProtocol |
Selects http or grpc inference. The HTTP port remains available for health and management endpoints in gRPC mode. |
http |
model.selection.type |
Optional runtime selector mapped to NIM_MODEL_TYPE. |
"" |
model.selection.variant |
Optional model variant mapped to NIM_MODEL_VARIANT. |
"" |
model.selection.precision |
Optional precision mapped to NIM_PRECISION; empty preserves runtime auto-selection. |
"" |
model.selection.performanceProfile |
Optional Generator objective mapped to NIM_PERF_PROFILE. |
"" |
model.labels |
Specifies extra labels to be added on deployed pods. | {} |
model.jsonLogging |
Turns JSON lines logging on or off. | true |
model.logLevel |
Log level of the NIM service. Possible values are TRACE, DEBUG, INFO, WARNING, ERROR, and CRITICAL. | INFO |
Storage Parameters¶
| Name | Description | Value |
|---|---|---|
persistence |
Specify settings to modify the behavior and use of persistent volumes for model weights. | Refer to subkeys |
persistence.enabled |
Enables the use of persistent volumes. | false |
persistence.existingClaim |
Specifies an existing persistent volume claim. If using existingClaim, run only one replica or use a ReadWriteMany storage setup. |
"" |
persistence.storageClass |
Specifies the persistent volume storage class. If set to "-", this disables dynamic provisioning. If left undefined or set to null, the cluster default storage provisioner is used. |
"" |
persistence.accessMode |
Specify accessMode. If using an NFS or similar setup, you can use ReadWriteMany. |
ReadWriteOnce |
persistence.stsPersistentVolumeClaimRetentionPolicy.whenDeleted |
Specifies persistent volume claim retention policy when deleted. Only used with Stateful Set volume templates. | Retain |
persistence.stsPersistentVolumeClaimRetentionPolicy.whenScaled |
Specifies persistent volume claim retention policy when scaled. Only used with Stateful Set volume templates. | Retain |
persistence.size |
Specifies the size of the persistent volume claim (for example 40Gi). | 50Gi |
persistence.annotations |
Adds annotations to the persistent volume claim. | {} |
hostPath |
Configures model cache on local disk on the nodes using hostPath—for special cases. You should understand the security implications before using this option. |
Refer to subkeys |
hostPath.enabled |
Enable hostPath. |
false |
hostPath.path |
Specifies path on the node used as a hostPath volume. |
/model-store |
nfs |
Configures the model cache to sit on shared direct-mounted NFS. NOTE: you cannot set mount options using direct NFS mount to pods without a node-intalled nfsmount.conf. An NFS-based PersistentVolumeClaim is likely better in most cases. |
Refer to subkeys |
nfs.enabled |
Enables direct pod NFS mount. | false |
nfs.path |
Specify path on NFS server to mount. | /exports |
nfs.server |
Specify NFS server address. | nfs-server.example.com |
nfs.readOnly |
Set to true to mount as read-only. | false |
Service Parameters¶
| Name | Description | Value |
|---|---|---|
service.type |
Specifies the service type for the deployment. | ClusterIP |
service.name |
Overrides the default service name. | "" |
service.apiPort |
Specifies the HTTP API and management port for the service. | 8000 |
service.grpcPort |
Specifies the gRPC inference port for the service. It is exposed when model.inferenceProtocol=grpc. |
50051 |
service.annotations |
Specifies additional annotations to be added to the service. | {} |
service.labels |
Specifies additional labels to be added to the service. | {} |