Working with Pod Lifecycle Hooks
1. Understanding Lifecycle Hooks
| Hook | Fires When |
| postStart | Immediately after container created (async with ENTRYPOINT) |
| preStop | Before container receives SIGTERM during termination |
Note: Container will not enter Running until postStart completes; container is killed if postStart fails.
2. Configuring PostStart Hook
lifecycle:
postStart:
exec: { command: ["sh","-c","echo started > /tmp/ready"] }
| Handler | Format |
| exec | command: [...] |
| httpGet | path, port, host, scheme, httpHeaders |
| sleep NEW | sleep: { seconds: 5 } (1.32+) |
3. Configuring PreStop Hook
Example: Graceful nginx drain
lifecycle:
preStop:
exec: { command: ["/bin/sh","-c","nginx -s quit; sleep 10"] }
terminationGracePeriodSeconds: 30
| Sequence | Step |
| 1 | Pod marked Terminating; removed from Service endpoints |
| 2 | preStop hook runs |
| 3 | SIGTERM sent to PID 1 |
| 4 | SIGKILL after terminationGracePeriodSeconds |
4. Using Exec Handler
| Property | Detail |
| Runs in | Container's filesystem & network |
| Failure | Exit non-zero treated as hook failure |
| Best for | Local cleanup, signal sending |
5. Using HTTP Handler
lifecycle:
preStop:
httpGet:
path: /shutdown
port: 8080
httpHeaders: [{ name: X-Reason, value: drain }]
| Field | Default |
| scheme | HTTP |
| host | Pod IP |
| Success | 2xx/3xx response |
6. Implementing Graceful Shutdown
Graceful Shutdown Pattern
- preStop: mark unready (touch flag, drop from LB)
- preStop: sleep N seconds for in-flight requests
- SIGTERM: stop accepting new connections
- App drains workers, flushes logs, closes DB
- App exits cleanly before grace period ends
| Tip | Detail |
| Sleep length | Cover kube-proxy/iptables update lag (5-10s) |
| terminationGracePeriodSeconds | preStop + drain + buffer |
| PID 1 | Use tini/dumb-init to forward SIGTERM |
7. Understanding Hook Guarantees
| Guarantee | Reality |
| At-least-once | Hook may run multiple times on retries |
| postStart vs ENTRYPOINT | No ordering — race possible |
| preStop on node failure | Not guaranteed to run |
8. Setting Termination Grace Period
| Setting | Default |
| terminationGracePeriodSeconds | 30s |
| 0 | Force-immediate (SIGKILL); skips preStop |
| Override | kubectl delete --grace-period=60 |
9. Debugging Lifecycle Hooks
| Symptom | Check |
| FailedPostStartHook | kubectl describe pod events |
| FailedPreStopHook | Hook exceeded grace period |
| Stuck Terminating | Finalizers, kubelet unable to reach node |
10. Using Hooks for Deregistration
Example: Deregister from external service mesh
lifecycle:
preStop:
exec:
command: ["sh","-c","curl -X DELETE http://consul:8500/v1/agent/service/deregister/$HOSTNAME; sleep 10"]