ReplicaSets
A ReplicaSet keeps a fixed number of identical Pods running. In practice you almost never write one directly — you create a Deployment, which creates and rolls a ReplicaSet for you. Knowing how ReplicaSets work explains why rolling updates and rollbacks behave the way they do.
Manifest, owner refs, rolling updates
EXAMPLE
# 1) A ReplicaSet on its own (rare in real apps)
apiVersion: apps/v1
kind: ReplicaSet
metadata:
name: web
labels:
app: web
spec:
replicas: 3
selector:
matchLabels:
app: web
template:
metadata:
labels:
app: web
spec:
containers:
- name: web
image: nginx:1.27-alpine
ports:
- containerPort: 80
resources:
requests: { cpu: 50m, memory: 64Mi }
limits: { cpu: 200m, memory: 128Mi }
# selector.matchLabels MUST match template.metadata.labels.
# The ReplicaSet adopts any pod with those labels — and will DELETE
# excess pods if there are more than .spec.replicas.
# 2) In real life — let Deployment manage the ReplicaSet
apiVersion: apps/v1
kind: Deployment
metadata:
name: web
spec:
replicas: 3
selector:
matchLabels:
app: web
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1 # at most 1 extra pod during the roll
maxUnavailable: 0 # never drop below 'replicas' during the roll
template:
metadata:
labels:
app: web
spec:
containers:
- name: web
image: nginx:1.27-alpine
readinessProbe:
httpGet:
path: /
port: 80
initialDelaySeconds: 2
periodSeconds: 5
# 3) What kubectl shows
kubectl get deploy,rs,pods -l app=web
# deploy.apps/web 3/3 …
# replicaset.apps/web-7c8… 3 3 3 …
# pod/web-7c8…-abc12 1/1 Running
#
# Note: each Deployment update produces a NEW ReplicaSet.
# Old ReplicaSets stick around (scaled to 0) so you can rollback.
# 4) Rolling update — change image, watch new RS roll in
kubectl set image deploy/web web=nginx:1.27.1-alpine --record
kubectl rollout status deploy/web
kubectl rollout history deploy/web
kubectl rollout undo deploy/web # back to previous revision
kubectl rollout undo deploy/web --to-revision=3
# Behind the scenes:
# • Deployment creates a new ReplicaSet with the updated template
# • Scales new RS up by maxSurge, scales old RS down by maxUnavailable
# • Repeats until new RS == replicas, old RS == 0
# • All gated by readinessProbe — a pod is 'ready' only when its probe passes
# 5) Scale up or down
kubectl scale deploy/web --replicas=10
# The Deployment updates the active RS's .spec.replicas.
# Horizontal Pod Autoscaler — scale on metrics
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: web
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: web
minReplicas: 3
maxReplicas: 30
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 60
- type: Resource
resource:
name: memory
target:
type: Utilization
averageUtilization: 75
# 6) Owner references — how garbage collection works
kubectl get pod web-7c8…-abc12 -o jsonpath='{.metadata.ownerReferences}'
# Each pod's owner is the ReplicaSet. Delete the RS → pods deleted.
# Each RS's owner is the Deployment. Delete the Deployment → cascade kills all.
# kubectl delete deploy/web --cascade=orphan # rare: keep RS + pods
# 7) Selector trap — DO NOT change selector after creation
# If you edit selector to match different labels, the old pods become orphaned
# (not managed) and the RS may launch new pods. This was a footgun;
# Kubernetes now rejects most selector changes on Deployments to prevent it.
# 8) Pod template changes vs RS regeneration
# • Editing spec.template (image, env, resources) → new ReplicaSet
# • Editing spec.replicas only → same ReplicaSet, just scaled
# • Editing spec.strategy → next rollout uses the new strategy
# 9) revisionHistoryLimit — how many old ReplicaSets to keep for rollback
apiVersion: apps/v1
kind: Deployment
spec:
revisionHistoryLimit: 10 # default; lower for noisy CD pipelines
# 10) Debug a stuck rollout
kubectl rollout status deploy/web --timeout=2m
kubectl describe deploy/web # events at the bottom — readiness failures, image pull errors
kubectl get rs -l app=web -o wide # which RS has DESIRED != READY
kubectl describe pod web-7c8…-abc12 # individual pod events
kubectl logs -l app=web --tail=200 --max-log-requests=10
kubectl get events --sort-by=.lastTimestamp | tail -30
# 11) StatefulSet vs ReplicaSet
# ReplicaSet/Deployment — stateless, interchangeable pods, network identity ephemeral
# StatefulSet — ordered, named pods (web-0, web-1), stable storage
# For DBs, queues, anything with per-pod identity.
# 12) Common bugs
# • selector doesn't match template labels → 'invalid: selector does not match template labels'
# • Missing readinessProbe → rollout completes 'successfully' but pods can't serve traffic
# • maxUnavailable: 50% + replicas: 2 → outage during deploy; tune for small replicas
# • Image tag :latest → pod restart pulls a NEW build silently; pin tags or use digests
# • Forgetting resources.requests → unschedulable on heavily-packed nodes
Why it matters
ReplicaSets are the layer the Deployment controller drives, not something you usually create yourself. Treat the Deployment as the API you operate against — pin image tags, set a real readiness probe, and use maxUnavailable: 0 for small replica counts where 50% downtime during a rollout is unacceptable.
Tip: Tweak the snippet with Try it Yourself », then sit the quiz at the bottom of the page.
Discussion
Loading…