DEV Community

janak0ff
janak0ff

Posted on

Day 51: Execute Rolling Updates in Kubernetes

An application currently running on the Kubernetes cluster employs the nginx web server. The Nautilus application development team has introduced some recent changes that need deployment. They've crafted an image nginx:1.19 with the latest updates.

Execute a rolling update for this application, integrating the nginx:1.19 image. The deployment is named nginx-deployment.

Ensure all pods are operational post-update.


Introduction

Welcome to Day 51 of my 100 Days of DevOps journey! Today, we're learning about one of Kubernetes' most powerful features: Rolling Updates.

What is a Rolling Update?

Imagine you're updating a website. Instead of shutting everything down, updating, and restarting (which would cause downtime), a rolling update:

  1. ✅ Updates pods one by one
  2. ✅ Keeps the application available during updates
  3. Rolls back automatically if something fails
  4. ✅ Ensures zero downtime

📋 What We'll Build Today

We have an existing deployment running nginx:1.16. We need to update it to nginx:1.19 using a rolling update.

Our Task:

  • Deployment Name: nginx-deployment
  • Current Image: nginx:1.16
  • New Image: nginx:1.19
  • Goal: Zero-downtime update

📖 Understanding Rolling Updates

How Rolling Updates Work

┌─────────────────────────────────────────────────────────────────────────────┐
│                        Rolling Update Process                              │
│                                                                              │
│  ┌────────────────────────────────────────────────────────────────────┐     │
│  │  BEFORE: All pods running nginx:1.16                              │     │
│  │  ┌──────────┐ ┌──────────┐ ┌──────────┐                         │     │
│  │  │  Pod 1   │ │  Pod 2   │ │  Pod 3   │                         │     │
│  │  │ nginx:1.16│ │ nginx:1.16│ │ nginx:1.16│                         │     │
│  │  └──────────┘ └──────────┘ └──────────┘                         │     │
│  └────────────────────────────────────────────────────────────────────┘     │
│                                    │                                         │
│                                    ▼                                         │
│  ┌────────────────────────────────────────────────────────────────────┐     │
│  │  STEP 1: Create new pod with nginx:1.19                          │     │
│  │  ┌──────────┐ ┌──────────┐ ┌──────────┐                         │     │
│  │  │  Pod 1   │ │  Pod 2   │ │  Pod 3   │                         │     │
│  │  │ nginx:1.16│ │ nginx:1.16│ │ nginx:1.16│                         │     │
│  │  └──────────┘ └──────────┘ └──────────┘                         │     │
│  │  ┌──────────┐                                                    │     │
│  │  │  Pod 4   │  ← New pod with nginx:1.19                        │     │
│  │  │ nginx:1.19│                                                    │     │
│  │  └──────────┘                                                    │     │
│  └────────────────────────────────────────────────────────────────────┘     │
│                                    │                                         │
│                                    ▼                                         │
│  ┌────────────────────────────────────────────────────────────────────┐     │
│  │  STEP 2: Scale up new, scale down old                            │     │
│  │  ┌──────────┐ ┌──────────┐ ┌──────────┐                         │     │
│  │  │  Pod 1   │ │  Pod 2   │ │  Pod 3   │                         │     │
│  │  │ nginx:1.16│ │ nginx:1.16│ │ nginx:1.16│                         │     │
│  │  └──────────┘ └──────────┘ └──────────┘                         │     │
│  │  ┌──────────┐ ┌──────────┐                                       │     │
│  │  │  Pod 4   │ │  Pod 5   │  ← Another new pod                   │     │
│  │  │ nginx:1.19│ │ nginx:1.19│                                       │     │
│  │  └──────────┘ └──────────┘                                       │     │
│  └────────────────────────────────────────────────────────────────────┘     │
│                                    │                                         │
│                                    ▼                                         │
│  ┌────────────────────────────────────────────────────────────────────┐     │
│  │  AFTER: All pods running nginx:1.19                              │     │
│  │  ┌──────────┐ ┌──────────┐ ┌──────────┐                         │     │
│  │  │  Pod 4   │ │  Pod 5   │ │  Pod 6   │                         │     │
│  │  │ nginx:1.19│ │ nginx:1.19│ │ nginx:1.19│                         │     │
│  │  └──────────┘ └──────────┘ └──────────┘                         │     │
│  └────────────────────────────────────────────────────────────────────┘     │
└─────────────────────────────────────────────────────────────────────────────┘
Enter fullscreen mode Exit fullscreen mode

Key Benefits of Rolling Updates

Feature Benefit
Zero Downtime Application stays available during update
Gradual Rollout Updates happen one pod at a time
Automatic Rollback If update fails, it rolls back
Controlled Speed You control how fast the update happens
Health Checks Only updates if pods are healthy

