Azure AKS Enterprise Landing Zone & Governance Architecture¶
Skill metadata
Name azure-aks-enterprise-landing-zones · Level senior · Tags azure aks cni workload-identity policy cloud
"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."
Source: skills/cloud-azure/azure-aks-enterprise-landing-zones/SKILL.md
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¶
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 |
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:
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"
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.