Skip to content

AKS Platform: Cluster Baseline

The cluster baseline is the standard configuration of every AKS cluster of the solution. It is the Terraform layer cluster-baseline (modules aks-cluster, node-pools, cluster-identities, diagnostic-settings). This page lists the settings that matter and the values of the reference configuration.

Reference design, your deployment may differ

The values below are read from the Terraform modules and the nonprod and prod configuration files of the Azure variant. The design document describes a few other values; the differences are called out where they matter.

Fixed in the module

These settings are set in the module and cannot be switched off by a variable.

Setting Value Why
Entra ID integration On, with Azure RBAC for Kubernetes authorisation Humans sign in with Entra ID.
Local accounts Disabled No shared admin credential (local_account_disabled = true).
API server access VNet integration in a dedicated subnet The API server has a private address in the spoke, no public endpoint.
OIDC issuer and workload identity Enabled Pods get Azure access without stored secrets (Identity and access).
Azure Policy add-on Enabled Azure Policy for Kubernetes (Security policy).
System node pool Name system, autoscaling, managed OS disk, only critical add-ons, label node-pool=system Keeps application pods off the system nodes.
Cluster identity One user-assigned managed identity, used for both the control plane and the kubelet See Cluster identities.
Network plugin Azure CNI in overlay mode with the Calico network policy engine See Networking.

Environment values

Setting Production Non-production
Cluster name aks-prod aks-nonprod
Kubernetes version Minor version pinned in the configuration (1.34 in the reference files) Same
SKU tier Standard (SLA-backed) Free
Upgrade channel none (manual) patch
System pool VM size Standard_D4s_v5 Standard_D2s_v5
System pool nodes (min to max) 3 to 5 1 to 2
System pool zones 1, 2, 3 1
System pool max pods per node 30 100
User pool general VM size Standard_D4s_v5 Standard_D4s_v5
User pool general nodes (min to max) 3 to 20 1 to 5
User pool general zones 1, 2, 3 1
User pool general max pods per node 30 100
User pool label workload-type=general workload-type=general
OS disk 128 GB, managed 128 GB, managed
Surge during upgrades (user pool) 33% 33%
Resource group rg-prod-aks (nodes in rg-prod-aks-nodes) rg-nonprod-aks (nodes in rg-nonprod-aks-nodes)

Design document versus code

The design document describes non-production as 2 to 3 system nodes and 2 to 10 user nodes over zones 1 and 2, with 30 pods per node. The nonprod configuration file sets the smaller values shown above, to save cost. The hub-integrated non-production file uses the same sizes as nonprod.

User node pools are a map in the configuration. Adding a pool (for example a dedicated ingress, platform, spot or GPU pool) is a configuration change: name, VM size, min and max count, zones, disk size, max pods, labels, taints and surge. The pool module enables autoscaling on every pool.

Upgrades and maintenance windows

Production Non-production
Kubernetes version upgrades Manual, in the window, after non-production has been validated patch channel applies patch versions automatically; minor upgrades stay manual
Auto-upgrade window Saturday 03:00, 4 hours, UTC+1 Tuesday 20:00, 4 hours, UTC+1
Node OS window Saturday 03:00, 4 hours, UTC+1 Tuesday 20:00, 4 hours, UTC+1

Both windows are weekly. The offset is fixed, so the window moves by an hour against local time when daylight saving time starts or ends. Change the offset in the configuration if that matters.

The design document gives the node image window for production as Sunday and for non-production as Wednesday. The configuration files set it to the same day as the Kubernetes upgrade window.

Rules from the design:

  • non-production is upgraded first and production follows after a validation period, so that both clusters run the same minor version at steady state;
  • a minor version cannot be rolled back on AKS. The remedy after a bad upgrade is a forward fix or a workload-level rollback;
  • check for removed Kubernetes APIs (the design names kubent and pluto) before a minor upgrade;
  • Terraform tracks the version, so a manual version change outside Terraform shows up as drift.

Add-ons and options

Option Reference configuration Notes
Azure Policy add-on On Fixed in the module.
Key Vault Secrets Provider (CSI driver) On in nonprod, prod and nonprod-integrated, with secret rotation every 2 minutes The design document says the CSI driver is not used and that applications read Key Vault with the SDK. The code switch is on in the reference files.
Azure Monitor (Container Insights) Off Needs a Log Analytics workspace ID.
Image cleaner Off When on, runs every 168 hours (7 days).
Managed Prometheus Not in the code The design says to evaluate it later.
AKS diagnostic settings Off (deploy_aks_diagnostics = false) Production file lists the categories to enable before go-live: kube-apiserver, kube-audit-admin, kube-controller-manager, guard, cloud-controller-manager. Needs a Log Analytics workspace.
Defender for Containers Off See Security policy.

The design says diagnostic settings are mandatory before production go-live, with retention of 90 days (production) and 30 days (non-production) in Log Analytics. Retention is a property of the workspace, not set by this solution.

Cluster identities

The identity layer creates one user-assigned managed identity per cluster (mi-kubelet-<env>). The cluster baseline uses it as the control plane identity and as the kubelet identity. The cluster-identities module gives it these Azure roles:

Role Scope Purpose
Network Contributor Node subnet Join nodes to the subnet
Network Contributor API server subnet API server VNet integration
Private DNS Zone Contributor Each private DNS zone in aks_private_dns_zone_ids Manage private DNS records (none set in the reference files)
Managed Identity Operator The identity itself Assign the kubelet identity to the node scale sets
AcrPull Each registry in aks_acr_ids Pull images without pull secrets (none set in the production and nonprod files)

The environment root also assigns Network Contributor on the spoke VNet to the same identity.

Design document versus code

The IAM design document describes a system-assigned control plane identity and a separate user-assigned kubelet identity. The code uses one user-assigned identity for both. Treat the code as authoritative.

Bootstrap for GitOps

The cluster baseline gives GitOps a reachable, authenticated cluster with workload identity and a network policy engine. It does not deploy namespaces, RBAC or platform services. The design lists these as GitOps bootstrap resources:

Resource Purpose
Namespaces platform-system, gateway-system, monitoring, policy-system Homes of platform components
Priority class platform-critical (value 1000000) Core platform pods that must not be evicted
Priority class platform-high (value 900000) GitOps controller, ingress gateway, certificate management
Priority class workload-default (value 100000) Default for application pods, preempted first
Cluster role bindings for the platform groups Platform admin, operator, auditor, break-glass

Recovery model

The design treats a cluster as disposable and rebuildable: a destroyed cluster is rebuilt with Terraform (the design expects 30 to 60 minutes) and GitOps then restores platform services, RBAC, policies and applications. Persistent volume data is not covered. Plan Azure Backup for AKS or Velero per workload.

The design also names resource locks (CanNotDelete on the production resource group, and on the state storage account) and state storage with versioning and soft delete. The Terraform code of the solution does not create locks. Confirm with the platform team how these are set in your environment.