Apply Namespace Resource Quotas

KubernetesBeginner
Practice Now

Introduction

The previous lab focused on resource requests and limits inside individual Pods and Deployments. A ResourceQuota moves that idea up to the namespace level. It lets a team or platform owner set boundaries such as how many Pods can exist, how much CPU can be requested, and how much memory can be limited in one namespace.

In this lab, you will create a namespace ResourceQuota, inspect its hard limits, watch Kubernetes reject a Pod that does not declare required resources, and then run compliant Pods until the namespace reaches its Pod count quota.

Prepare a Quota Practice Namespace

In this step, you will prepare a clean namespace for ResourceQuota practice.

Start in /home/labex/project. You will write the quota and Pod manifests in this directory.

mkdir -p /home/labex/project
cd /home/labex/project

Check that the Kubernetes API server is reachable. If the VM has just started and the node is not ready yet, wait a few seconds and run the command again.

kubectl get nodes --request-timeout=5s

Expected output includes:

NAME         STATUS   ROLES           AGE   VERSION
labex-v135   Ready    control-plane   ...   v1.35...

Wait until the cluster networking Pod is Ready before creating application Pods.

kubectl wait --namespace kube-system --for=condition=Ready pod -l k8s-app=calico-node --timeout=120s

Expected output:

pod/calico-node-... condition met

Create a namespace named ckad-prep-quotas:

kubectl create namespace ckad-prep-quotas

Set this namespace as the current context namespace:

kubectl config set-context --current --namespace=ckad-prep-quotas

Confirm the current namespace:

kubectl config view --minify --output 'jsonpath={..namespace}'; echo

Expected output:

ckad-prep-quotas

Create a Namespace ResourceQuota

In this step, you will create a ResourceQuota that limits both object count and total requested resources.

The pods quota limits how many Pods can exist in the namespace. The requests.* and limits.* quotas track the sum of the resource requests and limits declared by all matching Pods. When a namespace has quota entries for CPU and memory requests or limits, new Pods must declare those fields so Kubernetes can account for them.

Create app-resource-quota.yaml:

cat > app-resource-quota.yaml <<'EOF'
apiVersion: v1
kind: ResourceQuota
metadata:
  name: app-resource-quota
spec:
  hard:
    pods: "2"
    requests.cpu: "400m"
    requests.memory: 256Mi
    limits.cpu: "800m"
    limits.memory: 512Mi
EOF

Apply the quota:

kubectl apply -f app-resource-quota.yaml

Expected output:

resourcequota/app-resource-quota created

Inspect the quota. At this point, no Pods are running in the namespace, so the used values should be zero.

kubectl describe resourcequota app-resource-quota

Expected output includes:

Name:            app-resource-quota
Resource         Used  Hard
limits.cpu       0     800m
limits.memory    0     512Mi
pods             0     2
requests.cpu     0     400m
requests.memory  0     256Mi

Observe a Pod Rejected by Quota

In this step, you will try to create a Pod without resource requests and limits.

This Pod is intentionally incomplete. Because the namespace quota tracks CPU and memory requests and limits, Kubernetes cannot admit a Pod that omits those fields. This is a useful failure to recognize in CKAD tasks: the manifest may be valid YAML, but admission can still reject it because of namespace policy.

Create no-resources-pod.yaml:

cat > no-resources-pod.yaml <<'EOF'
apiVersion: v1
kind: Pod
metadata:
  name: no-resources
  labels:
    app: no-resources
spec:
  terminationGracePeriodSeconds: 0
  containers:
  - name: app
    image: busybox:1.36
    command:
    - /bin/sh
    - -c
    - 'sleep 3600'
EOF

Try to apply the manifest. The || true at the end lets your shell continue after the expected error so you can inspect the result.

kubectl apply -f no-resources-pod.yaml || true

Expected output includes:

Error from server (Forbidden): error when creating "no-resources-pod.yaml": pods "no-resources" is forbidden: failed quota

Confirm that the Pod was not created:

kubectl get pod no-resources

Expected output includes:

Error from server (NotFound): pods "no-resources" not found

Check that the quota still shows zero Pods in use:

kubectl get resourcequota app-resource-quota -o 'jsonpath={.status.used.pods}{"\n"}'

Expected output:

0

Run Compliant Pods Until the Quota Is Full

In this step, you will create Pods that include resource requests and limits, then observe the Pod count quota stop a third Pod.

Each valid Pod below requests 100m CPU and 64Mi memory and limits itself to 200m CPU and 128Mi memory. Two such Pods fit inside the quota. A third Pod has valid resource fields, but the namespace allows only two Pods.

Create quota-workers.yaml:

cat > quota-workers.yaml <<'EOF'
apiVersion: v1
kind: Pod
metadata:
  name: quota-worker-a
  labels:
    app: quota-worker
spec:
  terminationGracePeriodSeconds: 0
  containers:
  - name: app
    image: busybox:1.36
    command: ["/bin/sh", "-c", "echo worker-a-ready; sleep 3600"]
    resources:
      requests:
        cpu: 100m
        memory: 64Mi
      limits:
        cpu: 200m
        memory: 128Mi
---
apiVersion: v1
kind: Pod
metadata:
  name: quota-worker-b
  labels:
    app: quota-worker
spec:
  terminationGracePeriodSeconds: 0
  containers:
  - name: app
    image: busybox:1.36
    command: ["/bin/sh", "-c", "echo worker-b-ready; sleep 3600"]
    resources:
      requests:
        cpu: 100m
        memory: 64Mi
      limits:
        cpu: 200m
        memory: 128Mi
EOF

Apply the manifest and wait for both Pods:

kubectl apply -f quota-workers.yaml
kubectl wait --for=condition=Ready pod/quota-worker-a pod/quota-worker-b --timeout=120s

Expected output:

pod/quota-worker-a created
pod/quota-worker-b created
pod/quota-worker-a condition met
pod/quota-worker-b condition met

Inspect the quota usage:

kubectl get resourcequota app-resource-quota -o 'jsonpath={.status.used.pods}{" "}{.status.used.requests\.cpu}{" "}{.status.used.requests\.memory}{" "}{.status.used.limits\.cpu}{" "}{.status.used.limits\.memory}{"\n"}'

Expected output:

2 200m 128Mi 400m 256Mi

Create a third Pod with valid resources:

cat > quota-worker-c.yaml <<'EOF'
apiVersion: v1
kind: Pod
metadata:
  name: quota-worker-c
  labels:
    app: quota-worker
spec:
  terminationGracePeriodSeconds: 0
  containers:
  - name: app
    image: busybox:1.36
    command: ["/bin/sh", "-c", "sleep 3600"]
    resources:
      requests:
        cpu: 100m
        memory: 64Mi
      limits:
        cpu: 200m
        memory: 128Mi
EOF
kubectl apply -f quota-worker-c.yaml || true

Expected output includes:

Error from server (Forbidden): error when creating "quota-worker-c.yaml": pods "quota-worker-c" is forbidden: exceeded quota

Summary

You created a namespace ResourceQuota, inspected its hard limits, observed Kubernetes rejecting a Pod that omitted required resource fields, and ran compliant Pods until the namespace reached its Pod count limit. This connects individual container resource settings with namespace-level resource governance.