✦ For everyone, free.

Practical knowledge for real and everyday life

Home

Kubernetes Graceful Shutdown Reliability

Kubernetes Graceful Shutdown Reliability ensures clean application termination during node shutdown, preserving data and service availability.

Kubernetes Graceful Shutdown Reliability is the practice of ensuring a pod's termination does not disrupt in-flight requests, addressing the specific race condition between a pod being marked for deletion and its removal from Service endpoints propagating across the cluster, through preStop hooks, application-level signal handling, and appropriately tuned grace periods.


The Core Race Condition

Termination Begins Before Endpoint Removal Completes

When a pod is deleted, two things happen concurrently: the kubelet begins sending SIGTERM to the container, and the endpoint controller begins removing the pod from its Service's endpoint list; because these are independent, asynchronous processes, and endpoint removal must further propagate to every node's kube-proxy (or equivalent) before it takes effect, a client can still route a new request to a pod that has already begun terminating.

SIGTERM sent Endpoint removed everywhere

Why This Matters for Availability

Without mitigation, this race produces intermittent connection failures during every routine pod termination, a scaling-down event, a rolling update, a node drain, since some fraction of in-flight or newly arriving requests during the propagation window are routed to a pod already shutting down.


The preStop Sleep as the Standard Mitigation

Delaying Actual Shutdown Until Endpoint Propagation Completes

lifecycle:
  preStop:
    exec:
      command: ["sh", "-c", "sleep 5"]

A preStop hook runs before SIGTERM is delivered to the container, and a simple sleep gives the endpoint removal time to propagate across the cluster before the application actually begins shutting down, ensuring that by the time the container starts terminating in earnest, no client is still attempting to route new traffic to it.

preStop Duration Endpoint Propagation Time

Continuing to Serve During preStop

Because the container is still fully running during the preStop hook's execution, an application already handling in-flight requests continues to do so throughout this window; the sleep does not pause the application, it simply delays the signal that would otherwise begin its shutdown sequence, which is precisely why this specific technique resolves the race rather than merely deferring it.


terminationGracePeriodSeconds Budgeting

The Total Time Available for Shutdown

spec:
  terminationGracePeriodSeconds: 30
  containers:
    - name: web
      lifecycle:
        preStop:
          exec:
            command: ["sh", "-c", "sleep 5"]

terminationGracePeriodSeconds bounds the entire shutdown sequence, preStop hook execution plus the application's own response to SIGTERM, before the kubelet issues SIGKILL unconditionally; the grace period must be sized to accommodate both the preStop delay and however long the application genuinely needs to drain in-flight requests and close connections cleanly afterward.

terminationGracePeriodSeconds preStop Duration + Application Drain Time

The Consequence of an Insufficient Grace Period

If the grace period is too short, SIGKILL arrives before the application has finished draining connections, causing abrupt termination of requests that were otherwise on track to complete cleanly, precisely the outcome graceful shutdown handling exists to prevent; a grace period tuned only for the common case, without margin for a slow request near the tail of the distribution, reintroduces the same disruption graceful shutdown was meant to eliminate.


Application-Level SIGTERM Handling

Stopping New Work While Finishing Existing Work

import signal

def handle_sigterm(signum, frame):
    server.stop_accepting_new_connections()
    server.wait_for_in_flight_requests(timeout=25)

signal.signal(signal.SIGTERM, handle_sigterm)

An application that ignores SIGTERM entirely relies solely on the preStop delay and ultimately gets forcibly killed once the grace period expires, abruptly terminating any request still in flight at that moment; explicit signal handling that stops accepting new connections while allowing existing ones to complete, up to a bounded timeout, is what actually achieves clean request completion rather than merely delaying the eventual abrupt termination.

Applications With No Signal Handling Capability

For workloads that cannot be modified to handle SIGTERM gracefully, the preStop delay alone still meaningfully reduces, though does not eliminate, disruption, since it addresses the endpoint-propagation race even if the application itself does nothing special upon receiving the termination signal.


Node-Level Graceful Shutdown

GracefulNodeShutdown for Node Termination Events

# kubelet configuration
shutdownGracePeriod: 30s
shutdownGracePeriodCriticalPods: 10s

The kubelet's graceful node shutdown feature applies the same pod-level graceful termination sequence, preStop, SIGTERM, grace period, SIGKILL, when the node itself is shutting down (a spot instance reclamation, a planned maintenance shutdown), with a separate, shorter grace period reserved specifically for critical system pods that must terminate quickly to allow the node to shut down within an externally imposed time limit.


Relationship to Pod Recovery Basics and Readiness Availability

Graceful shutdown reliability is the counterpart, at pod termination, to the traffic-eligibility mechanism described under readiness availability at pod startup: both exist to keep the set of pods actually receiving traffic accurately synchronized with the set of pods actually able to serve it, and both depend on the same underlying endpoint propagation mechanism whose inherent latency is what makes deliberate handling, preStop delays, signal-aware draining, necessary rather than optional for a workload that must avoid disrupting in-flight requests during routine, expected pod termination.

Delete issued preStop ends SIGTERM handled endpoint propagation window