# Azure Aks Enterprise Landing Zones

> Azure AKS enterprise landing zones: Azure CNI Overlay networking and IP planning, private clusters, Entra Workload Identity federation, Azure Policy for Kubernetes, and node-pool topology. Use when building or hardening AKS to an enterprise baseline, when AKS pods must authenticate to Key Vault or other Azure services without any stored secret, or when enforcing Kubernetes governance on Azure.

- Skill: `mchittineni/azure-aks-enterprise-landing-zones` (Agent Skill, multi-file: 2 files)
- Install (CLI): `npx skillmds@latest add mchittineni/azure-aks-enterprise-landing-zones`
- Raw SKILL.md: https://api.skillmd.com/api/skills/mchittineni/azure-aks-enterprise-landing-zones/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: DevOps & Infra
- Author: mchittineni (https://skillmd.com/u/mchittineni)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/mchittineni/azure-aks-enterprise-landing-zones

---


# Azure AKS Enterprise Landing Zone & Governance Architecture

## When to Use This Skill

**Triggers — load this skill when:**

- An AKS cluster must be built or hardened to an enterprise baseline
- Workloads need Entra ID access via Workload Identity instead of secrets
- Kubernetes governance must be enforced with Azure Policy

**Route elsewhere when:**

- Hub-spoke networking and platform services -> `azure-cloud-engineering-patterns`
- Chart authoring -> `helm-kubernetes-deployment`
- Multi-cluster reconciliation -> `gitops-multi-cluster-argo-flux`

## 1. Enterprise Terraform AKS Landing Zone Configuration

```hcl
resource "azurerm_kubernetes_cluster" "aks" {
  name                = "aks-prod-enterprise"
  location            = "eastus2"
  resource_group_name = "rg-production-compute"
  dns_prefix          = "aks-prod"
  kubernetes_version  = "1.29"

  default_node_pool {
    name                = "system"
    node_count          = 3
    vm_size             = "Standard_D4ds_v5"
    os_disk_type        = "Ephemeral"
    vnet_subnet_id      = "/subscriptions/.../subnets/aks-subnet"
    only_critical_addons_enabled = true
    zones               = ["1", "2", "3"]
  }

  identity {
    type = "UserAssigned"
    identity_ids = [azurerm_user_assigned_identity.aks_identity.id]
  }

  network_profile {
    network_plugin      = "azure"
    network_plugin_mode = "overlay"
    ebpf_data_plane     = "cilium"
    load_balancer_sku   = "standard"
  }

  oidc_issuer_enabled       = true
  workload_identity_enabled = true
  azure_policy_enabled      = true
}
```

---

## 2. Key Architecture Standards

- **Azure CNI Powered by Cilium**: High-performance eBPF-based data plane, network policy enforcement, and IP address conservation.
- **Entra ID Workload Identity**: Federate K8s Service Accounts directly to Azure Managed Identities without static client secrets.
- **System vs User Node Pool Separation**: Keep critical K8s control addons isolated on dedicated system node pools.

---

## 3. CNI Overlay Networking & Private Clusters

**Azure CNI Overlay** is the default choice for enterprise scale: pods get addresses from a
private overlay CIDR instead of consuming VNet address space, so a cluster no longer needs tens
of thousands of routable IPs. Nodes stay in the VNet; only nodes and Services consume VNet IPs.

| Mode | VNet IPs consumed | Direct pod addressability | Use when |
| --- | --- | --- | --- |
| CNI Overlay | Nodes + Services only | No (SNAT out of node IP) | Default; large or growing clusters |
| CNI (node subnet) | Every pod | Yes | Legacy peers must reach pods directly |
| Kubenet | Nodes only | No | Deprecated — do not start here |

```hcl
network_profile {
  network_plugin      = "azure"
  network_plugin_mode = "overlay"
  network_policy      = "cilium"
  pod_cidr            = "10.244.0.0/16"   # overlay, not from the VNet
  service_cidr        = "10.0.32.0/20"
  dns_service_ip      = "10.0.32.10"
}

private_cluster_enabled             = true       # API server has no public endpoint
private_cluster_public_fqdn_enabled = false
api_server_access_profile {
  authorized_ip_ranges = []                       # empty because access is private-only
}
```

A private cluster moves the API server behind a Private Endpoint, so CI runners and admin
tooling must reach it over the hub network (private DNS zone
`privatelink.<region>.azmk8s.io` linked to every VNet that resolves it). Plan that path before
enabling it — the usual failure is a working cluster nobody can reach. Keep system and user
node pools separate, taint the system pool, and pin the Kubernetes version per pool so upgrades
are staged rather than simultaneous.

---

## 4. Key Vault Access Without Stored Secrets

Workload Identity federates the pod's ServiceAccount token to Entra ID, so no secret, connection
string, or certificate is ever stored in the cluster:

```bash
az identity federated-credential create --name aks-payments   --identity-name id-payments --resource-group rg-platform   --issuer "$(az aks show -g rg-platform -n aks-prod --query oidcIssuerProfile.issuerUrl -o tsv)"   --subject "system:serviceaccount:prod-payments:payments" --audience api://AzureADTokenExchange

az role assignment create --assignee "$CLIENT_ID"   --role "Key Vault Secrets User"   --scope "/subscriptions/$SUB/resourceGroups/rg-platform/providers/Microsoft.KeyVault/vaults/kv-prod"
```

```yaml
apiVersion: v1
kind: ServiceAccount
metadata:
  name: payments
  namespace: prod-payments
  annotations:
    azure.workload.identity/client-id: <client-id>
---
# Pod template
metadata:
  labels: { azure.workload.identity/use: "true" }
spec:
  serviceAccountName: payments
```

The federated subject pins the identity to one namespace **and** one ServiceAccount — the
control that stops any other pod in the cluster from requesting the same token. Use the Key
Vault CSI driver when the application must read files rather than call the SDK; avoid the
deprecated pod-managed identity (aad-pod-identity) in new clusters.

