Calculate resource policy Limit Range in k8s

Article reprinted from: https://www.kuboard.cn/learning/k8s-advanced/policy/lr.html

By default, when the container runs on the Kubernetes cluster, it is not limited by computing resources. Using the Resource quota, cluster administrators can limit the use of resources for namespaces. Within a namespace, the resource consumption of a Pod (or container) is unlimited. The concern at this point is that there may be a Pod (or container) that monopolizes most of the resources of the namespace. Limit Range is a Policy used to limit the amount of resources that a Pod (or container) in a namespace can consume.

The Kubernetes LimitRange object can:

  • Limit the minimum and maximum computing resources for each Pod or container in the namespace
  • Limit the minimum and maximum storage space that each PersistentVolumeClaim in the namespace can use
  • Limit the ratio between the calculated resource request request and the qualified limit in the namespace
  • Set the request/limit of the default computing resource in the namespace and inject it into the container automatically at run time

Enable Limit Range

Execute the command kubectl API resources to check whether your cluster supports Limit Range. The output results are as follows. Generally, Limit Range is enabled by default.

NAME                              SHORTNAMES   APIGROUP                       NAMESPACED   KIND
bindings                                                                      true         Binding
componentstatuses                 cs                                          false        ComponentStatus
configmaps                        cm                                          true         ConfigMap
endpoints                         ep                                          true         Endpoints
events                            ev                                          true         Event
limitranges                       limits                                      true         LimitRange
namespaces                        ns                                          false        Namespace
nodes                             no                                          false        Node
persistentvolumeclaims            pvc                                         true         PersistentVolumeClaim
persistentvolumes                 pv                                          false        PersistentVolume
pods                              po                                          true         Pod
podtemplates                                                                  true         PodTemplate

Basic introduction

  • The Cluster Administrator creates a LimitRange object in the namespace
  • Users create objects such as workloads in the namespace, such as Pod, Container, PersistentVolumeClaim, and so on
  • For those pods and containers that do not have a computational resource request request and limit set, the LimitRanger sets the default resource request and response according to the LimitRange object in the namespace, and ensures that the actual consumption of computational resources by pods and containers does not exceed the specified value
  • If the request to create or update an object (Pod, Container, PersistentVolumeClaim) conflicts with the Limit Range, apiserver will return the HTTP status code 403 FORBIDDEN and the corresponding error message
  • If limit range is activated in the namespace to limit the use of computing resources such as cpu and memory, the user must specify the request and limit of cpu or memory when creating Pod and Container, otherwise the system will refuse to create Pod
  • Kubernetes only checks the qualification of LimitRange during Pod creation, and does not perform any checks when Pod is running

After the LimitRange object is activated, create a Pod, Container, and PersistentVolumeClaim. You must specify the request and limit of cpu or memory, otherwise the system will refuse to create a Pod
First create the Pod, Container and PersistentVolumeClaim, and then create the active LimitRange object. The Pod and Container for calculating the resource request request and limit are not set. The LimitRanger sets the default resource request and response according to the LimitRange object in the namespace

Examples of using LimitRange are:

  • On a 2-node cluster with a total capacity of 8G memory and 16 core CPU, the Pod in a namespace is limited to use 100m CPU request and no more than 500m CPU limit, 200Mi memory request and no more than 600Mi memory online limit
  • For containers without defined CPU and memory requests, specify that the default CPU request and limit are 150m and the default memory request is 300Mi

When the total limit of the namespace is less than the sum of the limits of Pod/Container in the namespace, resource contention will occur, and the container or Pod cannot be created.
When resource contention occurs or limit range is modified, the created Pod/Container will not be affected.

Limit the computing resources of the container

Suppose a Pod contains four containers, and each container defines spec.resource. At this time, the LimitRanger management controller handles the four containers in the Pod differently.

The demonstration steps are as follows:
1. Execute the following command to create the namespace limitrange demo

kubectl create namespace limitrange-demo

Switch the kubectl default namespace to limitrange demo

kubectl config set-context --current --namespace=limitrange-demo

2. The yaml file of the limitrange object is as follows:

apiVersion: v1
kind: LimitRange
metadata:
  name: limit-mem-cpu-per-container
spec:
  limits:
  - max:
      cpu: "800m"
      memory: "1Gi"
    min:
      cpu: "100m"
      memory: "99Mi"
    default:
      cpu: "700m"
      memory: "900Mi"
    defaultRequest:
      cpu: "110m"
      memory: "111Mi"
    type: Container

This object defines the following for containers in the namespace:

  • Maximum and minimum CPU / memory
  • Default CPU / memory limit
  • Default CPU / memory request

Execute the command to create the object:

kubectl create -f https://kuboard.cn/statics/learning/policy/lr-container-limit-range.yaml -n limitrange-demo

Execute commands to view results

kubectl describe limitrange/limit-mem-cpu-per-container -n limitrange-demo

Type        Resource  Min   Max   Default Request  Default Limit  Max Limit/Request Ratio
----        --------  ---   ---   ---------------  -------------  -----------------------
Container   cpu       100m  800m  110m             700m           -
Container   memory    99Mi  1Gi   111Mi            900Mi          -

3. The yaml file of the Pod with 4 containers mentioned above is as follows:

apiVersion: v1
kind: Pod
metadata:
  name: busybox1
spec:
  containers:
  - name: busybox-cnt01
    image: busybox
    command: ["/bin/sh"]
    args: ["-c", "while true; do echo hello from cnt01; sleep 10;done"]
    resources:
      requests:
        memory: "100Mi"
        cpu: "100m"
      limits:
        memory: "200Mi"
        cpu: "500m"
  - name: busybox-cnt02
    image: busybox
    command: ["/bin/sh"]
    args: ["-c", "while true; do echo hello from cnt02; sleep 10;done"]
    resources:
      requests:
        memory: "100Mi"
        cpu: "100m"
  - name: busybox-cnt03
    image: busybox
    command: ["/bin/sh"]
    args: ["-c", "while true; do echo hello from cnt03; sleep 10;done"]
    resources:
      limits:
        memory: "200Mi"
        cpu: "500m"
  - name: busybox-cnt04
    image: busybox
    command: ["/bin/sh"]
    args: ["-c", "while true; do echo hello from cnt04; sleep 10;done"]

Execute the command to create the Pod

kubectl apply -f https://kuboard.cn/statics/learning/policy/lr-container-pod.yaml

The container contains valid CPU / memory requests/limits

Execute the following command to view the configuration information of busybox-cnt01

kubectl get  po/busybox1 -n limitrange-demo -o json | jq ".spec.containers[0].resources"

{
  "limits": {
    "cpu": "500m",
    "memory": "200Mi"
  },
  "requests": {
    "cpu": "100m",
    "memory": "100Mi"
  }
}
  • The container busybox-cnt01 in busybox Pod defines requests CPU = 100m and requests memory=100Mi
  • The cpu limit (500m) of the 100m < = 500m < = 800m container is within the range specified by the namespace LimitRange
  • 99mi < = 200Mi < = 1gi the memory limit (200Mi) of the container is within the range specified by the namespace LimitRange
  • request/limit ratio is not specified for CPU / memory
  • At this point, the container definition is valid and will be created

The container contains valid CPU / memory requests and limits are not specified

Execute the following command to view the configuration information of busybox-cnt02

kubectl get  po/busybox1 -n limitrange-demo -o json | jq ".spec.containers[1].resources"

{
  "limits": {
    "cpu": "700m",
    "memory": "900Mi"
  },
  "requests": {
    "cpu": "100m",
    "memory": "100Mi"
  }
}
  • The container busybox-cnt02 in busybox Pod defines requests CPU = 100m and requests Memory = 100mi, and is the maximum limit of the specified CPU / memory
  • Since the container does not define limits, the namespace's LimitRange defines limits CPU = 700mi and limits Memory = 900mi is injected into the container
  • The maximum CPU limit (700m) of 100m < = 700m < = 800m container is within the range specified by namespace LimitRange
  • 99mi < = 900Mi < = 1gi the memory limit (900Mi) of the container is within the range specified by the namespace LimitRange
  • request/limit ratio is not specified for CPU / memory
  • At this point, the container definition is valid and will be created

The container contains valid CPU / memory limits and does not specify requests

Execute the following command to view the configuration information of busybox-cnt03

kubectl get  po/busybox1 -n limitrange-demo -o json | jq ".spec.containers[2].resources"

{
  "limits": {
    "cpu": "500m",
    "memory": "200Mi"
  },
  "requests": {
    "cpu": "500m",
    "memory": "200Mi"
  }
}
  • The container busybox-cnt03 in busybox Pod defines limits CPU = 500m and limits Memory = 200mi, and no CPU / memory requests are specified
  • Since the container does not define requests, the defaultRequest defined by LimitRange in the namespace is not injected into the request field of the container. Instead, the limits defined by the container is set to its requests field: limits CPU = 500m and limits memory=200Mi
  • The maximum cpu limit (500m) of the 100m < = 500m < = 800m container is within the range specified by the namespace LimitRange
  • 99mi < = 200Mi < = 1gi the maximum memory limit (200Mi) of the container is within the range specified by the namespace LimitRange
  • request/limit ratio is not specified for CPU / memory
  • At this point, the container definition is valid and will be created

The container does not contain requests/limits for CPU / memory

Execute the following command to view the configuration information of busybox-cnt04

kubectl get  po/busybox1 -n limitrange-demo -o json | jq ".spec.containers[3].resources"

{
  "limits": {
    "cpu": "700m",
    "memory": "900Mi"
  },
  "requests": {
    "cpu": "110m",
    "memory": "111Mi"
  }
}
  • The container busybox-cnt04 in busybox Pod defines neither request nor limits
  • Since the container does not define limits, the namespace's LimitRange defines limits CPU = 700mi and limits Memory = 900mi is injected into the container
  • Since the container does not define requests, the LimitRange of the namespace defines requests CPU = 110m and requests Memory = 110mi is injected into the container
  • The maximum cpu limit (700m) of the 100m < = 700m < = 800m container is within the range specified in the namespace LimitRange
  • 99mi < = 900Mi < = 1gi the memory limit (900Mi) of the container is within the range specified by the namespace LimitRange
  • request/limit ratio is not specified for CPU / memory
  • At this point, the container definition is valid and will be created

All containers in the Pod busybox have passed the namespace LimitRange check, and this Pod will be created

Limit Pod's computing resources

The following is a LimitRange object used to limit the use of Pod resources.

apiVersion: v1
kind: LimitRange
metadata:
  name: limit-mem-cpu-per-pod
spec:
  limits:
  - max:
      cpu: "2"
      memory: "2Gi"
    type: Pod

Before starting, complete the calculation resources of the container, and ensure that the limitrange, limit MEM CPU per container and Pod busybox1 in this tutorial have been created.

1. Execute the following command to create the LimitRange in yaml above the limit MEM CPU Pod, which limits the CPU usage of each Pod to no more than 2 cores and memory to no more than 2Gi.

kubectl apply -f https://kuboard.cn/statics/learning/policy/lr-pod-limit-range.yaml -n limitrange-demo

Execute the command to view the creation result of limit MEM CPU per pod:

kubectl describe limitrange/limit-mem-cpu-per-pod -n limitrange-demo

Name:       limit-mem-cpu-per-pod
Namespace:  limitrange-demo
Type        Resource  Min  Max  Default Request  Default Limit  Max Limit/Request Ratio
----        --------  ---  ---  ---------------  -------------  -----------------------
Pod         cpu       -    2    -                -              -
Pod         memory    -    2Gi  -                -              -

2. Create a second Pod, yaml file as follows:

apiVersion: v1
kind: Pod
metadata:
  name: busybox2
spec:
  containers:
  - name: busybox-cnt01
    image: busybox
    command: ["/bin/sh"]
    args: ["-c", "while true; do echo hello from cnt01; sleep 10;done"]
    resources:
      requests:
        memory: "100Mi"
        cpu: "100m"
      limits:
        memory: "200Mi"
        cpu: "500m"
  - name: busybox-cnt02
    image: busybox
    command: ["/bin/sh"]
    args: ["-c", "while true; do echo hello from cnt02; sleep 10;done"]
    resources:
      requests:
        memory: "100Mi"
        cpu: "100m"
  - name: busybox-cnt03
    image: busybox
    command: ["/bin/sh"]
    args: ["-c", "while true; do echo hello from cnt03; sleep 10;done"]
    resources:
      limits:
        memory: "200Mi"
        cpu: "500m"
  - name: busybox-cnt04
    image: busybox
    command: ["/bin/sh"]
    args: ["-c", "while true; do echo hello from cnt04; sleep 10;done"]

Execute the following command to create the Pod

kubectl apply -f https://kuboard.cn/statics/learning/policy/lr-pod-pod.yaml -n limitrange-demo

The definition of Pod busybox2 is exactly the same as that of busybox1, but the following errors will be encountered when executing the create command, because the resources available to Pod are now limited:

Error from server (Forbidden): error when creating "limit-range-pod-2.yaml": pods "busybox2" is forbidden: [maximum cpu usage per Pod is 2, but limit is 2400m., maximum memory usage per Pod is 2Gi, but limit is 2306867200.]

Execute the command to view the resource usage of busybox1

kubectl get  po/busybox1  -n limitrange-demo -o json | jq ".spec.containers[].resources.limits.memory" 

"200Mi"
"900Mi"
"200Mi"
"900Mi"

Pod busybox2 will not be created in the cluster because the sum of the memory limits of all containers in it exceeds the limit in limitrange, limit MEM CPU per pod. busybox1 will not be expelled because the pod has been created when the limitrange limit MEM CPU per pod is created.

Limited storage resources

Through the LimitRange object, the cluster administrator can limit the minimum and maximum storage space that can be used by each PersistentVolumeClaim (storage volume declaration) in the namespace.

Please refer to the following example:

apiVersion: v1
kind: LimitRange
metadata:
  name: storagelimits
spec:
  limits:
  - type: PersistentVolumeClaim
    max:
      storage: 2Gi
    min:
      storage: 1Gi

Execute the command to create the LimitRange:

kubectl create -f https://kuboard.cn/statics/learning/policy/lr-storage-limit.yaml -n limitrange-demo

kubectl describe limits/storagelimits -n limitrange-demo
Name:                  storagelimits
Namespace:             limitrange-demo
Type                   Resource  Min  Max  Default Request  Default Limit  Max Limit/Request Ratio
----                   --------  ---  ---  ---------------  -------------  -----------------------
PersistentVolumeClaim  storage   1Gi  2Gi  -                -              -

Now suppose there is a PVC (storage volume declaration), and the definition file is as follows:

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: pvc-limit-lower
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 500Mi

Execute the command to create the PVC (storage volume declaration)

kubectl create -f https://kuboard.cn/statics/learning/policy/lr-storage-pvc-lower.yaml -n limitrange-demo

Due to the field requests defined in PVC Storage is greater than limits [0] in LimitRange storagelimits The definition of min.storage is small, so creating the PVC will fail:

Error from server (Forbidden): error when creating "lr-storage-pvc-lower.yaml": persistentvolumeclaims "pvc-limit-lower" is forbidden: minimum storage usage per PersistentVolumeClaim is 1Gi, but request is 500Mi.

If PVC requests Storage is greater than limits [0] in LimitRange Max.storage cannot be created successfully. Please refer to the following example:

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: pvc-limit-greater
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 5Gi

Execute the command to create the PVC (storage volume declaration)

kubectl create -f https://kuboard.cn/statics/learning/policy/lr-storage-pvc-greater.yaml

Error from server (Forbidden): error when creating "lr-storage-pvc-greater.yaml": persistentvolumeclaims "pvc-limit-greater" is forbidden: maximum storage usage per PersistentVolumeClaim is 2Gi, but request is 5Gi.

Limit/Request ratio

If spec.limits.of the LimitRange object is specified Maxlimitrequestratio field, the request and limit of Pod / container in namespace cannot be 0, and the result of limit divided by request must be less than or equal to spec.limits of LimitRange maxLimitRequestRatio

In the following example, LimitRange defines that the maximum memory limit of any Pod in the namespace cannot exceed twice the minimum memory request:

apiVersion: v1
kind: LimitRange
metadata:
  name: limit-memory-ratio-pod
spec:
  limits:
  - maxLimitRequestRatio:
      memory: 2
    type: Pod

Execute the command to create the LimitRange:

kubectl create -f https://kuboard.cn/statics/learning/policy/lr-ratio-limit-range.yaml -n limitrange-demo

Execute the command to view the creation results:

kubectl describe limitrange/limit-memory-ratio-pod -n limitrange-demo

Name:       limit-memory-ratio-pod
Namespace:  limitrange-demo
Type        Resource  Min  Max  Default Request  Default Limit  Max Limit/Request Ratio
----        --------  ---  ---  ---------------  -------------  -----------------------
Pod         memory    -    -    -                -              2

At this point, if we create a Pod containing the following attribute requests Memory = 100mi and limits memory=300Mi:

apiVersion: v1
kind: Pod
metadata:
  name: busybox3
spec:
  containers:
  - name: busybox-cnt01
    image: busybox
    resources:
      limits:
        memory: "300Mi"
      requests:
        memory: "100Mi"

Execute the command to create the Pod:

kubectl apply -f https://kuboard.cn/statics/learning/policy/lr-ratio-pod.yaml -n limitrange-demo

Since the memory limit request ratio of the Pod is 3, which exceeds 2 defined in the LimitRange, the Pod cannot be created successfully:

Error from server (Forbidden): error when creating "lr-ratio-pod.yaml": pods "busybox3" is forbidden: memory max limit to request ratio per Pod is 2, but provided ratio is 3.000000.

Keywords: Kubernetes

Added by beachcomber on Fri, 21 Jan 2022 05:44:03 +0200