Wat je aan het eind hebt
Een Deployment-manifest met de juiste combinatie liveness-, readiness- en startup-probes voor je service, ingevuld met startwaarden die passen bij je runtime, en gekoppeld aan een complete apps/v1 Deployment-spec die je direct kunt kubectl apply-en. De configuratie is bewust voorzichtig: hij neigt naar stabiliteit, en wijst je daarna naar het troubleshooting-artikel zodra je gaat tunen.
Vereisten
kubectlverbonden met een Kubernetes 1.27+ cluster (1.27 is wanneer de gRPC-probe GA werd; oudere versies werken prima zolang je gRPC overslaat).- Een container image die een health-endpoint blootstelt, of waar je een klein endpoint omheen kunt zetten. Heb je nog niets? Het stuk over endpoint-ontwerp in het troubleshooting-artikel legt uit wat een endpoint wel en niet moet checken.
- Basiskennis van Deployment-specs:
apiVersion,kind,spec.template.spec.containers. - Een idee van hoe lang je applicatie nodig heeft om op te starten. Een ruwe schatting volstaat; de beslisboom hieronder dekt zowel snelle als trage runtimes.
Welke probe heb je nodig? Een beslisboom
Drie probes, drie verschillende taken. De meeste eerste Deployments hebben er geen drie nodig. Loop deze lijst van boven naar beneden door en voeg alleen toe wat van toepassing is.
1. Wil je vanaf een Service verkeer naar deze pod sturen? Bijna altijd ja. Voeg een readiness-probe toe. Zonder probe stuurt Kubernetes verkeer naar de pod zodra de container start, dus ook tijdens het opstarten als de applicatie nog geen requests kan verwerken.
2. Kan de applicatie in een staat raken waarin hij wel leeft maar vastzit (deadlock, vastgelopen event loop, uitgeputte thread pool) en alleen een herstart helpt? Zo ja, voeg een liveness-probe toe. Crasht het proces zelf altijd netjes als er iets misgaat? Dan heb je geen liveness-probe nodig. Kubernetes herstart een gecrashte container sowieso.
3. Doet je container er langer over om op te starten dan failureThreshold x periodSeconds van je liveness-probe (default: 30 seconden)? Zo ja, voeg een startup-probe toe. Hij blokkeert liveness en readiness totdat het opstarten klaar is, zodat je geen grote initialDelaySeconds op de liveness-probe hoeft te zetten als compensatie.
Een veelgemaakte fout is uit reflex alle drie de probes toevoegen. Voor een Go-webservice die in twee seconden opstart is een readiness-probe alleen genoeg. Voor een Spring Boot-applicatie die 90 seconden nodig heeft, verdienen alle drie hun plek.
| Jouw situatie | Readiness | Liveness | Startup |
|---|---|---|---|
| Stateless HTTP-API, snelle boot (< 10s), crasht zelf bij fouten | Ja | Optioneel | Nee |
| Langlopende service die kan deadlocken | Ja | Ja | Nee |
| Trage JVM, .NET, of grote Python/Ruby-app | Ja | Ja | Ja |
| Worker-pod zonder inkomend verkeer | Nee | Optioneel | Bij trage boot |
Probetypen: HTTP, TCP, exec, gRPC
Elke probe-definitie kiest precies een mechanisme. Welk je kiest hangt vrijwel altijd af van het protocol dat je service spreekt.
HTTP-probe (httpGet)
De kubelet stuurt een HTTP GET-request. Statuscodes 200 tot en met 399 tellen als succes; alles anders is een fout. Dit is de juiste keuze voor elke service die al HTTP spreekt.
readinessProbe:
httpGet:
path: /healthz
port: 8080
periodSeconds: 10
failureThreshold: 3
Startwaarden: defaults werken. Verhoog timeoutSeconds van 1 naar 2 of 3 als je endpoint een database raakt. De kubelet stuurt standaard User-Agent: kube-probe/<versie>; via httpHeaders kun je extra headers meegeven als je endpoint die nodig heeft.
TCP-probe (tcpSocket)
De kubelet opent een TCP-verbinding. Succes betekent dat de verbinding werd geaccepteerd; het verifieert niet of de applicatie ook echt requests verwerkt. Gebruik dit voor databases, message brokers en andere niet-HTTP services.
readinessProbe:
tcpSocket:
port: 5432
periodSeconds: 10
failureThreshold: 3
Startwaarden: zelfde defaults. De grootste valkuil is dat een TCP-probe groen blijft op een half-stukke applicatie die wel verbindingen accepteert maar nooit antwoord geeft.
Exec-probe (exec)
De kubelet voert een commando uit binnen de container. Exit code 0 is succes, alles anders is een fout. Gebruik dit als er geen netwerkendpoint is, bijvoorbeeld een worker die een heartbeat-bestand schrijft.
livenessProbe:
exec:
command:
- cat
- /tmp/healthy
periodSeconds: 30
failureThreshold: 3
Startwaarden: gebruik een hogere periodSeconds (30 in plaats van 10), want exec-probes starten elke keer een child-proces. Als PID 1 in je container je applicatie zelf is (en niet tini of dumb-init) lekken korte intervallen zombies en raakt de PID-ruimte van de node uitgeput. Geef de voorkeur aan HTTP of TCP zodra de applicatie dat ondersteunt.
gRPC-probe (grpc)
De kubelet roept het standaard gRPC Health Checking Protocol aan (grpc.health.v1.Health/Check). GA sinds Kubernetes 1.27, geen feature gate nodig.
readinessProbe:
grpc:
port: 50051
periodSeconds: 10
failureThreshold: 3
Startwaarden: defaults werken. Beperkingen om vooraf te weten:
- Poort moet numeriek zijn. Named ports worden niet ondersteund.
- Geen client-certificaten. Services die mTLS eisen op het health-endpoint kunnen de ingebouwde probe niet gebruiken.
- Geen server-certificaatvalidatie. De probe negeert certificaatfouten volledig.
- Geen service-name chaining. Je kunt een probe niet richten op een multi-service health-aggregator.
Zijn die beperkingen dealbreakers? Wikkel dan een klein HTTP-endpoint om je gRPC-service of draai grpc-health-probe als exec-commando.
Aanbevolen startwaarden per runtime
Dit zijn voorzichtige startpunten, geen optima. Het doel is dat je eerste deploy stabiel draait, zodat je daarna kunt tunen op echte data en niet hoeft te gokken.
Snelle gecompileerde runtimes (Go, Rust, statisch gelinkte binaries, Node.js)
Opstarttijd doorgaans onder de 5 seconden. Een readiness-probe alleen is meestal genoeg; voeg liveness toe als je een specifiek deadlock-scenario hebt.
readinessProbe:
httpGet:
path: /readyz
port: 8080
periodSeconds: 5
timeoutSeconds: 2
failureThreshold: 3
livenessProbe:
httpGet:
path: /healthz
port: 8080
periodSeconds: 10
timeoutSeconds: 2
failureThreshold: 6 # pas herstarten na 60s onafgebroken falen
Geen startup-probe nodig. De default failureThreshold * periodSeconds van 30 seconden vangt cold starts ruim op.
Geinterpreteerde runtimes (Python, Ruby, PHP)
Opstarttijd is meestal 10 tot 40 seconden voor Django, Rails of Laravel onder normale workloads, afhankelijk van het aantal geladen packages. Een startup-probe is aanbevolen zodra de cold start de 30 seconden overschrijdt.
startupProbe:
httpGet:
path: /readyz
port: 8080
periodSeconds: 10
failureThreshold: 12 # 12 x 10 = 120s, ruim boven typische Django/Rails-coldstart
readinessProbe:
httpGet:
path: /readyz
port: 8080
periodSeconds: 5
timeoutSeconds: 3
failureThreshold: 3
livenessProbe:
httpGet:
path: /healthz
port: 8080
periodSeconds: 10
timeoutSeconds: 2
failureThreshold: 6
De startup-probe vangt migraties, cache-opwarming en lazy module-imports op.
JVM- en .NET-runtimes (Spring Boot, Quarkus, ASP.NET Core)
Opstarttijd kan 30 tot 180 seconden duren afhankelijk van dependency injection, classpath-scanning en JIT-warmup. Een startup-probe is feitelijk verplicht.
startupProbe:
httpGet:
path: /actuator/health/liveness # Spring Boot Actuator-pad; .NET gebruikt /healthz
port: 8080
periodSeconds: 10
failureThreshold: 30 # 30 x 10 = 300s, dekt cold starts tot 5 minuten
readinessProbe:
httpGet:
path: /actuator/health/readiness
port: 8080
periodSeconds: 10
timeoutSeconds: 3
failureThreshold: 3
livenessProbe:
httpGet:
path: /actuator/health/liveness
port: 8080
periodSeconds: 15
timeoutSeconds: 3
failureThreshold: 4 # herstart pas na een minuut falen, niet na 30s
Het opstart-venster van 5 minuten is bewust ruim. Cold start van een JVM onder CPU-druk kan onvoorspelbaar uitlopen, en een probe die de pod doodt voor hij klaar is met booten produceert een CrashLoopBackOff die het echte symptoom maskeert.
Gebruikt je applicatie de liveness- en readiness-groups van Spring Boot Actuator, gebruik dan de paden hierboven. Anders maak je zelf twee endpoints: een die 200 retourneert zodra de applicatie klaar is met opstarten (liveness), en een die ook kritieke dependencies checkt (readiness).
Reference: elke probe-parameter op een rij
Zes parameters bepalen probe-gedrag. De defaults zijn redelijk voor snelle services; meestal hoeven alleen de timeouts getuned te worden.
| Parameter | Default | Wat het regelt | Tuning-tip |
|---|---|---|---|
initialDelaySeconds |
0 | Seconden voor de eerste probe afgaat | Liever een startup-probe dan deze opblazen |
periodSeconds |
10 | Seconden tussen probe-uitvoeringen | Lager voor readiness (sneller schakelen), hoger voor liveness |
timeoutSeconds |
1 | Seconden dat de kubelet wacht op antwoord | Verhoog naar 2-3 als het endpoint een dependency raakt |
successThreshold |
1 | Opeenvolgende successen om healthy te markeren | Moet 1 zijn voor liveness en startup (API dwingt dit af) |
failureThreshold |
3 | Opeenvolgende fouten voor actie | Verhoog voor liveness om voortijdige herstarts te voorkomen |
terminationGracePeriodSeconds |
Erft van pod-level | Override voor probe-getriggerde herstarts | Alleen liveness/startup; geweigerd op readiness (1.25+) |
Alle defaults staan in de officiele Kubernetes probe-reference. Twee API-beperkingen zijn handig om vooraf te weten:
successThresholdvoor liveness- en startup-probes moet1zijn. De API-server weigert andere waarden.- Probe-level
terminationGracePeriodSeconds(toegevoegd in 1.25) geldt alleen voor liveness en startup. Hem zetten op een readiness-probe wordt geweigerd door de API-server, omdat een readiness-fout sowieso geen termination triggert.
Versie-afhankelijk gedrag tussen clusterversies
Probe-features landen in fasen. Twijfel je wat je cluster ondersteunt? Run kubectl version en check de tabel hieronder.
| Feature | Eerste versie | Stabiel | Notities |
|---|---|---|---|
| Liveness, readiness probes | Alle ondersteunde versies | Alle | Foundation feature |
| Startup probe | 1.16 (alpha) | 1.20 (GA) | Beta in 1.18 |
| gRPC probe | 1.23 (alpha, default uit) | 1.27 (GA) | Beta in 1.24 |
Probe-level terminationGracePeriodSeconds |
1.22 (alpha) | 1.25 (GA) | Alleen liveness en startup; readiness geweigerd |
Draai je op een cluster ouder dan 1.27 en wil je gRPC? Dan heb je twee opties: zet de GRPCContainerProbe feature gate aan (alleen mogelijk op een self-managed cluster) of val terug op grpc-health-probe als exec-commando.
Waar probes NIET voor zijn
Probes worden vaak misbruikt als generieke monitoring-laag. Dat zijn ze niet.
Liveness-probes zijn niet voor het checken van externe dependencies. Dit is veruit het meest schadelijke antipatroon. Als elke pod's liveness-check de database pingt en die database heeft een korte hapering, herstarten alle pods tegelijk. Het cluster gaat van "degraded database" naar "degraded database plus nul gezonde applicatie-pods". Het Google SRE Book is duidelijk dat monitoring geen dependency-keten in alerting-logica hoort te bouwen; dezelfde voorzichtigheid geldt voor probes die destructief gedrag triggeren.
Probes zijn geen vervanging voor metrics. Een liveness-probe vertelt de kubelet "kill deze pod"; hij vertelt jou niet waarom. Combineer probes altijd met fatsoenlijke observability. Het artikel over Kubernetes OpenTelemetry observability loopt door wat je in plaats daarvan moet vastleggen.
Readiness-probes zijn niet "alleen voor opstarten". Ze draaien gedurende de hele levensduur van de pod. Een pod die vijf minuten geleden Ready was kan onmiddellijk niet-Ready worden zodra de probe begint te falen. Behandel ze als "moet deze pod nu verkeer ontvangen?", niet als "is deze pod klaar met opstarten?".
Probes zijn geen application-level health monitoring. Ze bepalen of de kubelet een specifieke actie moet uitvoeren: container herstarten of verkeer stoppen. Alles wat genuanceerder is (queue-diepte, business-correctheid, downstream SLO-overschrijdingen) hoort in metrics en alerting, niet in probes.
Alles samen: compleet Deployment-manifest
Een productieklaar manifest voor een Spring Boot-service. Pas het probe-blok aan naar de runtime-set uit de vorige sectie.
apiVersion: apps/v1
kind: Deployment
metadata:
name: orders-api
labels:
app: orders-api
spec:
replicas: 3
selector:
matchLabels:
app: orders-api
template:
metadata:
labels:
app: orders-api
spec:
terminationGracePeriodSeconds: 60
containers:
- name: app
image: registry.internal/orders-api:1.7.4 # Spring Boot 3.4 image
ports:
- name: http
containerPort: 8080
# Startup-probe: blokkeert de andere tot de JVM draait
startupProbe:
httpGet:
path: /actuator/health/liveness
port: http
periodSeconds: 10
failureThreshold: 30 # 5 minuten worst-case cold start
# Readiness-probe: stuurt verkeer op basis van dependency-gezondheid
readinessProbe:
httpGet:
path: /actuator/health/readiness
port: http
periodSeconds: 10
timeoutSeconds: 3 # /readiness raakt de database
failureThreshold: 3
# Liveness-probe: laatste redmiddel bij deadlock
livenessProbe:
httpGet:
path: /actuator/health/liveness
port: http
periodSeconds: 15
timeoutSeconds: 3
failureThreshold: 4 # pas herstarten na ~60s falen
terminationGracePeriodSeconds: 10 # snelle herstart bij deadlock (1.25+)
resources:
requests:
cpu: "250m"
memory: "512Mi"
limits:
memory: "1Gi"
Toepassen en bevestigen dat de pods Ready worden zonder restart-events:
kubectl apply -f deployment.yaml
kubectl rollout status deployment/orders-api --timeout=5m
kubectl describe pod -l app=orders-api | grep -A 3 "Events:"
Verwachte output: deployment "orders-api" successfully rolled out, en de events-sectie toont alleen probe-successen, geen Unhealthy-regels. Zie je Liveness probe failed-events terwijl de applicatie nog aan het opstarten is, dan staat de startup-probe verkeerd: verhoog failureThreshold totdat het opstart-venster comfortabel past.
Dit manifest combineert prima met de rollout-instellingen uit Kubernetes rolling updates en zero-downtime deployments, die maxUnavailable: 0, een preStop-hook en een PodDisruptionBudget toevoegen voor volledige productie-hardening.
Wat te doen als probes zich misdragen
Komen je pods in CrashLoopBackOff, worden ze onder load herstart, of vallen ze allemaal tegelijk in niet-Ready bij een korte dependency-hapering? Die symptomen mappen op specifieke configuratiefouten. Het zustertje How to configure Kubernetes health probes loopt elk geval door: de regels voor endpoint-ontwerp, de vijf veelvoorkomende misconfiguratiepatronen, de diagnose-commando's, en de escalatie-checklist als een probe blijft falen ondanks een ogenschijnlijk correcte configuratie.
Voor het verwante geval waarin pods 1/1 Running zijn maar tijdens deploys gekilld worden, ligt het probleem niet bij de probe maar bij de endpoint-removal race condition tijdens termination. Dat behandelt Kubernetes graceful shutdown.