- How-to guides
- Providers
- Microsoft Azure
Microsoft Azure
Microsoft Azure is Microsoft's public cloud. NKP deploys onto it as a managed Azure Kubernetes Service (AKS) cluster, so Azure runs and upgrades the Kubernetes control plane for you while nic (the Nebari Infrastructure Core CLI) provisions the cluster, its node pools, and the supporting infrastructure.
This guide walks you through a deployment from end to end: from an empty subscription to a running cluster you can manage and tear down. If you have deployed NKP on AWS, the flow will feel familiar; the differences are mostly in how you authenticate and in a few Azure-specific fields.
What your team gets
Section titled “What your team gets”When nic deploy finishes, your team will have all standard NKP services plus:
- A managed Kubernetes cluster ready for workloads (Azure AKS, with one System node pool and any number of User node pools).
- Block storage through Azure managed disks (AKS's built-in disk StorageClasses; NKP's own databases use
managed-csi).
Prerequisites
Section titled “Prerequisites”Azure subscription
Section titled “Azure subscription”You will need an Azure subscription you can deploy into. If you don't have one, create an Azure account.
- Region: pick a region where AKS is available. The example uses
eastus. - Role: the identity that runs
nic deploy(youraz loginuser or a service principal) needs Owner, or Contributor plus Role Based Access Control Administrator, on the subscription.niccreates role assignments for the cluster's managed identities, which Contributor alone cannot do. - Quotas: confirm your subscription has enough regional vCPU quota for the VM sizes in your node pools. The example below needs 12 Dv3-family vCPUs at its minimum size (52 at full scale, or 72 if you keep the starter config's
workerpool), which is more than many new subscriptions allow, andnicdoes not check quota before it starts provisioning. - Cost: see Cost considerations for what bills.
Azure authentication
Section titled “Azure authentication”nic needs one value from you directly, your subscription ID, and finds your identity through the standard Azure credential chain, DefaultAzureCredential. It tries environment-variable credentials first, then workload identity and managed identity, then the Azure CLI.
For most people the simplest path is the Azure CLI:
az loginaz account set --subscription <subscription-id> # if you have more than oneaz account show --query id --output tsv # prints your subscription IDInstall nic
Section titled “Install nic”Follow the Install NIC guide to download and install the nic CLI for your platform.
GitOps repository
Section titled “GitOps repository”See GitOps repository in the Prepare to deploy guide.
Secrets and credentials
Section titled “Secrets and credentials”From inside your GitOps repo clone, download the template:
cd /path/to/your-gitops-repocurl -o .env https://raw.githubusercontent.com/nebari-dev/nebari-infrastructure-core/v0.14.0/.env.exampleThen fill in the GitOps tokens and your subscription ID. The template has a commented-out AZURE_SUBSCRIPTION_ID line under its Azure DNS heading; uncomment and set that one, or add the block below (not both). The template has no ARM_* lines, so add them yourself if you use a service principal. For .gitignore setup and GitOps token configuration, see Secrets and credentials in the Prepare to deploy guide.
# AzureAZURE_SUBSCRIPTION_ID=00000000-0000-0000-0000-000000000000 # az account show --query id --output tsv
# Service-principal auth only (skip these if you use az login):# AZURE_CLIENT_ID=...# AZURE_TENANT_ID=...# AZURE_CLIENT_SECRET=...# ARM_CLIENT_ID=... # same value as AZURE_CLIENT_ID# ARM_TENANT_ID=... # same value as AZURE_TENANT_ID# ARM_CLIENT_SECRET=... # same value as AZURE_CLIENT_SECRETnic deploy (including nic deploy --dry-run) fails before creating anything if AZURE_SUBSCRIPTION_ID is not set. You do not need to set ARM_SUBSCRIPTION_ID: nic passes the subscription ID through to OpenTofu for you.
Cost considerations
Section titled “Cost considerations”A NKP deployment provisions several Azure services that bill from day one. Check the Azure pricing calculator for current rates in your region.
- AKS control plane: the
Freetier (the default) has no control-plane charge; settingsku_tiertoStandardorPremiumadds a per-cluster hourly fee for an uptime SLA. - Virtual machines in your node pools: per-hour cost for each running node.
- Managed disks: an OS disk on each node (128 GB unless you set
os_disk_size_gb) plus anymanaged-csipersistent volumes your workloads request. - Load balancer: the Standard Load Balancer that AKS creates for outbound traffic and ingress, and its public IP addresses.
- Bandwidth: outbound data transfer.
Configuration
Section titled “Configuration”Download the starter config from the nebari-infrastructure-core v0.14.0 release into the same directory as your .env, which is the directory you will deploy from:
curl -O https://raw.githubusercontent.com/nebari-dev/nebari-infrastructure-core/v0.14.0/examples/azure-config.yamlAt minimum, edit these fields:
project_name: my-cluster # letters, digits, and hyphens; see the naming note belowdomain: nebari.example.com # a hostname you own
certificate: type: letsencrypt acme: email: you@example.com # required for Let's Encrypt; renewal notices go here
repository: existing: # the repository provider url: "https://github.com/<your-org>/<your-gitops-repo>.git" branch: main path: clusters/my-cluster # subdirectory in the repo; conventionally matches project_name auth: token: env: GIT_TOKEN # matches the GIT_TOKEN set in .env
cluster: azure: region: eastus # an AKS-supported region (required) kubernetes_version: "1.35" # az aks get-versions --location <region> node_groups: # at least one pool is required system: instance: Standard_D4_v3 min_nodes: 1 max_nodes: 3 mode: System # the pool that runs cluster services user: instance: Standard_D8_v3 min_nodes: 1 max_nodes: 5The starter config authenticates to Git with an SSH key (auth.ssh.env: GIT_SSH_PRIVATE_KEY) instead. Either works as long as you set exactly one: replace its auth.ssh block with the auth.token block above, or keep it (with an SSH git@… URL) and set GIT_SSH_PRIVATE_KEY in .env (see the repository reference).
Every AKS cluster needs one System node pool to run cluster services. Set mode: System on the pool you want to play that role; pools without a mode are User pools. At most one pool may be System. If none is, the pool whose name sorts first alphabetically becomes the System pool, so set it explicitly rather than relying on the order of your pool names.
By default nic creates a resource group named <project_name>-rg. Set resource_group_name to deploy into one you already manage.
Networking uses Azure CNI Overlay, with the azure (default) or cilium dataplane set by network.dataplane, and the cluster runs under user-assigned managed identities that nic creates.
For the full schema (custom networking and existing VNets, network.dataplane, private clusters, authorized IP ranges, sku_tier, Node Auto Provisioning, per-pool disks, labels, taints, and zones), see the Azure provider configuration reference. If you enable private_cluster_enabled or authorized_ip_ranges, run nic from a network that can reach the cluster's API server: after provisioning, nic installs Argo CD and the foundational services through it.
Deploy and verify
Section titled “Deploy and verify”Follow Deploy a cluster to deploy and verify. Expect the first deployment to take 20 minutes or more as AKS provisions the control plane and node pools, followed by ArgoCD syncing the foundational services.
On Azure, nic does not write a kubeconfig to a local path. Retrieve one with nic kubeconfig, as Deploy a cluster shows; it returns cluster-admin credentials directly from Azure, so you do not need the az CLI for kubectl to work.
Once the platform has converged, nic outputs prints its entry points, including the gateway's public IP address, which you need for DNS:
nic outputs -f <config-file> --waitAKS gives the gateway a public IP address, so you point your domain at it with A records. Add a dns.cloudflare block to have nic create the records for you, or create them by hand with any DNS provider. See Cloudflare DNS for both paths.
First sign-in
Section titled “First sign-in”See Keycloak authentication for first sign-in. Then add Software Packs from the pack catalog, as described in Deploying a pack.
Update an existing deployment
Section titled “Update an existing deployment”To change something about a running cluster (scale a node pool, add a pool, change tags), edit your config and re-run the deploy commands as described in Update a cluster.
Upgrade Kubernetes version
Section titled “Upgrade Kubernetes version”To upgrade, set kubernetes_version under cluster.azure and re-deploy:
cluster: azure: kubernetes_version: "1.36" # was "1.35"nic passes the version straight through to AKS and does not sequence the upgrade itself; the rules come from AKS. AKS upgrades one minor version at a time and does not allow skipping versions or downgrading, so going from 1.34 to 1.36 means two re-deploys (1.34 → 1.35 → 1.36).
A re-deploy upgrades the AKS control plane only; your node pools keep their Kubernetes version until you upgrade them. After the re-deploy, upgrade the node pools to match, either all at once or one pool at a time:
# All node pools. The CLI warns that the cluster is already on this version;# the node pools still upgrade.az aks upgrade --resource-group <project_name>-rg --name <project_name>-aks \ --kubernetes-version 1.36
# Or a single poolaz aks nodepool upgrade --resource-group <project_name>-rg --cluster-name <project_name>-aks \ --name <pool> --kubernetes-version 1.36Use your resource_group_name instead of <project_name>-rg if you set one. Both commands ask for confirmation unless you add --yes. Node pools can lag the control plane by at most three minor versions, so do not skip this step. For the control-plane-first workflow and node-pool upgrade options, see Upgrade the AKS cluster control plane.
See Upgrade Kubernetes version for the nic commands and the post-upgrade checks; run the node-pool upgrade above before you verify.
Destroy
Section titled “Destroy”Run the destroy commands as described in Destroy a cluster.
nic destroy removes the AKS cluster and its node pools, the virtual network (when nic created it), the managed identities, the load balancer, any DNS records nic created, and (when nic created it) the <project_name>-rg resource group. When it finishes, it lists any resources tagged for the cluster that are still present, with an az resource delete command to remove them.
It does not remove the shared nic-tfstate-rg state backend; remove that by hand once you are finished with every cluster in the subscription.