跳到导航

Installation Guide

Install accelerator support and the Dynamo Platform on Kubernetes.
以 Markdown 格式查看

This guide walks you through installing everything needed to deploy models with Dynamo on Kubernetes. Follow the steps in order — each builds on the previous one.

Prerequisites

Before you begin, make sure you have Helm v3 or later and choose the accelerator type in your cluster:

The GPU Operator in the first installation step can install NVIDIA drivers. Do not also enable provider-managed drivers when you create the GPU node pool. If the nodes already have drivers, disable GPU Operator driver management as shown in that step.

Verify the client tools:

kubectl version --client
helm version

Overview

Every Dynamo deployment requires accelerator support and the Dynamo Platform. NVIDIA GPU clusters can use the NVIDIA GPU Operator. Intel GPU clusters use the Intel resource driver with DRA. The Dynamo Platform installation is the same after the cluster exposes its accelerator resources. Everything else is optional.

Optional ComponentWhen you need itRequired for
Grove + KAI SchedulerMultinode or disaggregated inferenceMultinode deployments (operator errors without Grove or LWS)
Network Operator / RDMADisaggregated inference in productionAcceptable KV cache transfer performance (TCP fallback has ~200-500x degradation)
kube-prometheus-stackAutoscaling, metrics dashboards, or the PlannerPlanner sla mode, KEDA/HPA autoscaling
Shared storage (model cache)Large models (>70B) or many replicasAvoiding per-pod downloads and HuggingFace rate limits

Grove + KAI Scheduler — Grove is the default multinode orchestrator. The operator returns a hard error on multinode deployments if neither Grove nor LeaderWorkerSet (LWS) is available. KAI Scheduler is optional but recommended alongside Grove for GPU-aware scheduling. See Multinode Orchestration for details.

Network Operator / RDMA — Without RDMA, disaggregated inference falls back to TCP automatically, but with severe performance degradation (~98s TTFT vs ~200-500ms with RDMA). Required for any production disaggregated deployment. Setup is cloud-provider-specific — see RDMA Setup and your cloud provider guide.

kube-prometheus-stack — Required for the Planner’s sla optimization mode (it reads live TTFT/ITL metrics from Prometheus). Also required for KEDA/HPA-based autoscaling. The Planner’s throughput mode can function without it using internal queue depth signals, but metrics-driven features will not work. See Metrics for details.

Shared storage — Prevents each pod from downloading model weights independently. Without it, large models (>70B) take hours to download per pod, and many replicas will hit HuggingFace rate limits. Not enforced by the operator — this is an operational concern. See the Model Storage Overview to choose a storage backend.

1

Install accelerator support

The NVIDIA GPU Operator automates deployment of the drivers, container toolkit, device plugin, and monitoring components used by NVIDIA GPU nodes.

helm repo add nvidia https://helm.ngc.nvidia.com/nvidia
helm repo update
helm install gpu-operator nvidia/gpu-operator \
--namespace gpu-operator \
--create-namespace
# Add a trailing \ above before uncommenting the following setting.
# --set driver.enabled=false

Set driver.enabled=false when the nodes already have provider-managed NVIDIA drivers. See the AKS, EKS, or GKE guide for provider-specific requirements.

Verify the installation:

kubectl get pods --namespace gpu-operator
2

Install the Dynamo Platform

Set your environment variables:

export NAMESPACE=dynamo-system
export RELEASE_VERSION=1.2.1 # match a version from https://github.com/ai-dynamo/dynamo/releases
helm fetch https://helm.ngc.nvidia.com/nvidia/ai-dynamo/charts/dynamo-platform-$RELEASE_VERSION.tgz
helm install dynamo-platform dynamo-platform-$RELEASE_VERSION.tgz \
--namespace $NAMESPACE \
--create-namespace
# Note: add \ to --create-namespace above when uncommenting any optional flags below
#
# Grove + KAI Scheduler — uncomment if using multinode or disaggregated inference.
# Option A (install=true): Dynamo installs and manages Grove/KAI as bundled subcharts (dev/testing):
# --set "global.grove.install=true" \
# --set "global.kai-scheduler.install=true" \
# --set-string "kai-scheduler.scheduler.args.default-staleness-grace-period=-1s" \
# Option B (enabled=true): Grove/KAI are already installed externally (production):
# --set "global.grove.enabled=true" \
# --set "global.kai-scheduler.enabled=true" \
#
# kube-prometheus-stack — uncomment if Prometheus is installed (required for Planner sla mode and autoscaling):
# --set "dynamo-operator.dynamo.metrics.prometheusEndpoint=http://prometheus-kube-prometheus-prometheus.monitoring.svc.cluster.local:9090"

All helm install commands can be customized with your own values file: helm install ... -f your-values.yaml

