Kubernetes & platform5 min read

Kubernetes Zero-Downtime Deployments: A Complete Guide

How to deploy updates to your Kubernetes applications without any service interruption. Rolling updates, blue-green, canary releases, and the critical configurations most teams miss.

TL;DR - Quick Answer

  • Zero-downtime deployment means releasing updates without service interruption
  • Requires: proper readiness probes, rolling update strategy, graceful shutdown handling
  • Common strategies: Rolling Updates (default), Blue-Green, Canary Releases
  • Most failures are caused by missing readiness probes or improper connection draining

What is Zero-Downtime Deployment?

Zero-downtime deployment is a deployment strategy where application updates are released without any service interruption. Users continue to access the application normally throughout the entire deployment process - they don't experience errors, timeouts, or any indication that an update is happening.

In Kubernetes, this is achieved through a combination of proper deployment configuration, health checks, and graceful shutdown handling. When done correctly, you can deploy multiple times per day with complete confidence that users won't be affected.

Why Zero-Downtime Matters

Every minute of downtime has a cost:

  • Revenue loss - E-commerce sites lose sales, SaaS platforms lose usage-based revenue
  • User trust - Frequent outages erode confidence in your platform
  • Developer velocity - Fear of deployments leads to infrequent releases with larger, riskier changes
  • On-call burden - Risky deployments mean more incidents and stressed engineers

Teams that achieve reliable zero-downtime deployments deploy more frequently, ship smaller changes, and have higher confidence in their releases.

Deployment Strategies Compared

Strategy How It Works Best For
Rolling Update Gradually replaces old pods with new ones Most applications (default strategy)
Blue-Green Two identical environments, switch traffic at once Database migrations, major changes
Canary Route small % of traffic to new version first High-risk changes, gradual rollout

Rolling update is the built-in strategy of the Deployment object. Kubernetes does not offer blue-green or canary directly: they are usually built from two Deployments and a Service selector switch, or from weighted routing, for example an HTTPRoute in Gateway API, where backend weights set the share of traffic for the new version.

Step 1: Configure Readiness Probes

The readiness probe tells Kubernetes when your pod is ready to receive traffic. If you don't define one, the kubelet treats the result as Success and the pod receives traffic as soon as the container starts, even if the application isn't ready yet. That causes errors during deployment.

spec:
  containers:
  - name: app
    readinessProbe:
      httpGet:
        path: /health
        port: 8080
      initialDelaySeconds: 5
      periodSeconds: 5
      failureThreshold: 3

Common Mistake

Don't rely on a liveness probe alone! A liveness probe restarts the container, but the readiness probe controls traffic routing. A liveness probe should only detect an unrecoverable process state (e.g. a deadlock), not a database outage: an incorrectly configured liveness probe leads to cascading restarts under load. That is why the complete example below uses a separate /livez endpoint.

Your health endpoint should verify that the application is truly ready:

  • Database connections are established
  • Cache is warmed (if needed)
  • Dependencies are reachable

Step 2: Configure Rolling Update Strategy

The rolling update strategy controls how Kubernetes replaces old pods with new ones. The defaults are 25% for both maxUnavailable and maxSurge, so with default settings part of your capacity can be down during a rollout. Two parameters worth setting explicitly:

spec:
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxUnavailable: 0
      maxSurge: 1
  • maxUnavailable: 0 - Never have fewer than desired pods (zero-downtime)
  • maxSurge: 1 - Allow one extra pod during rollout

With this configuration, Kubernetes will:

  1. Create a new pod with the updated version
  2. Wait for it to pass readiness checks
  3. Start routing traffic to the new pod
  4. Terminate an old pod
  5. Repeat until all pods are updated

Step 3: Implement Graceful Shutdown

When Kubernetes terminates a pod, it sends a SIGTERM signal. Your application must handle this signal gracefully:

  • Stop accepting new requests
  • Finish processing in-flight requests
  • Close database connections cleanly
  • Exit the process
