Frontend Labs
⋯

Chapter 58 — Scheduling and scaling

In one sentence

The scheduler decides which node a new pod runs on (based on available resources and constraints you can specify), and autoscaling — both of pods (more replicas) and of nodes (more machines) — is how a cluster responds to changing real demand without a human manually intervening every time.

Why this matters

Understanding scheduling explains why a pod sometimes stays stuck Pending, and autoscaling is the concrete, practical payoff of everything this Part has built toward: a system that genuinely handles real, unpredictable load on its own.

How it actually works

   # resource REQUESTS and LIMITS -- the scheduler's primary inputs
   resources:
     requests:                # "I need AT LEAST this much" -- the
       cpu: "250m"              # SCHEDULER uses this to decide which
       memory: "256Mi"           # node has room
     limits:                   # "never let me use MORE than this" --
       cpu: "500m"                # enforced by the KERNEL via cgroups
       memory: "512Mi"             # (Chapter 43!) -- exceed the memory
                                 # limit and the OOM killer (Chapter 13)
                                 # acts, scoped to this pod's cgroup,
                                 # exactly as Chapter 44 described
   THE SCHEDULER'S JOB, each time a new pod needs a node: look at every
   node's AVAILABLE capacity (total minus what's already requested by
   other pods there), filter out nodes that don't meet any
   CONSTRAINTS (taints/tolerations, node selectors, affinity rules --
   ways to say "only run on nodes with this label" or "never run two of
   these on the same node"), and pick a node from what's left (using a
   scoring algorithm to balance the cluster reasonably).

   IF NO NODE HAS ENOUGH ROOM: the pod stays in `Pending` state
   (Chapter 59 covers diagnosing this) -- it's not an error exactly,
   it's the scheduler correctly reporting "I have nowhere to safely put
   this yet."

   AUTOSCALING, two distinct, complementary layers:
     HORIZONTAL POD AUTOSCALER (HPA)   watches a metric (commonly CPU
       or memory utilisation, or a custom metric) and automatically
       adjusts a Deployment's REPLICA COUNT within a range you define --
       more pods when busy, fewer when quiet. This is Chapter 55's
       ReplicaSet mechanism, driven automatically instead of manually.
     CLUSTER AUTOSCALER (on a cloud provider)   watches for pods stuck
       `Pending` because NO EXISTING NODE has room, and automatically
       provisions ADDITIONAL NODES (real cloud instances) to make room --
       then, just as importantly, removes nodes again once they're no
       longer needed, to control cost.
   TOGETHER: HPA scales PODS to match demand; the cluster autoscaler
   scales the underlying MACHINES to make sure there's actually room for
   however many pods HPA has decided are needed.

Real-world example

   Handling large, predictable seasonal traffic spikes -- the Black
   Friday/Cyber Monday retail shopping period being the most widely-
   discussed, most publicly-documented recurring real example across
   the industry -- is one of the most common, real-world-validated use
   cases explicitly cited for exactly this chapter's two-layer
   autoscaling model. Many retailers and e-commerce platforms have
   publicly published engineering blog posts and conference talks
   describing their own Kubernetes-based autoscaling architecture
   specifically built to handle this kind of extreme, well-understood-
   in-advance-but-still-massive traffic multiplier -- scaling from
   normal baseline capacity up to many times that, automatically, for a
   short, intense period, then scaling back down once demand subsides,
   without needing to PERMANENTLY provision (and pay for) peak-level
   infrastructure year-round.
   This is precisely the real, practical payoff this entire Part has
   been building toward: a Deployment declares the DESIRED shape of an
   application (Chapter 55), a Service gives it a stable address
   (Chapter 56), configuration is externalised cleanly (Chapter 57),
   and autoscaling makes the whole thing RESPOND to real demand
   automatically -- the full, connected picture of why an organisation
   takes on Kubernetes' real complexity in the first place.

Try it yourself

# See scheduling decisions and resource requests/limits directly
cat > scheduled.yaml << 'EOF'
apiVersion: v1
kind: Pod
metadata:
  name: resource-demo
spec:
  containers:
  - name: demo
    image: nginx
    resources:
      requests:
        cpu: "100m"
        memory: "64Mi"
      limits:
        cpu: "200m"
        memory: "128Mi"
EOF
kubectl apply -f scheduled.yaml
kubectl get pod resource-demo -o wide     # which node did it land on?
kubectl describe pod resource-demo | grep -A5 "Requests\|Limits"

# Deliberately request more than your (single-node kind) cluster has,
# and watch it stay Pending
cat > toobig.yaml << 'EOF'
apiVersion: v1
kind: Pod
metadata:
  name: too-big
spec:
  containers:
  - name: demo
    image: nginx
    resources:
      requests:
        cpu: "999"          # deliberately absurd -- no real node has
        memory: "999Gi"     # this much capacity
EOF
kubectl apply -f toobig.yaml
sleep 2
kubectl get pod too-big              # Pending
kubectl describe pod too-big | grep -A3 Events   # the scheduler
                                                  # explains WHY

kubectl delete -f scheduled.yaml -f toobig.yaml

Common mistakes

  • Setting no resource requests/limits at all. The scheduler has nothing to reason about, and a runaway pod (Chapter 13's OOM-killer story, one layer up) can starve its neighbours on the same node.
  • Setting requests and limits to the SAME value for everything, reflexively. Sometimes appropriate (predictable workloads); often overly rigid — understand the actual trade-off (limits above requests allows "bursting" into spare capacity) rather than copy-pasting a pattern.
  • Assuming autoscaling reacts instantly. Both HPA and cluster autoscaling take real, observable TIME (metric collection intervals, actual cloud-instance provisioning time) — plan for that lag, don't assume it's immediate.

Check yourself

  1. What's the difference between a resource request and a limit?
  2. Why does a pod stay Pending when no node has enough capacity, and is that an error?
  3. What's the difference between the Horizontal Pod Autoscaler and a Cluster Autoscaler, and why do you typically need both together?

Further reading

  • Docs: Kubernetes' own official "Assigning Pods to Nodes," "Horizontal Pod Autoscaling," and "Cluster Autoscaler" documentation.
  • Reference: kubectl describe node <name> — see a real node's actual allocated vs. available capacity.
  • Guide: this wiki's advanced security guide covers multi-tenancy and node isolation (Part 4 Chapter 21) as a related, deeper topic once scheduling basics are solid.

Generated from real-life-os-guide.md · 8 Oct 2026 16:36