Azure Kubernetes Service Cluster
Hardened AKS with system/user node pools, workload identity, Entra RBAC integration, Azure CNI overlay, and Container Insights wired in.
Verification
Static-verifiedPassed: validated and lint-clean (provider-schema-validated for AWS/Azure/GCP; Terraform-language lint elsewhere).
Conformance
- Static validation (fmt · validate · tflint)
- Security scan: findings disclosed (Checkov)
- Plan tests (mocked: validation rules · outputs)
Provenance
- SHA-256 checksum
- Signature (pending)
Functional
- Live test pending (no cloud run yet)
Last verified 2026-06-28 · how we verify
Documentation
azure-aks
Hardened AKS cluster with system/user node pools, workload identity, Entra
RBAC integration, Azure CNI overlay, and Container Insights wired in. Works
with Terraform and OpenTofu (>= 1.6), AzureRM provider >= 4.0, < 5.0.
Secure defaults:
- Entra ID RBAC with Azure RBAC authorization; local accounts disabled
- Workload identity + OIDC issuer enabled (no node-level credentials for pods)
- User-assigned control-plane identity (role assignments before cluster create)
- Azure CNI overlay networking with Azure network policy (Cilium optional)
- System pool tainted
CriticalAddonsOnly— workloads go to user pools - No public IPs on nodes; Standard tier (uptime SLA); Azure Policy add-on on
- Container Insights + Key Vault secrets CSI driver (with rotation) enabled
Usage
module "aks" {
source = "./azure-aks"
name = "prod-aks"
location = "westeurope"
resource_group_name = "rg-prod-aks"
entra_rbac = {
admin_group_object_ids = ["<aks-admins-group-object-id>"]
}
node_pools = {
apps = {
vm_size = "Standard_D4s_v5"
min_count = 2
max_count = 6
}
}
acr_pull_registry_ids = {
main = "<acr-resource-id>"
}
tags = { Environment = "prod" }
}
Inputs
| Name | Type | Default | Description |
|---|---|---|---|
name | string | — | Cluster name; prefix for supporting resources (required) |
location | string | — | Azure region (required) |
resource_group_name | string | — | Existing resource group (required) |
dns_prefix | string | null | API server DNS prefix; defaults to name |
kubernetes_version | string | null | Pin a version, or follow the upgrade channel |
sku_tier | string | "Standard" | Free, Standard, Premium |
automatic_upgrade_channel | string | "patch" | patch/stable/rapid/node-image; null disables |
node_os_upgrade_channel | string | "NodeImage" | Node OS image patching channel |
private_cluster_enabled | bool | false | Private API server |
local_account_disabled | bool | true | Entra-only auth (requires entra_rbac) |
azure_policy_enabled | bool | true | Azure Policy (Gatekeeper) add-on |
entra_rbac | object | {} | Azure RBAC on, admin groups; null disables |
api_server_authorized_ip_ranges | list(string) | [] | API server allowlist |
key_vault_secrets_provider_enabled | bool | true | Key Vault CSI driver + rotation |
secret_rotation_interval | string | "2m" | CSI secret rotation poll interval |
container_insights_enabled | bool | true | Container Insights via oms_agent |
log_analytics_workspace_id | string | null | BYO workspace; one is created if null |
log_retention_in_days | number | 30 | Retention for the created workspace |
network_policy | string | "azure" | azure/calico/cilium/null |
network_data_plane | string | "azure" | azure or cilium |
pod_cidr | string | "10.244.0.0/16" | Overlay pod CIDR |
service_cidr | string | "10.0.0.0/16" | Service CIDR |
dns_service_ip | string | "10.0.0.10" | Cluster DNS IP (inside service_cidr) |
outbound_type | string | "loadBalancer" | Node egress path |
default_node_pool | object | {} | System pool (size, autoscaling, subnet, ...) |
node_pools | map(object) | {} | User pools keyed by name (spot supported) |
acr_pull_registry_ids | map(string) | {} | ACR IDs to grant the kubelet AcrPull on |
tags | map(string) | {} | Tags applied to all resources |
Outputs
id, name, fqdn, private_fqdn, node_resource_group,
oidc_issuer_url, cluster_identity_principal_id,
cluster_identity_client_id, kubelet_identity_object_id,
kube_config_raw (sensitive), log_analytics_workspace_id.
Requirements
- Terraform or OpenTofu
>= 1.6 hashicorp/azurerm>= 4.0, < 5.0- Subscription vCPU quota for the chosen VM sizes; expect 15–25 min apply/destroy
Notes for integrators:
- With
local_account_disabled = true(default), useaz aks get-credentials+kubelogin;kube_config_rawwill be empty. acr_pull_registry_idsis a map with static keys so registry IDs may be unknown at plan time.- When deploying into an existing subnet (
default_node_pool.vnet_subnet_id), the module grants the control-plane identity Network Contributor on it.
Verification
Static-validated (fmt, validate, tflint). Live apply/destroy testing pending cloud sandbox availability — see catalog status.
License
Commercial — IaC Bazaar EULA. © IaC Bazaar. Original work (not derived from a third-party module).