Experimental. Development clusters only. The unfinished DGDR v1beta2 schemas are disabled by default. The 1.2.1 chart shown above does not support this feature gate. To test the API before a supporting release is available, use a development chart built from the current main branch and add --set "dynamo-operator.dgdrV1Beta2.enabled=true" to the Helm command. The flag adds the v1beta2 DynamoGraphDeploymentRequest schema and installs the DynamoGraphDeploymentRun and DynamoGraphDeploymentCandidate Custom Resource Definitions (CRDs). It does not enable v1beta2 reconciliation, so the operator does not process resources created with these schemas.

Kubernetes persists Run and Candidate objects in etcd. Because the schemas are not finalized, later schema changes can make stored objects unreadable or prevent a CRD upgrade. Do not enable this API on production or shared clusters.

Shared/Multi-Tenant Clusters: If a cluster-wide Dynamo operator is already running, do not install another one. Check with:

kubectl get clusterrolebinding -o json | \
jq -r '.items[] | select(.metadata.name | contains("dynamo-operator-manager")) |
"Cluster-wide operator found in namespace: \(.subjects[0].namespace)"'

Namespace-restricted mode (namespaceRestriction.enabled=true) is only for development and testing. It is not supported for production. Set dynamo-operator.upgradeCRD=false when you enable this mode.

Verify the Dynamo platform is running:

# Check CRDs
kubectl get crd | grep dynamo
# Expected: dynamographdeployments, dynamocomponentdeployments, dynamographdeploymentrequests, etc.
# Check operator and platform pods
kubectl get pods -n $NAMESPACE
# Expected: dynamo-operator-* and nats-* pods all Running
3

Install Optional Components

The Dynamo install command above includes commented flags for each optional component. Install the component first, then uncomment the corresponding flag before running helm install in Step 2 (or run helm upgrade --reuse-values with the flag if you’ve already installed Dynamo).

Multinode:

Multinode deployments require an orchestrator for workloads that span multiple nodes. Gang scheduling is strongly recommended to schedule all required Pods together and avoid partial resource allocation that can leave workloads stalled. See Multinode Orchestration for details on orchestrator selection and configuration.

DisaggregatedSet is an opt-in multinode pathway below Grove. To request it for a new DGD, install an LWS release that serves disaggregatedset.x-k8s.io/v1 and set nvidia.com/enable-disaggregatedset: "true". When Grove is available and enabled, also set nvidia.com/enable-grove: "false". Dynamo persists the selected provider in nvidia.com/workload-provider; installing the DS API or changing the enable annotations does not change existing deployments. If the selected provider becomes unavailable, Dynamo reports Ready=False instead of silently switching providers. Delete and recreate the DGD to choose a different pathway.

The following sections describe how to enable gang scheduling for each supported orchestrator.

Grove + KAI Scheduler

There are two ways to enable Grove and KAI Scheduler, controlled by which flags you uncomment in the Dynamo install command:

  • install=true — Dynamo installs and manages Grove/KAI as bundled subcharts. Simplest path; recommended for dev/testing.
  • enabled=true — Tells Dynamo that Grove/KAI are already installed and externally managed. Use this when you install Grove/KAI separately (e.g., to manage their lifecycle independently or share them across namespaces). Recommended for production.

For the enabled=true path, install Grove and KAI Scheduler separately first. See the Grove installation guide and KAI Scheduler deployment guide for instructions.

Compatibility matrix:

dynamo-platformkai-schedulerGrove
1.0.x>= v0.13.0>= v0.1.0-alpha.6
1.1.x>= v0.13.4>= v0.1.0-alpha.8
1.3.x>= v0.13.4>= v0.1.0-alpha.8, < v0.1.0-alpha.9
1.4.x>= v0.13.4>= v0.1.0-alpha.10
1.5.x>= v0.17.0>= v0.1.0-alpha.13
1.6.x>= v0.17.0>= v0.1.0-alpha.15

Upgrade Grove in lockstep with Dynamo while the Grove APIs remain unstable. Dynamo 1.3.x expects Grove’s earlier ClusterTopology API and is incompatible with the newer ClusterTopologyBinding API. Dynamo 1.4.x expects ClusterTopologyBinding.

LWS + Volcano

If you are not using Grove for multinode, you can use LeaderWorkerSet (LWS) (>= v0.7.0) with Volcano for gang scheduling. Both must be installed before deploying multinode workloads.

  1. Install Volcano:
helm repo add volcano-sh https://volcano-sh.github.io/helm-charts
helm repo update
helm install volcano volcano-sh/volcano -n volcano-system --create-namespace
  1. Install LWS with Volcano gang scheduling enabled. Use an LWS release that serves disaggregatedset.x-k8s.io/v1 (the current Dynamo operator dependency is LWS v0.10.0) when enabling DS; the standard DCD pathway supports LWS v0.7.0 or newer:
