Kubernetes is a declarative control-plane system for scheduling and
reconciling containerized workloads across a fleet of machines. AKS
is Microsoft Azure's managed distribution of Kubernetes: Azure
operates and pays the SLA on the control plane (API server, etcd,
scheduler, controller-manager), while you manage — or, with
AKS Automatic, largely delegate — node pools,
networking, and add-ons.
Why this matters
The exam-style trap engineers fall into is treating AKS as
"Kubernetes with an Azure logo." In practice, half of production
incidents on AKS come from Azure-specific plumbing: CNI IP
exhaustion, node image upgrades, Entra ID/RBAC interaction, and load
balancer SKUs — not raw Kubernetes concepts. This guide treats both
layers explicitly.
Kubernetes core
Declarative desired-state reconciliation via controllers watching
the API server, backed by etcd as the single source of truth.
AKS value-add
Managed, free control plane (Base tier) or SLA-backed (Standard
tier), managed upgrades, Entra ID integration, Azure CNI, node
auto-provisioning.
Operating model shift
AKS Automatic (GA) removes node pool and add-on decisions entirely
— Microsoft's opinionated "batteries-included" cluster,
recommended as the 2026 default starting point.
Core Concepts
The declarative reconciliation loop
Everything in Kubernetes reduces to one pattern: you write
desired state as an object in etcd (via the API server); a
controller continuously observes actual state and drives it
toward desired state. There is no imperative "do this now" — only
convergence loops running forever.
Flash: What is a "reconciliation loop"?
A control loop: Observe current state → Diff against desired state
→ Act to reduce the diff → repeat. Every built-in controller
(Deployment, ReplicaSet, Node) and every custom operator follows
this pattern.
Pods, not containers
The Pod — not the container — is the atomic scheduling unit. A Pod
is one or more containers sharing a network namespace (one IP) and
optionally storage volumes. Containers in the same Pod always
co-locate on the same node.
Concept
Purpose
Key trait
Pod
Smallest deployable unit
Ephemeral, gets a cluster-internal IP
ReplicaSet
Maintains N identical pod replicas
Rarely created directly
Deployment
Manages ReplicaSets, enables rollout/rollback
Standard way to run stateless apps
StatefulSet
Ordered, stable identity workloads
Stable network name + stable storage per replica
DaemonSet
One pod per (matching) node
Used for node agents: log shippers, CNI, CSI
Job / CronJob
Run-to-completion / scheduled tasks
Not restarted after success
Service
Stable virtual IP + DNS name for a set of pods
Decouples callers from pod churn
Ingress / Gateway API
L7 HTTP(S) routing into the cluster
Requires a controller (NGINX, App Routing, etc.)
ConfigMap / Secret
Externalized configuration/credentials
Secrets are base64-encoded, not encrypted by default
Namespace
Logical partition within a cluster
Scope for RBAC, quotas, network policy
Common confusion
Pod IPs are not stable — pods are recreated, not repaired,
on failure. Anything needing a stable address must go through a
Service.
Architecture Overview
A Kubernetes cluster splits into a
control plane (brains) and a
data plane (worker nodes running your workloads).
In AKS, Microsoft hosts and manages the control plane in an
Azure-managed subscription; you only see and pay for (in
Standard/Premium tiers) the API endpoint and SLA.
Fig 1. Kubernetes control plane vs. data plane, mapped to AKS's
managed/customer-managed split.
AKS specifics
Control plane cost: Free tier (no SLA,
best-effort availability) vs
Standard/Premium tier (financially backed
99.95% SLA with Availability Zones, up to 99.99%).
Every AKS cluster has a mandatory
system node pool (runs CoreDNS, metrics-server,
tunnel/konnectivity agents) — you add
user node pools for application workloads.
AKS Automatic removes the node-pool distinction from your view
entirely: platform components run on Azure-managed capacity
outside your billed node pools.
Internal Working
Scheduling: filter, then score
The scheduler runs two phases per unscheduled pod:
Filtering — eliminate nodes that cannot run the
pod (insufficient CPU/memory, taints without matching tolerations,
node selectors/affinity not satisfied, port conflicts).
Scoring — rank remaining nodes (spread pods
across nodes/zones, prefer nodes with the image already cached,
balance resource utilization) and bind to the top-scoring node.
kubelet's control loop
Each node's kubelet watches the API server for pods
bound to it, then drives the container runtime (via the CRI —
Container Runtime Interface) to start/stop containers, reports node
and pod status back, and runs liveness/readiness/startup probes.
Networking model
Every pod gets its own IP; pods can reach all other pods without
NAT (the "flat network" requirement).
kube-proxy (or eBPF dataplanes like Cilium) programs
iptables/IPVS/eBPF rules so a Service's virtual IP load-balances
to healthy pod IPs.
CoreDNS resolves in-cluster DNS names
(svc-name.namespace.svc.cluster.local).
etcd: the only stateful thing that matters
Interview trap
Nothing in Kubernetes is "durable" except what's written to etcd.
Controllers, schedulers, and API servers are all stateless and
horizontally restartable — lose etcd (without backup) and you lose
the cluster's brain, even though nodes/pods might keep running
briefly.
Key Components
kube-apiserver
Stateless REST front door. Handles authn/authz, admission control
(mutating + validating webhooks), and is the only component that
talks to etcd directly.
etcd
Raft-based distributed KV store. Odd-numbered quorum (3 or 5
members). All cluster state lives here.
kube-scheduler
Assigns unscheduled pods to nodes using filter+score plugins
(scheduling framework).
Cloud-specific glue: provisions Azure Load Balancers for
type: LoadBalancer Services, attaches Azure Disks,
manages node lifecycle against Azure APIs.
kubelet
Node agent; the only component that talks to the container runtime
via CRI, and to CNI/CSI plugins.
kube-proxy
Implements Service virtual IPs on each node (iptables/IPVS), or is
replaced entirely by Cilium's eBPF dataplane.
CoreDNS
Cluster DNS; resolves Service and Pod DNS names.
Container runtime
containerd is the default in AKS (Docker Engine was
removed as a supported node runtime years ago).
Request / Execution Flow
Trace of kubectl apply -f deployment.yaml from client
to running containers:
Fig 2. End-to-end reconciliation path for a Deployment rollout.
Key insight
Almost every step above is asynchronous watch-and-react, not a
synchronous call chain. This is why
kubectl apply returns instantly — it only guarantees
the object was accepted and persisted, not that pods are
running.
AKS Networking
This is the single most consequential decision at cluster creation
time — hard to change later.
Model
Pod IP source
Scale ceiling
Notes (2026)
Kubenet
Separate CIDR, NAT'd via UDR/route table
~400 nodes (200 in dual-stack)
Being retired — Microsoft has announced kubenet networking
for AKS will be retired on 31 March 2028; Linux-only, Calico policy only.
Azure CNI (VNet mode)
Pod gets a real VNet IP
Limited by subnet size — large subnet required
Broadest feature support (App Gateway ingress, Windows nodes)
but consumes IP address space fast.
Azure CNI Overlay
Overlay CIDR, decoupled from VNet
Scales like kubenet, performs like CNI
Solves the IP-exhaustion problem of traditional CNI by
assigning pods addresses from a space logically separate from
the VNet. Recommended default for new clusters.
Azure CNI Overlay + Cilium
Overlay CIDR + eBPF dataplane
Best of both
This is the default networking configuration for AKS
Automatic clusters;
Cilium enforces network policy directly, removing the need
for a separate policy engine such as Azure Network Policy
Manager or Calico.
Practical guidance
Traditional Azure CNI gives pods VNet IPs directly from the
subnet, making pods first-class network citizens that can talk to
other Azure resources without extra hops, but
the alternative overlay/kubenet designs introduce an extra
network hop with minor latency
in exchange for IP efficiency. For new production clusters in 2026,
default to Azure CNI Overlay (with Cilium) unless
you have a specific requirement (e.g., Application Gateway Ingress
Controller) that needs VNet-mode CNI.
Explanation: --network-plugin-mode overlay decouples
pod IPs from the VNet; --network-dataplane cilium swaps
kube-proxy's iptables rules for Cilium's eBPF programs, which also
unlocks L3/L4/L7 network policies and better observability.
Identity & Access (AKS)
Two separate identity problems
1. Who can call the Kubernetes API?
Microsoft Entra ID integration is the recommended approach,
letting Entra identities and groups sign in to the cluster,
with the integration provisioned and rotated
automatically.
Local admin certificate accounts bypass Entra ID entirely and
should be disabled in production.
Authorization is then via
either native Kubernetes RBAC (Role/ClusterRole/RoleBinding
objects living in the cluster) or Azure RBAC, where an AKS
authorization webhook delegates decisions to Entra ID using
Azure role assignments.
2. How do pods call Azure services?
Microsoft Entra Workload ID federates pod service accounts
with Azure AD so pods authenticate to Azure resources (Key
Vault, Storage, Microsoft Graph) without storing any
credential in the cluster.
It works via Service Account Token Volume Projection: a
Kubernetes token is issued and exchanged through OIDC
federation for an Entra access token.
Deprecated — do not use
Azure AD Pod Identity lost official support in September
2025. If you inherit a cluster still using it, migrating to Microsoft
Entra Workload ID is not optional — plan it now.
Example: federate a Kubernetes ServiceAccount with an Entra Workload
Identity
# 1. Create a user-assigned managed identity and federated credential
az identity create -g rg-platform-prod -n wi-orders-api
az identity federated-credential create \
--name orders-api-fic \
--identity-name wi-orders-api \
--resource-group rg-platform-prod \
--issuer "$(az aks show -g rg-platform-prod -n aks-prod-eastus --query oidcIssuerProfile.issuerUrl -o tsv)" \
--subject system:serviceaccount:orders:orders-api-sa \
--audience api://AzureADTokenExchange
Explanation: the annotation tells the AKS-managed webhook which
Entra app to mint tokens for; the label opts the ServiceAccount's
pods into token projection. No client secret ever touches the
cluster.
AKS Automatic vs Standard
Dimension
AKS Automatic
AKS Standard
Node pools
Node management is handled automatically without manual user
node pool creation — system pools and components are managed
by AKS
You create and size system + user node pools explicitly
Networking
Automatic clusters use a managed VNet powered by Azure CNI
Overlay with Cilium
by default
You choose plugin/dataplane/mode
Identity
Workload identity with Microsoft Entra Workload ID and OIDC
issuer preconfigured
You enable and configure it
Scaling
KEDA is shipped as a native add-on for scale-to-zero, plus a
managed Karpenter-based node autoprovisioner, GA in AKS
You wire up Cluster Autoscaler / KEDA / VPA yourself
Ingress
Managed NGINX via the application routing add-on, integrated
with Azure DNS and Key Vault
You deploy and manage your own ingress controller
Guardrails
Deployment Safeguards in enforcement mode, and Image Cleaner
enabled by default
Opt-in via Azure Policy add-on
When to pick
Recommended starting point for most production
workloads
Choose when you have compliance needs for specific node
images/patch schedules, specialized affinity/taint topology,
or existing IaC that can't adapt to Automatic's model
2026 guidance
Start every new cluster as AKS Automatic; fall back to Standard only
when you hit a concrete, named limitation — not speculative future
flexibility.
Autoscaling Model
HPA — Horizontal Pod Autoscaler
Scales pod replica count based on CPU/memory or
custom/external metrics (e.g., via KEDA scalers on queue depth).
VPA — Vertical Pod Autoscaler
Adjusts a pod's CPU/memory requests over time based on
observed usage; typically run in recommendation-only mode
alongside HPA.
KEDA
Event-driven scaling, including scale-to-zero, triggered by
external signals (queue length, HTTP rate, cron). Shipped as a
native AKS add-on.
Cluster Autoscaler / Node Auto Provisioning (Karpenter)
Microsoft's managed Karpenter provider bypasses VM Scale Set
provisioning latencies and provisions right-sized instances in
seconds, GA in AKS, replacing the older per-node-pool Cluster Autoscaler for new
deployments.
Order of operations
HPA/KEDA decide "we need more pods" → scheduler tries to place them
→ if no node fits, Karpenter/Cluster Autoscaler provisions a new
node → kubelet on the new node starts the pods. A slow
node-provisioning step is the most common cause of scaling latency
complaints.
Explanation: CPU requests influence scheduling; only a
memory limit is set, since exceeding a CPU limit throttles
(usually fine) while exceeding a memory limit OOM-kills the pod —
many teams intentionally omit CPU limits to avoid artificial
throttling.
PodDisruptionBudget — protect availability during node
drains/upgrades
Explanation: guarantees at least 2 of 3 replicas stay up during
voluntary disruptions (node drains, AKS node-image upgrades) —
without this, an upgrade can legally evict all replicas at once.
Always set resource requests; be deliberate about whether
you set CPU limits (throttling risk) vs leaving CPU
unbounded.
Define PodDisruptionBudgets for every multi-replica
workload before your first cluster upgrade.
Use readiness probes to gate traffic and liveness probes only to
catch true deadlocks — an overly aggressive liveness probe causes
needless restarts.
Prefer Microsoft Entra Workload Identity over any static
credential/secret for pod-to-Azure auth.
Default new clusters to Azure CNI Overlay + Cilium; reserve
VNet-mode CNI for workloads needing direct VNet routability or
Application Gateway ingress.
Pin and stagger Kubernetes upgrades: AKS supports 3 GA minor
versions at a time — don't let clusters drift onto a version
approaching End of Life.
Separate system and user node pools (or use AKS Automatic, which
does this for you) so app workloads never crowd out
CoreDNS/metrics-server.
Enable Azure Policy / Deployment Safeguards to prevent common
misconfigurations (privileged containers, missing resource limits)
before they reach production.
Use namespaces + ResourceQuotas + NetworkPolicies as your default
multi-tenant isolation boundary, not just RBAC.
Common Mistakes
Mistake Treating Pod IPs as stable and
hardcoding them, instead of using a Service/DNS name.
Mistake Setting CPU limits equal
to requests "for consistency" — this throttles bursty workloads
under load for no correctness benefit.
Mistake Skipping PodDisruptionBudgets,
then being surprised when an AKS node-image upgrade evicts an entire
Deployment at once.
Mistake Choosing legacy VNet-mode Azure
CNI for a large cluster without subnet capacity planning, then
hitting IP exhaustion mid-scale-out.
Mistake Leaving local cluster admin
accounts enabled in production instead of enforcing Entra ID-only
authentication.
Mistake Letting clusters sit on an
AKS-deprecated Kubernetes minor version until forced auto-upgrade,
instead of planned, tested upgrades.
Mistake Assuming
kubectl apply completing means the workload is healthy
— it only means the API object was accepted.
Performance Considerations
Networking dataplane:
Azure CNI Overlay performs within 2-3% of VNET-mode CNI for
inter-pod traffic, whereas Kubenet shows a 10-15% latency
penalty from the extra routing hop and NAT complexity.
Node provisioning latency: managed
Karpenter-based Node Auto Provisioning provisions right-sized
nodes far faster than legacy VM Scale Set-based Cluster Autoscaler
paths — matters directly for burst-scaling SLAs.
Image pulls: cold-start latency is dominated by
image pull time on new nodes; use smaller base images and, where
available, artifact streaming/pre-caching.
etcd health: although Azure-managed in AKS, etcd
write latency (driven by object churn — excessive ConfigMap/Secret
updates, high-frequency status writes) is still the ultimate
ceiling on API responsiveness.
DNS: CoreDNS can become a bottleneck at scale;
AKS Automatic's LocalDNS caches resolutions per-node to cut
latency and query volume.
Security Considerations
Disable local cluster admin accounts; enforce Microsoft Entra ID
for API authentication, with Azure RBAC or Kubernetes RBAC for
authorization.
Use Microsoft Entra Workload ID (not the deprecated Pod Identity
add-on) for all pod-to-Azure authentication — no long-lived
secrets in the cluster.
Default-deny NetworkPolicies per namespace, opening only required
paths — trivial with a Cilium dataplane, which enforces policy
natively.
Enable Image Cleaner to automatically remove images with known
vulnerabilities from nodes (on by default in AKS Automatic).
Use Azure Policy / Deployment Safeguards to block privileged
containers, hostPath mounts, and missing resource limits at
admission time.
Encrypt etcd secrets at rest — AKS supports customer-managed keys
for an additional layer beyond the platform default.
Scope Azure Container Registry pulls via managed identity, not
static registry credentials embedded in imagePullSecrets.
Troubleshooting Guide
Pod stuck in Pending
Diagnose:kubectl describe pod <name> → check Events
for FailedScheduling.
Common causes: insufficient CPU/memory across
all nodes; unsatisfied node selector/affinity; taints without a
matching toleration; PVC that can't bind (no matching
StorageClass/zone).
Fix: scale the node pool, relax affinity, or
add the required toleration; for storage, verify the
StorageClass and zone alignment.
Pod stuck in CrashLoopBackOff
Diagnose:kubectl logs <pod> --previous to see the last
crash's output.
Common causes: app fails on startup (bad
config/env var, missing secret), liveness probe firing before
app is ready, OOM-kill from a too-low memory limit.
Fix: check
kubectl describe pod for
Last State: Terminated, Reason: OOMKilled vs
application error; adjust probe
initialDelaySeconds or the memory limit
accordingly.
Service has no endpoints / connection refused
Diagnose:kubectl get endpoints <svc> — empty means the
Service's selector doesn't match any Ready pod.
Fix: confirm pod labels match the Service
selector exactly; check readiness probe status; verify
NetworkPolicy allows the caller's namespace/labels.
Node stuck NotReady
Diagnose:kubectl describe node <name>; check
kubelet/network agent health via node conditions.
Common causes: CNI plugin failure, disk
pressure, kubelet unable to reach the API server
(DNS/NSG/firewall issue in AKS), VM-level Azure platform fault.
Fix: check Azure activity log for platform
events; for AKS,
az aks nodepool upgrade --node-image-only often
resolves node-level agent bugs; cordon and replace the node if
unrecoverable.
Cluster upgrade stuck / node drain not completing
Diagnose:kubectl get pdb -A — an
overly strict PodDisruptionBudget (e.g.,
minAvailable equal to replica count) can block
eviction indefinitely.
Fix: relax the PDB temporarily, or ensure it
allows at least one voluntary eviction at a time.
Workload can't authenticate to Azure resource (Key Vault, Storage)
Diagnose: confirm the ServiceAccount has the
azure.workload.identity/use: "true" label and
correct client-id annotation; confirm the federated
credential's subject matches
system:serviceaccount:<ns>:<sa>
exactly.
Fix: re-check the OIDC issuer URL used when
creating the federated credential — a stale issuer URL after
cluster recreation is a frequent cause of silent auth failures.
Interview Questions
Q: What's the difference between a ReplicaSet and a Deployment?
A ReplicaSet only guarantees N running pod replicas. A Deployment
manages ReplicaSets on top of that, adding rolling updates,
rollback history, and declarative rollout strategy — you should
almost never create a ReplicaSet directly.
Q: Why might a pod exceed its memory limit but not its CPU limit
ever cause an OOM kill?
CPU is a compressible resource — exceeding a CPU limit only
throttles the process. Memory is incompressible — exceeding a
memory limit gets the container OOM-killed by the kernel cgroup
controller.
Q: How does kube-proxy implement a Service's virtual IP?
By watching Endpoints/EndpointSlices and programming iptables (or
IPVS) rules on every node that DNAT traffic bound for the
Service's ClusterIP to a healthy backend pod IP. eBPF dataplanes
(like Cilium) replace this entirely with eBPF programs attached to
the network stack.
Q: What's the practical difference between Azure CNI Overlay and
Kubenet, given both use a separate pod CIDR?
Kubenet relies on Azure route tables for cross-node pod routing,
capping scale around a few hundred nodes and adding NAT latency.
CNI Overlay uses Azure's native networking stack for the same
decoupled-IP benefit without the route-table ceiling, and supports
more network policy engines.
Q: Why is AKS's control plane "free" in the Free tier, and what's
the tradeoff?
Azure absorbs the compute cost of running the API
server/etcd/scheduler for you, but the Free tier carries no SLA —
Standard/Premium tiers add a financially backed uptime guarantee,
typically paired with Availability Zone spread.
Q: How does Microsoft Entra Workload Identity avoid storing
credentials in the cluster?
Pods present a Kubernetes-issued, projected ServiceAccount token
to Entra ID via OIDC federation; Entra exchanges it for a
short-lived Azure access token based on a pre-configured trust
relationship (federated credential) — no static secret ever
exists.
Q: What happens if etcd loses quorum?
The API server can no longer accept writes (and often reads), so
no new pods can be scheduled and no state changes persist — though
already-running pods/kubelets continue operating independently
until they need a state change or restart.
Q: Why default to AKS Automatic in 2026 rather than Standard?
Automatic pre-wires the accumulated best practices (Cilium network
policy, workload identity, KEDA, Karpenter-based autoprovisioning,
deployment safeguards, image cleaning) that most teams eventually
hand-build on Standard anyway — Standard is reserved for cases
with a concrete, named constraint Automatic can't satisfy.
Cheat Sheet
Atomic unit: Pod (not container)
Source of truth: etcd
Scheduling: filter → score → bind
Stateless components: API server, scheduler,
controller-manager
Only stateful component: etcd
Stable network identity: Service, not Pod
Default AKS runtime: containerd
2026 default AKS network: Azure CNI Overlay +
Cilium
Deprecated identity add-on: Azure AD Pod Identity
(EOL Sep 2025)
Current pod-to-Azure identity: Microsoft Entra
Workload ID
Node-level scaling (new): managed Karpenter (Node
Auto Provisioning)
Event-driven pod scaling: KEDA
AKS supports: 3 GA Kubernetes minor versions at a
time