Kubernetes 提供了 LimitRange 机制对 Pod 和容器的 Requests 和 Limits 配置做进一步限制。下面的示例中首先如何将 LimitsRange 应用到一个 Kubernetes 的命名空间中,然后说明 LimitRange 的几种限制方式,比如最大及最小范围、Requests 和 Limits 的默认值、Limits 与 Requests 的最大比例上线,等等。下面用过 LimitRange 的设置和应用对其进行说明。
1. 创建一个命名空间
创建一个名为 limit-example 的 Namespace:
[root@master1 ~]# kubectl create namespace limit-example
namespace/limit-example created
2. 为命名空间设置 LimitRange
为命名空间 limit-example 创建一个简单的 LimitRange。创建 limits.yaml 配置文件,内容如下:
apiVersion: v1
kind: LimitRange
metadata:
name: mylimits
spec:
limits:
- max:
cpu: "4"
memory: 2Gi
min:
cpu: 200m
memory: 6Mi
maxLimitRequestRatio:
cpu: 3
memory: 2
type: Pod
- default:
cpu: 300m
memory: 200Mi
defaultRequest:
cpu: 200m
memory: 100Mi
max:
cpu: "2"
memory: 1Gi
min:
cpu: 100m
memory: 3Mi
maxLimitRequestRatio:
cpu: 5
memory: 4
type: Container
创建该 LimitRange:
[root@master1 ~]# kubectl create -f limits.yaml --namespace=limit-example
limitrange/mylimits created
查看 namespace limit-example 中的 LimitRange:
[root@master1 ~]# kubectl describe limitranges mylimits --namespace=limit-example
Name: mylimits
Namespace: limit-example
Type Resource Min Max Default Request Default Limit Max Limit/Request Ratio
---- -------- --- --- --------------- ------------- -----------------------
Pod cpu 200m 4 - - 3
Pod memory 6Mi 2Gi - - 2
Container cpu 100m 2 200m 300m 5
Container memory 3Mi 1Gi 100Mi 200Mi 4
LimitRange 中各项配置的意义和特点如下:
-
不论是 CPU 还是内存,在 LimitRange 中,Pod 和 Container 都可以设置 Min、Max 和 Max Limit / Requests Ratio 参数。Container 还可以设置 Default Request 和 Default Limit 参数,而 Pod 不能设置 Default Request 和Default Limit 参数。
-
对 Pod 和 Container 的参数解释如下。
- Container:
- Container 的 Min(上面的 100m 和 3Mi)是 Pod 中所有容器的 Requests 值下限;
- Container 的 Max(上面的 2 和 1Gi)是 Pod 中所有容器的 Limits 值上限;
- Container 的 Default Request(上面的 200m 和 100Mi)是 Pod 中所有未指定 Requests 值的容器的默认 Requests 值;
- Container 的 Default Limit(上面的300m和200Mi)是 Pod 中所有未指定 Limits 值的容器的默认 Limits 值。
- 对于同一资源类型,这 4 个参数必须满足以下关系:Min ≤ Default Request ≤ Default Limit ≤ Max。
- Pod:
- Pod 的 Min(上面的 200m 和 6Mi)是 Pod 中所有容器的 Requests 值的总和下限;
- Pod 的 Max(上面的 4 和 2Gi)是 Pod 中所有容器的 Limits 值的总和上限。
- 容器未指定 Requests 值或者 Limits 值时,将使用 Container 的 Default Request 值或者 Default Limit 值。
- Container 的 Max Limit/Requests Ratio(上面的 5 和 4)限制了 Pod 中所有容器的 Limits 值与 Requests 值的比例上限;而 Pod 的 Max Limit / Requests Ratio(上面的 3 和 2)限制了 Pod 中所有容器的 Limits 值总和与 Requests 值总和的比例上限。
- Container:
-
如果设置了 Container 的 Max,那么对于该类资源而言,整个集群中的所有容器都必须设置 Limits,否则无法成功创建。Pod 内的容器未配置 Limits 时,将使用 Default Limit 的值(本例中的 300m CPU 和 200MiB 内存),如果也未配置 Default,则无法成功创建。
-
如果设置了 Container 的 Min,那么对于该类资源而言,整个集群中的所有容器都必须设置 Requests。如果创建 Pod 的容器时未配置该类资源的 Requests,那么在创建过程中会报验证错误。Pod 里容器的 Requests 在未配置时,可以使用默认值 defaultRequest(本例中的 200m CPU 和 100MiB 内存);如果未配置而且没有使用默认值 defaultRequest,那么默认等于该容器的 Limits;如果容器的 Limits 也未定义,就会报错。
-
对于任意一个 Pod 而言,该 Pod 中所有容器的 Requests 总和都必须大于或等于 6MiB,而且所有容器的 Limits 总和都必须小于或等于 1GiB;同样,所有容器的 CPU Requests 总和都必须大于或等于 200m,而且所有容器的 CPU Limits 总和都必须小于或等于 2。
-
Pod里任何容器的 Limits 与 Requests 的比例都不能超过 Container 的Max Limit / Requests Ratio;Pod 里所有容器的 Limits 总和与 Requests 总和的比例都不能超过 Pod 的 Max Limit / Requests Ratio。
3. 创建 Pod 时触发 LimitRange 限制
命名空间中的 LimitRange 只会在 Pod 创建或者更新时执行检查。如果手动修改 LimitRange 为一个新的值,那么这个新的值不会去检查或限制之前已经在该命名空间中创建好的 Pod。
如果在创建 Pod 时配置的资源值(CPU 或者内存)超出了 LimitRange 的限制,那么该创建过程会报错,在错误信息中会说明详细的错误原因。
下面通过创建一个单容器 Pod 来展示默认限制是如何被配置到 Pod 上的:
[root@master1 ~]# kubectl run nginx --image=nginx --replicas=1 --namespace=limit-example
Flag --replicas has been deprecated, has no effect and will be removed in the future.
pod/nginx created
查看已创建的Pod:
[root@master1 ~]# kubectl get pods --namespace=limit-example
NAME READY STATUS RESTARTS AGE
nginx 1/1 Running 0 2m8s
查看该 Pod 的 resources 相关信息:
[root@master1 ~]# kubectl get pods nginx --namespace=limit-example -o yaml | grep resource -C 8
resourceVersion: "489149"
selfLink: /api/v1/namespaces/limit-example/pods/nginx
uid: 6836fd71-c59f-40fc-9d86-def510525c6c
spec:
containers:
- image: nginx
imagePullPolicy: Always
name: nginx
resources:
limits:
cpu: 300m
memory: 200Mi
requests:
cpu: 200m
memory: 100Mi
terminationMessagePath: /dev/termination-log
terminationMessagePolicy: File
由于该 Pod 未配置资源 Requests 和 Limits,所以使用了 namespace limit-example 中的默认 CPU 和内存定义的 Requests 和 Limits 值。
下面通过 invalid-pod.yaml 创建一个超出资源限制的 Pod(使用 3 个 CPU):
apiVersion: v1
kind: Pod
metadata:
name: invalid-pod
spec:
containers:
- name: nginx
image: nginx
resources:
limits:
cpu: "3"
memory: 100Mi
创建该 Pod,可以看到系统报错,并且提供的错误原因为超出资源限制:
[root@master1 ~]# kubectl create -f invalid-pod.yaml --namespace=limit-example
Error from server (Forbidden): error when creating "invalid-pod.yaml": pods "invalid-pod" is forbidden: maximum cpu usage per Container is 2, but limit is 3
通过 limit-test-nginx.yaml 文件的例子展示了 LimitRange 对 maxLimitRequestRatio 的限制过程:
apiVersion: v1
kind: Pod
metadata:
name: limit-test-nginx
labels:
name: limit-test-nginx
spec:
containers:
- name: limit-test-nginx
image: nginx
resources:
limits:
cpu: "1"
memory: 512Mi
requests:
cpu: "0.8"
memory: 250Mi
由于 limit-test-nginx 这个 Pod 的全部内存 Limits 总和与 Requests 总和的比例为 512:250,大于在 LimitRange 中定义的 Pod 的最大比率为 2(maxLimitRequestRatio.memory=2),因此创建失败:
[root@master1 ~]# kubectl create -f limit-test-nginx.yaml --namespace=limit-example
Error from server (Forbidden): error when creating "limit-test-nginx.yaml": pods "limit-test-nginx" is forbidden: memory max limit to request ratio per Pod is 2, but provided ratio is 2.048000
通过 valid-pod.yaml 文件的例子为满足 LimitRange 限制的 Pod:
apiVersion: v1
kind: Pod
metadata:
name: valid-pod
labels:
name: valid-pod
spec:
containers:
- name: nginx
image: nginx
resources:
limits:
cpu: "1"
memory: 512Mi
创建 Pod 将会成功:
[root@master1 ~]# kubectl create -f valid-pod.yaml --namespace=limit-example
pod/valid-pod created
查看该 Pod 的资源信息:
[root@master1 ~]# kubectl get pods valid-pod --namespace=limit-example -o yaml | grep -C 6 resources
uid: 3aa42389-ed29-42f9-9ca6-9f6ded0d9c68
spec:
containers:
- image: nginx
imagePullPolicy: Always
name: nginx
resources:
limits:
cpu: "1"
memory: 512Mi
requests:
cpu: "1"
memory: 512Mi
可以看到该 Pod 明确的 Limits 和 Requests,因此该 Pod 不会使用在 namespace limit-example 中定义的 default 和 defaultRequests。
需要注意的是,CPU Limits 强制配置这个选项,在 Kubernetes 集群中默认是开启的;除非在部署kubelet服务时通过设置--cpu-cfs-quota=false
来关闭该限制。
参考:《Kubernetes权威指南(第五版)》