Azure#
This guide covers deploying NIM LLM on Microsoft Azure, including standard NIM LLM and Dynamo mode paths:
Deployment Path |
Description |
|---|---|
AKS (Azure Kubernetes Service) |
Self-managed Kubernetes deployment using the NIM LLM Helm chart. Provides full control over infrastructure, including GPU node pools and persistent storage. |
Microsoft Foundry |
Managed deployment using Azure ML Managed Online Endpoints. Simplifies infrastructure management with built-in health checks. |
Dynamo mode on AKS or Foundry |
AKS DynamoGraphDeployment (DGD) and Foundry single-container paths. Refer to Dynamo Deployment. |
AKS Deployment#
To deploy NIM LLM on Azure AKS, follow these steps to create an AKS cluster with GPU nodes and prepare the environment for running NIM LLM workloads. This section will walk you through prerequisites, cluster creation, and initial setup.
Prerequisites#
Install the following tools before proceeding:
Tip
If you use preview AKS features, also install the aks-preview extension.
Log in to Azure:
az login --use-device-code
You also need an NGC API key with access to NIM LLM container images and Helm charts.
Create an AKS Cluster with GPU Nodes#
Complete the following steps to create the AKS cluster, add a GPU node pool, and get the cluster credentials.
Create a resource group and AKS cluster:
export RESOURCE_GROUP="nim-resource-group" export REGION="southcentralus" export AKS_NAME="nim-cluster" az group create --name $RESOURCE_GROUP --location $REGION az aks create --resource-group $RESOURCE_GROUP --name $AKS_NAME \ --location $REGION --generate-ssh-keys
For detailed steps, refer to the AKS quickstart guide.
Add a GPU node pool. Skip automatic GPU driver installation so the NVIDIA GPU Operator manages drivers later in this guide.
az aks nodepool add --resource-group $RESOURCE_GROUP --cluster-name $AKS_NAME \ --name gpupool --node-count 1 --node-vm-size Standard_ND96amsr_A100_v4 \ --gpu-driver none --node-osdisk-size 2048 --max-pods 110
Note
Azure CLI 2.72.2 or later is required for
--gpu-driver none. On older CLI versions, use--skip-gpu-driver-installinstead (deprecated after August 2025).Tip
Choose a GPU-enabled VM size that matches your model requirements. For supported options, refer to GPU workloads in AKS.
Get the cluster credentials:
az aks get-credentials --resource-group $RESOURCE_GROUP --name $AKS_NAME \ --overwrite-existing
Install the NVIDIA GPU Operator#
Install the NVIDIA GPU Operator after the AKS cluster is ready.
Add the NVIDIA Helm repository:
helm repo add nvidia https://helm.ngc.nvidia.com/nvidia --pass-credentials
Update the local Helm repository index:
helm repo update
Install the GPU Operator:
helm install --create-namespace --namespace gpu-operator \ nvidia/gpu-operator --wait --generate-name
For more information, refer to the NVIDIA GPU Operator documentation.
Create Kubernetes Secrets#
Create the namespace and secrets that the Helm deployment uses.
Set the required environment variables:
export NGC_API_KEY="${YOUR_NGC_API_KEY}" export NAMESPACE="nim-llm" export IMAGE_PULL_SECRET="ngc-secret"
Create the namespace:
kubectl create namespace $NAMESPACE
Create the NGC image pull secret:
kubectl create secret docker-registry $IMAGE_PULL_SECRET \ --namespace $NAMESPACE \ --docker-server=nvcr.io \ --docker-username='$oauthtoken' \ --docker-password="$NGC_API_KEY"
Create the NGC API key secret:
kubectl create secret generic ngc-api \ --namespace $NAMESPACE \ --from-literal=NGC_API_KEY="$NGC_API_KEY"
Optional: For gated Hugging Face models, create an additional secret.
Set the Hugging Face token:
export HF_TOKEN="${YOUR_HF_TOKEN}"
Create the secret:
kubectl create secret generic hf-token \ --namespace $NAMESPACE \ --from-literal=HF_TOKEN="$HF_TOKEN"
Deploy NIM LLM with Helm#
To deploy NVIDIA NIM for LLMs with Helm, follow these steps:
Fetch the Helm chart from NGC:
export NIM_LLM_CHART_VERSION="1.0.0" # Set to your desired chart version helm fetch https://helm.ngc.nvidia.com/nim/charts/nim-llm-${NIM_LLM_CHART_VERSION}.tgz \ --username='$oauthtoken' --password=$NGC_API_KEY
Optional: View the default chart values to understand available configuration options:
helm show values nim-llm-${NIM_LLM_CHART_VERSION}.tgz
Tip
For help choosing the right model configuration for your
values.yaml, refer to Model Profiles and Selection.Deploy using a custom values file:
helm install my-nim nim-llm-${NIM_LLM_CHART_VERSION}.tgz \ --namespace $NAMESPACE \ -f path/to/your/custom-values.yaml
Verify the Deployment#
Complete the following steps to confirm that the service is reachable and serving inference requests.
Get the service endpoint:
kubectl -n $NAMESPACE get svc -l app.kubernetes.io/name=nim-llm
Check the health endpoint (set
NIM_EXTERNAL_IPfrom the service EXTERNAL-IP):export NIM_EXTERNAL_IP=$(kubectl -n $NAMESPACE get svc -l app.kubernetes.io/name=nim-llm -o jsonpath='{.items[0].status.loadBalancer.ingress[0].ip}') curl -s "http://${NIM_EXTERNAL_IP}:8000/v1/health/ready"
Send an inference request:
curl -X POST "http://${NIM_EXTERNAL_IP}:8000/v1/chat/completions" \ -H "Content-Type: application/json" \ -d '{ "model": "meta/llama3.1-8b-instruct", "messages": [{"role": "user", "content": "Hello!"}], "max_tokens": 128 }'
Microsoft Foundry Deployment#
To deploy NIM on Microsoft Foundry, follow these steps to provision the necessary Azure Machine Learning resources and prepare your environment for running NIM workloads. This section will walk you through prerequisites, workspace setup, and deployment of NIM as a managed online endpoint.
Prerequisites#
Before deploying NIM to Microsoft Foundry, make sure you have the following:
The Azure CLI and Azure ML extension:
az extension add -n ml -y
An Azure Machine Learning workspace:
az ml workspace create --name ${WORKSPACE_NAME} --resource-group ${RESOURCE_GROUP}
An NGC API key for pulling NIM container images and downloading model artifacts.
-
pip install azure-ai-ml azure-identity
Note
Some Azure regions have limited GPU quota. If you encounter quota errors, refer to Troubleshoot online endpoints: OutOfQuota.
Deploy with the Python SDK#
The following steps deploy a NIM container as an Azure ML managed online endpoint.
Tip
The nim_model_profile variable determines which model configuration is used. For help choosing the right profile, refer to Model Profiles and Selection.
Create the ML client and endpoint:
from azure.ai.ml import MLClient from azure.ai.ml.entities import ( ManagedOnlineEndpoint, ManagedOnlineDeployment, Environment, OnlineRequestSettings, ProbeSettings, ) from azure.identity import DefaultAzureCredential subscription_id = "<your-subscription-id>" resource_group = "<your-resource-group>" workspace_name = "<your-workspace-name>" endpoint_name = "<your-endpoint-name>" acr_image = "<your-acr-or-ngc-nim-image-uri>" ngc_api_key = "<your-ngc-api-key>" nim_model_profile = "<your-nim-model-profile>" instance_type = "Standard_NC24ads_A100_v4" client = MLClient( credential=DefaultAzureCredential(), subscription_id=subscription_id, resource_group_name=resource_group, workspace_name=workspace_name, ) endpoint = ManagedOnlineEndpoint( name=endpoint_name, description=f"NIM deployment: {acr_image}", auth_mode="key", ) client.online_endpoints.begin_create_or_update(endpoint).result()
Define the environment and deployment:
env = Environment( name=f"nim-env-{endpoint_name}", image=acr_image, inference_config={ "liveness_route": {"port": 8000, "path": "/v1/health/live"}, "readiness_route": {"port": 8000, "path": "/v1/health/ready"}, "scoring_route": {"port": 8000, "path": "/"}, }, ) deployment = ManagedOnlineDeployment( name="nim", endpoint_name=endpoint_name, environment=env, instance_type=instance_type, instance_count=1, environment_variables={ "NGC_API_KEY": ngc_api_key, "NIM_MODEL_PROFILE": nim_model_profile, }, request_settings=OnlineRequestSettings( request_timeout_ms=90000, max_concurrent_requests_per_instance=1, ), liveness_probe=ProbeSettings( initial_delay=600, period=30, timeout=10, failure_threshold=30 ), readiness_probe=ProbeSettings( initial_delay=600, period=30, timeout=10, failure_threshold=30 ), ) client.online_deployments.begin_create_or_update(deployment).result()
Route traffic to the deployment:
endpoint = client.online_endpoints.get(endpoint_name) endpoint.traffic = {"nim": 100} client.online_endpoints.begin_create_or_update(endpoint).result()
Retrieve the endpoint URL and key:
endpoint_info = client.online_endpoints.get(endpoint_name) keys = client.online_endpoints.get_keys(endpoint_name) endpoint_url = endpoint_info.scoring_uri.rstrip("/") api_key = keys.primary_key
Verify the Deployment#
Send an inference request to the endpoint:
import httpx
headers = {
"Authorization": f"Bearer {api_key}",
"Content-Type": "application/json",
}
payload = {
"model": "meta/llama3.1-8b-instruct", # or your deployed model name
"messages": [{"role": "user", "content": "Hello!"}],
"max_tokens": 128,
}
with httpx.Client(timeout=60) as http:
response = http.post(
f"{endpoint_url}/v1/chat/completions",
headers=headers,
json=payload,
)
response.raise_for_status()
print(response.json())
Dynamo Deployment#
Deploy NIM with Dynamo on Microsoft Azure by using one of these paths:
Path |
Guide |
|---|---|
AKS, multi-pod DGD (Dynamo Operator) |
|
AI Foundry, single container |
For general Azure cluster setup (subscription, AKS creation, GPU node pools, and Foundry workspace), refer to the preceding sections on this page.
Prerequisites#
Requirement |
Notes |
|---|---|
Azure subscription |
With quota for GPU VMs in your target region |
Region |
Choose a region where your GPU SKU is available (for example |
Tools |
|
Cluster |
AKS 1.24+ with a GPU node pool; NVIDIA GPU Operator installed |
Secrets |
|
Container image |
A NIM 3.0 vLLM image published for Dynamo mode |
Verify GPUs are visible after GPU Operator install:
kubectl get nodes -o jsonpath='{.items[*].status.allocatable.nvidia\.com/gpu}{"\n"}'
AKS + DynamoGraphDeployment (DGD)#
Deploy the multi-pod topology with the NVIDIA Dynamo Operator and the DGD recipe published in the model’s NGC collection. The NIM-LLM Helm chart does not support DGD mode in this release, and the release does not publish a separate Helm chart for Dynamo mode.
Complete the shared prerequisites, including the AKS GPU node pool and namespace credentials. Then follow Dynamo Graph Deployment on Kubernetes. That procedure:
Installs the validated
dynamo-platform1.2.0 chart, which includes the required CRDs and needs no additional component flags.Downloads the model-, GPU-, and workload-specific DGD recipe from the model’s NGC collection.
Preserves the image, profile, GPU count, replica count, and worker tuning validated with that recipe.
Uses
/v1/health/readyfor Frontend readiness.
Azure AI Foundry (managed online endpoint)#
Deploy NIM in Dynamo mode on Azure Machine Learning managed online
endpoints as a single container with NIM_DYNAMO_SINGLE=1. The
container runs a Dynamo frontend and one worker with file discovery and ZMQ.
This path does not use Kubernetes or the Dynamo Operator. Multi-pod DGD remains AKS-only (refer to AKS + DynamoGraphDeployment (DGD)).
For workspace creation and GPU quota requests, refer to the Azure CSP deployment guide.
Prerequisites#
Requirement |
Notes |
|---|---|
Azure ML workspace |
In a region with GPU quota for your instance type |
Tools |
|
Python packages |
|
Credentials |
|
Container image |
A NIM 3.0 vLLM image published for Dynamo mode |
RBAC |
Azure ML Data Scientist or Contributor on the workspace |
az extension add -n ml -y
pip install azure-ai-ml azure-identity
az login
Request GPU quota in the AML workspace if deploy fails with OutOfQuota. Refer to troubleshooting online endpoints.
Step 1: Environment variables#
cp deploy/azure/env.example deploy/azure/.env
# Edit .env with subscription, workspace, image, and credentials.
source deploy/azure/.env
export FOUNDRY_HEALTH_PATH=/v1/health/ready
Step 2: Deploy#
From the repository root:
python3 deploy/azure/foundry/deploy_nim_d_foundry.py deploy
The script creates (or updates):
A
ManagedOnlineEndpointwith key authA
ManagedOnlineDeploymentwith Dynamo mode environment variables100% traffic to the deployment
Key Dynamo mode settings:
Variable |
Purpose |
|---|---|
|
Single-container Dynamo mode |
|
Model URI from a supported source, such as Hugging Face or NGC |
|
OpenAI API model id |
|
Hugging Face cache directory in the container |
|
Internal vLLM port (default |
|
Frontend management readiness route ( |
The deployment helper reads FOUNDRY_HEALTH_PATH and configures both managed
endpoint probes on port 8000.
First startup can take 15-45 minutes (model download + Dynamo bootstrap). Default probe initial_delay is 600 seconds (FOUNDRY_PROBE_INITIAL_DELAY).
Step 3: Smoke test#
After deploy, the script prints the scoring_uri and a command that fetches the endpoint key at run time. The key is never printed, so it does not leak into terminal history or CI logs. In another shell:
export SMOKE_BASE_URL="https://<endpoint>.<region>.inference.ml.azure.com"
export SMOKE_API_KEY=$(az ml online-endpoint get-credentials \
-n "$ENDPOINT_NAME" -g "$RESOURCE_GROUP" -w "$WORKSPACE_NAME" \
--query primaryKey -o tsv)
export SMOKE_MODEL="TinyLlama/TinyLlama-1.1B-Chat-v1.0" # optional override
deploy/azure/scripts/smoke-test.sh foundry
Teardown#
source deploy/azure/.env
python3 deploy/azure/foundry/deploy_nim_d_foundry.py delete
Azure notes#
Topic |
Guidance |
|---|---|
Startup time |
Use generous probe delays while NIM downloads weights and starts the Dynamo frontend and worker |
GPU memory |
Size |
Auth |
Endpoint uses key auth; pass |
Storage |
Managed endpoints use ephemeral container disk; large models need sufficient instance disk |
RBAC |
Workspace read is not enough; you need deploy permissions on the AML workspace |
Customize for your model#
For single-container Foundry deployments, set the model and resource controls
supported by the selected NIM image and keep NIM_DYNAMO_SINGLE=1. Use
/v1/health/ready for frontend readiness.
For the Kubernetes workflow, refer to Dynamo Graph Deployment on Kubernetes. Do not replace the image, model profile, GPU count, or workload tuning in the recipe downloaded from the model’s NGC collection. The published recipe and image are validated as one configuration.
Override the smoke-test model with export SMOKE_MODEL=<your-model-id> if /v1/models lists more than one id.
References#
Refer to the following Azure documentation for more information: