關于K8s中資源配置范圍管理(LimitRange)的一些筆記
寫在前面
分享一些 K8s 中 LimitRange 的筆記
博文內容涉及:
LimitRange 簡單介紹
LimitRange 資源對象創(chuàng)建使用
準入檢查和資源約束的一些 Demo
理解不足小伙伴幫忙指正
跳出童年時代吧,朋友,覺醒呵!--- J.J. 盧梭
LimitRange 介紹
在默認情況下,Kubernetes 不會對 Pod 做 CPU 和內存資源限制,即 Kubernetes 系統(tǒng)中任何 Pod 都可以使用其所在節(jié)點的所有可用的CPU和內存。
通過配置 Pod 的計算資源 Requests和 Limits,我們可以限制 Pod 的資源使用,配置最高要求和最低要求。
但對于 Kubernetes 集群管理員而言,為每一個 Pod 配置 Requests和Limits 是麻煩的,同時維護特別的不方便。需要考慮如何確保一個 Pod 不會壟斷命名空間內所有可用的資源。
更多時候,我們需要對集群內Requests和Limits的配置做一個全局限制。這里就要用到 Limitrange ,LimitRange 用來限制命名空間內 適用的對象類別 (例如 Pod 或 PersistentVolumeClaim) 指定的資源分配量(限制和請求)的一個策略對象。對 Pod 和容器的 Requests 和 Limits 配置做進一步做出限制。
LimitRange 可以做什么:
在一個命名空間中實施對每個 Pod 或 Container 最小和最大的資源使用量的限制。
在一個命名空間中實施對每個 PersistentVolumeClaim 能申請的最小和最大的存儲空間大小的限制。
在一個命名空間中實施對一種資源的 申請值和限制值 的 比值的控制 。
設置一個命名空間中對計算資源的默認申請/限制值,并且自動的在運行時注入到多個Container中。
當某命名空間中有一個LimitRange對象時,會在該命名空間中實施 LimitRange 限制。
LimitRange 的名稱必須是合法的 DNS 子域名。
資源限制和請求的約束
管理員在一個命名空間內創(chuàng)建一個 LimitRange 對象。用戶在此命名空間內創(chuàng)建(或嘗試創(chuàng)建) Pod 和 PersistentVolumeClaim 等對象。
首先,LimitRanger 準入控制器對所有沒有設置計算資源需求的所有 Pod(及其容器)設置默認請求值與限制值。也就是(limits 和 Request)
其次,LimitRange 跟蹤其使用量 以保證沒有超出命名空間中存在的任意 LimitRange 所定義的最小、最大資源使用量以及使用量比值。
若嘗試創(chuàng)建或更新的對象(Pod 和 PersistentVolumeClaim)違反了 LimitRange 的約束, 向 API 服務器的請求會失敗,并返回 HTTP 狀態(tài)碼 403 Forbidden以及描述哪一項約束被違反的消息。
若你在命名空間中添加 LimitRange 啟用了對 cpu 和 memory 等計算相關資源的限制(Max,Min), 你必須指定這些值的請求使用量 requests 與限制使用量 limits ,否則,系統(tǒng)將會拒絕創(chuàng)建 Pod,除非在 LimitRange 定義 默認的 ( limits 和 requests )。
LimitRange 的 驗證僅在 Pod 準入階段進行,不對正在運行的 Pod 進行驗證。如果你添加或修改 LimitRange,命名空間中已存在的 Pod 將繼續(xù)不變。
如果命名空間中存在兩個或更多 LimitRange 對象,應用哪個默認值是不確定的。
創(chuàng)建 LimitsRange 對象
將 LimitsRange 應用到一個 Kubernetes 的命名空間中,需要先定義一個 LimitRange ,定義最大及最小范圍、Requests 和 Limits 的 默認值、Limits 與 Requests 的最大比例上限等。
創(chuàng)建一個命名空間
┌──[root@vms81.liruilongs.github.io]-[/]
└─$kubectl create ns limitrange-example
namespace/limitrange-example created
┌──[root@vms81.liruilongs.github.io]-[/]
└─$vim limit.yaml
編寫一個 LimitRange ,并運行
┌──[root@vms81.liruilongs.github.io]-[/]
└─$kubectl apply -f limit.yaml -n limitrange-example
limitrange/mylimits created
查看狀態(tài)
┌──[root@vms81.liruilongs.github.io]-[/]
└─$kubectl get limitRange -n limitrange-example
NAME CREATED AT
mylimits 2022-11-06T17:56:20Z
資源文件信息
┌──[root@vms81.liruilongs.github.io]-[/]
└─$cat limit.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 #0.1C
memory: 3Mi
maxLimitRequestRatio:
cpu: 5
memory: 4
type: Container
上面的 資源文件是相對全的一個資源文件的定義(不涉及PVC),查看定義的詳細信息
┌──[root@vms81.liruilongs.github.io]-[/]
└─$kubectl describe limitRange mylimits -n limitrange-example
Name: mylimits
Namespace: limitrange-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
┌──[root@vms81.liruilongs.github.io]-[/]
└─$
在定義 LimitRange 時,當 LimitRange 中 container 類型限制沒有指定 Limits 和 Requests 的默認值時,會使用 Man 作為默認值
┌──[root@vms81.liruilongs.github.io]-[/]
└─$cat limit-Max.yaml
apiVersion: v1
kind: LimitRange
metadata:
name: mylimits
spec:
limits:
- max:
cpu: "2"
memory: 1Gi
min:
cpu: 100m
memory: 3Mi
type: Container
┌──[root@vms81.liruilongs.github.io]-[/]
└─$kubectl apply -f limit-Max.yaml -n limitrange-example
limitrange/mylimits created
┌──[root@vms81.liruilongs.github.io]-[/]
└─$kubectl describe limitranges mylimits -n limitrange-example
Name: mylimits
Namespace: limitrange-example
Type Resource Min Max Default Request Default Limit Max Limit/Request Ratio
---- -------- --- --- --------------- ------------- -----------------------
Container cpu 100m 2 2 2 -
Container memory 3Mi 1Gi 1Gi 1Gi -
具體的屬性解釋
在 LimitRange 中整體分為兩部分,pod 部分和 Container(容器) 部分,Pod 和 Container 都可以設置 Min、Max和 Max Limit/Requests Ratio參數(shù)。分別來看下,
對于容器部分:
不同的是 Container 還可以設置 Default Request 和 Default Limit 參數(shù),而 Pod 不能設置 Default Request和 Default Limit 參數(shù)。
Container 的 Min (100m 和 3Mi)是 Pod 中所有容器的 Requests 值下限,即創(chuàng)建 pod 等資源時,申請值 Requests 的值不能低于 Min 的值,否則提示違反約束
Container 的 Max (2C 和 1Gi)是 Pod 中所有容器的 Limits 值上限,同理, 限制 資源使用 Limits 不能超過 2000m、 1Gi( 二進制的字節(jié)表示) ;
Container 的 Default Request (200m 和 100Mi)是 Pod 中所有未指定 Requests 值的容器的默認 Requests 值;
Container 的 Default Limit (300m 和 200Mi)是 Pod 中所有未指定 Limits 值的容器的默認 Limits 值。
Container 的 Max Limit/Requests Ratio (5 和 4)限制了 Pod 中所有容器的 Limits 值與 Requests 值的比例上限;
Type Resource Min Max Default Request Default Limit Max Limit/Request Ratio
---- -------- --- --- --------------- ------------- -----------------------
..............
Container cpu 100m 2 200m 300m 5
Container memory 3Mi 1Gi 100Mi 200Mi 4
當創(chuàng)建的容器未指定 Requests 值或者 Limits 值時,將使用 Container 的 Default Request 值或者 Default Limit 值。
┌──[root@vms81.liruilongs.github.io]-[/]
└─$kubectl describe limitranges mylimits -n limitrange-example
Name: mylimits
Namespace: limitrange-example
Type Resource Min Max Default Request Default Limit Max Limit/Request Ratio
---- -------- --- --- --------------- ------------- -----------------------
Container cpu 100m 2 200m 300m 5
Container memory 3Mi 1Gi 100Mi 200Mi 4
┌──[root@vms81.liruilongs.github.io]-[/]
└─$cat pod1.yaml
apiVersion: v1
kind: Pod
metadata:
creationTimestamp: null
labels:
run: pod-demo
name: pod-demo
spec:
containers:
- image: nginx
imagePullPolicy: IfNotPresent
name: pod-demo
resources:
dnsPolicy: ClusterFirst
restartPolicy: Always
status: {}
┌──[root@vms81.liruilongs.github.io]-[/]
└─$
沒有指定時,會使用默認值
┌──[root@vms81.liruilongs.github.io]-[/]
└─$kubectl get pods pod-demo -n limitrange-example -o json | jq .spec.containers[0].resources
{
"limits": {
"cpu": "300m",
"memory": "200Mi"
},
"requests": {
"cpu": "200m",
"memory": "100Mi"
}
}
對于同一資源類型,這 4 個參數(shù)必須滿足以下關系:Min ≤ Default Request ≤ Default Limit ≤ Max。
對于 Pod 部分:
這里需要注意的是容器的總和:
Pod 的 Min(200m 和 6Mi)是 Pod 中所有容器的 Requests 值的 總和 下限;
Pod 的 Max(4 和 2Gi)是 Pod 中所有容器的 Limits 值的 總和 上限。
Pod 的 Max Limit/Requests Ratio (3 和 2)限制了 Pod 中所有容器的 Limits 值總和與 Requests 值總和的比例上限。
Type Resource Min Max Default Request Default Limit Max Limit/Request Ratio
---- -------- --- --- --------------- ------------- -----------------------
Pod cpu 200m 4 - - 3
Pod memory 6Mi 2Gi - - 2
........
對于任意一個 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
準入檢查 Demo
當前的 LimitRange 定義為:
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
當容器中定義的申請的最小 request 值 大于 LimitRange 默認定義的限制資源 limits 的值時,是無法調度的。在上面定義了 Limitrange 的命名空間內創(chuàng)建一個 pod, 沒有指定 limits 所以使用默認的 limits 值,但是默認的 limits 值 300m 小于當前 容器的值
┌──[root@vms81.liruilongs.github.io]-[~/ansible/k8s-pod-create]
└─$cat pod-demo-limitrange.yaml
apiVersion: v1
kind: Pod
metadata:
creationTimestamp: null
labels:
run: pod-demo
name: pod-demo
spec:
containers:
- image: nginx
imagePullPolicy: IfNotPresent
name: pod-demo
resources:
requests:
cpu: 500m
dnsPolicy: ClusterFirst
restartPolicy: Always
status: {}
申請的最小值大于默認的最大值,顯然不符合邏輯,所以 pod 無法調度創(chuàng)建,
┌──[root@vms81.liruilongs.github.io]-[~/ansible/k8s-pod-create]
└─$kubectl apply -f pod-demo-limitrange.yaml -n limitrange-example
The Pod "pod-demo" is invalid: spec.containers[0].resources.requests: Invalid value: "500m": must be less than or equal to cpu limit
如果同時設置了 requests 和 limits,那么 limits 不使用默認值
┌──[root@vms81.liruilongs.github.io]-[~/ansible/k8s-pod-create]
└─$cat pod-demo-limitrange.yaml
apiVersion: v1
kind: Pod
metadata:
creationTimestamp: null
labels:
run: pod-demo
name: pod-demo
spec:
containers:
- image: nginx
imagePullPolicy: IfNotPresent
name: pod-demo
resources:
requests:
cpu: 500m
limits:
cpu: 800m
dnsPolicy: ClusterFirst
restartPolicy: Always
status: {}
新 Pod 會被成功調度,但是這里需要注意的是, requests 和 limits 要符合 Limitrange 中 容器的MAX,MIN配置
┌──[root@vms81.liruilongs.github.io]-[~/ansible/k8s-pod-create]
└─$kubectl apply -f pod-demo-limitrange.yaml -n limitrange-example
pod/pod-demo created
┌──[root@vms81.liruilongs.github.io]-[~/ansible/k8s-pod-create]
└─$kubectl get pods -n limitrange-example
NAME READY STATUS RESTARTS AGE
pod-demo 1/1 Running 0 11s
Max 限制 ,當 Limits 大于 Max 值時,Pod 不會創(chuàng)建成功, 我的定義如下一個 LimiRanga 的資源對象
┌──[root@vms81.liruilongs.github.io]-[/]
└─$kubectl describe limitranges -n limitrange-example mylimits
Name: mylimits
Namespace: limitrange-example
Type Resource Min Max Default Request Default Limit Max Limit/Request Ratio
---- -------- --- --- --------------- ------------- -----------------------
Container cpu 100m 2 2 2 -
Container memory 3Mi 1Gi 1Gi 1Gi -
┌──[root@vms81.liruilongs.github.io]-[/]
└─$
當前的命名空間限制 容器 Limits CUP 大小為 2C ,這里創(chuàng)建一個 3C 的 容器來看下
┌──[root@vms81.liruilongs.github.io]-[/]
└─$cat pod1.yaml
apiVersion: v1
kind: Pod
metadata:
creationTimestamp: null
labels:
run: pod-demo
name: pod-demo
spec:
containers:
- image: nginx
imagePullPolicy: IfNotPresent
name: pod-demo
resources:
limits:
cpu: '3'
dnsPolicy: ClusterFirst
restartPolicy: Always
status: {}
┌──[root@vms81.liruilongs.github.io]-[/]
└─$
創(chuàng)建失敗,提示不滿足準入規(guī)則
┌──[root@vms81.liruilongs.github.io]-[/]
└─$kubectl apply -f pod1.yaml -n limitrange-example
Error from server (Forbidden): error when creating "pod1.yaml": pods "pod-demo" is forbidden: maximum cpu usage per Container is 2, but limit is 3
Max Limit/Request Ratio 限制 ,當 Limit/Request 的比值 超過 Max Limit/Request Ratio 時調度失敗
定義如下一個 LimitRange :
┌──[root@vms81.liruilongs.github.io]-[/]
└─$cat limit-Ratio.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
┌──[root@vms81.liruilongs.github.io]-[/]
└─$vim limit-Ratio.yaml
┌──[root@vms81.liruilongs.github.io]-[/]
└─$kubectl apply -f limit-Ratio.yaml -n limitrange-example
limitrange/mylimits configured
生成的 規(guī)則如下:
┌──[root@vms81.liruilongs.github.io]-[/]
└─$kubectl describe limitranges -n limitrange-example mylimits
Name: mylimits
Namespace: limitrange-example
Type Resource Min Max Default Request Default Limit Max Limit/Request Ratio
---- -------- --- --- --------------- ------------- -----------------------
Pod cpu 200m 4 - - 3
Pod memory 6Mi 2Gi - - 2
┌──[root@vms81.liruilongs.github.io]-[/]
└─$
可以看到 限制 pod 中 cpu 的 Max Limit/Request Ratio 比值 為 3,即 Requests 是 Limits 的 3 倍,最大和小之間最多可以相差 2 個單位
┌──[root@vms81.liruilongs.github.io]-[/]
└─$cat pod1.yaml
apiVersion: v1
kind: Pod
metadata:
creationTimestamp: null
labels:
run: pod-demo
name: pod-demo
spec:
containers:
- image: nginx
imagePullPolicy: IfNotPresent
name: pod-demo
resources:
limits:
cpu: '4'
requests:
cpu: '1'
dnsPolicy: ClusterFirst
restartPolicy: Always
status: {}
我們創(chuàng)建這樣一個 pod ,cpu 總和 最大和最小相差 3 個單位,Requests 是 Limits 的 4 倍
┌──[root@vms81.liruilongs.github.io]-[/]
└─$kubectl apply -f pod1.yaml -n limitrange-example
Error from server (Forbidden): error when creating "pod1.yaml": pods "pod-demo" is forbidden: [minimum memory usage per Pod is 6Mi. No request is specified, maximum memory usage per Pod is 2Gi. No limit is specified, cpu max limit to request ratio per Pod is 3, but provided ratio is 4.000000, memory max limit to request ratio per Pod is 2, but no request is specified or request is 0]
┌──[root@vms81.liruilongs.github.io]-[/]
└─$
可以看到提示準入規(guī)則校驗失敗。相差了 4 倍不符合要求
Pod 的 Limits 和 Requests 限制 ,當設置了 Pod 的 Max 和 Min 、Max Limit/Request Ratio 時,如果沒有定義對應的 Limits 和 Requests ,則創(chuàng)建失敗.
還使用之前的 Limitrange,
Namespace: limitrange-example
Type Resource Min Max Default Request Default Limit Max Limit/Request Ratio
---- -------- --- --- --------------- ------------- -----------------------
Pod cpu 200m 4 - - 3
Pod memory 6Mi 2Gi - - 2
創(chuàng)建一個 pod ,只定義 cpu 的相關屬性,沒有定義 memory 相關屬性
┌──[root@vms81.liruilongs.github.io]-[/]
└─$cat pod1.yaml
apiVersion: v1
kind: Pod
metadata:
creationTimestamp: null
labels:
run: pod-demo
name: pod-demo
spec:
containers:
- image: nginx
imagePullPolicy: IfNotPresent
name: pod-demo
resources:
limits:
cpu: '4'
requests:
cpu: '1'
dnsPolicy: ClusterFirst
restartPolicy: Always
status: {}
Limitrange 中定義了 Max 所以必須要設置 Limit ,設置了 Min ,需要設置 Request。
┌──[root@vms81.liruilongs.github.io]-[/]
└─$kubectl apply -f pod1.yaml -n limitrange-example
Error from server (Forbidden): error when creating "pod1.yaml": pods "pod-demo" is forbidden: [minimum memory usage per Pod is 6Mi. No request is specified, maximum memory usage per Pod is 2Gi. No limit is specified, memory max limit to request ratio per Pod is 2, but no request is specified or request is 0]
創(chuàng)建失敗 ,提示,沒有內存相關的資源限制定義
資源約束 Demo
為命名空間配置 CPU 最小和最大約束
┌──[root@vms81.liruilongs.github.io]-[~/ansible/k8s-pod-create]
└─$kubectl create namespace constraints-cpu-example
namespace/constraints-cpu-example created
┌──[root@vms81.liruilongs.github.io]-[~/ansible/k8s-pod-create]
└─$vim cpu-constraints.yaml
┌──[root@vms81.liruilongs.github.io]-[~/ansible/k8s-pod-create]
└─$kubectl apply -f cpu-constraints.yaml -n constraints-cpu-example
limitrange/cpu-min-max-demo-lr created
創(chuàng)建 LimitRange yaml 文件
┌──[root@vms81.liruilongs.github.io]-[~/ansible/k8s-pod-create]
└─$ cat cpu-constraints.yaml
apiVersion: v1
kind: LimitRange
metadata:
name: cpu-min-max-demo-lr
spec:
limits:
- max:
cpu: "800m"
min:
cpu: "200m"
type: Container
┌──[root@vms81.liruilongs.github.io]-[~/ansible/k8s-pod-create]
└─$
輸出結果顯示 CPU 的最小和最大限制符合預期。但需要注意的是,盡管你在 LimitRange 的配置文件中你沒有聲明默認值,默認值也會被自動創(chuàng)建。默人資源限制為 limits 和 requests 都是 max 的值
┌──[root@vms81.liruilongs.github.io]-[~/ansible/k8s-pod-create]
└─$kubectl describe limitrange cpu-min-max-demo-lr -n constraints-cpu-example
Name: cpu-min-max-demo-lr
Namespace: constraints-cpu-example
Type Resource Min Max Default Request Default Limit Max Limit/Request Ratio
---- -------- --- --- --------------- ------------- -----------------------
Container cpu 200m 800m 800m 800m -
┌──[root@vms81.liruilongs.github.io]-[~/ansible/k8s-pod-create]
└─$
創(chuàng)建一個不定義 資源限制 pod
┌──[root@vms81.liruilongs.github.io]-[~/ansible/k8s-pod-create]
└─$kubectl run pod-demo-limitrange --image=nginx --image-pull-policy=IfNotPresent -n constraints-cpu-e
xample
pod/pod-demo-limitrange created
┌──[root@vms81.liruilongs.github.io]-[~/ansible/k8s-pod-create]
└─$kubectl get pods -n constraints-cpu-example
NAME READY STATUS RESTARTS AGE
pod-demo-limitrange 1/1 Running 0 30s
可以看到使用了默認值,當前 pod 的 limits 值為 800m,requests 值為 800m,即最少為 800m pod 才能被調度,超過 800m 。pod 被 kill
┌──[root@vms81.liruilongs.github.io]-[~/ansible/k8s-pod-create]
└─$kubectl get pods pod-demo-limitrange -n constraints-cpu-example -o json | jq .spec.containers[0].resources
{
"limits": {
"cpu": "800m"
},
"requests": {
"cpu": "800m"
}
}
這里的 demo 官網文檔有比較全面的描述, 感興趣小伙伴可以看看,https://kubernetes.io/zh-cn/docs/concepts/policy/limit-range/ ,這里不多介紹
最后看下 使用 LimitRange 限制 PVC 的使用
┌──[root@vms81.liruilongs.github.io]-[/]
└─$cat limit-pvc.yaml
apiVersion: v1
kind: LimitRange
metadata:
name: storagelimits
spec:
limits:
- type: PersistentVolumeClaim
max:
storage: 2Gi
min:
storage: 1Gi
定義資源,查看限制信息
┌──[root@vms81.liruilongs.github.io]-[/]
└─$kubectl apply -f limit-pvc.yaml -n limitrange-example
limitrange/storagelimits created
┌──[root@vms81.liruilongs.github.io]-[/]
└─$kubectl describe limitranges -n limitrange-example
Name: storagelimits
Namespace: limitrange-example
Type Resource Min Max Default Request Default Limit Max Limit/Request Ratio
---- -------- --- --- --------------- ------------- -----------------------
PersistentVolumeClaim storage 1Gi 2Gi - - -
┌──[root@vms81.liruilongs.github.io]-[/]
└─$
關于 LimitRange 資源對象和小伙伴們分享到這樣,之前會陸續(xù)分享一些其他資源管理的筆記, 生活加油哦 ^_^
博文參考
《Kubernetes 權威指南 第四版 》
https://kubernetes.io/zh-cn/docs/concepts/policy/limit-range/
作者:山河已無恙
歡迎關注微信公眾號 :山河已無恙