export LWS_VERSION=0.10.0
helm install lws oci://registry.k8s.io/lws/charts/lws \
--version=$LWS_VERSION \
--namespace lws-system \
--create-namespace \
--set gangSchedulingManagement.schedulerProvider=volcano \
--wait --timeout 300s

See the LWS docs and Volcano docs for configuration options. See Multinode Orchestration to compare the supported orchestrators.

Network Operator / RDMA

RDMA setup is cloud-provider-specific. See RDMA Setup for requirements and platform-specific instructions:

kube-prometheus-stack

Install Prometheus before running the Dynamo install command so you can set the endpoint in one pass:

helm repo add prometheus-community https://prometheus-community.github.io/helm-charts
helm repo update
helm install prometheus prometheus-community/kube-prometheus-stack \
--namespace monitoring --create-namespace \
--set prometheus.prometheusSpec.podMonitorSelectorNilUsesHelmValues=false \
--set-json 'prometheus.prometheusSpec.podMonitorNamespaceSelector={}' \
--set-json 'prometheus.prometheusSpec.probeNamespaceSelector={}'

Then uncomment the prometheusEndpoint line in the Dynamo install command. The Dynamo operator automatically creates PodMonitors for its components. See Metrics for dashboard setup and available metrics, and Logging for the Grafana Loki + Alloy logging stack.

Shared Storage for Model Caching

Set up a ReadWriteMany PVC so all pods share downloaded model weights instead of each downloading independently. No Dynamo chart flags are needed — storage is configured in your deployment spec. Setup is cloud-provider-specific:

For large clusters with frequent model updates, consider ModelExpress for P2P model distribution and ModelStreamer for direct streaming from object storage. See Model Caching for the full walkthrough including the download Job, mount configuration, and ModelExpress setup.

4

Pre-Deployment Check

Run the pre-deployment check script to validate your cluster is ready for deployments:

./deploy/pre-deployment/pre-deployment-check.sh

This checks kubectl connectivity, default StorageClass configuration, GPU node availability, and GPU Operator status. See Pre-Deployment Checks for details.

Upgrade Dynamo

Dynamo supports Helm upgrades and downgrades within the installed minor release and between adjacent minor releases. Upgrade from N.M to N.(M+1) or downgrade from N.(M+1) to N.M. Move through every intermediate minor release for larger changes. For example, upgrade 1.2.x to 1.3.x, then 1.3.x to 1.4.x; a direct transition from 1.2.x to 1.4.x is unsupported.

Flux users need helm-controller v1.7.0 or later, first included in Flux v2.10.0. Earlier helm-controller versions panic on this chart’s helm.sh/hook-output-log-policy annotation. If a preflight fails, inspect the retained Job Pod logs as shown in Troubleshooting; Flux does not forward hook output to controller logs or events.

  1. Check the installed release and operator versions:

    helm list --namespace $NAMESPACE
    kubectl get deployments --namespace $NAMESPACE \
    -l app.kubernetes.io/name=dynamo-operator \
    -L app.kubernetes.io/version
  2. Read the chart upgrade notes for every minor release you cross, including the Grove and KAI Scheduler requirements.

  3. Set RELEASE_VERSION to the next target release, download its chart, and upgrade with your existing configuration in your-values.yaml. Include all settings from the current installation, including any originally passed with --set. For example, from 1.6.x to 1.7.0:

    export RELEASE_VERSION=1.7.0
    helm fetch https://helm.ngc.nvidia.com/nvidia/ai-dynamo/charts/dynamo-platform-$RELEASE_VERSION.tgz
    helm upgrade dynamo-platform dynamo-platform-$RELEASE_VERSION.tgz \
    --namespace $NAMESPACE \
    -f your-values.yaml

    Wait for the operator rollout before repeating this step for the next minor:

    kubectl rollout status deployment --namespace $NAMESPACE \
    -l app.kubernetes.io/name=dynamo-operator --timeout=120s

The upgrade-path check is enforced by target charts v1.7.0 and later when dynamo-operator.enabled=true. Upgrades or downgrades to earlier charts are not checked. The read-only pre-install,pre-upgrade Job runs before the operator Deployment changes; an initial installation passes when no Deployment exists. Helm and Flux run the hook directly; Argo CD maps it to PreSync. Raw kubectl apply, Argo CD selective sync, or disabled hooks do not enforce the check. A separately managed operator release owns its upgrade policy when the subchart is disabled. See the chart configuration for upgradePreflight.job settings, including images for internal registries and per-check overrides.

Unsupported Transitions

