Exercise

In this exercise, we will create a namespace and add quotas to limit the resources that can be used within it.

  1. Create the test namespace:
kubectl create namespace test
  1. Copy the content below into the quota.yaml file:
quota.yaml
apiVersion: v1
kind: ResourceQuota
metadata:
  name: quota
spec:
  hard:
    requests.cpu: "1"
    requests.memory: 1Gi
    limits.cpu: "2"
    limits.memory: 2Gi

This defines a ResourceQuota resource that will limit memory and CPU usage in the associated namespace. Within this namespace:

  • each container must specify requests and limits for RAM and CPU
  • all containers combined cannot request more than 1GB of RAM
  • all containers combined cannot use more than 2GB of RAM
  • all containers combined cannot request more than 1 CPU
  • all containers combined cannot use more than 2 CPUs

Using the following command, create this new resource and associate it with the test namespace.

kubectl apply -f quota.yaml --namespace=test
  1. Create a pod-quota-1.yaml file, and copy the following content:
pod-quota-1.yaml
apiVersion: v1
kind: Pod
metadata:
  name: quota-mem-cpu-1
  namespace: test
spec:
  containers:
  - name: www
    image: nginx:1.22
    resources:
      limits:
        memory: "800Mi"
        cpu: "800m"
      requests:
        memory: "600Mi"
        cpu: "400m"

The single container in this Pod defines requests and limits for RAM and CPU.

Create this Pod with the following command:

kubectl apply -f pod-quota-1.yaml

Verify that the Pod was created correctly:

$ kubectl get po -n test
NAME                 READY   STATUS    RESTARTS   AGE
quota-mem-cpu-1      1/1     Running   0          11s
  1. Use the following command to see the RAM and CPU resources used within the namespace:
kubectl describe resourcequota quota --namespace=test
  1. Launching a 2nd Pod

Create a pod-quota-2.yaml file, and copy the following content:

pod-quota-2.yaml
apiVersion: v1
kind: Pod
metadata:
  name: quota-mem-cpu-2
  namespace: test
spec:
  containers:
  - name: db
    image: mongo:5.0
    resources:
      limits:
        memory: "1Gi"
        cpu: "800m"      
      requests:
        memory: "700Mi"
        cpu: "400m"

Create this Pod:

kubectl apply -f pod-quota-2.yaml

You should get a message similar to the one below

Error from server (Forbidden): error when creating "pod-quota-2.yaml": pods "quota-mem-cpu-2" is forbidden: exceeded quota: quota, requested: requests.memory=700Mi, used: requests.memory=600Mi, limited: requests.memory=1Gi

This new Pod cannot be created because there aren’t enough resources available in the test namespace

  1. Modify the ResourceQuota to limit the number of Pods to 5 in the namespace

Limiting the number of Pods is done by adding the spec.hard.pods property as shown below:

quota.yaml
apiVersion: v1
kind: ResourceQuota
metadata:
  name: quota
spec:
  hard:
    requests.cpu: "1"
    requests.memory: 1Gi
    limits.cpu: "2"
    limits.memory: 2Gi
    pods: "5"
  1. Create the following Deployment, which defines 5 replicas of a Pod based on nginx:
apiVersion: apps/v1
kind: Deployment
metadata:
  namespace: test
  name: nginx
spec:
  replicas: 5
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - image: nginx:1.22
        name: nginx
        resources:
          limits:
            memory: "50Mi"
            cpu: "50m"      
          requests:
            memory: "50Mi"
            cpu: "50m"

Verify that the 5th Pod cannot be launched (the Deployment should indicate that only 4 pods out of the requested 5 are available)

$ kubectl -n test get deploy nginx
NAME    READY   UP-TO-DATE   AVAILABLE   AGE
nginx   4/5     4            4           26s

The events indicate that an additional pod cannot be launched due to the limitation (in terms of number of pods) specified in the quota:

kubectl get events -n test
  1. Delete the test namespace:
kubectl delete ns test