Kubernetes & Azure Kubernetes Service (AKS)

A senior-engineer revision guide: architecture, internals, AKS-specific operations, and interview-ready recall.

Kubernetes 1.36 (latest, June 2026) AKS supports 1.34 / 1.35 / 1.36 Updated Jul 2026

Executive Summary

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.

Control Plane (Azure-managed in AKS) API Server auth, validation, REST front door etcd distributed KV store single source of truth Scheduler binds pods → nodes (filter+score) Controller Manager Deployment, Node, Endpoint controllers Cloud Controller Azure LB, disks, routes Data Plane — Node Pools (customer-managed VMs / VMSS) Node (System Pool) kubelet kube-proxy container runtime (containerd) coredns / metrics-server pods Node (User Pool) kubelet kube-proxy container runtime (containerd) app pods (Deployment/StatefulSet) Node (User Pool, GPU/spot) kubelet CNI + Cilium container runtime (containerd) batch / GPU workload pods

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:

  1. Filtering — eliminate nodes that cannot run the pod (insufficient CPU/memory, taints without matching tolerations, node selectors/affinity not satisfied, port conflicts).
  2. 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).

kube-controller-manager

Runs core reconciliation loops: Node, ReplicaSet, Endpoint, Job, Namespace, ServiceAccount controllers, etc.

cloud-controller-manager

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:

kubectl API server etcd Scheduler Controller Mgr kubelet (node) 1. POST Deployment manifest (HTTPS) 2. AuthN → AuthZ (RBAC) → Admission (mutating/validating webhooks) 3. Persist Deployment object 4. Deployment controller watches → creates ReplicaSet (round trip persisted via etcd, shown collapsed for clarity) 5. ReplicaSet controller creates N Pod objects (Pending, unscheduled) 6. Scheduler watches unscheduled pods 7. Filter + score nodes; write binding (Pod.spec.nodeName) to etcd 8. Target node's kubelet watches, sees pod bound to itself 9. kubelet → CRI: pull image, create sandbox + containers containerd 10. kubelet → CNI: attach pod network, assign IP 11. kubelet runs readiness probe; reports Pod status = Running 12. Endpoint controller adds pod IP to Service's Endpoints/EndpointSlice Total elapsed: typically 1–15s for a cached image; longer on cold pulls or new nodes.

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.

Example: create a cluster with Overlay + Cilium

# az CLI — network-plugin-mode=overlay + Cilium dataplane
az aks create \
  --resource-group rg-platform-prod \
  --name aks-prod-eastus \
  --network-plugin azure \
  --network-plugin-mode overlay \
  --network-dataplane cilium \
  --pod-cidr 192.168.0.0/16 \
  --service-cidr 10.0.0.0/16 \
  --dns-service-ip 10.0.0.10 \
  --node-vm-size Standard_D4s_v5 \
  --enable-managed-identity \
  --generate-ssh-keys

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
apiVersion: v1
kind: ServiceAccount
metadata:
  name: orders-api-sa
  namespace: orders
  annotations:
    azure.workload.identity/client-id: "<managed-identity-client-id>"
  labels:
    azure.workload.identity/use: "true"

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.

Important APIs & Objects

API group Example kinds Use for
core/v1 Pod, Service, ConfigMap, Secret, Namespace, Node, PersistentVolume(Claim) Fundamental building blocks
apps/v1 Deployment, StatefulSet, DaemonSet, ReplicaSet Workload controllers
batch/v1 Job, CronJob Run-to-completion / scheduled tasks
networking.k8s.io/v1 Ingress, NetworkPolicy, IngressClass L4/L7 traffic control
gateway.networking.k8s.io Gateway, HTTPRoute Next-gen, role-oriented ingress model (Gateway API)
rbac.authorization.k8s.io/v1 Role, ClusterRole, RoleBinding, ClusterRoleBinding In-cluster authorization
autoscaling/v2 HorizontalPodAutoscaler Metric-based replica scaling
policy/v1 PodDisruptionBudget Guard voluntary disruptions during drains/upgrades
storage.k8s.io/v1 StorageClass, CSIDriver Dynamic volume provisioning
apiextensions.k8s.io/v1 CustomResourceDefinition Extend the API with your own kinds (operators)

Command Cheat Sheets

kubectl — everyday operations

Command What it does
kubectl get pods -n ns -o wide List pods with node/IP columns
kubectl describe pod <name> Full event history — first stop for troubleshooting
kubectl logs -f <pod> -c <container> Stream logs for a specific container
kubectl exec -it <pod> -- sh Shell into a running container
kubectl rollout status deploy/<name> Watch a rollout progress
kubectl rollout undo deploy/<name> Roll back to previous ReplicaSet revision
kubectl apply -f file.yaml Create or update objects declaratively
kubectl diff -f file.yaml Preview changes before applying
kubectl top pods / nodes Live resource usage (needs metrics-server)
kubectl get events --sort-by=.lastTimestamp Cluster-wide chronological events
kubectl explain deployment.spec Inline API field docs
kubectl port-forward svc/<name> 8080:80 Tunnel a local port to a cluster Service
kubectl cordon/drain <node> Mark unschedulable / evict pods before maintenance
kubectl auth can-i <verb> <resource> Check RBAC permissions for the current identity