If you have separately validated an unsupported forward upgrade, set unsupportedUpgradeOverride to the target minor version. For example, to upgrade from 1.7.x to 1.9.x, set RELEASE_VERSION to the intended 1.9.x release and download that chart as above, then run:

helm upgrade dynamo-platform dynamo-platform-$RELEASE_VERSION.tgz \
--namespace $NAMESPACE \
-f your-values.yaml \
--set-string dynamo-operator.upgradePreflight.checks.upgradePath.unsupportedUpgradeOverride=1.9

For an unsupported downgrade from 1.9.x to 1.7.x, set RELEASE_VERSION to the intended 1.7.x release and download that chart as above. Authorize the lower target minor with the downgrade override:

helm upgrade dynamo-platform dynamo-platform-$RELEASE_VERSION.tgz \
--namespace $NAMESPACE \
-f your-values.yaml \
--set-string dynamo-operator.upgradePreflight.checks.upgradePath.unsupportedDowngradeOverride=1.7

The override must match the target operator’s N.M version. If you leave the override in your values, it has no effect on later upgrades or downgrades to a different minor. It applies only to the upgrade-path check; other preflight checks still run. It permits the Helm operation but does not make that upgrade or downgrade path supported.

Alternative: Install with AICR

NVIDIA AI Cluster Runtime (AICR) generates a version-locked recipe for the whole GPU and Dynamo stack, then deploys and validates it. Choose AICR when your cluster matches a validated Dynamo recipe and you want one reproducible install. Use the manual steps above for any other cluster. For the full walkthrough, see Install with AICR.

Next Steps

Your cluster is ready. Follow the Model Deployment guide to choose between applying a tuned DGD recipe, creating a DGD directly, or using DGDR to generate one.

Troubleshooting

“Dynamo upgrade-path preflight failed: Unsupported Dynamo upgrade” (or downgrade)

Cause: The target chart rejected a skipped-minor or major-version upgrade or downgrade. For example:

Dynamo upgrade-path preflight failed: Unsupported Dynamo upgrade from 1.5.0 to 1.7.0. ...

Find the retained Job and inspect its logs, replacing <job-name> with the name from the first command:

kubectl get jobs -n $NAMESPACE | grep check-upgrade-path
kubectl logs job/<job-name> -n $NAMESPACE

Move through every intermediate minor release. If you have validated the unsupported path, use the target-minor override under Unsupported Transitions.

“Installed operator Deployment has no app.kubernetes.io/version label”

Cause: The check cannot determine the installed operator version. Target-minor overrides cannot bypass this error.

Inspect the installed release and the Deployment’s metadata and image:

helm list --namespace $NAMESPACE
kubectl get deployments --namespace $NAMESPACE \
-l app.kubernetes.io/name=dynamo-operator -o yaml

Confirm the version of the running operator from its image and release records. Restore the Deployment’s metadata.labels.app.kubernetes.io/version to that verified version in the Helm or GitOps configuration that manages it, then retry. Do not use the target version as the installed version; custom image tags or digests require checking the corresponding build records.

“VALIDATION ERROR: Cannot install cluster-wide Dynamo operator”

VALIDATION ERROR: Cannot install cluster-wide Dynamo operator.
Found existing namespace-restricted Dynamo operators in namespaces: ...

Cause: Attempting cluster-wide install on a shared cluster with existing namespace-restricted operators.

Solution: Remove the development/test namespace-restricted operators, then install one cluster-wide operator for production use.

CRDs already exist

Cause: Installing CRDs on a cluster where they’re already present (common on shared clusters).

Solution: The cluster-wide operator’s crd-apply init container manages CRDs automatically. If you encounter conflicts, check existing CRDs with kubectl get crd | grep dynamo.

Pods not starting?

kubectl describe pod <pod-name> -n $NAMESPACE
kubectl logs <pod-name> -n $NAMESPACE

Bitnami etcd “unrecognized” image?

ERROR: Original containers have been substituted for unrecognized ones.

Add to the helm install command:

--set "etcd.image.repository=bitnamilegacy/etcd" --set "etcd.global.security.allowInsecureImages=true"

Clean uninstall?

Before uninstalling, record any customized hook names with helm get hooks dynamo-platform -n $NAMESPACE. For the default release and operator names shown in this guide, remove the retained upgrade-path Job and its supporting resources after uninstalling:

# Uninstall the platform
helm uninstall dynamo-platform --namespace $NAMESPACE
# Remove upgrade-path hook resources that Helm does not uninstall
kubectl delete job,serviceaccount,role,rolebinding dynamo-platform-dynamo-operator-check-upgrade-path \
--namespace $NAMESPACE --ignore-not-found
# List Dynamo CRDs
kubectl get crd | grep "dynamo.*nvidia.com"
# Delete each CRD
kubectl delete crd <crd-name>

Reference