Kubernetes is ontworpen om zelf-herstellend te zijn, maar wat betekent dat eigenlijk? En belangrijker: wat gebeurt er als de componenten die het herstel doen zelf falen?

Ik heb Kubernetes clusters door allerlei failures heen geleid — gepland, ongepland, en “hold my beer” experimenten. Hier is wat er daadwerkelijk gebeurt als dingen kapot gaan.

De Componenten Die Kunnen Falen

Voordat we in failure scenario’s duiken, laten we uitzetten waarmee we werken:

Control Plane:

  • kube-apiserver: De API waar alles mee praat
  • etcd: De database die alle cluster state opslaat
  • kube-scheduler: Bepaalt waar pods draaien
  • kube-controller-manager: Draait controllers (ReplicaSet, Deployment, etc.)
  • cloud-controller-manager: Cloud provider integraties (indien van toepassing)

Node Componenten:

  • kubelet: Beheert pods op elke node
  • kube-proxy: Handelt netwerkregels af voor Services
  • Container runtime: Draait daadwerkelijk containers

Scenario 1: API Server Down

De kube-apiserver is het enkele punt waardoor alle Kubernetes API requests stromen. Wat gebeurt er als deze uitvalt?

Directe impact:

  • kubectl commando’s falen
  • Geen nieuwe deployments of updates mogelijk
  • Geen nieuwe pod scheduling
  • Bestaande pods blijven draaien

Wat blijft werken:

  • Draaiende pods blijven draaien
  • Containers blijven levend
  • Netwerkconnectiviteit tussen pods
  • Services blijven verkeer routeren

Wat breekt:

  • Geen nieuwe pods kunnen worden gemaakt
  • Gefaalde pods worden niet vervangen
  • Horizontal Pod Autoscaler stopt
  • Geen wijzigingen aan resources
flowchart TD
    subgraph api_down["API Server Down"]
        subgraph control["Control Plane"]
            etcd["etcd ✓"]
            sched["scheduler<br/>idle"]
            ctrl["controller-mgr<br/>idle"]
            apiX["✗ API Server"]
        end
        control -->|"geen updates"| nodes
        subgraph nodes["Worker Nodes"]
            N1["Node 1<br/>Pods ✓"]
            N2["Node 2<br/>Pods ✓"]
            N3["Node 3<br/>Pods ✓"]
        end
    end
    note["Pods blijven draaien - ze hebben de API niet nodig"]

Dit is het belangrijkste inzicht: Kubernetes is ontworpen voor API server outages. Het systeem degradeert graceful — workloads blijven draaien, je kunt alleen niets veranderen.

Voor HA setups wil je meerdere API servers achter een load balancer. Zie Kubernetes High Availability: stacked vs external etcd voor architectuur opties.

Scenario 2: etcd Down

etcd is het brein van Kubernetes. Alle cluster state leeft hier. Dit is de engste failure.

Directe impact:

  • API server kan state niet lezen of schrijven
  • Effectief hetzelfde als API server down
  • Bestaande pods blijven draaien

Wat blijft werken:

  • Draaiende pods blijven draaien
  • Containers blijven levend
  • Netwerkconnectiviteit
  • Services werken

Wat breekt:

  • Zelfde als API server down, plus:
  • Risico op state inconsistentie bij recovery
  • Split-brain scenario’s bij gedeeltelijke failures
flowchart TD
    subgraph etcd_down["etcd Down"]
        subgraph control["Control Plane"]
            etcdX["etcd ✗"] --> apiX["API ✗"]
            apiX --> other["andere componenten"]
        end
    end
    note["Zonder etcd kan API server niet functioneren<br/>Nodes blijven draaien - ze cachen hun toewijzingen"]

etcd failures zijn waarom backups niet onderhandelbaar zijn. Zie etcd Deep Dive voor begrip van etcd’s rol en backup strategieën.

Scenario 3: Scheduler Down

De kube-scheduler bepaalt waar pods draaien. Als deze down is:

Directe impact:

  • Nieuwe pods blijven in Pending state
  • Geen scheduling beslissingen worden gemaakt

Wat blijft werken:

  • Bestaande pods blijven draaien
  • API server functioneert normaal
  • Je kunt resources aanmaken (ze worden alleen niet gescheduled)

Wat breekt:

  • Nieuwe pods kunnen niet gescheduled worden
  • Herscheduling na node failure gebeurt niet
  • HPA maakt pods die Pending blijven
flowchart TD
    subgraph sched_down["Scheduler Down"]
        apply["kubectl apply deployment"] --> api["API accepteert"]
        api --> pending["Pod: Pending..."]
        subgraph queue["Pending Queue"]
            web["Pod: web"]
            apiPod["Pod: api"]
            job["Pod: job"]
            waiting["... wacht"]
        end
    end
    note["Nodes hebben capaciteit maar niemand wijst pods toe"]

In HA setups draai je meerdere schedulers met leader election. Er is er maar één actief, anderen wachten.

Scenario 4: Controller Manager Down

De controller manager draait alle controllers die Kubernetes “zelf-herstellend” maken.

Directe impact:

  • ReplicaSet controller stopt
  • Deployment controller stopt
  • Node controller stopt
  • Alle reconciliation loops stoppen

Wat blijft werken:

  • Bestaande pods blijven draaien
  • Scheduling werkt nog
  • API server werkt nog

Wat breekt:

  • Gefaalde pods worden niet vervangen
  • Deployments rollen niet uit
  • Node failures worden niet afgehandeld
  • Orphaned resources worden niet opgeruimd
