本文主要基於Kubernetes1.21.9和Linux作業系統CentOS7.4。
伺服器版本 | docker軟體版本 | Kubernetes(k8s)叢集版本 | CPU架構 |
---|---|---|---|
CentOS Linux release 7.4.1708 (Core) | Docker version 20.10.12 | v1.21.9 | x86_64 |
Kubernetes叢集架構:k8scloude1作為master節點,k8scloude2,k8scloude3作為worker節點。
伺服器 | 作業系統版本 | CPU架構 | 程序 | 功能描述 |
---|---|---|---|---|
k8scloude1/192.168.110.130 | CentOS Linux release 7.4.1708 (Core) | x86_64 | docker,kube-apiserver,etcd,kube-scheduler,kube-controller-manager,kubelet,kube-proxy,coredns,calico | k8s master節點 |
k8scloude2/192.168.110.129 | CentOS Linux release 7.4.1708 (Core) | x86_64 | docker,kubelet,kube-proxy,calico | k8s worker節點 |
k8scloude3/192.168.110.128 | CentOS Linux release 7.4.1708 (Core) | x86_64 | docker,kubelet,kube-proxy,calico | k8s worker節點 |
在Kubernetes中,資源限制是一種管理和控制容器資源使用的重要機制。通過資源限制,我們可以為容器分配適當的計算資源,確保叢集的穩定性和效能。
本篇部落格將介紹Kubernetes中的資源限制的概念,並詳細說明如何使用resources
、LimitRange
和ResourceQuota
來管理容器資源。
使用Kubernetes資源限制的前提是已經有一套可以正常執行的Kubernetes叢集,關於Kubernetes(k8s)叢集的安裝部署,可以檢視部落格《Centos7 安裝部署Kubernetes(k8s)叢集》https://www.cnblogs.com/renshengdezheli/p/16686769.html。
在Kubernetes中,資源限制是一種指定容器在節點上可使用的資源量的方法。資源主要包括計算資源(如CPU和記憶體),還可以包括其他擴充套件資源(如GPU、儲存等)。通過資源限制,我們可以控制容器對叢集資源的使用,並確保不同容器之間的資源分配合理,避免資源競爭和衝突。
在kubernetes叢集的所有節點下載centos映象。
[root@k8scloude1 ~]# cd safe/
[root@k8scloude1 safe]# docker pull hub.c.163.com/library/centos:latest
[root@k8scloude2 ~]# docker pull hub.c.163.com/library/centos:latest
[root@k8scloude3 ~]# docker pull hub.c.163.com/library/centos:latest
準備好memload安裝包,memload是記憶體消耗測試工具。
[root@k8scloude1 safe]# ls memload-7.0-1.r29766.x86_64.rpm
memload-7.0-1.r29766.x86_64.rpm
如下yaml檔案功能為:使用hub.c.163.com/library/centos:latest映象建立一個休眠10000000秒的pod。
[root@k8scloude1 safe]# vim pod.yaml
[root@k8scloude1 safe]# cat pod.yaml
apiVersion: v1
kind: Pod
metadata:
labels:
test: podtest
name: podtest
spec:
#當需要關閉容器時,立即殺死容器而不等待預設的30秒優雅停機時長。
terminationGracePeriodSeconds: 0
containers:
- name: centos
image: hub.c.163.com/library/centos:latest
#imagePullPolicy: IfNotPresent:表示如果本地已經存在該映象,則不重新下載;否則從遠端 Docker Hub 下載該映象
imagePullPolicy: IfNotPresent
#command: ["sh","-c","sleep 10000000"]指定容器啟動時要執行的命令,這裡是在容器內部執行一個sleep命令,休眠時間為10000000秒。
command: ["sh","-c","sleep 10000000"]
resources: {}
dnsPolicy: ClusterFirst
restartPolicy: Always
status: {}
建立pod。
[root@k8scloude1 safe]# kubectl apply -f pod.yaml
pod/podtest created
檢視pod,可以看到pod執行在k8scloude2節點上。
[root@k8scloude1 safe]# kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
podtest 1/1 Running 0 7s 10.244.112.180 k8scloude2 <none> <none>
把memload安裝包拷貝到pod裡面。
[root@k8scloude1 safe]# kubectl cp memload-7.0-1.r29766.x86_64.rpm podtest:/opt
進入pod裡面。
[root@k8scloude1 safe]# kubectl exec -it podtest -- bash
#memload-7.0-1.r29766.x86_64.rpm安裝包已經在容器裡了
[root@podtest /]# ls /opt/
memload-7.0-1.r29766.x86_64.rpm
#安裝memload
[root@podtest /]# rpm -ivh /opt/memload-7.0-1.r29766.x86_64.rpm
Preparing... ################################# [100%]
Updating / installing...
1:memload-7.0-1.r29766 ################################# [100%]
#在pod裡面執行memload 1024,使其消耗1024M的記憶體
[root@podtest /]# memload 1024
Attempting to allocate 1024 Mebibytes of resident memory...
^C
因為podtest執行在k8scloude2節點上,所以在k8scloude2節點上觀察記憶體消耗情況,podtest裡沒執行memload 1024之前,k8scloude2節點記憶體消耗情況如下。
[root@k8scloude2 ~]# free -m
total used free shared buff/cache available
Mem: 2920 692 660 17 1567 1910
Swap: 0 0 0
在podtest裡執行memload 1024之後,k8scloude2節點記憶體消耗情況如下。
[root@k8scloude2 ~]# free -m
total used free shared buff/cache available
Mem: 2920 1718 101 17 1099 886
Swap: 0 0 0
podtest裡取消執行memload 1024之後,記憶體消耗降下來了。
[root@k8scloude2 ~]# free -m
total used free shared buff/cache available
Mem: 2920 688 1126 17 1105 1916
Swap: 0 0 0
在podtest裡繼續執行memload 1500,使其消耗1500M的記憶體。
[root@podtest /]# memload 1500
Attempting to allocate 1500 Mebibytes of resident memory...
^C
在k8scloude2節點上繼續觀察記憶體消耗。
首先清除一下快取。
[root@k8scloude2 ~]# echo 3 > /proc/sys/vm/drop_caches
podtest裡沒執行memload 1500之前,k8scloude2節點記憶體消耗情況如下。
[root@k8scloude2 ~]# free -m
total used free shared buff/cache available
Mem: 2920 670 1770 17 479 1957
Swap: 0 0 0
在podtest裡執行memload 1500之後,k8scloude2節點記憶體消耗情況如下。
[root@k8scloude2 ~]# free -m
total used free shared buff/cache available
Mem: 2920 2178 134 17 607 448
Swap: 0 0 0
podtest裡取消執行memload 1500之後,記憶體消耗降下來了。
[root@k8scloude2 ~]# free -m
total used free shared buff/cache available
Mem: 2920 671 1640 17 608 1956
Swap: 0 0 0
刪除pod。
[root@k8scloude1 safe]# kubectl get pod
NAME READY STATUS RESTARTS AGE
podtest 1/1 Running 0 26m
[root@k8scloude1 safe]# kubectl delete pod podtest
pod "podtest" deleted
[root@k8scloude1 safe]# kubectl get pod
No resources found in safe namespace.
由此我們可以發現:現在沒有對pod進行資源限制,pod可以無限制的使用記憶體,CPU等等,接下來對pod進行資源限制。
在Kubernetes中,resources
欄位是一種用於定義和管理容器資源需求和限制的物件。通過指定資源請求和限制,Kubernetes可以根據叢集的可用資源進行排程和管理。
資源包括計算資源(如CPU和記憶體)以及其他可選的擴充套件資源(如GPU、儲存等)。通過合理設定資源,我們可以避免容器之間的資源競爭和衝突,提高應用程式的效能和可靠性。
修改yaml檔案,對pod的資源限制可以通過pod裡的resource欄位來限制,resources裡的requests欄位表示容器所在節點資源的最小值,最低要求,滿足不了這個要求pod建立不成功。
requests:memory: 100Gi表示podtest最低要求100Gi記憶體,滿足不了,pod就建立失敗。
[root@k8scloude1 safe]# vim pod.yaml
[root@k8scloude1 safe]# cat pod.yaml
apiVersion: v1
kind: Pod
metadata:
labels:
test: podtest
name: podtest
spec:
#當需要關閉容器時,立即殺死容器而不等待預設的30秒優雅停機時長。
terminationGracePeriodSeconds: 0
containers:
- name: centos
image: hub.c.163.com/library/centos:latest
#imagePullPolicy: IfNotPresent:表示如果本地已經存在該映象,則不重新下載;否則從遠端 Docker Hub 下載該映象
imagePullPolicy: IfNotPresent
#command: ["sh","-c","sleep 10000000"]指定容器啟動時要執行的命令,這裡是在容器內部執行一個sleep命令,休眠時間為10000000秒。
command: ["sh","-c","sleep 10000000"]
resources:
#requests:memory: 100Gi表示podtest最低要求100Gi記憶體,滿足不了pod就建立失敗。
requests:
memory: 100Gi
dnsPolicy: ClusterFirst
restartPolicy: Always
status: {}
建立pod。
[root@k8scloude1 safe]# kubectl apply -f pod.yaml
pod/podtest created
檢視pod,我們現在的機器環境滿足不了100G的記憶體要求,所以pod狀態為Pending。
[root@k8scloude1 safe]# kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
podtest 0/1 Pending 0 9s <none> <none> <none> <none>
刪除pod。
[root@k8scloude1 safe]# kubectl delete pod podtest
pod "podtest" deleted
修改yaml檔案,requests:cpu: 4 表示podtest最低要求有4核CPU,滿足不了,pod就建立失敗。
[root@k8scloude1 safe]# vim pod.yaml
[root@k8scloude1 safe]# cat pod.yaml
apiVersion: v1
kind: Pod
metadata:
labels:
test: podtest
name: podtest
spec:
#當需要關閉容器時,立即殺死容器而不等待預設的30秒優雅停機時長。
terminationGracePeriodSeconds: 0
containers:
- name: centos
image: hub.c.163.com/library/centos:latest
#imagePullPolicy: IfNotPresent:表示如果本地已經存在該映象,則不重新下載;否則從遠端 Docker Hub 下載該映象
imagePullPolicy: IfNotPresent
#command: ["sh","-c","sleep 10000000"]指定容器啟動時要執行的命令,這裡是在容器內部執行一個sleep命令,休眠時間為10000000秒。
command: ["sh","-c","sleep 10000000"]
resources:
#requests:cpu: 4 表示podtest最低要求有4核CPU,滿足不了,pod就建立失敗
requests:
cpu: 4
dnsPolicy: ClusterFirst
restartPolicy: Always
status: {}
建立pod。
[root@k8scloude1 safe]# kubectl apply -f pod.yaml
pod/podtest created
檢視pod,4核CPU無法滿足,pod狀態為Pending。
[root@k8scloude1 safe]# kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
podtest 0/1 Pending 0 13s <none> <none> <none> <none>
刪除pod。
[root@k8scloude1 safe]# kubectl delete pod podtest
pod "podtest" deleted
修改yaml檔案,requests:cpu: 3 表示podtest最低要求有3核CPU,滿足不了,pod就建立失敗。
[root@k8scloude1 safe]# vim pod.yaml
[root@k8scloude1 safe]# cat pod.yaml
apiVersion: v1
kind: Pod
metadata:
labels:
test: podtest
name: podtest
spec:
terminationGracePeriodSeconds: 0
containers:
- name: centos
image: hub.c.163.com/library/centos:latest
imagePullPolicy: IfNotPresent
command: ["sh","-c","sleep 10000000"]
resources:
#requests:cpu: 3 表示podtest最低要求有3核CPU,滿足不了,pod就建立失敗
requests:
cpu: 3
dnsPolicy: ClusterFirst
restartPolicy: Always
status: {}
建立pod。
[root@k8scloude1 safe]# kubectl apply -f pod.yaml
pod/podtest created
requests:cpu: 3 要求有3核CPU之後,podtest滿足條件,pod就執行起來了。requests:cpu: 3 可以換成requests:cpu: 3000m ,兩者是等價的,1核等於1000個微核心。
[root@k8scloude1 safe]# kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
podtest 1/1 Running 0 4s 10.244.112.170 k8scloude2 <none> <none>
檢視節點負載。
[root@k8scloude1 safe]# kubectl top node
W0323 08:56:05.755124 39033 top_node.go:119] Using json format to get metrics. Next release will switch to protocol-buffers, switch early by passing --use-protocol-buffers flag
NAME CPU(cores) CPU% MEMORY(bytes) MEMORY%
k8scloude1 311m 7% 1429Mi 50%
k8scloude2 172m 4% 839Mi 29%
k8scloude3 188m 4% 959Mi 34%
檢視safe名稱空間的pod負載。
[root@k8scloude1 safe]# kubectl top pod -n safe
W0323 08:56:47.844614 39714 top_pod.go:140] Using json format to get metrics. Next release will switch to protocol-buffers, switch early by passing --use-protocol-buffers flag
NAME CPU(cores) MEMORY(bytes)
podtest 0m 2Mi
刪除pod。
[root@k8scloude1 safe]# kubectl delete pod podtest
pod "podtest" deleted
[root@k8scloude1 safe]# kubectl get pod
No resources found in safe namespace.
修改yaml檔案,resources:limits表示容器消耗資源最大值,limits: memory: 500Mi 表示容器最多消耗500M記憶體,requests:cpu: 300m 表示podtest最低要求有300個微核心,滿足不了,pod就建立失敗。
[root@k8scloude1 safe]# vim pod.yaml
[root@k8scloude1 safe]# cat pod.yaml
apiVersion: v1
kind: Pod
metadata:
labels:
test: podtest
name: podtest
spec:
#當需要關閉容器時,立即殺死容器而不等待預設的30秒優雅停機時長。
terminationGracePeriodSeconds: 0
containers:
- name: centos
image: hub.c.163.com/library/centos:latest
#imagePullPolicy: IfNotPresent:表示如果本地已經存在該映象,則不重新下載;否則從遠端 Docker Hub 下載該映象
imagePullPolicy: IfNotPresent
#command: ["sh","-c","sleep 10000000"]指定容器啟動時要執行的命令,這裡是在容器內部執行一個sleep命令,休眠時間為10000000秒。
command: ["sh","-c","sleep 10000000"]
resources:
#requests:cpu: 300m 表示podtest最低要求有300個微核心,滿足不了,pod就建立失敗
requests:
cpu: 300m
#limits: memory: 500Mi 表示容器最多消耗500M記憶體
limits:
memory: 500Mi
dnsPolicy: ClusterFirst
restartPolicy: Always
status: {}
建立pod。
[root@k8scloude1 safe]# kubectl apply -f pod.yaml
pod/podtest created
檢視pod,pod建立成功。
[root@k8scloude1 safe]# kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
podtest 1/1 Running 0 7s 10.244.112.188 k8scloude2 <none> <none>
再次進行資源消耗測試,把memload-7.0-1.r29766.x86_64.rpm安裝包拷貝到podtest裡。
[root@k8scloude1 safe]# kubectl cp memload-7.0-1.r29766.x86_64.rpm podtest:/opt
進入pod。
[root@k8scloude1 safe]# kubectl exec -it podtest -- bash
#安裝memload
[root@podtest /]# rpm -ivh /opt/memload-7.0-1.r29766.x86_64.rpm
Preparing... ################################# [100%]
Updating / installing...
1:memload-7.0-1.r29766 ################################# [100%]
#memload 1024消耗1024M記憶體就自動 killed了
[root@podtest /]# memload 1024
Attempting to allocate 1024 Mebibytes of resident memory...
Killed
#memload 600消耗600M記憶體就自動 killed了
[root@podtest /]# memload 600
Attempting to allocate 600 Mebibytes of resident memory...
Killed
#memload 490消耗490M記憶體就可以
[root@podtest /]# memload 490
Attempting to allocate 490 Mebibytes of resident memory...
^C
#退出pod
[root@podtest /]# exit
exit
command terminated with exit code 130
可以發現記憶體消耗不能大於limits:memory: 500Mi,大於500M的記憶體設定就會OOM Killed,資源限制成功。
刪除pod。
[root@k8scloude1 safe]# kubectl delete pod podtest
pod "podtest" deleted
[root@k8scloude1 safe]# kubectl get pod
No resources found in safe namespace.
LimitRange
是一種用於限制容器資源使用的設定物件。它允許叢集管理員定義資源的最小和最大限制,並確保容器在這些限制範圍內使用資源。
通過使用LimitRange
,可以避免容器使用過多或過少的資源,保護叢集免受資源耗盡和應用程式崩潰的影響。
預設情況下, Kubernetes 叢集上的容器執行使用的計算資源沒有限制。 使用 Kubernetes 資源配額, 管理員(也稱為 叢集操作者)可以在一個指定的名稱空間內限制叢集資源的使用與建立。 在名稱空間中,一個 Pod 最多能夠使用名稱空間的資源配額所定義的 CPU 和記憶體用量。 作為叢集操作者或名稱空間級的管理員,你可能也會擔心如何確保一個 Pod 不會壟斷名稱空間內所有可用的資源。
LimitRange 是限制名稱空間內可為每個適用的物件類別 (例如 Pod 或 PersistentVolumeClaim) 指定的資源分配量(限制和請求)的策略物件。
一個 LimitRange(限制範圍) 物件提供的限制能夠做到:
在一個名稱空間中實施對每個 Pod 或 Container 最小和最大的資源使用量的限制。
在一個名稱空間中實施對每個 PersistentVolumeClaim 能申請的最小和最大的儲存空間大小的限制。
在一個名稱空間中實施對一種資源的申請值和限制值的比值的控制。
設定一個名稱空間中對計算資源的預設申請/限制值,並且自動的在執行時注入到多個 Container 中。
當某名稱空間中有一個 LimitRange 物件時,將在該名稱空間中實施 LimitRange 限制。
如下LimitRange的功能為:建立了一個名為"mem-limit-range"的LimitRange資源物件,用於限制容器的記憶體使用範圍。容器的記憶體限制在256Mi到512Mi之間,並且僅適用於容器。
[root@k8scloude1 safe]# vim limitRange.yaml
[root@k8scloude1 safe]# cat limitRange.yaml
apiVersion: v1
kind: LimitRange
metadata:
name: mem-limit-range
spec:
limits:
#memory: 512Mi:設定容器的最大記憶體限制為512MiB。
- max:
memory: 512Mi
#memory: 256Mi:設定容器的最小記憶體限制為256MiB。
min:
memory: 256Mi
#type: Container:指定這些限制適用於容器。
type: Container
建立LimitRange。
[root@k8scloude1 safe]# kubectl apply -f limitRange.yaml
limitrange/mem-limit-range created
檢視LimitRange。
[root@k8scloude1 safe]# kubectl get LimitRange
NAME CREATED AT
mem-limit-range 2022-03-23T01:23:04Z
[root@k8scloude1 safe]# kubectl get -f limitRange.yaml
NAME CREATED AT
mem-limit-range 2022-03-23T01:23:04Z
檢視mem-limit-range的描述資訊。
[root@k8scloude1 safe]# kubectl describe LimitRange mem-limit-range
Name: mem-limit-range
Namespace: safe
Type Resource Min Max Default Request Default Limit Max Limit/Request Ratio
---- -------- --- --- --------------- ------------- -----------------------
Container memory 256Mi 512Mi 512Mi 512Mi -
[root@k8scloude1 safe]# kubectl describe -f limitRange.yaml
Name: mem-limit-range
Namespace: safe
Type Resource Min Max Default Request Default Limit Max Limit/Request Ratio
---- -------- --- --- --------------- ------------- -----------------------
Container memory 256Mi 512Mi 512Mi 512Mi -
使用hub.c.163.com/library/centos:latest映象建立pod。
[root@k8scloude1 safe]# vim pod.yaml
[root@k8scloude1 safe]# cat pod.yaml
apiVersion: v1
kind: Pod
metadata:
labels:
test: podtest
name: podtest
spec:
#當需要關閉容器時,立即殺死容器而不等待預設的30秒優雅停機時長。
terminationGracePeriodSeconds: 0
containers:
- name: centos
image: hub.c.163.com/library/centos:latest
#imagePullPolicy: IfNotPresent:表示如果本地已經存在該映象,則不重新下載;否則從遠端 Docker Hub 下載該映象
imagePullPolicy: IfNotPresent
#command: ["sh","-c","sleep 10000000"]指定容器啟動時要執行的命令,這裡是在容器內部執行一個sleep命令,休眠時間為10000000秒。
command: ["sh","-c","sleep 10000000"]
resources: {}
dnsPolicy: ClusterFirst
restartPolicy: Always
status: {}
建立pod。
[root@k8scloude1 safe]# kubectl apply -f pod.yaml
pod/podtest created
[root@k8scloude1 safe]# kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
podtest 1/1 Running 0 7s 10.244.112.189 k8scloude2 <none> <none>
把memload安裝包拷貝到podtest裡。
[root@k8scloude1 safe]# kubectl cp memload-7.0-1.r29766.x86_64.rpm podtest:/opt
進入pod,進行記憶體消耗測試。
[root@k8scloude1 safe]# kubectl exec -it podtest -- bash
#安裝memload
[root@podtest /]# rpm -ivh /opt/memload-7.0-1.r29766.x86_64.rpm
Preparing... ################################# [100%]
Updating / installing...
1:memload-7.0-1.r29766 ################################# [100%]
#memload 1024表示消耗1024M記憶體,1024M記憶體超過limits:max:memory: 512Mi,直接就Killed
[root@podtest /]# memload 1024
Attempting to allocate 1024 Mebibytes of resident memory...
Killed
#memload 500 表示消耗500M記憶體,500M小於limits:max:memory: 512Mi,成功消耗記憶體
[root@podtest /]# memload 500
Attempting to allocate 500 Mebibytes of resident memory...
^C
[root@podtest /]# exit
exit
command terminated with exit code 130
可以發現容器記憶體設定不能超過limits:max:memory: 512Mi,成功進行資源限制。
刪除pod。
[root@k8scloude1 safe]# kubectl delete pod podtest
pod "podtest" deleted
修改yaml檔案,resources欄位和LimitRange都進行了資源限制,requests:memory: 200Mi表示podtest最低要求200Mi記憶體,滿足不了pod就建立失敗,limits: memory: 600Mi 表示容器最多消耗600Mi記憶體 。
[root@k8scloude1 safe]# vim pod.yaml
[root@k8scloude1 safe]# cat pod.yaml
apiVersion: v1
kind: Pod
metadata:
labels:
test: podtest
name: podtest
spec:
terminationGracePeriodSeconds: 0
containers:
- name: centos
image: hub.c.163.com/library/centos:latest
imagePullPolicy: IfNotPresent
command: ["sh","-c","sleep 10000000"]
resources:
#requests:memory: 200Mi表示podtest最低要求200Mi記憶體,滿足不了pod就建立失敗。
requests:
memory: 200Mi
#limits: memory: 600Mi 表示容器最多消耗600Mi記憶體
limits:
memory: 600Mi
dnsPolicy: ClusterFirst
restartPolicy: Always
status: {}
LimitRange的限制範圍為256Mi到512Mi記憶體。
[root@k8scloude1 safe]# kubectl get LimitRange
NAME CREATED AT
mem-limit-range 2022-03-23T01:23:04Z
[root@k8scloude1 safe]# kubectl describe -f limitRange.yaml
Name: mem-limit-range
Namespace: safe
Type Resource Min Max Default Request Default Limit Max Limit/Request Ratio
---- -------- --- --- --------------- ------------- -----------------------
Container memory 256Mi 512Mi 512Mi 512Mi -
建立pod,pod建立失敗,只有滿足LimitRange min <= requests <limits <= LimitRange max 條件,pod才能建立成功,resources欄位指定的記憶體範圍應該是LimitRange的真子集。
[root@k8scloude1 safe]# kubectl apply -f pod.yaml
Error from server (Forbidden): error when creating "pod.yaml": pods "podtest" is forbidden: [minimum memory usage per Container is 256Mi, but request is 200Mi, maximum memory usage per Container is 512Mi, but limit is 600Mi]
修改yaml檔案,requests:memory: 300Mi表示podtest最低要求300Mi記憶體,滿足不了pod就建立失敗,limits: memory: 500Mi 表示容器最多消耗500M記憶體 。
[root@k8scloude1 safe]# vim pod.yaml
[root@k8scloude1 safe]# cat pod.yaml
apiVersion: v1
kind: Pod
metadata:
labels:
test: podtest
name: podtest
spec:
terminationGracePeriodSeconds: 0
containers:
- name: centos
image: hub.c.163.com/library/centos:latest
imagePullPolicy: IfNotPresent
command: ["sh","-c","sleep 10000000"]
resources:
#requests:memory: 300Mi表示podtest最低要求300Mi記憶體,滿足不了pod就建立失敗。
requests:
memory: 300Mi
#limits: memory: 500Mi 表示容器最多消耗500M記憶體
limits:
memory: 500Mi
dnsPolicy: ClusterFirst
restartPolicy: Always
status: {}
LimitRange的限制範圍為256Mi到512Mi記憶體。
[root@k8scloude1 safe]# kubectl describe -f limitRange.yaml
Name: mem-limit-range
Namespace: safe
Type Resource Min Max Default Request Default Limit Max Limit/Request Ratio
---- -------- --- --- --------------- ------------- -----------------------
Container memory 256Mi 512Mi 512Mi 512Mi -
建立pod,pod建立成功,因為滿足LimitRange min <= requests <limits <= LimitRange max 條件。
[root@k8scloude1 safe]# kubectl apply -f pod.yaml
pod/podtest created
[root@k8scloude1 safe]# kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
podtest 1/1 Running 0 7s 10.244.112.190 k8scloude2 <none> <none>
如果resources欄位和LimitRange都進行了資源限制,最終是resources欄位生效,容器記憶體設定不能大於500Mi。
刪除limitrange和pod。
[root@k8scloude1 safe]# kubectl delete -f limitRange.yaml
limitrange "mem-limit-range" deleted
[root@k8scloude1 safe]# kubectl delete pod podtest
pod "podtest" deleted
ResourceQuota
是一種用於限制名稱空間內資源使用的物件。它允許叢集管理員對名稱空間中的資源使用進行配額管理,確保不同的團隊或專案之間資源的公平分配和有效利用。
使用ResourceQuota
,可以限制名稱空間中的CPU、記憶體和其他資源的總量,防止資源濫用和浪費。
資源配額,通過 ResourceQuota 物件來定義,對每個名稱空間的資源消耗總量提供限制。 它可以限制名稱空間中某種型別的物件的總數目上限,也可以限制名稱空間中的 Pod 可以使用的計算資源的總上限。
資源配額的工作方式如下:
不同的團隊可以在不同的名稱空間下工作。這可以通過 RBAC 強制執行。
叢集管理員可以為每個名稱空間建立一個或多個 ResourceQuota 物件。
當用戶在名稱空間下建立資源(如 Pod、Service 等)時,Kubernetes 的配額系統會跟蹤叢集的資源使用情況, 以確保使用的資源用量不超過 ResourceQuota 中定義的硬性資源限額。
如果資源建立或者更新請求違反了配額約束,那麼該請求會報錯(HTTP 403 FORBIDDEN), 並在訊息中給出有可能違反的約束。
如果名稱空間下的計算資源 (如 cpu 和 memory)的配額被啟用, 則使用者必須為這些資源設定請求值(request)和約束值(limit),否則配額系統將拒絕 Pod 的建立。 提示: 可使用 LimitRanger 准入控制器來為沒有設定計算資源需求的 Pod 設定預設值。
簡而言之,resourcequota 配額就是用來設定一個名稱空間最多能建立多少個物件,比如能建立多少svc,能建立多少pod/deploy。
如下yaml檔案功能為:使用hub.c.163.com/library/centos:latest映象建立一個休眠10000000秒的pod。
[root@k8scloude1 safe]# vim pod.yaml
[root@k8scloude1 safe]# cat pod.yaml
apiVersion: v1
kind: Pod
metadata:
labels:
test: podtest
name: podtest
spec:
#當需要關閉容器時,立即殺死容器而不等待預設的30秒優雅停機時長。
terminationGracePeriodSeconds: 0
containers:
- name: centos
image: hub.c.163.com/library/centos:latest
#imagePullPolicy: IfNotPresent:表示如果本地已經存在該映象,則不重新下載;否則從遠端 Docker Hub 下載該映象
imagePullPolicy: IfNotPresent
#command: ["sh","-c","sleep 10000000"]指定容器啟動時要執行的命令,這裡是在容器內部執行一個sleep命令,休眠時間為10000000秒。
command: ["sh","-c","sleep 10000000"]
resources: {}
dnsPolicy: ClusterFirst
restartPolicy: Always
status: {}
建立pod。
[root@k8scloude1 safe]# kubectl apply -f pod.yaml
pod/podtest created
[root@k8scloude1 safe]# kubectl get pod
NAME READY STATUS RESTARTS AGE
podtest 1/1 Running 0 3s
給podtest建立4個svc,關於svc的詳細內容,請檢視部落格《Kubernetes(k8s)服務service:service的發現和service的釋出》。
[root@k8scloude1 safe]# kubectl expose --name=svc1 pod podtest --port=80
service/svc1 exposed
[root@k8scloude1 safe]# kubectl expose --name=svc2 pod podtest --port=80
service/svc2 exposed
[root@k8scloude1 safe]# kubectl expose --name=svc3 pod podtest --port=80
service/svc3 exposed
[root@k8scloude1 safe]# kubectl expose --name=svc4 pod podtest --port=80
service/svc4 exposed
可以發現,此時可以建立很多個svc。
[root@k8scloude1 safe]# kubectl get svc -o wide
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR
svc1 ClusterIP 10.98.89.245 <none> 80/TCP 21s test=podtest
svc2 ClusterIP 10.109.215.162 <none> 80/TCP 15s test=podtest
svc3 ClusterIP 10.96.10.12 <none> 80/TCP 12s test=podtest
svc4 ClusterIP 10.109.113.59 <none> 80/TCP 7s test=podtest
刪除svc。
[root@k8scloude1 safe]# kubectl delete svc svc1 svc2 svc3 svc4
service "svc1" deleted
service "svc2" deleted
service "svc3" deleted
service "svc4" deleted
[root@k8scloude1 safe]# kubectl get svc -o wide
No resources found in safe namespace.
現在還沒有資源配額resourcequotas。
[root@k8scloude1 safe]# kubectl get resourcequotas
No resources found in safe namespace.
設定ResourceQuota,功能為建立了一個名為"resourcequota"的ResourceQuota資源物件,用於限制叢集中的資源配額。使用該ResourceQuota,最多隻能建立4個Pod和4個Service。當達到或超過這些限制時,將無法再建立新的Pod或Service,從而避免過度消耗資源並提高整個叢集的可靠性和穩定性。
[root@k8scloude1 safe]# vim resourcequotas.yaml
#只能建立4個pod和4個svc
[root@k8scloude1 safe]# cat resourcequotas.yaml
apiVersion: v1
kind: ResourceQuota
metadata:
name: resourcequota
spec:
#hard:指定資源的硬性限制,即最大允許使用的資源數量。
hard:
#pods: "4":設定該叢集中最多可以建立4個Pod。
pods: "4"
#services: "4":設定該叢集中最多可以建立4個Service。
services: "4"
建立ResourceQuota。
[root@k8scloude1 safe]# kubectl apply -f resourcequotas.yaml
resourcequota/resourcequota created
檢視ResourceQuota。
[root@k8scloude1 safe]# kubectl get resourcequotas
NAME AGE REQUEST LIMIT
resourcequota 6s pods: 1/4, services: 0/4
現在有1個pod,0個service。
[root@k8scloude1 safe]# kubectl get pod
NAME READY STATUS RESTARTS AGE
podtest 1/1 Running 0 10m
[root@k8scloude1 safe]# kubectl get svc
No resources found in safe namespace.
檢視resourcequota的描述資訊。
[root@k8scloude1 safe]# kubectl describe -f resourcequotas.yaml
Name: resourcequota
Namespace: safe
Resource Used Hard
-------- ---- ----
pods 1 4
services 0 4
建立svc。
[root@k8scloude1 safe]# kubectl expose --name=svc1 pod podtest --port=80
service/svc1 exposed
[root@k8scloude1 safe]# kubectl expose --name=svc2 pod podtest --port=80
service/svc2 exposed
[root@k8scloude1 safe]# kubectl expose --name=svc3 pod podtest --port=80
service/svc3 exposed
[root@k8scloude1 safe]# kubectl expose --name=svc4 pod podtest --port=80
service/svc4 exposed
[root@k8scloude1 safe]# kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
svc1 ClusterIP 10.110.233.61 <none> 80/TCP 37s
svc2 ClusterIP 10.105.108.94 <none> 80/TCP 34s
svc3 ClusterIP 10.105.226.140 <none> 80/TCP 29s
svc4 ClusterIP 10.98.10.38 <none> 80/TCP 25s
svc只能建立4個,第五個就建立失敗了。
[root@k8scloude1 safe]# kubectl expose --name=svc5 pod podtest --port=80
Error from server (Forbidden): services "svc5" is forbidden: exceeded quota: resourcequota, requested: services=1, used: services=4, limited: services=4
檢視resourcequotas,可以看到service配額已經滿了。
[root@k8scloude1 safe]# kubectl get resourcequotas
NAME AGE REQUEST LIMIT
resourcequota 2m17s pods: 1/4, services: 4/4
刪除svc,pod,resourcequotas。
[root@k8scloude1 safe]# kubectl delete svc svc1 svc2
service "svc1" deleted
service "svc2" deleted
[root@k8scloude1 safe]# kubectl delete svc svc3 svc4
service "svc3" deleted
service "svc4" deleted
[root@k8scloude1 safe]# kubectl delete pod podtest
pod "podtest" deleted
[root@k8scloude1 safe]# kubectl delete -f resourcequotas.yaml
resourcequota "resourcequota" deleted
本篇部落格介紹了Kubernetes中資源限制的概念以及如何使用resources
、LimitRange
和ResourceQuota
來管理容器資源。通過合理設定資源限制,可以提高叢集的穩定性和效能,並確保資源的公平分配和有效利用。
資源限制是Kubernetes中重要的管理和控制機制,對於構建可靠且高效的應用程式環境至關重要。