How Does Deployment Revision History Work in Kubernetes?

intermediate|deploymentsdevopssreCKACKAD
TL;DR

Every change to a Deployment's Pod template creates a new revision backed by a ReplicaSet. Kubernetes retains old ReplicaSets (controlled by revisionHistoryLimit) so you can inspect previous versions and roll back to them.

Detailed Answer

Every time you change the Pod template of a Deployment, Kubernetes creates a new revision. This revision system is what makes rollbacks possible -- and understanding it is essential for operating Deployments in production.

How Revisions Are Created

A new revision is created when anything in .spec.template changes:

  • Container image
  • Environment variables
  • Resource requests or limits
  • Volume mounts
  • Labels on the Pod template

Changes outside .spec.template (like replicas, strategy, or revisionHistoryLimit) do not create new revisions.

Viewing Revision History

# List all revisions
kubectl rollout history deployment/web-app

Output:

REVISION  CHANGE-CAUSE
1         Initial deployment
2         Update to v1.1
3         Update to v1.2 with memory fix
4         Update to v2.0

To inspect a specific revision:

kubectl rollout history deployment/web-app --revision=2

Output:

deployment.apps/web-app with revision #2
Pod Template:
  Labels:       app=web-app
                pod-template-hash=6b9d5c7f8
  Annotations:  kubernetes.io/change-cause: Update to v1.1
  Containers:
   web-app:
    Image:      web-app:1.1
    Port:       8080/TCP
    Limits:
      cpu:      500m
      memory:   256Mi
    Requests:
      cpu:      100m
      memory:   128Mi

The Relationship Between Revisions and ReplicaSets

Each revision maps directly to a ReplicaSet:

kubectl get replicasets -l app=web-app

Output:

NAME                  DESIRED   CURRENT   READY   AGE
web-app-5d7b9f6c4     0         0         0       4d    # revision 1
web-app-6b9d5c7f8     0         0         0       3d    # revision 2
web-app-7c8e6d9a1     0         0         0       2d    # revision 3
web-app-8d9f7e0b2     3         3         3       1d    # revision 4 (current)

Old ReplicaSets are scaled to 0 replicas. Only the current revision has active Pods.

Configuring revisionHistoryLimit

apiVersion: apps/v1
kind: Deployment
metadata:
  name: web-app
spec:
  revisionHistoryLimit: 5
  replicas: 3
  selector:
    matchLabels:
      app: web-app
  template:
    metadata:
      labels:
        app: web-app
    spec:
      containers:
        - name: web-app
          image: web-app:2.0
          ports:
            - containerPort: 8080

With revisionHistoryLimit: 5, Kubernetes keeps the 5 most recent old ReplicaSets. When a 6th old ReplicaSet is created, the oldest one is garbage-collected.

What Happens with revisionHistoryLimit: 0

spec:
  revisionHistoryLimit: 0

All old ReplicaSets are deleted immediately after a new revision is created. This means:

  • You cannot use kubectl rollout undo.
  • You cannot inspect previous revision details.
  • The only way to revert is to re-apply a previous manifest from source control.

This is almost never recommended for production workloads.

Adding Change-Cause Annotations

The CHANGE-CAUSE column in rollout history is populated from an annotation:

# Set change-cause when deploying
kubectl apply -f deployment.yaml
kubectl annotate deployment/web-app \
  kubernetes.io/change-cause="Deploy v2.0 with new auth module" --overwrite

Or include it directly in the manifest:

metadata:
  name: web-app
  annotations:
    kubernetes.io/change-cause: "Deploy v2.0 with new auth module"

Best practice is to update this annotation in your CI/CD pipeline with the commit hash or release tag:

kubectl annotate deployment/web-app \
  kubernetes.io/change-cause="Release ${GIT_TAG} (${GIT_SHA:0:8})" --overwrite

Revision Numbers After Rollback

Revision numbering can be confusing after rollbacks. Consider this sequence:

REVISION  CHANGE-CAUSE
1         Deploy v1.0
2         Deploy v1.1
3         Deploy v2.0

After running kubectl rollout undo --to-revision=1:

REVISION  CHANGE-CAUSE
2         Deploy v1.1
3         Deploy v2.0
4         Deploy v1.0 (rollback from revision 1)

Revision 1 is gone. Its Pod template was moved to revision 4. The revision number always increments -- it never reuses old numbers.

Practical Implications for CI/CD

  1. Set revisionHistoryLimit to match your rollback needs. If you never roll back more than 3 versions, revisionHistoryLimit: 5 gives you some buffer.

  2. Always annotate change-cause in your pipeline. Without it, rollout history shows <none> and becomes useless for debugging.

  3. Keep manifests in Git. Revision history is useful for quick rollbacks, but your source of truth should always be version control.

  4. Monitor old ReplicaSets in large clusters. Thousands of Deployments with high revisionHistoryLimit values create many ReplicaSet objects in etcd.

# Count total ReplicaSets in a namespace
kubectl get replicasets -n production --no-headers | wc -l

Summary

Kubernetes Deployment revision history is powered by retained ReplicaSets. Each Pod template change creates a new revision, and revisionHistoryLimit controls how many are kept. This system enables instant rollbacks and provides an audit trail of changes. Always annotate your deployments with change-cause information and set a reasonable revisionHistoryLimit to balance rollback flexibility with cluster resource usage.

Why Interviewers Ask This

Understanding revision history shows that you know how Kubernetes tracks changes under the hood and can effectively troubleshoot or revert production issues.

Common Follow-Up Questions

What is the default value of revisionHistoryLimit?
The default is 10. Kubernetes retains up to 10 old ReplicaSets for each Deployment.
Do old ReplicaSets consume resources?
Old ReplicaSets are scaled to 0 replicas, so they do not consume compute resources. However, they are API objects stored in etcd, so very large numbers can affect cluster performance.
What happens to revision numbers after a rollback?
The rolled-back revision is moved to a new revision number. The original revision number disappears from history because Kubernetes reuses the ReplicaSet.

Key Takeaways

  • Each Deployment revision maps to a ReplicaSet with 0 replicas.
  • revisionHistoryLimit controls how many old ReplicaSets are kept.
  • Setting revisionHistoryLimit to 0 disables rollback capability entirely.

Related Questions