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:
kubectlcommando’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:
| Timeout | Default | Wat het doet |
|---|---|---|
node-monitor-grace-period | 40s | Hoe lang voordat node NotReady wordt |
pod-eviction-timeout | 5m | Hoe lang voordat pods van NotReady node evicted worden |
node-monitor-period | 5s | Hoe 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”:
| Component | Blast Radius |
|---|---|
| Container | Enkele container |
| Pod | Alle containers in pod |
| Kubelet | Alle pods op node |
| Node | Alle pods op node |
| Scheduler | Nieuwe pod scheduling cluster-wide |
| Controller Manager | Self-healing cluster-wide |
| API Server | Alle management operaties |
| etcd | Alles |
Ontwerp je HA hierop. etcd en API server hebben de meeste redundantie nodig.
Wat Dit Betekent voor Jou
- Draaiende workloads zijn resilient: Bestaande pods overleven de meeste control plane failures
- Management operaties niet: Je hebt control plane HA nodig voor continuous deployment
- etcd is het kritieke pad: Bescherm het, backup het, monitor het
- Failures cascaderen: API server down → lijkt alsof alles down is
- 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.