🔧 Step-by-Step Guide

Step 1: Check Current Deployment Status

First, let's see what we're working with:

# Check cluster status
kubectl cluster-info

# Get current deployments
kubectl get deployments

# Check current pods
kubectl get pods

# Get detailed deployment information
kubectl describe deployment nginx-deployment

# Check current image
kubectl describe deployment nginx-deployment | grep -i image
Enter fullscreen mode Exit fullscreen mode

Before Update Output:

NAME               READY   UP-TO-DATE   AVAILABLE   AGE
nginx-deployment   3/3     3            3           24m

NAME                               READY   STATUS    RESTARTS   AGE
nginx-deployment-fc677cbc9-88rb6   1/1     Running   0          24m
nginx-deployment-fc677cbc9-dqrzm   1/1     Running   0          24m
nginx-deployment-fc677cbc9-l8w5t   1/1     Running   0          24m

Containers:
   nginx-container:
    Image:         nginx:1.16
Enter fullscreen mode Exit fullscreen mode

Key Observations:

  • ✅ Deployment has 3 replicas
  • ✅ All pods are running
  • ✅ Current image: nginx:1.16
  • ✅ Container name: nginx-container

Step 2: Identify the Container Name

This is critical for the update command. We need the exact container name:

# Find the container name
kubectl describe deployment nginx-deployment | grep -A 10 "Containers:"
Enter fullscreen mode Exit fullscreen mode

Output:

Containers:
   nginx-container:
    Image:         nginx:1.16
Enter fullscreen mode Exit fullscreen mode

The container name is nginx-container – we'll need this for the update command.


Step 3: Perform the Rolling Update

Now let's update the image:

# The correct syntax: deployment-name container-name=new-image
kubectl set image deployment/nginx-deployment nginx-container=nginx:1.19
Enter fullscreen mode Exit fullscreen mode

Output:

deployment.apps/nginx-deployment image updated
Enter fullscreen mode Exit fullscreen mode

Command Breakdown:

kubectl set image           ← Kubernetes command to update image
deployment/nginx-deployment ← The deployment to update
nginx-container             ← The container name (IMPORTANT!)
nginx:1.19                  ← The new image with tag
Enter fullscreen mode Exit fullscreen mode

Step 4: Monitor the Rollout

# Check rollout status
kubectl rollout status deployment nginx-deployment
Enter fullscreen mode Exit fullscreen mode

Output:

Waiting for deployment "nginx-deployment" rollout to finish: 0 of 3 updated replicas are available...
Waiting for deployment "nginx-deployment" rollout to finish: 1 of 3 updated replicas are available...
Waiting for deployment "nginx-deployment" rollout to finish: 2 of 3 updated replicas are available...
deployment "nginx-deployment" successfully rolled out
Enter fullscreen mode Exit fullscreen mode
# Watch pods being updated in real-time
kubectl get pods -w
Enter fullscreen mode Exit fullscreen mode

During Update Output:

NAME                                READY   STATUS              RESTARTS   AGE
nginx-deployment-6655dc8cfb-g9dkq   0/1     ContainerCreating   0          1s
nginx-deployment-6655dc8cfb-krrrx   0/1     ContainerCreating   0          2s
nginx-deployment-6655dc8cfb-lhssp   1/1     Running             0          5s
Enter fullscreen mode Exit fullscreen mode

Step 5: Verify the Update

# Check deployment status
kubectl get deployments
Enter fullscreen mode Exit fullscreen mode

Output:

NAME               READY   UP-TO-DATE   AVAILABLE   AGE
nginx-deployment   3/3     3            3           31m
Enter fullscreen mode Exit fullscreen mode
# Check pods
kubectl get pods
Enter fullscreen mode Exit fullscreen mode

Output:

NAME                                READY   STATUS    RESTARTS   AGE
nginx-deployment-6655dc8cfb-g9dkq   1/1     Running   0          4m
nginx-deployment-6655dc8cfb-krrrx   1/1     Running   0          4m
nginx-deployment-6655dc8cfb-lhssp   1/1     Running   0          4m
Enter fullscreen mode Exit fullscreen mode
# Verify the new image
kubectl describe deployment nginx-deployment | grep -i image
Enter fullscreen mode Exit fullscreen mode

Output:

Image:         nginx:1.19
Enter fullscreen mode Exit fullscreen mode
# Check rollout history
kubectl rollout history deployment nginx-deployment
Enter fullscreen mode Exit fullscreen mode

Output:

deployment.apps/nginx-deployment
REVISION  CHANGE-CAUSE
1         <none>
2         <none>
Enter fullscreen mode Exit fullscreen mode

📝 Complete Commands Summary

