Modifying Container Images in Kubernetes

4 minute read

Why Modify Images?

In production, you frequently need to update the container image for a workload — to deploy a new version, patch a vulnerability, or roll back a broken release. Kubernetes provides multiple approaches depending on the resource type.

Updating Deployment Images

Deployments are the most common workload. You can update their images imperatively or declaratively.

Imperative: kubectl set image

This is the fastest method for the CKAD exam:

# Update the image of the 'app' container in deployment 'web'
kubectl set image deployment/web app=nginx:1.27

# Verify the rollout
kubectl rollout status deployment/web

Syntax:

kubectl set image deployment/<deployment-name> <container-name>=<new-image>

You can update multiple containers at once:

kubectl set image deployment/web \
  app=nginx:1.27 \
  sidecar=fluentd:v1.16

Imperative: kubectl edit

Open the resource in your editor and change the image directly:

kubectl edit deployment web

Find the image: field, change it, save, and exit. The Deployment controller will trigger a rolling update.

Declarative: Update YAML and Apply

apiVersion: apps/v1
kind: Deployment
metadata:
  name: web
spec:
  replicas: 3
  selector:
    matchLabels:
      app: web
  template:
    spec:
      containers:
      - name: app
        image: nginx:1.27   # ← Updated from nginx:1.26
kubectl apply -f deployment.yaml

Rolling Updates

When you update a Deployment’s image, Kubernetes performs a rolling update by default:

Old Pods:    [v1] [v1] [v1]
                      ↓ Rolling update starts
Step 1:      [v1] [v1] [v2]    ← New Pod created
Step 2:      [v1] [v2] [v2]    ← Old Pod terminated
Step 3:      [v2] [v2] [v2]    ← Complete

Monitoring Rollouts

# Watch the rollout status
kubectl rollout status deployment/web

# View rollout history
kubectl rollout history deployment/web

# See details of a specific revision
kubectl rollout history deployment/web --revision=2

Rolling Back

If the new image has issues, roll back instantly:

# Roll back to the previous revision
kubectl rollout undo deployment/web

# Roll back to a specific revision
kubectl rollout undo deployment/web --to-revision=3

Exam tip: kubectl rollout undo is one of the fastest ways to recover from a bad deployment. Know this command well.

Editing Pod Images

Pods are immutable — you cannot change the image of a running Pod directly. To update a Pod’s image, you must delete and recreate it.

Method 1: Export, Edit, Recreate

# Export the current Pod definition
kubectl get pod my-pod -o yaml > pod.yaml

# Edit the image in the YAML file
vi pod.yaml
# Change: image: nginx:1.26
# To:     image: nginx:1.27

# Delete the old Pod and create the new one
kubectl delete pod my-pod
kubectl apply -f pod.yaml

Method 2: kubectl replace –force

A quicker approach — deletes and recreates in one step:

# Get the Pod YAML, pipe to replace
kubectl get pod my-pod -o yaml | \
  sed 's|nginx:1.26|nginx:1.27|' | \
  kubectl replace --force -f -

Warning: --force deletes the Pod before recreating. There will be momentary downtime.

Method 3: kubectl edit (triggers recreate)

kubectl edit pod my-pod

If you change the image field, kubectl edit will attempt to apply the change. For Pods, Kubernetes will reject changes to most container fields (including image) on a running Pod. You’ll need to use the export-delete-recreate approach.

Note: Some fields on Pods can be edited in place (like metadata.labels, spec.activeDeadlineSeconds), but spec.containers[*].image is not one of them.

Updating Other Workload Types

StatefulSet

# Same syntax as Deployments
kubectl set image statefulset/db postgres=postgres:16.1

# StatefulSets update Pods in order (ordinal index)
kubectl rollout status statefulset/db

DaemonSet

kubectl set image daemonset/logging fluentd=fluentd:v1.17

kubectl rollout status daemonset/logging

CronJob / Job

Jobs and CronJobs are immutable once created. To update the image:

# For CronJobs: edit the template, new Jobs use the new image
kubectl edit cronjob my-backup
# Change the image in spec.jobTemplate.spec.template.spec.containers

# For existing Jobs: delete and recreate
kubectl delete job my-job
kubectl apply -f job.yaml

kubectl set image — Complete Reference

# Deployment
kubectl set image deployment/NAME CONTAINER=IMAGE

# StatefulSet
kubectl set image statefulset/NAME CONTAINER=IMAGE

# DaemonSet
kubectl set image daemonset/NAME CONTAINER=IMAGE

# ReplicaSet (rare — usually managed by Deployment)
kubectl set image replicaset/NAME CONTAINER=IMAGE

# Dry run — see what would change without applying
kubectl set image deployment/web app=nginx:1.27 --dry-run=client -o yaml

Practical Exam Scenarios

Scenario 1: Update a Deployment Image

# Task: Update deployment 'frontend' container 'web' to nginx:1.27
kubectl set image deployment/frontend web=nginx:1.27
kubectl rollout status deployment/frontend

Scenario 2: Roll Back a Failed Update

# Check current status
kubectl rollout status deployment/frontend
# → Waiting for deployment "frontend" rollout to finish: 1 old replicas pending

# Roll back
kubectl rollout undo deployment/frontend

# Verify
kubectl rollout status deployment/frontend

Scenario 3: Update a Pod Image

# Get the Pod YAML
kubectl get pod my-pod -o yaml > pod.yaml

# Edit the image
vi pod.yaml

# Recreate
kubectl delete pod my-pod
kubectl apply -f pod.yaml

# Verify
kubectl get pod my-pod -o wide
kubectl describe pod my-pod | grep "Image:"

Quick Reference

Task Command
Update Deployment image kubectl set image deployment/NAME CONTAINER=IMAGE
Watch rollout kubectl rollout status deployment/NAME
View rollout history kubectl rollout history deployment/NAME
Roll back kubectl rollout undo deployment/NAME
Roll back to revision kubectl rollout undo deployment/NAME --to-revision=N
Edit resource live kubectl edit deployment/NAME
Recreate Pod Export YAML → Edit → Delete → Apply

Updated: