Kubernetes Fundamentals · Module 08 of 14

Requests, limits, basic scheduling and QoS

Understand how requests influence scheduling, how limits constrain containers, and how selectors/taints affect placement decisions.

Learning objectives

By the end of this module, you should be able to:

  • Distinguish resource requests from limits.
  • Explain why the scheduler uses requests when evaluating node capacity.
  • Use a safe node selector and inspect Pod QoS/placement.

Requests are scheduling signals

CPU and memory requests tell Kubernetes how much resource a container is expected to need. The scheduler considers requests against node allocatable capacity when placing Pods.

Limits are runtime ceilings

CPU limits are enforced through throttling. Memory limits can lead to OOM termination when the container exceeds available memory under its limit. Requests and limits also contribute to Pod QoS classification.

Placement constraints are separate

nodeSelector and node affinity constrain eligible nodes. Taints repel Pods unless they tolerate the taint. These mechanisms influence placement but do not replace resource requests.

Worked examples

See the idea in practice.

Inspect resources

kubectl -n gnu-k8s-fundamentals get pod resource-demo -o jsonpath='{.spec.containers[0].resources}'
kubectl -n gnu-k8s-fundamentals get pod resource-demo -o jsonpath='{.status.qosClass}{"\n"}'
  • Requests and limits are part of the Pod spec.
  • QoS class appears in Pod status.
Hands-on lab

Lab — Schedule with explicit resources

Goal: Run a small Pod with CPU/memory requests and limits, pinned only to Linux nodes.

Before you start

  • kubectl is installed and can reach the lab cluster.
  • Use the dedicated gnu-k8s-fundamentals namespace unless a step explicitly says otherwise.
STEP 1

Apply a resource-aware Pod

cat <<'EOF' | kubectl apply -f -
apiVersion: v1
kind: Pod
metadata:
  name: resource-demo
  namespace: gnu-k8s-fundamentals
spec:
  nodeSelector:
    kubernetes.io/os: linux
  containers:
  - name: app
    image: busybox:1.36
    command: ["sh","-c","sleep 3600"]
    resources:
      requests:
        cpu: 10m
        memory: 16Mi
      limits:
        cpu: 100m
        memory: 64Mi
EOF
STEP 2

Wait and inspect placement

kubectl -n gnu-k8s-fundamentals wait --for=condition=Ready pod/resource-demo --timeout=90s
kubectl -n gnu-k8s-fundamentals get pod resource-demo -o wide
STEP 3

Inspect resources and QoS

kubectl -n gnu-k8s-fundamentals get pod resource-demo -o jsonpath='{.spec.containers[0].resources}{"\n"}{.status.qosClass}{"\n"}'
STEP 4

Clean up

kubectl -n gnu-k8s-fundamentals delete pod resource-demo

Verify

  • The Pod is scheduled to a Linux node.
  • Requests and limits are visible.
  • The QoS class is Burstable because requests differ from limits.

Expected outcome

  • The scheduler finds a node with enough requested capacity.

If it fails

  • If the Pod is Pending, describe it and read scheduler Events.
  • If using an existing cluster, ensure at least one schedulable Linux node exists.
Real-world connection

Accurate requests make scheduling and cluster capacity planning more reliable; arbitrary limits can cause throttling or OOM failures.

Avoid these traps

Common mistakes

  • Setting requests to zero for every production workload.
  • Assuming CPU and memory limits behave identically.
  • Using nodeSelector for a label that no node has, then treating Pending as an application failure.
Knowledge check

Can you explain it without looking back?

Open each answer only after you have tried to answer the question yourself.

1Which values does the scheduler primarily consider for resource fit?

Resource requests.

2What can happen when a container exceeds a memory limit?

It can be terminated due to out-of-memory enforcement.

3What does nodeSelector do?

Restricts a Pod to nodes carrying the specified labels.