flowchart TD
    subgraph ctrl_down["Controller Manager Down"]
        rs["ReplicaSet: 3 desired, 2 running → geen actie"]
        deploy["Deployment: rollout bezig → stuck"]
        node["Node marked NotReady → pods niet evicted"]
    end
    note["Het 'zelf-herstellende' deel van Kubernetes stopt"]

Dit is waar je merkt dat Kubernetes geen magie is — het is gewoon software die reconciliation loops draait. Stop de loops, stop de magie.

Scenario 5: Kubelet Down op een Node

De kubelet is de Kubernetes agent op elke node. Als deze faalt:

Directe impact (op die node):

  • Node gemarkeerd als NotReady na timeout (standaard ~40 seconden)
  • Pods op die node worden evicted (na nog een timeout)
  • Geen nieuwe pods gescheduled naar die node

Wat blijft werken:

  • Containers blijven draaien (ze hebben kubelet niet nodig)
  • Netwerk werkt mogelijk nog (hangt af van CNI)
  • Andere nodes onbeïnvloed

Wat breekt:

  • Geen pod lifecycle management op die node
  • Health checks stoppen
  • Resource updates stoppen
  • Uiteindelijk worden pods elders herscheduled
flowchart LR
    subgraph kubelet_down["Kubelet Down op Node 2"]
        subgraph N1["Node 1 ✓ Ready"]
            P1["pod ✓"]
        end
        subgraph N2["Node 2 ✗ NotReady"]
            P2["pod ?<br/>orphaned"]
        end
        subgraph N3["Node 3 ✓ Ready"]
            P3["pod ✓<br/>rescheduled"]
        end
        P2 -.->|"rescheduled"| P3
    end
    note["Na pod-eviction-timeout worden pods herscheduled"]

Het interessante: containers blijven draaien zelfs zonder kubelet. De kubelet beheert ze, maar houdt ze niet in leven.

Scenario 6: Container Runtime Down

Als de container runtime (containerd, CRI-O) faalt:

Directe impact:

  • Draaiende containers kunnen sterven
  • Nieuwe containers kunnen niet starten
  • Health checks falen

Wat daarna gebeurt:

  • kubelet detecteert failures
  • Pods gemarkeerd als Failed
  • Pods worden herscheduled naar andere nodes

Dit is typisch een node-level failure die pod eviction triggert.

Scenario 7: Netwerk Partitie

Netwerk partities zijn de lastigste failures. Een node verliest connectiviteit met de control plane maar kan nog steeds containers draaien.

Wat er gebeurt:

  • Node gemarkeerd NotReady (kan API server niet bereiken)
  • Pods uiteindelijk evicted
  • Maar ze draaien mogelijk nog op de gepartitioneerde node
  • Potentieel voor “split brain” — dezelfde pod draait op twee plekken
flowchart LR
    subgraph partition["Netwerk Partitie"]
        subgraph control["Control Plane"]
            cp["Node 2 is NotReady<br/>Evicting pods..."]
        end
        control x--x|"✗"| partitioned
        subgraph partitioned["Gepartitioneerde Node"]
            pn["Ik ben prima, draai<br/>deze pods..."]
        end
    end
    note["Pod 'web-abc123' draait nu op Node 1 EN Node 2<br/>Beide denken dat zij de echte zijn"]

Dit is waarom stateful applicaties zorgvuldige handling nodig hebben. Databases met split-brain kunnen data corrumperen.

Failure Timeouts om te Kennen

Deze timeouts beïnvloeden hoe snel Kubernetes reageert op failures:

TimeoutDefaultWat het doet
node-monitor-grace-period40sHoe lang voordat node NotReady wordt
pod-eviction-timeout5mHoe lang voordat pods van NotReady node evicted worden
node-monitor-period5sHoe vaak node status wordt gecheckt

Voor snellere failover kun je deze tunen — maar pas op voor false positives tijdens tijdelijke netwerkproblemen.

Het Blast Radius Principe

Elke failure beïnvloedt een “blast radius”:

ComponentBlast Radius
ContainerEnkele container
PodAlle containers in pod
KubeletAlle pods op node
NodeAlle pods op node
SchedulerNieuwe pod scheduling cluster-wide
Controller ManagerSelf-healing cluster-wide
API ServerAlle management operaties
etcdAlles

Ontwerp je HA hierop. etcd en API server hebben de meeste redundantie nodig.

Wat Dit Betekent voor Jou

  1. Draaiende workloads zijn resilient: Bestaande pods overleven de meeste control plane failures
  2. Management operaties niet: Je hebt control plane HA nodig voor continuous deployment
  3. etcd is het kritieke pad: Bescherm het, backup het, monitor het
  4. Failures cascaderen: API server down → lijkt alsof alles down is
  5. Timeouts zijn belangrijk: Ken je failure detection tijden

De schoonheid van Kubernetes is dat het ontworpen is met failures in gedachten. De vraag is niet óf componenten zullen falen — het is of je ervoor gearchitecteerd hebt.

Failures Testen

Wacht niet op productie om te ontdekken hoe je cluster zich gedraagt. Test:

# Simuleer API server failure (op een test cluster!)
kubectl exec -it -n kube-system kube-apiserver-xxx -- kill 1

# Simuleer scheduler failure
kubectl scale deployment kube-scheduler -n kube-system --replicas=0

# Simuleer kubelet failure op een node
ssh node-1 'sudo systemctl stop kubelet'

Beter nog, gebruik chaos engineering tools zoals Litmus Chaos voor gecontroleerde experimenten.


Failure modes begrijpen is geen pessimisme — het is engineering. Elk systeem faalt. De vraag is of je ervoor ontworpen hebt of erdoor verrast wordt.