Someone stood up AKS in a sandbox subscription with a public API server, admin group set to their user object ID, and default outbound to the Internet. It worked. Then they asked platform to “onboard it to the landing zone” like networking was a sticker you peel onto a finished cluster.
I still walk into that ticket. The YAML is fine. The seams are not. Private DNS for the API never made the hub zones. The node subnet never got the UDR. Workload identity was “phase two.” By the time finance asks who owns the bill, three teams already have cluster-admin kubeconfigs on laptops from the week the cluster was “temporary.”
AKS is not a special cloud. It is a spoke product with sharper edges. Subscription, identity, and hub seams come before CNI debates, addon marketplaces, or which ingress controller looks modern this quarter.
This is article one of Series 4. Series 1 built the zone. Series 2 wrote the spoke contract: platform owns the seams, workloads own the app. Series 3 made evidence real. Here the cluster has to land inside that same story, or you are operating a second cloud next to the one you already paid to build.
Where the cluster lives
Put the cluster where every other production spoke lives.
- Subscription under the correct management group (prod or nonprod), not a leftover sandbox that “has Contributor for everyone”
- Spoke VNet from the Series 2 module, or a dedicated AKS spoke pattern that still peers to the hub and uses the same DNS and UDR story
- Platform tags, budget, and diagnostics baseline on day one
- Platform-owned cluster creation: the apply identity is the platform pipeline, not every developer with Contributor on the subscription
App teams do not get Owner on the cluster subscription by default. They get namespace-scoped access and a deploy pipeline. Article five draws that line the same way Deployment Model did for portal clicks.
If the cluster resource group is where random VMs and a second VNet also live, you will spend Day 2 sorting blast radius instead of shipping upgrades. Keep AKS and its node resource group intentional. Treat the managed node resource group as platform territory even when Azure created it for you.
Subscription design already argued that billing boundaries and blast radius travel together. AKS does not get a free pass because “Kubernetes is shared infrastructure.” Shared infrastructure without an owner is how chargeback becomes a meeting and IR becomes a scavenger hunt.
Identity before pods
Identity already argued that standing Owner is how Friday happens. The API server is the same control plane with a different client.
Use Microsoft Entra ID integration for the API server. Prefer Azure RBAC for Kubernetes authorization when your team can operate it. Microsoft’s own cluster authentication guidance pushes Entra for the control plane so Conditional Access, MFA, and PIM apply to kubectl the same way they apply to the portal. The admin group is a PIM-eligible security group, not a named human pasted into az aks create.
Disable local accounts in production. Local accounts use a built-in admin certificate path that bypasses Entra. Anyone who can list that credential gets full admin without your centralized audit trail. Built-in Azure Policy can audit or deny clusters that leave local authentication enabled. Put that assignment next to the other AKS baselines, not in a wiki titled “hardening backlog.”
Kubeconfig with cluster-admin for everyone is the opposite of Series 3. Break-glass exists. Standing cluster-admin on laptops does not. The cluster identity model has to match the landing zone: pipeline identities for day-to-day change, PIM for humans, audited elevation when something is on fire.
Node identity is powerful. Treat the kubelet identity and any cluster managed identity like platform secrets. Pods that need Azure resources use workload identity (article four), not the node’s credentials with a shrug.
Network is the landing zone network
Networking already defined the hub: firewall, private DNS, private endpoints. AKS does not get a snowflake hub because Kubernetes feels special.
Private cluster is the default for production. Microsoft documents private clusters so API traffic between the control plane and node pools stays on the private network. That is a common regulatory ask, not a boutique preference. Public API with authorized IP ranges is an exception you write down, canary, and revisit. “For convenience” is not a control.
When you run private clusters, decide private DNS explicitly. System-managed zones, bring-your-own privatelink.<region>.azmk8s.io zones owned by platform, or patterns that disable public FQDN so the control plane address is not disclosed. Microsoft’s baseline AKS architecture recommends turning off public FQDN on private clusters and enforcing private clusters with Policy. Wire DNS like every other privatelink zone: platform owns the zone story, spokes get links, operators get a VPN or bastion path that is still audited.
Outbound goes through the hub firewall. That usually means outboundType of userDefinedRouting on a bring-your-own VNet, with a 0.0.0.0/0 next hop to Azure Firewall on the node subnet. AKS will not invent that path for you when you choose UDR. If create succeeds only after someone opens * on the firewall and nobody closes it, you built an expensive NAT gateway that happens to run pods.
Private endpoints from nodes and pods to PaaS use the same platform private DNS zones linked to the AKS VNet. If pods cannot resolve privatelink.blob.core.windows.net, Kubernetes did not break DNS. The landing zone seam did. Article three goes deep on that path.
If AKS requires a special hub, a second firewall policy nobody owns, or DNS zones that only the cluster knows about, you do not have a landing zone. You have an exception farm with YAML.
What “platform product” means here
Platform versions the cluster module. Workloads version Helm charts. Mixing those in one repo with one identity returns you to Friday portal culture.
The platform product for AKS includes:
- Cluster SKU and support tier that match how you page people
- Private cluster (or the documented exception), including public FQDN posture
- Outbound type aligned to the hub
- Node pool baselines: system pool, user pools, autoscaler floors you can pay for
- Addons you actually operate: Azure Policy for AKS, monitoring you sized, workload identity, secrets store CSI if that is your secrets pattern
- Entra integration, Azure RBAC settings, and local accounts disabled
- Private DNS wiring for the API when the cluster is private
- Tags, budget, diagnostics to the platform workspace seams from logging and cost
Workloads own Deployments, Services, ConfigMaps, app-level NetworkPolicies, their charts, and their federated identities inside the namespaces you vend. They do not own flipping private cluster off in prod tfvars because a laptop could not reach the API.
Publish the product next to the spoke contract. README in the module is fine. A short markdown file that answers “what do I get when platform stands up AKS” and “what do I still own” is better. If the only copy lives in a wiki that died at the last reorg, you will recreate this article as a ticket.
Cost and blast radius land with the cluster
Cost already said shared subscriptions turn chargeback into a meeting. AKS makes that worse when one giant cluster hosts every business unit “to save money.”
Decide the unit of blast radius before the first node pool. One application (or tightly coupled product) per cluster per environment is a clean default. Shared clusters are allowed when you staff namespace isolation, quotas, network policy, and an on-call graph that still works at 2 a.m. Shared clusters without that staffing are a discount on the invoice and a premium on every incident.
Put a consumption budget on the AKS subscription. Alert Owner and platform at 50, 80, and 100 percent. Container Insights at default verbosity will teach FinOps faster than any spreadsheet. That is article seven. Here you only need to admit that the cluster bill includes compute, outbound, and the workspace it fills.
The four tags still apply on the managed cluster resource and the surrounding resource groups: Environment, CostCenter, Owner, Application. Terraform default_tags covers the pipeline. Policy catches the portal. AKS is not exempt because the node resource group has a generated name.
Onboarding an existing cluster is usually a rebuild
Teams love the word “onboard.” They mean “keep the cluster, add peering.” That path fails when the API is public, local accounts are on, outbound bypasses the firewall, and identities were created as personal object IDs.
Be honest in the intake form. If the cluster was born outside the module, the supported path is rebuild into the product: new cluster from the platform pipeline, migrate workloads, decommission the sandbox. Lift-and-shift of a snowflake into prod management groups imports every anti-pattern you spent Series 1 removing.
Exceptions exist for regulated cutovers with a written plan. Exceptions are not the default catalog item.
Anti-patterns that keep showing up
- Cluster in the hub resource group, or sharing the hub VNet “so peering is easier”
- Public API with no authorized ranges, justified by a temporary VPN that became permanent
- Private cluster with public FQDN left on because nobody read the baseline architecture notes
- Using the cluster as a jump box network for unrelated VMs
- One giant cluster for all business units without blast-radius design from Series 2
- Admin group set to a person’s object ID so “we can get started”
- Local accounts left enabled after Entra integration “just in case”
- Onboarding a sandbox cluster into prod management groups without rebuilding the seams
- Enabling every addon on day one because the portal checkbox was green
Each of those fails a Series 1 or Series 2 rule with Kubernetes vocabulary on top.
What success looks like
The next app team asks for a namespace and a pipeline identity, not a cluster. The platform pipeline can recreate the cluster from state. Hub firewall rules for AKS required endpoints are documented next to the module. Private DNS links exist before the first pod tries Key Vault. Nobody has standing cluster-admin on a laptop. Policy already denies the public API and local-account snowflakes that used to sneak in through a portal click.
You will still argue about CNI Overlay versus pod subnet, AGIC versus Front Door, Flux versus pipeline deploys. Those arguments belong after the cluster is a spoke product. They do not replace it.
Next: the cluster baseline you will defend. node pools, outbound, addons, version pins, and what you refuse to enable until someone owns the runbook.
Randy Bordeaux
Azure Trainer | Veteran | Engineer
Helping IT professionals grow through cloud, leadership, and shared knowledge.