# Python example
import signal
import sys

def graceful_shutdown(signum, frame):
    print("Received SIGTERM, shutting down gracefully...")
    # Stop accepting new requests
    server.stop_accepting()
    # Wait for in-flight requests to complete
    server.wait_for_pending_requests(timeout=30)
    # Close connections
    db.close()
    sys.exit(0)

signal.signal(signal.SIGTERM, graceful_shutdown)

Step 4: Add PreStop Hook

There's a race condition: when the kubelet starts terminating the pod (runs the preStop hook, then sends SIGTERM), the control plane updates the Service's EndpointSlices at the same time. Until that change reaches kube-proxy, load balancers and ingress controllers, traffic may still arrive at the pod.

The preStop hook adds a delay before shutdown, giving time for endpoint updates to propagate. The native sleep action has been stable since Kubernetes 1.34, so every currently supported release has it. The kubelet runs it, so it also works in distroless images without /bin/sh. On older clusters, use exec with ["/bin/sh", "-c", "sleep 10"].

spec:
  containers:
  - name: app
    lifecycle:
      preStop:
        sleep:
          seconds: 10

This 10-second sleep gives load balancers and ingress controllers time to stop sending traffic to this pod before it begins shutdown.

Pro Tip

Set terminationGracePeriodSeconds to at least preStop sleep + your application's shutdown time. The countdown starts before the preStop hook runs and covers both. Default is 30 seconds.

Complete Example

Here's a complete deployment configuration for zero-downtime:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-app
spec:
  replicas: 3
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxUnavailable: 0
      maxSurge: 1
  selector:
    matchLabels:
      app: my-app
  template:
    metadata:
      labels:
        app: my-app
    spec:
      terminationGracePeriodSeconds: 60
      containers:
      - name: app
        image: my-app:v2
        ports:
        - containerPort: 8080
        readinessProbe:
          httpGet:
            path: /health
            port: 8080
          initialDelaySeconds: 5
          periodSeconds: 5
          failureThreshold: 3
        livenessProbe:
          httpGet:
            path: /livez
            port: 8080
          initialDelaySeconds: 15
          periodSeconds: 10
        lifecycle:
          preStop:
            sleep:
              seconds: 10

Troubleshooting Common Issues

1. Errors During Deployment

Symptom: Users see 502/503 errors during deployments.
Cause: Usually missing or misconfigured readiness probes.
Fix: Ensure readiness probe returns healthy only when app is truly ready.

2. Connection Resets

Symptom: In-flight requests fail with connection reset.
Cause: App not handling SIGTERM gracefully.
Fix: Implement graceful shutdown and add preStop hook.

3. Slow Rollouts

Symptom: Deployments take too long.
Cause: Usually slow readiness probes or conservative settings.
Fix: Tune initialDelaySeconds and periodSeconds, increase maxSurge.

Key Takeaways

  • Zero-downtime deployment is achievable with proper configuration
  • Readiness probes are critical - they control traffic routing
  • Use maxUnavailable: 0 to ensure capacity throughout deployment
  • Implement graceful shutdown in your application
  • Add preStop hook to handle the endpoint update race condition
  • Test your deployment strategy before relying on it in production

Sources

  1. Kubernetes: Deployments (July 2026)
  2. Kubernetes: Liveness, Readiness, and Startup Probes (June 2026)
  3. Kubernetes: Pod Lifecycle, Termination of Pods (July 2026)
  4. Kubernetes: Container Lifecycle Hooks (February 2026)
  5. Kubernetes: Feature Gates (PodLifecycleSleepAction) (January 2026)
  6. Kubernetes: Releases (September 2026)
  7. Gateway API: HTTP traffic splitting (May 2026)

Need Help with Kubernetes Deployments?

We've helped companies achieve zero-downtime deployments and reduce deployment anxiety. Let's talk about your infrastructure.

Or write to info@devsecops.cz. We process your data under our privacy policy.