Skip to content

Deploying to AKS

llms.txt lists every page for an agent
Optional: hand this page to your coding agentThe steps work by hand too.
Show the whole prompt
Read https://intentius.io/chant/lexicons/azure/aks-kubernetes/.
Set up the cross-lexicon project the page describes: the azure lexicon for the cluster, registry, identities and DNS zone, the k8s lexicon for the workloads, with the ARM outputs flowing through `.env` into `config.ts`.
Run `npm run build` and `npx chant lint src`, and open a pull request with the source and the built template and manifests.
List the deploy steps (`az group create`, `npm run deploy-infra`, `npm run load-outputs`, `npm run apply`) for me to run in order, and do not run them or kubectl against any cluster yourself.
Never deploy to a real cloud account or shared environment (with `chant run`, `chant components` or a platform's own CLI), approve (a pull request review, `chant approve` or `chant run approve`), override a policy denial (`chant approve policy-override`), or merge; never cut or publish a release (`chant release cut --yes` or `chant release publish`), push or delete a `ci/*` tag (`chant ci tick` pushes them), or change the value of an existing flag; never touch `.chant/allowed_signers` or `chant/lifecycle`.

Azure infrastructure and Kubernetes workloads can live in the same src/ directory. The Azure lexicon produces an ARM template; the K8s lexicon produces kubectl-ready YAML.

┌─────────────────────────────────────────────────────────┐
│ Azure Lexicon (ARM) │
│ ├── VNet + Subnets + NSG + Route Table │
│ ├── AKS Cluster (SystemAssigned identity) │
│ ├── Container Registry (Premium, admin disabled) │
│ ├── 3× Managed Identities (app, dns, monitor) │
│ ├── Role Assignments (ACR Pull, DNS Contributor, etc.) │
│ └── Azure DNS Zone │
└────────────────────┬────────────────────────────────────┘
│ client IDs via .env → config.ts
┌────────────────────▼────────────────────────────────────┐
│ K8s Lexicon │
│ ├── Namespace (quotas, limits, network policy) │
│ ├── AutoscaledService (Deployment + HPA + PDB) │
│ ├── WorkloadIdentityServiceAccount (AKS) │
│ ├── AGIC Ingress + AksExternalDnsAgent │
│ ├── AzureDiskStorageClass │
│ └── AzureMonitorCollector │
└─────────────────────────────────────────────────────────┘

ARM template outputs map to K8s composite props via .env:

ARM OutputK8s Composite Prop
APP_CLIENT_IDAksWorkloadIdentityServiceAccount({ clientId })
EXTERNAL_DNS_CLIENT_IDAksExternalDnsAgent({ clientId })
MONITOR_CLIENT_IDAzureMonitorCollector({ clientId })
AZURE_TENANT_IDtenantId props on multiple composites
AKS_CLUSTER_NAMEclusterName props

Values pass from .env to config.ts to the K8s source files. npm run load-outputs refreshes .env after any infra deploy.

The K8s lexicon provides AKS-specific composites for the workload side:

  • AksWorkloadIdentityServiceAccount — ServiceAccount with Azure client ID annotation
  • AgicIngress — Ingress with Application Gateway annotations, WAF, health probes
  • AzureDiskStorageClass — Azure Disk CSI StorageClass (Premium/Standard/Ultra)
  • AzureFileStorageClass — ReadWriteMany StorageClass via Azure Files (SMB/NFS)
  • AksExternalDnsAgent — Azure DNS record management
  • AzureMonitorCollector — Log Analytics + OTel metrics

See the AKS Composites reference for full API details.

Terminal window
az group create --name $AZURE_RESOURCE_GROUP --location eastus
npm run build # Build ARM template + K8s manifests
npm run deploy-infra # Deploy ARM template
npm run configure-kubectl # Set up kubeconfig
npm run load-outputs # Write client IDs to .env
npm run build:k8s # Rebuild K8s with real values
npm run apply # kubectl apply

chant