Sidharth R
  • Home
  • Posts
  • Journal
  • Home
  • Posts
  • Journal
  • Search
Posts

CKA Prep: Creating And Manually Scaling A Deployment

Updated: 29 Aug 2026

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) and node01 (172.16.8.6), both Ready, 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.

Create the namespace
controlplane:~$ kubectl create namespace pluto
namespace/pluto created

Creating 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.

Create the Deployment in pluto
controlplane:~$ k create deploy --image=nginx:1.17.0 --replicas=2 -n pluto nginx
deployment.apps/nginx created

Created is not available

This is the part that’s easy to miss. The Deployment existed immediately, but the Pods behind it were still starting.

Polling the Deployment
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           81s

UP-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:

Deployment conditions during rollout
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 2

The 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.

Rollout complete
controlplane:~$ k get deploy -n pluto
NAME    READY   UP-TO-DATE   AVAILABLE   AGE
nginx   2/2     2            2           8m28s

Scaling 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.

Scale to seven replicas
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           10m

Full 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:

Both scale events on one ReplicaSet
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 7

Scaling 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.

All seven Pods Running
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          2m5s

There 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

  1. kubectl scale resolves against your current namespace, not the last one you typed. If you create the Deployment in pluto but forget -n pluto when scaling it, you’ll get an error like this:
Namespace-scoped resource, unscoped command
controlplane:~$ k scale --replicas=7 deploy/nginx
error: no objects passed to scale deployments.apps "nginx" not found

The 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.

  1. deploy/nginx and deploy nginx are interchangeable, but the flag isn’t. k scale --replicas=7 deploy/nginx -n pluto and k scale deploy nginx --replicas=7 -n pluto both 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:

  1. Polled get deploy and ran describe during the pull window rather than treating deployment.apps/nginx created as 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 the Available=False / Progressing=True state.
  2. 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.0

Step two, declaratively:

Diff
--- 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.

Further reading

  • Deployments
  • kubectl scale
  • kubectl create deployment
  • kubectl quick reference
Tags: kubernetes kubectl deployments scaling cka … views

Keep reading

  • Deployments in Kubernetes
  • The Kubernetes Pod That Refused to Die
  • Kubernetes DaemonSets
  • Kubernetes Resource Limits

  • Home
  • Posts
  • Journal
  • Quotes
  • Links worth your time
  • About
  • Contact
  • Style guide
  • RSS

© 2026 Sidharth R. · Licensed CC BY-NC-SA 4.0