# 1. Check current deployment
kubectl get deployments
kubectl get pods
kubectl describe deployment nginx-deployment | grep -i image

# 2. Find the container name
kubectl describe deployment nginx-deployment | grep -A 10 "Containers:"

# 3. Perform rolling update
kubectl set image deployment/nginx-deployment nginx-container=nginx:1.19

# 4. Monitor the rollout
kubectl rollout status deployment nginx-deployment
kubectl get pods -w

# 5. Verify the update
kubectl get deployments
kubectl get pods
kubectl describe deployment nginx-deployment | grep -i image
kubectl rollout history deployment nginx-deployment
Enter fullscreen mode Exit fullscreen mode

📊 Before and After Comparison

Aspect Before Update After Update
Image Version nginx:1.16 nginx:1.19
Replicas 3 3
Pods 3 running 3 running
Deployment Status Available ✅ Available ✅
Downtime - None ✅

🛠️ Troubleshooting

Issue 1: Container Name Not Found

Error:

error: unable to find container named "nginx"
Enter fullscreen mode Exit fullscreen mode

Solution:

# Check the container name
kubectl describe deployment nginx-deployment | grep -A 10 "Containers:"

# Use the correct container name
kubectl set image deployment/nginx-deployment <correct-container-name>=nginx:1.19
Enter fullscreen mode Exit fullscreen mode

Issue 2: Rollout Gets Stuck

# Check the status
kubectl rollout status deployment nginx-deployment

# Check pod details
kubectl describe pod <pod-name>

# Check pod logs
kubectl logs <pod-name>

# Check events
kubectl get events --sort-by='.lastTimestamp'
Enter fullscreen mode Exit fullscreen mode

Issue 3: Image Pull Failed

# Check image pull errors
kubectl describe pod <pod-name> | grep -A 5 "Failed"

# Verify image exists
docker pull nginx:1.19
Enter fullscreen mode Exit fullscreen mode

🔧 Advanced Commands

Rolling Update Options

# Update with different strategy
kubectl patch deployment nginx-deployment -p '{"spec":{"strategy":{"rollingUpdate":{"maxSurge":2,"maxUnavailable":1}}}}'

# Pause the rollout
kubectl rollout pause deployment nginx-deployment

# Resume the rollout
kubectl rollout resume deployment nginx-deployment

# Check rollout status with timeout
kubectl rollout status deployment nginx-deployment --timeout=60s
Enter fullscreen mode Exit fullscreen mode

Rollback Commands

# Check history
kubectl rollout history deployment nginx-deployment

# Rollback to previous version
kubectl rollout undo deployment nginx-deployment

# Rollback to specific revision
kubectl rollout undo deployment nginx-deployment --to-revision=1
Enter fullscreen mode Exit fullscreen mode

🎯 Key Learnings

1. Container Name is Critical

Always check the container name before updating:

kubectl describe deployment nginx-deployment | grep -A 10 "Containers:"
Enter fullscreen mode Exit fullscreen mode

2. Rolling Update Formula

kubectl set image deployment/<deployment-name> <container-name>=<new-image>:<tag>
Enter fullscreen mode Exit fullscreen mode

3. Monitoring is Essential

Always monitor the rollout:

  • kubectl rollout status – Check progress
  • kubectl get pods -w – Watch pods update
  • kubectl describe deployment – Get detailed info

4. Zero Downtime is Achievable

With rolling updates, you can update applications without downtime.


✅ Task Summary

Requirement Status
Deployment identified
Container name found
Image updated to nginx:1.19
Rollout completed
All pods running
Zero downtime achieved
Verification complete

🚀 Next Steps

After a successful rolling update:

  1. Monitor performance:
   kubectl top pods
Enter fullscreen mode Exit fullscreen mode
  1. Check application health:
   # If service exists
   kubectl get svc
   curl http://<service-ip>
Enter fullscreen mode Exit fullscreen mode
  1. Update deployment strategy:
   kubectl patch deployment nginx-deployment -p '{"spec":{"strategy":{"rollingUpdate":{"maxSurge":1,"maxUnavailable":0}}}}'
Enter fullscreen mode Exit fullscreen mode

📚 Quick Reference

Rolling Update Commands

Command Purpose
kubectl set image deployment/<name> <container>=<image> Update image
kubectl rollout status deployment/<name> Check status
kubectl rollout history deployment/<name> View history
kubectl rollout undo deployment/<name> Rollback
kubectl rollout pause deployment/<name> Pause rollout
kubectl rollout resume deployment/<name> Resume rollout

Common Errors and Solutions

Error Solution
"unable to find container named" Check container name with describe
Rollout stuck Check pod logs and events
Image pull failed Verify image exists
Pods not ready Check health checks

Top comments (0)