IaC Bazaar
AzureStatic-verified

Azure Kubernetes Service Cluster

Hardened AKS with system/user node pools, workload identity, Entra RBAC integration, Azure CNI overlay, and Container Insights wired in.

terraformAzure#azure

Compare Managed Kubernetes across clouds →

azure-aksterraform v1.7

Verification

Static-verified

Passed: 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

NameTypeDefaultDescription
namestringCluster name; prefix for supporting resources (required)
locationstringAzure region (required)
resource_group_namestringExisting resource group (required)
dns_prefixstringnullAPI server DNS prefix; defaults to name
kubernetes_versionstringnullPin a version, or follow the upgrade channel
sku_tierstring"Standard"Free, Standard, Premium
automatic_upgrade_channelstring"patch"patch/stable/rapid/node-image; null disables
node_os_upgrade_channelstring"NodeImage"Node OS image patching channel
private_cluster_enabledboolfalsePrivate API server
local_account_disabledbooltrueEntra-only auth (requires entra_rbac)
azure_policy_enabledbooltrueAzure Policy (Gatekeeper) add-on
entra_rbacobject{}Azure RBAC on, admin groups; null disables
api_server_authorized_ip_rangeslist(string)[]API server allowlist
key_vault_secrets_provider_enabledbooltrueKey Vault CSI driver + rotation
secret_rotation_intervalstring"2m"CSI secret rotation poll interval
container_insights_enabledbooltrueContainer Insights via oms_agent
log_analytics_workspace_idstringnullBYO workspace; one is created if null
log_retention_in_daysnumber30Retention for the created workspace
network_policystring"azure"azure/calico/cilium/null
network_data_planestring"azure"azure or cilium
pod_cidrstring"10.244.0.0/16"Overlay pod CIDR
service_cidrstring"10.0.0.0/16"Service CIDR
dns_service_ipstring"10.0.0.10"Cluster DNS IP (inside service_cidr)
outbound_typestring"loadBalancer"Node egress path
default_node_poolobject{}System pool (size, autoscaling, subnet, ...)
node_poolsmap(object){}User pools keyed by name (spot supported)
acr_pull_registry_idsmap(string){}ACR IDs to grant the kubelet AcrPull on
tagsmap(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), use az aks get-credentials + kubelogin; kube_config_raw will be empty.
  • acr_pull_registry_ids is 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).