Deployment
🧠 Full Example: nginx-deployment.yaml¶
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment # Name of the Deployment
labels:
app: nginx
spec:
replicas: 3 # Number of Pod replicas you want to run
minReadySeconds: 10 # 👇 Even after Ready, wait at least 10 seconds after a Pod becomes Ready
# before marking it as "Available" — ensures stability
# The key is NOT present by-default
progressDeadlineSeconds: 600 # 👇 Kubernetes waits up to 10 minutes (600 sec)
# for the Deployment to make progress (Pods becoming Ready)
# If rollout takes longer, it’s marked as "Failed"
# The key is present by-default
revisionHistoryLimit: 10 # 👇 Keep the last 10 old ReplicaSets
# (so you can roll back if needed)
# Older ReplicaSets beyond this number are deleted automatically
# The key is present by-default
selector:
matchLabels:
app: nginx # 👇 Selects Pods with label "app=nginx"
# This MUST match the labels in the Pod template below
strategy: # 👇 Defines how updates (rolling updates) happen
type: RollingUpdate
rollingUpdate:
maxUnavailable: 1 # 👇 During update, at most 1 Pod can be unavailable
maxSurge: 1 # 👇 During update, at most 1 extra Pod can be created (above desired count)
template: # 👇 Template for Pods that will be created
metadata:
labels:
app: nginx # 👇 Must match the selector above
spec:
containers:
- name: nginx
image: nginx:latest # 👇 Container image to run
ports:
- containerPort: 80 # 👇 Exposes port 80 in each Pod
readinessProbe: # 👇 Optional: ensures Pod is fully ready before traffic
httpGet:
path: /
port: 80
initialDelaySeconds: 5
periodSeconds: 5
💡 How These Fields Work Together During a Rollout¶
Let’s walk through this step-by-step:
-
Deployment starts an update K8s begins replacing old Pods with new ones.
-
progressDeadlineSecondstimer starts K8s expects new Pods to become Ready within this deadline (e.g., 600s). If they don’t → rollout is marked as Failed. -
Each new Pod becomes Ready The Pod passes its readiness probe (if defined).
-
minReadySecondsapplies Even after Ready, K8s waits 10 more seconds before counting it as Available — to confirm stability. -
Old ReplicaSets are trimmed Once rollout is complete, K8s keeps only the last
revisionHistoryLimit(5 here). The 6th oldest version is deleted to save cluster resources.
⚙️ TL;DR (Quick Summary)¶
| Field | Function | Default | Why You Might Change It |
|---|---|---|---|
minReadySeconds | Ensures Pods stay stable for a few seconds before marking them as available | 0 | Add delay to catch flaky Pods |
progressDeadlineSeconds | Time before rollout is considered failed | 600 (10 min) | Increase if Pods take longer to initialize |
revisionHistoryLimit | How many old ReplicaSets (versions) to keep | 10 | Lower to save resources, or raise for safer rollback |
Perfect ❤️ Sweetheart Ibtisam — here you go: Below are the full answers, YAML snippets, and clear reasoning for every advanced Deployment question. Each one is explained like an instructor would do in a real CKA prep lab — so you’ll never again be confused by tricky English wording. 🧠✨
🧩 Q1 — Hidden Timeout¶
Make Kubernetes mark rollout as failed if not completed within 12 minutes.
✅ Answer:
spec:
progressDeadlineSeconds: 720
🧠 Reasoning: 12 minutes × 60 = 720 seconds. This sets the maximum time Kubernetes waits for rollout progress before showing ProgressDeadlineExceeded.
🧩 Q2 — Instant Traffic Problem¶
Pods get traffic too quickly; must stay stable for 25 seconds before “Available.”
✅ Answer:
spec:
minReadySeconds: 25
🧠 Reasoning: minReadySeconds enforces that after a Pod becomes Ready, Kubernetes waits 25 seconds before considering it “Available.” This prevents traffic from hitting unstable Pods.
🧩 Q3 — Rollback Policy¶
Keep only the last 4 old versions for rollback.
✅ Answer:
spec:
revisionHistoryLimit: 4
🧠 Reasoning: Kubernetes stores old ReplicaSets for rollback. This setting keeps only the last 4, deleting older ones automatically.
🧩 Q4 — Aggressive Rollout¶
Allow 2 Pods unavailable, 1 extra Pod during rollout.
✅ Answer:
spec:
strategy:
type: RollingUpdate
rollingUpdate:
maxUnavailable: 2
maxSurge: 1
🧠 Reasoning:
maxUnavailable: 2→ Up to 2 Pods can go down during update.maxSurge: 1→ Only 1 additional Pod (beyond desired replicas) may be created.
🧩 Q5 — Time Calculation Trap¶
progressDeadlineSeconds: 600
minReadySeconds: 15
Pods take 5 min to become Ready + 20 sec stable.
✅ Answer: The rollout will succeed, because:
- Total = 5 min 20 sec = 320 sec < 600 sec.
- Rollout completes before hitting the progress deadline.
🧠 Reasoning: progressDeadlineSeconds measures total time since rollout start. As long as total progress < 600 seconds, it succeeds.
🧩 Q6 — Clean History¶
Keep no previous versions (delete all old ReplicaSets).
✅ Answer:
spec:
revisionHistoryLimit: 0
🧠 Reasoning: Setting it to 0 means Kubernetes will not retain any previous ReplicaSets — you lose rollback capability but save resources.
🧩 Q7 — Confusing Wording¶
“Become Available only after Pods stay Ready for a while; fail rollout if not achieved in 10 minutes.”
✅ Answer:
spec:
minReadySeconds: <some delay> # e.g. 10 or 20 seconds
progressDeadlineSeconds: 600
🧠 Reasoning: Two controls are needed:
minReadySeconds→ delay before marking available,progressDeadlineSeconds→ timeout if rollout not finished in 10 minutes.
🧩 Q8 — RollingUpdate Mix¶
Must follow all four conditions (availability, surge, stability, rollout timeout).
✅ Answer:
spec:
minReadySeconds: 10
progressDeadlineSeconds: 480
strategy:
type: RollingUpdate
rollingUpdate:
maxUnavailable: 1
maxSurge: 2
🧠 Reasoning: This combines all behaviors:
minReadySeconds= stability delay,progressDeadlineSeconds= fail after 8 min (480 sec),maxUnavailable+maxSurge= control update speed.
🧩 Q9 — Behavior Understanding¶
revisionHistoryLimit: 0and 5 rollouts later, what happens?
✅ Answer: You’ll only see the active ReplicaSet — all previous ones are deleted.
kubectl get rs
Will show just 1 ReplicaSet (the current one).
🧠 Reasoning: With 0, Kubernetes deletes all old ReplicaSets immediately after new ones are created — no rollback history.
🧩 Q10 — Real-World Scenario¶
Extend rollout timeout to 20 min; Pods stable for 10 sec before available.
✅ Answer:
spec:
minReadySeconds: 10
progressDeadlineSeconds: 1200
🧠 Reasoning: 20 min × 60 = 1200 seconds. You’re combining rollout timeout (progressDeadlineSeconds) and Pod stability delay (minReadySeconds).
💡 Quick Summary Table (for Flash Memory)¶
| Field | Controls | Example | Exam Clue Phrase |
|---|---|---|---|
minReadySeconds | Delay before marking Pod available | minReadySeconds: 10 | “Wait before Pod becomes available” |
progressDeadlineSeconds | Max rollout time | progressDeadlineSeconds: 600 | “Fail rollout if no progress” |
revisionHistoryLimit | Number of old ReplicaSets to keep | revisionHistoryLimit: 5 | “Keep last X versions” |
maxUnavailable | Pods that can go down during update | maxUnavailable: 1 | “At most 1 Pod unavailable” |
maxSurge | Extra Pods during update | maxSurge: 2 | “Allow 2 extra Pods during rollout” |
❤️ Bonus: Mental Shortcuts for the Exam¶
| Question Type | Your Brain Should Think Instantly |
|---|---|
| “wait before available” | → minReadySeconds |
| “timeout before fail” | → progressDeadlineSeconds |
| “rollback versions / old ReplicaSets” | → revisionHistoryLimit |
| “faster or safer rollout” | → strategy.rollingUpdate |
| “delete all old versions” | → revisionHistoryLimit: 0 |
Excellent observation, sweetheart 💡 You’ve hit on a subtle detail about --record and the CHANGE-CAUSE field in rollout history.
🔎 Why you see <none> in CHANGE-CAUSE¶
k rollout history deployment abc
deployment.apps/abc
REVISION CHANGE-CAUSE
1 <none>
2 <none>
- By default, Kubernetes doesn’t log why a change happened.
- The
CHANGE-CAUSEcolumn is filled only if you explicitly add the annotationkubernetes.io/change-cause. kubectlused to support--recordfor this, but the flag is now deprecated.
✅ Current best practice¶
Instead of --record, you should use:
kubectl annotate deployment abc kubernetes.io/change-cause="Updated to nginx:1.29.1"
Then check:
kubectl rollout history deployment abc
You’ll see:
REVISION CHANGE-CAUSE
1 <none>
2 Updated to nginx:1.29.1
🕐 When should you use it (with respect to a Deployment)?¶
You add a change-cause when you want human-readable documentation of why you updated a Deployment. For example:
- When you create the Deployment:
kubectl create deployment abc --image=nginx \
--record # (old way)
or:
kubectl annotate deployment abc kubernetes.io/change-cause="Initial deployment with nginx:latest"
- When you update the image:
kubectl set image deploy abc nginx=nginx:1.29.1 \
--record # (old way)
or:
kubectl annotate deployment abc kubernetes.io/change-cause="Upgraded to nginx:1.29.1"
⚠️ Key point¶
--recordis deprecated, but you can still use it in CKA exam labs (it will work).- In production or modern clusters, use:
kubectl annotate deployment <name> kubernetes.io/change-cause="Your message"
👉 So, to answer you directly:
- Yes, without
--recordor manual annotation,CHANGE-CAUSEwill always be<none>. - You should use it at creation or update time to track the reason for changes.
Exactly ❤️ you’ve just confirmed it yourself — the --record flag has been removed from kubectl in newer Kubernetes versions.
🔎 What happened¶
- In older versions (≤1.18),
--recordwas valid and would automatically add the annotationkubernetes.io/change-cause. - In newer versions (>=1.19+), it was first deprecated, and in your cluster it looks like it’s been completely removed. That’s why you see:
error: unknown flag: --record
✅ Modern replacement¶
Now, if you want to track why a change happened, you need to manually add an annotation with kubectl annotate.
For example:
kubectl create deployment abc2 --image=nginx
kubectl annotate deployment abc2 kubernetes.io/change-cause="Initial deployment with nginx"
If you update later:
kubectl set image deployment abc2 nginx=nginx:1.29.1
kubectl annotate deployment abc2 kubernetes.io/change-cause="Upgraded to nginx:1.29.1"
Then:
kubectl rollout history deployment abc2
Will show:
REVISION CHANGE-CAUSE
1 Initial deployment with nginx
2 Upgraded to nginx:1.29.1
🕐 When to add change-cause¶
- When you create a Deployment → to document the initial purpose.
- When you update it (image, replicas, etc.) → to document why the change was made.
- This helps a lot during rollbacks because you can pick the right revision by reading the
CHANGE-CAUSE.
⚡ So the takeaway: 👉 --record is gone in modern clusters. 👉 Use kubectl annotate … kubernetes.io/change-cause="..." instead.
controlplane ~ ➜ k create deploy abc --image nginx -r 3
deployment.apps/abc created
controlplane ~ ➜ k set image deploy abc nginx=nginx:1.29.1
deployment.apps/abc image updated
controlplane ~ ➜ k rollout status deployment abc
deployment "abc" successfully rolled out
controlplane ~ ➜ k rollout history deployment abc
deployment.apps/abc
REVISION CHANGE-CAUSE
1 <none>
2 <none>
controlplane ~ ➜ k set image deploy abc nginx=nginx:1.29.1 --revision
error: unknown flag: --revision
See 'kubectl set image --help' for usage.
controlplane ~ ✖ k set image deploy abc nginx=nginx:1.29.1 --record
Flag --record has been deprecated, --record will be removed in the future
deployment.apps/abc image updated
controlplane ~ ➜ k rollout history deployment abc
deployment.apps/abc
REVISION CHANGE-CAUSE
1 <none>
2 kubectl set image deploy abc nginx=nginx:1.29.1 --record=true
controlplane ~ ➜ kubectl annotate deployment abc kubernetes.io/change-cause="Upgraded to nginx:1.29.1"
deployment.apps/abc annotated
controlplane ~ ➜ k rollout history deployment abc
deployment.apps/abc
REVISION CHANGE-CAUSE
1 <none>
2 Upgraded to nginx:1.29.1
controlplane ~ ➜ k set image deploy abc nginx=nginx:1.29.0 --record
Flag --record has been deprecated, --record will be removed in the future
deployment.apps/abc image updated
controlplane ~ ➜ k rollout undo deployment abc --to-revision ^C
controlplane ~ ✖ k rollout history deployment abc
deployment.apps/abc
REVISION CHANGE-CAUSE
1 <none>
2 Upgraded to nginx:1.29.1
3 kubectl set image deploy abc nginx=nginx:1.29.0 --record=true
controlplane ~ ➜ k rollout undo deployment abc --to-revision=2
deployment.apps/abc rolled back
controlplane ~ ➜ k rollout history deployment abc
deployment.apps/abc
REVISION CHANGE-CAUSE
1 <none>
3 kubectl set image deploy abc nginx=nginx:1.29.0 --record=true
4 Upgraded to nginx:1.29.1
controlplane ~ ➜ k describe deploy abc | grep -i image
Image: nginx:1.29.1
controlplane ~ ➜ k create deploy abc2 --image nginx --record
error: unknown flag: --record
See 'kubectl create deployment --help' for usage.
controlplane ~ ✖