Scale a Deployment Manually
Learn to scale a Kubernetes Deployment manually — practical step-by-step guide for controlling replica count, with tips on when to use manual scaling vs autoscaling.
Focus: scale a deployment manually
You've deployed your application to Kubernetes, and it's running — but now traffic spikes, and your single pod can't keep up. Without the ability to add or remove replicas on demand, your app becomes a bottleneck. Scaling a deployment manually is the fastest, most direct way to control how many pod replicas serve your traffic, and it's a skill you'll use constantly when managing production workloads.
The Problem This Lesson Solves
A Kubernetes Deployment guarantees a desired state — for example, "I want 3 replicas of my nginx server running." When that desired state is too low (or too high), your application suffers.
- Too few replicas → request timeouts, high latency, 503 errors.
- Too many replicas → wasted compute resources, unnecessary cloud costs.
Manual scaling gives you immediate control. No waiting for metrics to trigger autoscaling — you, the operator, decide the replica count right now. This is essential for: - Handling predictable traffic spikes (e.g., Black Friday, product launches). - Performing rolling updates with safety buffers. - Testing how your app behaves under different load levels.
But scaling isn't just about changing numbers — it's about understanding what changes, how it happens, and when to use it over other strategies.
Core Concept / Mental Model
Think of a Deployment as a host managing a flock of identical birds (your pods). Each bird does exactly the same job — handling requests equally.
- Manual scaling = you tell the host: "I need 5 birds right now. Not 4, not 6 — exactly 5."
- The host immediately sends out or recalls birds to hit that exact count.
Under the hood, the Deployment interacts with a ReplicaSet — the component responsible for creating and destroying pods. When you scale a Deployment, you update its replicas field. The Deployment controller then adjusts the ReplicaSet's desired size, which in turn creates or terminates pods.
Pro Tip: Manual scaling is declarative. You set the desired replica count, and Kubernetes converges toward that state. If a pod crashes, Kubernetes will recreate it to maintain the desired number — scaling is about the target count, not just the initial count.
Key Definitions
- ReplicaSet: An older API object (still used internally) that ensures a specific number of identical pods are running.
- Desired replicas: The value specified in
spec.replicasin the Deployment YAML. - Current replicas: The actual number of pods running at any moment.
How It Works Step by Step
When you scale a Deployment manually, Kubernetes performs a predictable sequence:
- You issue a scale command — either via
kubectl scale, by editing the YAML file, or through a dashboard. - The Deployment controller receives the update and checks the new
spec.replicasvalue. - The Deployment updates its underlying ReplicaSet to match the new desired count.
- The ReplicaSet controller calculates the difference between desired and current pod count:
- If desired > current → creates new pods using the pod template.
- If desired < current → terminates excess pods gracefully (with
terminationGracePeriodSeconds). - Pods are scheduled onto available nodes (or terminated).
- The Deployment status shows updated
readyReplicasandavailableReplicas.
The entire process takes seconds for stateless apps, but can take longer if container images need pulling or if resource limits prevent scheduling.
Blockquote Pro Tip: Scaling down (reducing replicas) terminates pods in no particular order by default. Use
pod-management-policy: OrderedReady(for StatefulSets) if you need ordered termination, but for Deployments, it's typically fine to let Kubernetes pick.
Hands-On Walkthrough
Let's practice manual scaling with a real nginx Deployment. We'll start without any YAML and use imperative commands, then move to declarative YAML.
Prerequisites
- A running Kubernetes cluster (minikube, kind, or cloud cluster).
-namespace created (we'll use
defaultfor simplicity).
Step 1: Create a Deployment (1 replica)
kubectl create deployment nginx-demo --image=nginx:alpine --replicas=1
kubectl get deployments
Expected output:
NAME READY UP-TO-DATE AVAILABLE AGE
nginx-demo 1/1 1 1 5s
Step 2: Scale up to 3 replicas
kubectl scale deployment nginx-demo --replicas=3
kubectl get pods
Expected output:
NAME READY STATUS RESTARTS AGE
nginx-demo-7f7c6c7b4c-abc12 1/1 Running 0 12s
nginx-demo-7f7c6c7b4c-def34 1/1 Running 0 3s
nginx-demo-7f7c6c7b4c-ghi56 1/1 Running 0 3s
Notice two new pods appeared within seconds.
Step 3: Scale down to 2 replicas
kubectl scale deployment nginx-demo --replicas=2
kubectl get pods
One pod disappears (terminated gracefully).
Step 4: Scaling via YAML (declarative)
Create a file deployment-scaled.yaml:
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-demo
spec:
replicas: 5
selector:
matchLabels:
app: nginx-demo
template:
metadata:
labels:
app: nginx-demo
spec:
containers:
- name: nginx
image: nginx:alpine
Apply the change:
kubectl apply -f deployment-scaled.yaml
kubectl get deployments nginx-demo
Expected output:
NAME READY UP-TO-DATE AVAILABLE AGE
nginx-demo 5/5 5 5 2m
Blockquote Pro Tip:
kubectl scaleis imperative and convenient, but for reproducibility, always version your YAML files and usekubectl applyto keep your cluster in sync with your source of truth.
Step 5: Verify with kubectl describe
kubectl describe deployment nginx-demo | grep -E "Replicas|ReplicaSet:"
Sample output:
Replicas: 5 desired | 5 updated | 5 total | 5 available | 0 unavailable
OldReplicaSets: <none>
NewReplicaSet: nginx-demo-7f7c6c7b4c (5/5 replicas created)
Compare Options / When to Choose What
| Approach | Command / Method | When to Use | Pros | Cons |
|---|---|---|---|---|
Imperative kubectl scale |
kubectl scale deploy/name --replicas=X |
Quick ad-hoc changes, testing | Fast, no file edits | Not idempotent, harder to audit |
| Declarative YAML edit & apply | kubectl edit deployment name or kubectl apply -f file.yaml |
Production changes, CI/CD pipelines | Reproducible, version-controlled | Slightly heavier workflow |
| Horizontal Pod Autoscaler (HPA) | kubectl autoscale deployment name --min=X --max=Y |
Dynamic traffic, variable load | Auto-scales, no manual intervention | Requires metrics server, more complex |
When to scale manually: - You know the exact load profile (e.g., scheduled batch jobs). - You're debugging and need deterministic replica count. - You want full control over cost vs. performance trade-offs.
When to use HPA: - Unpredictable traffic patterns. - You want to avoid under- or over-provisioning automatically. - You have metrics (CPU, memory, custom) available.
Troubleshooting & Edge Cases
Pods Not Scaling Up
- Symptom:
kubectl scalesucceeds, but pods stay at old count. - Root cause: Deployment name typo, or pod template has invalid image (always pull fails).
- Fix:
bash kubectl get events --sort-by='.lastTimestamp' kubectl describe deployment nginx-demoCheck forFailedCreate,ImagePullBackOfferrors.
Scaling Down but Pods Not Terminating
- Symptom:
kubectl get podsshows terminating state for too long. - Root cause: PodDisruptionBudget (PDB) preventing healthy quorum, or
preStophooks taking time. - Fix: Check PDB:
kubectl get pdb, or delete forcefully:kubectl delete pod <name> --grace-period=0 --force(use sparingly).
Wrong Replica Count Objected to by Cluster
- Symptom:
kubectl scalereturnsthe server rejected our request for an unknown reason. - Root cause: You're exceeding resource quota or node capacity.
- Fix:
bash kubectl describe quota kubectl top nodesAdd more nodes or reduce desired replicas.
Accidental Scale to Zero
- Symptom: All pods disappear — but you meant to scale down, not kill everything.
- Cure: Always double-check the number. Use
--dry-run=clientto preview:bash kubectl scale deployment nginx-demo --replicas=0 --dry-run=client
Blockquote Pro Tip: If you scale to zero, the Deployment still exists but has no running pods. To delete the Deployment entirely, use
kubectl delete deployment.
What You Learned & What's Next
You now understand how to scale a deployment manually using both imperative and declarative approaches, the underlying ReplicaSet mechanism, and when to choose manual scaling over autoscaling. You can confidently:
- Use kubectl scale for rapid adjustments.
- Update spec.replicas in YAML and apply it.
- Diagnose common scaling failures.
Next step: Manual scaling is great for quick changes, but what if you want your Deployment to survive node failures automatically? That's where self-healing and pod anti-affinity come in — your next lesson covers how Deployments stay healthy even when nodes go down. Continue to Node Failure & Pod Rescheduling.
Practice recap
Practice exercise: Create a Deployment with 2 replicas running nginx:alpine. Scale it to 4 using kubectl scale, then check that all 4 pods are running. Next, edit the YAML to reduce spec.replicas to 1 and apply the change — confirm only 1 pod remains. Finally, try scaling to 0 and back to 2, observing the pod lifecycle.
Common mistakes
- Using
kubectl scaleon a Deployment that is already managed by an HPA — the HPA will override your manual change within moments. - Forgetting that scaling down terminates pods gracefully; if your app has long-lived connections, clients may experience disconnection until readiness probes stabilize.
- Typing
kubectl scale deployment nginx-demo --replicas=0by accident — which kills all pods but keeps the Deployment intact. - Assuming scaling changes are immediate on nodes with limited resources — pods may remain pending until resources free up.
Variations
- Use
kubectl autoscaleto create an HPA that automatically adjusts replicas based on CPU usage, with commands likekubectl autoscale deployment nginx-demo --min=2 --max=10 --cpu-percent=50. - Edit the Deployment spec directly via
kubectl edit deployment nginx-demoand change thereplicasfield interactively. - Use a Helm chart with
--set replicaCount=Xto scale as part of a deploy pipeline declaratively.
Real-world use cases
- E-commerce site during Black Friday: operations manually scale a front-end Deployment from 20 to 150 replicas an hour before the sale starts.
- Batch job worker pool: an admin scales a worker Deployment to 0 after processing completes, then back to 20 for the next batch.
- Canary rollout: a team scales a new version Deployment to 1 replica, tests it, then scales to 50 while scaling the old version to 0.
Key takeaways
- Manual scaling changes the
spec.replicasfield, and the Deployment controller adjusts the ReplicaSet accordingly. - Use
kubectl scale deployment <name> --replicas=<n>for quick, imperative scaling; use YAML apply for version-controlled changes. - Scaling down terminates pods gracefully, respecting preStop hooks and terminationGracePeriodSeconds.
- Manual scaling gives immediate, deterministic control — ideal for predictable traffic or testing.
- Do not use manual scaling on Deployments controlled by an HPA, as they will fight for control.
- Always verify scaling outcomes with
kubectl get podsandkubectl describe deployment.
Keep learning
Related tutorials, quizzes, and articles for this topic.
Discussion
Questions, corrections, and tips help everyone reading this page.
0 comments
Add a comment
No comments yet — start the thread.