az aks — cluster lifecycle

Command What it does
az aks create -g RG -n NAME --network-plugin azure --network-plugin-mode overlay Create a cluster with CNI Overlay
az aks get-credentials -g RG -n NAME Merge cluster context into local kubeconfig
az aks nodepool add -g RG --cluster-name NAME -n userpool --node-count 3 Add a user node pool
az aks upgrade -g RG -n NAME -k 1.36.2 Upgrade control plane + node images
az aks nodepool upgrade --node-image-only Roll node OS/security patches without a k8s version bump
az aks scale --node-count N --nodepool-name pool Manually resize a node pool
az aks show -g RG -n NAME --query kubernetesVersion Check current cluster version
az aks nodepool list --cluster-name NAME -g RG -o table List node pools and VM sizes
az aks update --enable-cluster-autoscaler --min-count 1 --max-count 10 Enable/tune Cluster Autoscaler
az aks command invoke -g RG -n NAME -c "kubectl get pods -A" Run kubectl against a private cluster without direct network access

helm — package management

Command What it does
helm install rel chart/ -f values.yaml Install a chart with overrides
helm upgrade --install rel chart/ Idempotent install-or-upgrade (common in CI/CD)
helm rollback rel 3 Roll back a release to revision 3
helm diff upgrade rel chart/ Preview a chart change (diff plugin)

Configuration Examples

Deployment with resource requests/limits + probes

apiVersion: apps/v1
kind: Deployment
metadata:
  name: orders-api
  namespace: orders
spec:
  replicas: 3
  selector:
    matchLabels: { app: orders-api }
  template:
    metadata:
      labels: { app: orders-api }
    spec:
      serviceAccountName: orders-api-sa
      containers:
        - name: api
          image: myacr.azurecr.io/orders-api:1.4.2
          resources:
            requests: { cpu: "250m", memory: "256Mi" }
            limits:   { memory: "512Mi" }
          readinessProbe:
            httpGet: { path: /healthz, port: 8080 }
            initialDelaySeconds: 5
          livenessProbe:
            httpGet: { path: /livez, port: 8080 }
            periodSeconds: 10

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

apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
  name: orders-api-pdb
  namespace: orders
spec:
  minAvailable: 2
  selector:
    matchLabels: { app: orders-api }

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.

HorizontalPodAutoscaler

apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: orders-api-hpa
  namespace: orders
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: orders-api
  minReplicas: 3
  maxReplicas: 20
  metrics:
    - type: Resource
      resource:
        name: cpu
        target: { type: Utilization, averageUtilization: 70 }

NetworkPolicy — default-deny then allow

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default-deny-all
  namespace: orders
spec:
  podSelector: {}
  policyTypes: [Ingress, Egress]
---
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-from-gateway
  namespace: orders
spec:
  podSelector: { matchLabels: { app: orders-api } }
  policyTypes: [Ingress]
  ingress:
    - from:
        - namespaceSelector: { matchLabels: { kubernetes.io/metadata.name: ingress } }

Terraform — minimal AKS Automatic-style cluster

resource "azurerm_kubernetes_cluster" "aks" {
  name                = "aks-prod-eastus"
  location            = azurerm_resource_group.rg.location
  resource_group_name = azurerm_resource_group.rg.name
  dns_prefix          = "aksprod"
  sku_tier            = "Standard"  # financially backed SLA

  default_node_pool {
    name       = "system"
    vm_size    = "Standard_D4s_v5"
    auto_scaling_enabled = true
    min_count  = 3
    max_count  = 6
  }

  identity { type = "SystemAssigned" }

  network_profile {
    network_plugin      = "azure"
    network_plugin_mode = "overlay"
    network_data_plane  = "cilium"
  }

  oidc_issuer_enabled       = true
  workload_identity_enabled = true
}

Best Practices

  • 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.

Common causes: label selector mismatch, pods failing readiness probe, NetworkPolicy blocking traffic.

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
Kubenet fate: retiring 31 March 2028
2026 opinionated default: AKS Automatic
Latest upstream Kubernetes: 1.36 (released Apr 2026)

Glossary

CNI Container Network Interface — plugin spec for pod networking.
CRI Container Runtime Interface — kubelet's plugin spec for the container runtime (containerd).
CSI Container Storage Interface — plugin spec for dynamic volume provisioning.
CRD Custom Resource Definition — extends the Kubernetes API with new object kinds.
Operator A controller managing a CRD, encoding operational knowledge as reconciliation logic.
eBPF Kernel technology letting Cilium program networking/observability without iptables.
OIDC OpenID Connect — federation protocol underlying Entra Workload Identity trust.
VMSS Virtual Machine Scale Set — Azure's backing infrastructure for AKS node pools.
PDB PodDisruptionBudget — limits concurrent voluntary pod evictions.
HPA / VPA Horizontal / Vertical Pod Autoscaler.
KEDA Kubernetes Event-Driven Autoscaling — scale on external event sources, including to zero.
System / User node pool AKS split between platform-critical pods (system) and application workloads (user).
LTS (AKS) Long Term Support — extends a Kubernetes minor version's AKS support window to two years.