Prereqs
Beforehelm install, the following must be in place on the cluster side.
Cluster
- AKS 1.30+
- OIDC issuer enabled on the cluster (
az aks update --enable-oidc-issuer --enable-workload-identity) — required for Workload Identity federation - Cluster nodes must have outbound internet access, or images must be mirrored to Azure Container Registry (ACR) first
Addons + controllers
Azure-managed resources (recommended)
- Azure Database for PostgreSQL Flexible Server in the same virtual network as the AKS cluster. Nebula requires
vector,pg_partman, andpg_cron; in the Azure portal, navigate to Server parameters →azure.extensionsand add the required extensions, then enablepg_cronpreloading before bootstrap. Runnebula-enterprise postgres provisionto create the Nebula database, user, extensions, and chart credential Secret. Private access (VNet-integrated) is strongly recommended. - Azure Blob Storage account with a container for graph segments. The chart’s object storage path uses Azure Blob’s S3-compatible API endpoint — see the note under Object storage below.
- DynamoDB-compatible service for orchestration state, reachable from Nebula pods. Before Helm install, run
nebula-enterprise orchestration dynamodb ensureto create or verify the fourpk/skorchestration tables and writer-authority records; use--endpoint-urlfor non-AWS endpoints and set the matchingNEBULA_ORCHESTRATION_DYNAMODB_*values in the chart.
objectStorage block emits S3-protocol environment variables (AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, S3_ENDPOINT_URL). Azure Blob exposes an S3-compatible endpoint (Storage account → Settings → S3 compatibility, currently in preview). Enable it and use HMAC access keys as the credentialsSecret. If the S3-compat preview is not available in your region or subscription tier, run a MinIO gateway in front of Azure Blob as a bridge.
Workload Identity setup
Workload Identity replaces the legacy aad-pod-identity approach. Steps:-
Create a managed identity in the same resource group as the cluster:
-
Federate the managed identity with the AKS OIDC issuer for the Nebula service account:
Replace
<release>with yourhelm installrelease name (e.g.nebula). - Grant the managed identity Storage Blob Data Contributor on the Blob container and Key Vault Secrets User on the Key Vault if ESO uses the same identity.
-
Record the managed identity Client ID — you’ll set it under
serviceAccount.annotationsin your values file.
Install
1. Push images to your ACR
image.*.repository in your values file:
2. Seed secrets in Azure Key Vault
Create a Key Vault and store one secret per Nebula key, or store a JSON blob at a single secret name and use ESO’sdataFrom extraction. Example using individual secrets:
Generate the JWT RSA private key with the commands in Service authentication before setting NEBULA-JWT-PRIVATE-KEY-PEM.
NEBULA-JWT-RETIRED-PUBLIC-KEYS-JSON can stay [] on a fresh install. Populate it only during JWT signing-key rotation; see Service authentication.
For an empty Flexible Server, use the bundle helper as the canonical logical bootstrap:
username and password keys. Run the read-only verifier before Helm install:
3. Copy + fill the reference values file
The bundle shipshelm/examples/aks/values.yaml with every AKS-specific knob pre-wired. Copy it, fill in the <placeholder> markers (ACR login server, Flexible Server hostname, Blob storage account, managed identity client ID, Key Vault name, domain), and save as your-values.yaml.
4. Install
_common/production-sizing.yaml is the shared production-shape sizing block (replicas, CPU/memory requests + limits, persistence) used by all three cloud-managed K8s examples (EKS/AKS/GKE). Omit it to keep the chart’s minimal-dev defaults; override per-workload in your-values.yaml to fit your AKS node SKUs.
The chart runs schema migrations and catalog-apply automatically via a per-revision Job (<release>-nebula-migrations-<revision>); API and worker pods gate startup on an init container that polls public.nebula_release_contract for the install’s release row. releaseContract.releaseId and releaseContract.gitSha are stamped into the bundled values by bundle.sh and are consumed automatically.
5. Verify
Upgrade
Pull the new bundle, push new images to your ACR, then:Sizing reference
Recommended AKS node SKUs for the starter shape:
Standard_D4s_v5 (4 vCPU / 16 GB) for API, worker, and Orchestration; Standard_D8s_v5 (8 vCPU / 32 GB) for graph-engine and compactor.
Troubleshooting
Workload Identity not bound — pods receive 401 from Azure APIs
Workload Identity not bound — pods receive 401 from Azure APIs
Check that the managed identity’s federated credential subject exactly matches
system:serviceaccount:<namespace>:<release>-nebula-sa. The release name prefix is part of the service account name. Confirm with kubectl -n nebula get sa and compare to az identity federated-credential list --identity-name nebula-wi --resource-group <rg>.Ingress provisioning slow or stuck
Ingress provisioning slow or stuck
nginx Ingress on AKS provisions a public Azure Load Balancer automatically. The provisioning can take 3-5 minutes on a fresh cluster. Check
kubectl -n ingress-nginx get svc ingress-nginx-controller for the external IP assignment. If it stays in Pending, verify that the cluster’s subnet has enough IP space and that the AKS service principal / managed identity has Network Contributor on the virtual network.pgvector missing on first start — API reports 'extension vector does not exist'
pgvector missing on first start — API reports 'extension vector does not exist'
The
azure.extensions server parameter must include vector before bootstrap. Then run nebula-enterprise postgres provision or have your platform workflow satisfy nebula-enterprise postgres verify; the contract requires the extension to be enabled at the server level and installed in the Nebula database.Blob credentials rejected — graph-engine 'InvalidAccessKeyId'
Blob credentials rejected — graph-engine 'InvalidAccessKeyId'
Azure Blob’s S3-compatible endpoint requires HMAC keys, not the storage account connection string. Generate HMAC keys under Storage account → Access keys → Enable S3 compatible HMAC. Store the Access Key ID and Secret Access Key in the Kubernetes Secret referenced by
objectStorage.credentialsSecret with keys AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY (those exact uppercase names — the chart’s nebula.objectStorageEnv helper reads them via secretKeyRef.key).