Kubernetes Quality of Service
Kubernetes Quality of Service
While describing Pods, I used to notice one line about QoS Class:
and it used to be mostly BestEffort
as shown in the description QoS Class: BestEffort
. Later when applying limits, noticed a change from BestEffort
to Burstable
. I thought these were the only two options. Today, I got chance to explore this topic and find out that there is a third option, Guaranteed
as well.
According to Kubernetes Documentation, when Kubernetes creates a Pod it assigns one of these QoS classes to the Pod:
-
Guaranteed
-
Burstable
-
BestEffort
QoS Class Condition Guaranteed Every Container in the Pod must have a memory, CPU limit and a memory, CPU request, also the limit must be equal to the request value Burstable The Pod does not meet the criteria for QoS class Guaranteed and at least one Container in the Pod has a memory or CPU request. BestEffort The Containers in the Pod must not have any memory or CPU limits or requests.
Let us test these three QoS options here.
BestEffort
pradeep@learnk8s$ cat besteffort.yaml
apiVersion: v1
kind: Pod
metadata:
name: qos-demo-besteffort
namespace: qos-example
spec:
containers:
- name: qos-demo-besteffort
image: nginx
pradeep@learnk8s$ kubectl create -f besteffort.yaml
pod/qos-demo-besteffort created
pradeep@learnk8s$ kubectl get pods -n qos-example
NAME READY STATUS RESTARTS AGE
qos-demo-besteffort 1/1 Running 0 94s
pradeep@learnk8s$ kubectl describe pods -n qos-example
Name: qos-demo-besteffort
Namespace: qos-example
Priority: 0
Node: minikube-m02/172.16.30.7
Start Time: Mon, 11 Apr 2022 08:32:39 +0530
Labels: <none>
Annotations: cni.projectcalico.org/containerID: 48d330b8d0089f9c010fee4a0c8b142229491c76c04d432f59de216c8f07821c
cni.projectcalico.org/podIP: 10.244.205.204/32
cni.projectcalico.org/podIPs: 10.244.205.204/32
Status: Running
IP: 10.244.205.204
IPs:
IP: 10.244.205.204
Containers:
qos-demo-besteffort:
Container ID: docker://4382b8719874f73a37847bb07e6111adaa66fa1cdb069af71b281b688eedf92d
Image: nginx
Image ID: docker-pullable://nginx@sha256:2275af0f20d71b293916f1958f8497f987b8d8fd8113df54635f2a5915002bf1
Port: <none>
Host Port: <none>
State: Running
Started: Mon, 11 Apr 2022 08:33:27 +0530
Ready: True
Restart Count: 0
Environment: <none>
Mounts:
/var/run/secrets/kubernetes.io/serviceaccount from kube-api-access-x4pmx (ro)
Conditions:
Type Status
Initialized True
Ready True
ContainersReady True
PodScheduled True
Volumes:
kube-api-access-x4pmx:
Type: Projected (a volume that contains injected data from multiple sources)
TokenExpirationSeconds: 3607
ConfigMapName: kube-root-ca.crt
ConfigMapOptional: <nil>
DownwardAPI: true
QoS Class: BestEffort
Node-Selectors: <none>
Tolerations: node.kubernetes.io/not-ready:NoExecute op=Exists for 300s
node.kubernetes.io/unreachable:NoExecute op=Exists for 300s
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Scheduled 2m8s default-scheduler Successfully assigned qos-example/qos-demo-besteffort to minikube-m02
Normal Pulling 2m3s kubelet Pulling image "nginx"
Normal Pulled 81s kubelet Successfully pulled image "nginx" in 41.600660801s
Normal Created 81s kubelet Created container qos-demo-besteffort
Normal Started 81s kubelet Started container qos-demo-besteffort
From this, as expected, we see the QoS Class
as BestEffort
, because our Pod did not have any memory or CPU limits or requests.
Burstable
pradeep@learnk8s$ cat burstable.yaml
apiVersion: v1
kind: Pod
metadata:
name: qos-demo-burstable
namespace: qos-example
spec:
containers:
- name: qos-demo-burstable
image: nginx
resources:
limits:
memory: "200Mi"
requests:
memory: "100Mi"
pradeep@learnk8s$ kubectl get pods -n qos-example
NAME READY STATUS RESTARTS AGE
qos-demo-besteffort 1/1 Running 0 5m15s
qos-demo-burstable 1/1 Running 0 38s
Let us describe the new pod
pradeep@learnk8s$ kubectl describe pods qos-demo-burstable -n qos-example
Name: qos-demo-burstable
Namespace: qos-example
Priority: 0
Node: minikube-m03/172.16.30.8
Start Time: Mon, 11 Apr 2022 08:37:16 +0530
Labels: <none>
Annotations: cni.projectcalico.org/containerID: 0c37628815b45cb2111696cb6512fe9d89c58772d17f878550bfe13d08002b20
cni.projectcalico.org/podIP: 10.244.151.12/32
cni.projectcalico.org/podIPs: 10.244.151.12/32
Status: Running
IP: 10.244.151.12
IPs:
IP: 10.244.151.12
Containers:
qos-demo-burstable:
Container ID: docker://17fe659a6280979b6dc08277a2482ec742a1fd54ebbbaf0a5689441ec45bdf33
Image: nginx
Image ID: docker-pullable://nginx@sha256:2275af0f20d71b293916f1958f8497f987b8d8fd8113df54635f2a5915002bf1
Port: <none>
Host Port: <none>
State: Running
Started: Mon, 11 Apr 2022 08:37:21 +0530
Ready: True
Restart Count: 0
Limits:
memory: 200Mi
Requests:
memory: 100Mi
Environment: <none>
Mounts:
/var/run/secrets/kubernetes.io/serviceaccount from kube-api-access-42ppk (ro)
Conditions:
Type Status
Initialized True
Ready True
ContainersReady True
PodScheduled True
Volumes:
kube-api-access-42ppk:
Type: Projected (a volume that contains injected data from multiple sources)
TokenExpirationSeconds: 3607
ConfigMapName: kube-root-ca.crt
ConfigMapOptional: <nil>
DownwardAPI: true
QoS Class: Burstable
Node-Selectors: <none>
Tolerations: node.kubernetes.io/not-ready:NoExecute op=Exists for 300s
node.kubernetes.io/unreachable:NoExecute op=Exists for 300s
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Scheduled 59s default-scheduler Successfully assigned qos-example/qos-demo-burstable to minikube-m03
Normal Pulling 57s kubelet Pulling image "nginx"
Normal Pulled 54s kubelet Successfully pulled image "nginx" in 2.813492871s
Normal Created 54s kubelet Created container qos-demo-burstable
Normal Started 54s kubelet Started container qos-demo-burstable
In this example, our Pod has a memory limit and request. Requested memory (100Mi) is less than the limits (200Mi) set, so Burstable
QoS class is assigned.
Guaranteed
pradeep@learnk8s$ cat guaranteed.yaml
apiVersion: v1
kind: Pod
metadata:
name: qos-demo-guaranteed
namespace: qos-example
spec:
containers:
- name: qos-demo-guaranteed
image: nginx
resources:
limits:
memory: "200Mi"
cpu: "300m"
requests:
memory: "200Mi"
cpu: "300m"
Create the pod
pradeep@learnk8s$ kubectl create -f guaranteed.yaml
pod/qos-demo-guaranteed created
List all Pods
pradeep@learnk8s$ kubectl get pods -n qos-example
NAME READY STATUS RESTARTS AGE
qos-demo-besteffort 1/1 Running 0 11m
qos-demo-burstable 1/1 Running 0 6m46s
qos-demo-guaranteed 1/1 Running 0 34s
Describe the new pod
pradeep@learnk8s$ kubectl describe pods qos-demo-guaranteed -n qos-example
Name: qos-demo-guaranteed
Namespace: qos-example
Priority: 0
Node: minikube-m03/172.16.30.8
Start Time: Mon, 11 Apr 2022 08:43:28 +0530
Labels: <none>
Annotations: cni.projectcalico.org/containerID: 0216b63d97760d90d9bb3235a4a9db09ababf751cf87971b0fa91e925c9f8fe3
cni.projectcalico.org/podIP: 10.244.151.13/32
cni.projectcalico.org/podIPs: 10.244.151.13/32
Status: Running
IP: 10.244.151.13
IPs:
IP: 10.244.151.13
Containers:
qos-demo-guaranteed:
Container ID: docker://e4cdb0a437d2890dd8c81896d5feece2ba0a166a2fef2fb0e46bc62dd7b16d7f
Image: nginx
Image ID: docker-pullable://nginx@sha256:2275af0f20d71b293916f1958f8497f987b8d8fd8113df54635f2a5915002bf1
Port: <none>
Host Port: <none>
State: Running
Started: Mon, 11 Apr 2022 08:43:36 +0530
Ready: True
Restart Count: 0
Limits:
cpu: 300m
memory: 200Mi
Requests:
cpu: 300m
memory: 200Mi
Environment: <none>
Mounts:
/var/run/secrets/kubernetes.io/serviceaccount from kube-api-access-mvkxt (ro)
Conditions:
Type Status
Initialized True
Ready True
ContainersReady True
PodScheduled True
Volumes:
kube-api-access-mvkxt:
Type: Projected (a volume that contains injected data from multiple sources)
TokenExpirationSeconds: 3607
ConfigMapName: kube-root-ca.crt
ConfigMapOptional: <nil>
DownwardAPI: true
QoS Class: Guaranteed
Node-Selectors: <none>
Tolerations: node.kubernetes.io/not-ready:NoExecute op=Exists for 300s
node.kubernetes.io/unreachable:NoExecute op=Exists for 300s
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Scheduled 2m11s default-scheduler Successfully assigned qos-example/qos-demo-guaranteed to minikube-m03
Normal Pulling 2m7s kubelet Pulling image "nginx"
Normal Pulled 2m4s kubelet Successfully pulled image "nginx" in 2.746371427s
Normal Created 2m4s kubelet Created container qos-demo-guaranteed
Normal Started 2m3s kubelet Started container qos-demo-guaranteed
In this example, the Container has a memory limit and a memory request, both equal to 200 MiB. The Container has a CPU limit and a CPU request, both equal to 300 milliCPU, meeting the conditions for Guaranteed
QoS Class.
This line from the description confirms the same.
QoS Class: Guaranteed
Pod with two containers
pradeep@learnk8s$ cat mixed-qos.yaml
apiVersion: v1
kind: Pod
metadata:
name: qos-demo-mixed-qos
namespace: qos-example
spec:
containers:
- name: qos-demo-mixed-1
image: nginx
resources:
requests:
memory: "200Mi"
- name: qos-demo-mixed-2
image: redis
Create the pod with two containers
pradeep@learnk8s$ kubectl create -f mixed-qos.yaml
pod/qos-demo-mixed-qos created
List all the pods
pradeep@learnk8s$ kubectl get pods -n qos-example
NAME READY STATUS RESTARTS AGE
qos-demo-besteffort 1/1 Running 0 18m
qos-demo-burstable 1/1 Running 0 13m
qos-demo-guaranteed 1/1 Running 0 7m38s
qos-demo-mixed-qos 2/2 Running 0 39s
Describe the latest pod with two containers and verify what QoS class is assgined to this Pod.
pradeep@learnk8s$ kubectl describe pod qos-demo-mixed-qos -n qos-example
Name: qos-demo-mixed-qos
Namespace: qos-example
Priority: 0
Node: minikube-m02/172.16.30.7
Start Time: Mon, 11 Apr 2022 08:50:27 +0530
Labels: <none>
Annotations: cni.projectcalico.org/containerID: 8cd859d87e66cc326fdaa1b443fd82591a699bdccca564b897c953ffca46a12d
cni.projectcalico.org/podIP: 10.244.205.205/32
cni.projectcalico.org/podIPs: 10.244.205.205/32
Status: Running
IP: 10.244.205.205
IPs:
IP: 10.244.205.205
Containers:
qos-demo-mixed-1:
Container ID: docker://4c46c37e173185999ac60a0c857d19638e25fe6170b7be720110a56b1fa54b1a
Image: nginx
Image ID: docker-pullable://nginx@sha256:2275af0f20d71b293916f1958f8497f987b8d8fd8113df54635f2a5915002bf1
Port: <none>
Host Port: <none>
State: Running
Started: Mon, 11 Apr 2022 08:50:33 +0530
Ready: True
Restart Count: 0
Requests:
memory: 200Mi
Environment: <none>
Mounts:
/var/run/secrets/kubernetes.io/serviceaccount from kube-api-access-bvptc (ro)
qos-demo-mixed-2:
Container ID: docker://a0b03ecae8aab3c35b0aa5167ebdbc919166ba5a8b49541394f33120bd2f29b1
Image: redis
Image ID: docker-pullable://redis@sha256:69a3ab2516b560690e37197b71bc61ba245aafe4525ebdece1d8a0bc5669e3e2
Port: <none>
Host Port: <none>
State: Running
Started: Mon, 11 Apr 2022 08:50:44 +0530
Ready: True
Restart Count: 0
Environment: <none>
Mounts:
/var/run/secrets/kubernetes.io/serviceaccount from kube-api-access-bvptc (ro)
Conditions:
Type Status
Initialized True
Ready True
ContainersReady True
PodScheduled True
Volumes:
kube-api-access-bvptc:
Type: Projected (a volume that contains injected data from multiple sources)
TokenExpirationSeconds: 3607
ConfigMapName: kube-root-ca.crt
ConfigMapOptional: <nil>
DownwardAPI: true
QoS Class: Burstable
Node-Selectors: <none>
Tolerations: node.kubernetes.io/not-ready:NoExecute op=Exists for 300s
node.kubernetes.io/unreachable:NoExecute op=Exists for 300s
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Scheduled 2m6s default-scheduler Successfully assigned qos-example/qos-demo-mixed-qos to minikube-m02
Normal Pulling 2m4s kubelet Pulling image "nginx"
Normal Pulled 2m1s kubelet Successfully pulled image "nginx" in 2.869276565s
Normal Created 2m1s kubelet Created container qos-demo-mixed-1
Normal Started 2m kubelet Started container qos-demo-mixed-1
Normal Pulling 2m kubelet Pulling image "redis"
Normal Pulled 110s kubelet Successfully pulled image "redis" in 9.722976428s
Normal Created 110s kubelet Created container qos-demo-mixed-2
Normal Started 109s kubelet Started container qos-demo-mixed-2
In this example Pod, one container specifies a memory request of 200 MiB. The other container does not specify any requests or limits. This Pod meets the criteria for QoS class Burstable
. That is, it does not meet the criteria for QoS class Guaranteed
, and one of its Containers has a memory request.
This line from the description confirms the same.
QoS Class: Burstable
Clean up
Let us clean up all resources in this qos-example
namespace.
pradeep@learnk8s$ kubectl delete ns qos-example
namespace "qos-example" deleted
pradeep@learnk8s$ kubectl get pods -n qos-example
No resources found in qos-example namespace.
This concludes our discussion on Kubernetes QoS.