A Deployment can be created in an instant, but that doesn’t mean it’s ready to use. In this lab, the Deployment still showed 0/2 available 81 seconds after creation. Nothing was broken. The worker node was simply pulling the image for the first time. If you treat the created message as confirmation that everything is ready and move on, you can end up debugging a problem that doesn’t actually exist.
This is a two-step lab: you’ll create a Deployment and then scale it.
This lab was tested on O’Reilly Interactive Labs with Kubernetes v1.32.8 in August 2026.
Environment
Captured 2026-08-29 17:00 UTC.
- OS: Ubuntu 24.04.3 LTS, kernel 6.8.0-137-generic, x86_64
- Cluster: kubeadm-style, two nodes —
controlplane(172.16.8.5) andnode01(172.16.8.6), bothReady, both v1.32.8 - kubectl / server: v1.32.8 / v1.32.8
- Container runtime: containerd 1.7.27 (
containerd://1.7.27), crictl v1.32.0, Docker 28.3.3 client and server - User: root, passwordless sudo, working directory
/root - Host resources: 95 CPUs, 251 GiB RAM, 3.5 TB overlay filesystem
- Other tooling: git 2.43.0, python3 3.12.3, go, node v18.19.1, jq 1.7, curl 8.5.0
Throughout the lab, k is the usual alias k=kubectl.
Setting up the namespace
The lab asks for the Deployment in a namespace called pluto, so that comes first.
controlplane:~$ kubectl create namespace pluto
namespace/pluto createdCreating the Deployment
The task wants two replicas. kubectl create deployment accepts --replicas directly, so this is one command rather than a create followed by a scale. Worth noting this for the exam, where every avoided command is a few seconds gained.
controlplane:~$ k create deploy --image=nginx:1.17.0 --replicas=2 -n pluto nginx
deployment.apps/nginx createdCreated is not available
This is the part that’s easy to miss. The Deployment existed immediately, but the Pods behind it were still starting.
controlplane:~$ k get deploy -n pluto
NAME READY UP-TO-DATE AVAILABLE AGE
nginx 0/2 2 0 9s
controlplane:~$ k get deploy -n pluto
NAME READY UP-TO-DATE AVAILABLE AGE
nginx 0/2 2 0 25s
controlplane:~$ k get deploy -n pluto
NAME READY UP-TO-DATE AVAILABLE AGE
nginx 0/2 2 0 81sUP-TO-DATE 2 with AVAILABLE 0 is the signature of a Deployment whose ReplicaSet has done its job while the kubelet is still fetching bytes. describe says so explicitly:
controlplane:~$ k describe deploy nginx -n pluto
Name: nginx
Namespace: pluto
Replicas: 2 desired | 2 updated | 2 total | 0 available | 2 unavailable
Conditions:
Type Status Reason
---- ------ ------
Available False MinimumReplicasUnavailable
Progressing True ReplicaSetUpdated
NewReplicaSet: nginx-cbcb6bc64 (2/2 replicas created)
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal ScalingReplicaSet 44s deployment-controller Scaled up replica set nginx-cbcb6bc64 from 0 to 2The useful signal here is Progressing=True with Available=False. It means the rollout is still moving forward, so give it time. If Progressing becomes False, that’s when you should start investigating.
I left it alone for about eight minutes and checked again. This time, the Deployment was ready.
controlplane:~$ k get deploy -n pluto
NAME READY UP-TO-DATE AVAILABLE AGE
nginx 2/2 2 2 8m28sScaling to seven
Now that the image is cached, the second half of the lab is much faster. That difference is exactly what makes the comparison useful.
controlplane:~$ k scale deploy/nginx --replicas=7 -n pluto
deployment.apps/nginx scaled
controlplane:~$ k get deploy nginx -n pluto
NAME READY UP-TO-DATE AVAILABLE AGE
nginx 7/7 7 7 10mFull seven, available, within about a minute of the scale command. The event log shows both scale-ups against the same ReplicaSet — no new ReplicaSet, because the Pod template never changed:
controlplane:~$ k describe deploy nginx -n pluto
Replicas: 7 desired | 7 updated | 7 total | 7 available | 0 unavailable
Conditions:
Type Status Reason
---- ------ ------
Progressing True NewReplicaSetAvailable
Available True MinimumReplicasAvailable
NewReplicaSet: nginx-cbcb6bc64 (7/7 replicas created)
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal ScalingReplicaSet 11m deployment-controller Scaled up replica set nginx-cbcb6bc64 from 0 to 2
Normal ScalingReplicaSet 23s deployment-controller Scaled up replica set nginx-cbcb6bc64 from 2 to 7Scaling is a ReplicaSet-size change, not a rollout. Editing the image would have produced a second ReplicaSet and a revision: 2 annotation.
Confirming the Pods
The Deployment tells you that seven replicas are available, but it’s worth checking the Pods themselves. That confirms the containers are actually running and healthy.
controlplane:~$ k get po -n pluto
NAME READY STATUS RESTARTS AGE
nginx-cbcb6bc64-4zqm2 1/1 Running 0 27s
nginx-cbcb6bc64-6qqlw 1/1 Running 0 27s
nginx-cbcb6bc64-84lmb 1/1 Running 0 27s
nginx-cbcb6bc64-8tvtz 1/1 Running 0 27s
nginx-cbcb6bc64-dt5zs 1/1 Running 0 2m5s
nginx-cbcb6bc64-stsnd 1/1 Running 0 27s
nginx-cbcb6bc64-tl2cj 1/1 Running 0 2m5sThere are three things worth noticing here. First, every Pod is 1/1 Running with zero restarts, so the scale-up didn’t cause any downtime.
Next, the Pod ages fall into two groups: five Pods were created when we scaled up, while the other two were already running.
Finally, all the Pods have the same ReplicaSet hash cbcb6bc64. That’s because the hash comes from the Pod template. If you rebuild the same template, Kubernetes generates the same ReplicaSet name.
Gotchas
kubectl scaleresolves against your current namespace, not the last one you typed. If you create the Deployment inplutobut forget-n plutowhen scaling it, you’ll get an error like this:
controlplane:~$ k scale --replicas=7 deploy/nginx
error: no objects passed to scale deployments.apps "nginx" not foundThe confusing part is that the error mentions the Deployment but not the missing namespace. You might think the Deployment is gone when the real problem is simply that kubectl is looking in the wrong namespace.
In CKA environment, it’s better to use kubectl config set-context --current --namespace=pluto once at the start to avoid this whole class of mistakes.
deploy/nginxanddeploy nginxare interchangeable, but the flag isn’t.k scale --replicas=7 deploy/nginx -n plutoandk scale deploy nginx --replicas=7 -n plutoboth work. The failure mode above is about scope, not syntax.
Going beyond the guided scenario
There are two places where it’s worth going beyond the guided steps:
- Polled
get deployand randescribeduring the pull window rather than treatingdeployment.apps/nginx createdas success. This gives you a better picture of what’s actually happening during the rollout. The lab moves straight from create to scale and never surfaces theAvailable=False / Progressing=Truestate. - Compared the two operations. The lab treats creation and scaling as separate exercises, but looking at them together reveals something useful. The first took more than 81 seconds with a cold image, while the second took less than 27 seconds with the image already cached. Both happened on the same ReplicaSet, which makes the difference much easier to understand.
For reference, here’s the declarative version. In this lab, you’ll only change the replicas field on line 7:
nginx-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx
namespace: pluto
spec:
replicas: 2
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.17.0Step two, declaratively:
--- nginx-deployment.yaml
+++ nginx-deployment.yaml
@@ -4,7 +4,7 @@
name: nginx
namespace: pluto
spec:
- replicas: 2
+ replicas: 7
selector:
matchLabels:
app: nginx
What you can do differently
Instead of checking the rollout manually, you can watch it happen with kubectl get po -n pluto -w. You’ll see each Pod move from ContainerCreating to Running, and you’ll get an exact time for when each Pod becomes ready instead of the eight-minute uncertainty above.
For Deployments, kubectl rollout status deploy/nginx -n pluto is even simpler. It waits for the Deployment to become available, so this is the command you’ll want to reach for when you need to check whether a rollout has finished.