環境說明:
主機名 | 操作系統版本 | ip | docker version | kubelet version | 配置 | 備註 |
---|---|---|---|---|---|---|
master | Centos 7.6.1810 | 172.27.9.131 | Docker 18.09.6 | V1.14.2 | 2C2G | 備註 |
node01 | Centos 7.6.1810 | 172.27.9.135 | Docker 18.09.6 | V1.14.2 | 2C2G | 備註 |
node02 | Centos 7.6.1810 | 172.27.9.136 | Docker 18.09.6 | V1.14.2 | 2C2G | 備註 |
k8s集羣部署詳見:Centos7.6部署k8s(v1.14.2)集羣
k8s學習資料詳見:基本概念、kubectl命令和資料分享
一、計算資源管理(Compute Resources)
1. 概念
在配置Pod時,我們可以爲其中的每個容器指定需要使用的計算資源(CPU和內存)。計算資源的配置項分爲兩種:Requests和Limits。Requests表示容器希望被分配到的、可完全保證的資源量(資源請求量);Limits是容器最多能使用的資源量的上限(資源限制量)。
資源請求量能夠保證Pod有足夠的資源來運行,資源限制量則是防止某個Pod無限制地使用資源,導致其他Pod崩潰。
我們創建一個pod時,可以指定容器對CPU和內存的資源請求量及資源限制量,它們並不在pod裏定義,而是針對每個容器單獨指定。pod對資源的請求量和限制量是它所包含的所有容器的請求量和限制量之和。
CPU和內存的Requests和Limits有如下特點:
- Requests和Limits都是可選的。在Pod創建和更新時,如果未設置Requests和Limits,則使用系統提供的默認值,該默認值取決於集羣配置。
- 如果Requests沒有配置,默認被設置等於Limits。
- 任何情況下Limits都應該設置爲大於或等於Requests。
2. 查看節點資源總量
2.1 命令方式
[root@master ~]# kubectl describe nodes
2.2 Dashboard方式
3. requests
3.1 創建包含資源requests的pod
[root@master ~]# more requests-pod.yaml
apiVersion: v1
kind: Pod
metadata:
name: requests-pod
spec:
containers:
- image: busybox
name: busybox
args:
- /bin/sh
- -c
- sleep 60000
resources:
requests: #資源申請
cpu: 500m #容器申請500毫核(一個CPU核心時間的1/2)
memory: 500Mi #容器申請500M內存
nodeName: node01
[root@master ~]# kubectl apply -f requests-pod.yaml
pod/requests-pod created
在Kubernetes系統上,l個單位的CPU相當於虛擬機上的l顆虛擬CPU(vCPU)或物理機上的一個超線程(Hyperthread,或稱爲一個邏輯CPU),它支持分數計量方式,一個核心(1core)相當於1000個微核心(millicores),因此500m相當於是0.5個核心,即二分之一個核心。內存的計量方式與日常使用方式相同,默認單位是字節,也可以使用E,P、T、G、M和K作爲單位後綴,或Ei、Pi、Ti、Gi、Mi和Ki形式的單位後綴。
3.2 查看pod
[root@master ~]# kubectl get po -o wide
[root@master ~]# kubectl describe po requests-pod
3.3 基於requests的pod調度機制
3.3.1 不指定requests
[root@master ~]# kubectl delete all --all
[root@master ~]# more deploy-busybox.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: busybox
spec:
selector:
matchLabels:
env: prod
replicas: 10
template:
metadata:
labels:
env: prod
spec:
containers:
- name: busybox
image: busybox
args:
- /bin/sh
- -c
- sleep 60000
nodeSelector:
node: node01
[root@master ~]# kubectl apply -f deploy-busybox.yaml
deployment.apps/busybox created
若不指定資源請求量,節點node01上可成功運行10個pod
3.3.2 OutOfmemory
[root@master ~]# more requests-pod.yaml
apiVersion: v1
kind: Pod
metadata:
name: requests-pod
spec:
containers:
- image: busybox
name: busybox
args:
- /bin/sh
- -c
- sleep 60000
resources:
requests: #資源申請
cpu: 500m #容器申請500毫核(一個CPU核心時間的1/2)
memory: 800Mi #容器申請800M內存
nodeName: node01
[root@master ~]# more requests-pod-2.yaml
apiVersion: v1
kind: Pod
metadata:
name: requests-pod-2
spec:
containers:
- image: busybox
name: busybox
args:
- /bin/sh
- -c
- sleep 60000
resources:
requests:
cpu: 500m
memory: 800Mi
nodeName: node01
[root@master ~]# kubectl apply -f requests-pod.yaml
pod/requests-pod created
[root@master ~]# kubectl get po -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
requests-pod 1/1 Running 0 4s 10.244.1.67 node01 <none> <none>
[root@master ~]# kubectl apply -f requests-pod-2.yaml
pod/requests-pod-2 created
[root@master ~]# kubectl get po -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
requests-pod 1/1 Running 0 14s 10.244.1.67 node01 <none> <none>
requests-pod-2 0/1 OutOfmemory 0 2s <none> node01 <none> <none>
報節點node01 內存資源不足,pod requests-pod-2調度失敗
3.3.3 OutOfcpu
[root@master ~]# kubectl delete all --all
[root@master ~]# more requests-pod.yaml
apiVersion: v1
kind: Pod
metadata:
name: requests-pod
spec:
containers:
- image: busybox
name: busybox
args:
- /bin/sh
- -c
- sleep 60000
resources:
requests: #資源申請
cpu: 1 #容器申請一個CPU核心時間
memory: 80Mi #容器申請80M內存
nodeName: node01
[root@master ~]# more requests-pod-2.yaml
apiVersion: v1
kind: Pod
metadata:
name: requests-pod-2
spec:
containers:
- image: busybox
name: busybox
args:
- /bin/sh
- -c
- sleep 60000
resources:
requests:
cpu: 1
memory: 80Mi
nodeName: node01
[root@master ~]# kubectl apply -f requests-pod.yaml
pod/requests-pod created
[root@master ~]# kubectl get po -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
requests-pod 1/1 Running 0 4s 10.244.1.68 node01 <none> <none>
[root@master ~]# kubectl apply -f requests-pod-2.yaml
pod/requests-pod-2 created
[root@master ~]# kubectl get po -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
requests-pod 1/1 Running 0 13s 10.244.1.68 node01 <none> <none>
requests-pod-2 0/1 OutOfcpu 0 2s <none> node01 <none> <none>
報節點node01 cpu資源不足,pod requests-pod-2調度失敗
3.3.4 結論
- 調度器在調度時並不關注各類資源在當前時刻的實際使用量(node01可以同時運行10個busybox pod)
- 調度器只關心節點上部署的所有pod的資源申請量之和(超出時就會報OutOfmemory或OutOfcpu)
- 儘管現有pods的資源實際使用量可能小於它的申請量,但如果使用基於實際資源消耗量的調度算法將打破系統爲這些已部署成功的pods提供足夠資源的保證
4. limits
4.1 創建包含資源limits的pod
[root@master ~]# more limited-pod.yaml
apiVersion: v1
kind: Pod
metadata:
name: limited-pod
spec:
containers:
- image: busybox
command: ["sleep","600000"]
name: busybox
resources:
requests: #資源申請
cpu: 200m #容器申請200毫核(一個CPU核心時間的1/5)
memory: 80Mi #容器申請80M內存
limits: #資源限制
cpu: 2 #容器最大允許使用2核CPU
memory: 2Gi #容器最大允許使用2GB內存
nodeName: node01
[root@master ~]# kubectl apply -f limited-pod.yaml
pod/limited-pod created
[root@master ~]# kubectl get po -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
limited-pod 1/1 Running 0 12s 10.244.1.75 node01 <none> <none>
創建pod limited-pod,資源限制爲cpu 2核,內存2G
4.2 limits overcommitted
4.2.1 創建pod
創建limited-pod和limited-pod-2,cpu爲2核,內存2G,pod運行正常。
4.2.2 查看node01資源使用
4.2.3 結論
- 節點上所有pod的資源limits之和可以超過節點資源總量的100%
- requests不同的是,limits並不會影響pod的調度結果
二、服務質量管理(QoS)
1. 概念
前面曾提到過,Kubernetes允許節點資源對Limits的過載使用,這意味着節點無法同時滿足其上的所有Pod對象以資源滿載的方式運行。於是,在內存資源緊缺時,應該以何種次序先後終止哪些Pod對象?Kubernetes無法自行對此做出決策,它需要藉助於Pod對象的優先級完成判定。根據Pod對象的requests和limits屬性,Kubernetes將Pod象歸類到BestEffort、Burstable和Guaranteed三個服務質量(Quality of Service,QoS)類別下,具體說明如下。
Guaranteed:每個容器都爲CPU資源設置了具有相同值的requests和limits屬性,以及每個容器都爲內存資源設置了具有相同值的requests和limits屬性的Pod資源會自動歸屬於此類別,這類Pod資源具有最高優先級。
Burstable:至少有一個容器設置了CPU或內存資源requests屬性,但不滿足Guaranteed類別要求的Pod資源將自動歸屬於此類別,它們具有中等優先級。
- BestEffort:未爲任何一個容器設置requests或limits屬性的Pod資源將自動歸屬於此類別,它們的優先級爲最低級別。
在一個overcommitted的系統,QoS等級決定着哪個容器第一個被殺掉,這樣釋放出的資源可以提供給高優先級的pod使用。BestEffort等級的pod首先被殺掉,其次是Burstable pod, 最後是Guaranteed pod。Guaranteed pod只有在系統進程需要內存時纔會被殺掉。
2. 定義QoS
資源的requests、limits和QoS等級
3. 相同等級QoS容器處理
每個行狀態容器都有其OOM得分,得分越高越會被優先殺死。OOM得分主要根據兩個緯度進行計算:由QoS類別繼承而來的默認分值和容器的可用內存資源比例。同等類別的Pod資源的默認分值相同,同等級別優先級的Pod資源在OOM時,與自身的requests屬性相比,其內存佔用比例最大的Pod對象將被首先殺死。
三、資源配置範圍管理(LimitRange)
1. 概念
默認情況下,Kubernetes中所有容器都沒有任何CPU和內存限制。LimitRange用來給Namespace增加一個資源限制,包括最小、最大和默認資源。
2. 爲什麼需要LimitRange
爲單個容器設置資源requests和limits很有必要性:1.提升QoS等級,防止在OOM時被首先kill;2.默認情況下Pod會以無限制的CPU和內存運行,很有可能因故吞掉所在工作節點上的所有可用計算資源。
通過配置Pod的計算資源Requests和Limits,我們可以限制Pod的資源使用,但對於Kubemetes集羣管理員而言,配置每一個Pod的Requests和Limits是煩瑣且限制性過強的。更多時,我們需要的是對集羣內Requests和Limits的配置做一個全局的統一的限制。
3 創建LimitRange
[root@master ~]# more limits.yaml
apiVersion: v1
kind: LimitRange
metadata:
name: limitrange
spec:
limits:
- type: Pod #指定整個pod的資源limits
min: #pod中所有容器的Requests值的總和的下限
cpu: 50m
memory: 5Mi
max: #pod中所有容器的Limits值的總和的上限
cpu: 1
memory: 1Gi
- type: Container #指定容器的資源限制
defaultRequest: #容器Requests默認值
cpu: 100m
memory: 10Mi
default: #容器Limits默認值
cpu: 200m
memory: 100Mi
min: #pod中所有容器的Requests值的下限
cpu: 50m
memory: 5Mi
max: #pod中所有容器的Limits值的上限
cpu: 1
memory: 1Gi
maxLimitRequestRatio: #每種資源Requests與Limits的最大比值
cpu: 4
memory: 10
- type: PersistentVolumeClaim #指定請求PVC存儲容量的最小值和最大值
min:
storage: 1Gi
max:
storage: 10Gi
[root@master ~]# kubectl apply -f limits.yaml
limitrange/limitrange created
LimitRange資源支持限制Container、Pod和PersistentVolumeClaim三種資源對象的系統資源用量
4. 查看LimitRange
[root@master ~]# kubectl describe limitranges limitrange
5. LimitRange測試
5.1 requests和limits默認值
新建pod
[root@master ~]# more default.yaml
apiVersion: v1
kind: Pod
metadata:
name: default-pod
spec:
containers:
- image: busybox
name: busybox
args:
- /bin/sh
- -c
- sleep 60000
[root@master ~]# kubectl apply -f default.yaml
pod/default-pod created
[root@master ~]# kubectl get po -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
default-pod 1/1 Running 0 8s 10.244.2.43 node02 <none> <none>
limited-pod 1/1 Running 1 22h 10.244.1.81 node01 <none> <none>
limited-pod-2 1/1 Running 1 22h 10.244.1.82 node01 <none> <none>
新建pod default-pod,yaml中未指定requests和limits
查看pod
容器的requests和limits與我們在LimitRange對象中設置的一致。
5.2 強制限制
5.2.1 cpu超限制
[root@master ~]# kubectl run cpu-over --image=busybox --restart=Never --requests='cpu=1200m,memory=30Mi' sleep 6000
The Pod "cpu-over" is invalid: spec.containers[0].resources.requests: Invalid value: "1200m": must be less than or equal to cpu limit
5.2.2 內存超限制
[root@master ~]# kubectl run cpu-over --image=busybox --restart=Never --requests='cpu=200m,memory=300Mi' sleep 6000
The Pod "cpu-over" is invalid: spec.containers[0].resources.requests: Invalid value: "300Mi": must be less than or equal to memory limit
四、資源配額管理(ResourceQuota)
1. 概念
Kubemetes可以通過存活探針(liveness probe)檢查容器是否還在運行。可以爲pod中的每個容器單獨指定存活探針。如果探測失敗,Kubemetes將定期執行探針並重新啓動容器。
資源配額(Resource Quotas)是用來限制用戶資源用量的一種機制,限制Pod的請求不會超過配額,需要在namespace中創建一個ResourceQuota對象
資源配額類型:
- 計算資源。包括 cpu 和 memory
- 存儲資源。包括存儲資源的總量以及指定 storage class 的總量
- 對象數。即可創建的對象的個數
2. ResourceQuota作用
儘管LimitRange資源能限制單個容器、Pod及PVC等相關計算資源或存儲資源的用量,但用戶依然可以創建數量衆多的此類資源對象進而侵佔所有的系統資源。於是,Kubernetes提供了ResourceQuota資源用於定義名稱空間的對象數量或系統資源配額。
3. 爲CPU和內存創建ResourceQuota
[root@master ~]# more quota-cpu-memory.yaml
apiVersion: v1
kind: ResourceQuota
metadata:
name: cpu-and-mem
spec:
hard:
requests.cpu: 1
requests.memory: 1Gi
limits.cpu: 1500m
limits.memory: 1500Mi
[root@master ~]# kubectl apply -f quota-cpu-memory.yaml
resourcequota/cpu-and-mem created
LimitRange應用於單獨的pod,ResourceQuota應用於命名空間中所有的pod
3.1 查看ResourceQuota
[root@master ~]# kubectl describe resourcequotas cpu-and-mem
3.2 resourcequota測試
[root@master ~]# kubectl run quota-test --image=busybox --limits='cpu=200m,memory=90Mi' --replicas=10 sleep 6000
kubectl run --generator=deployment/apps.v1 is DEPRECATED and will be removed in a future version. Use kubectl run --generator=run-pod/v1 or kubectl create instead.
deployment.apps/quota-test created
[root@master ~]# kubectl get po -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
default-pod 1/1 Running 0 31m 10.244.2.52 node02 <none> <none>
quota-test-5d4f79c664-2tq66 1/1 Running 0 5m44s 10.244.1.90 node01 <none> <none>
quota-test-5d4f79c664-cvptj 1/1 Running 0 5m44s 10.244.0.68 master <none> <none>
quota-test-5d4f79c664-ph79j 1/1 Running 0 5m44s 10.244.2.64 node02 <none> <none>
quota-test-5d4f79c664-tvwpz 1/1 Running 0 5m44s 10.244.2.65 node02 <none> <none>
發現只運行了4個pod,原因是requests的cpu爲200(requests值未設置時與limits相同),resourcequotas中requests.cpu的限制值爲1000m,系統之前使用了100m(default-pod),故只有900m可用,所以最多隻能新建4個pod
4. 限制可創建對象的個數
[root@master ~]# more quota-count.yaml
apiVersion: v1
kind: ResourceQuota
metadata:
name: count-quota
spec:
hard:
pods: 10
replicationcontrollers: 5
secrets: 10
configmaps: 10
persistentvolumeclaims: 5
services: 5
services.loadbalancers: 1
services.nodeports: 2
ssd.storageclass.storage.k8s.io/persistentvolumeclaims: 2
[root@master ~]# kubectl apply -f quota-count.yaml
resourcequota/count-quota created
該命名空間最多創建10個pod、5個Replication Controller、10個Secret、10個ConfigMap、4個PVC、5個Service、1個LoadBalancer、2個NodePort和2個StorageClass爲ssd的PVC。
pod | Replication Controller | Secret | ConfigMap | PVC | Service | LoadBalancer | NodePort | ssd PVC |
---|---|---|---|---|---|---|---|---|
10 | 5 | 10 | 10 | 4 | 5 | 1 | 2 | 2 |
4.1 查看ResourceQuota
[root@master ~]# kubectl describe resourcequotas count-quota
4.2 resourcequota測試
[root@master ~]# kubectl create service nodeport nodeport01 --tcp=5678:8080
service/nodeport01 created
[root@master ~]# kubectl create service nodeport nodeport02 --tcp=5678:8081
service/nodeport02 created
[root@master ~]# kubectl create service nodeport nodeport03 --tcp=5678:8082
Error from server (Forbidden): services "nodeport03" is forbidden: exceeded quota: count-quota, requested: services.nodeports=1, used: services.nodeports=2, limited: services.nodeports=2
services.nodeports只能創建2個,當創建第三個時報錯。
5. 特定的pod狀態或者QoS等級指定配額
[root@master ~]# more quota-scoped.yaml
apiVersion: v1
kind: ResourceQuota
metadata:
name: scoped-quota
spec:
scopes:
- BestEffort
- NotTerminating
hard:
pods: 4
[root@master ~]# kubectl apply -f quota-scoped.yaml
resourcequota/scoped-quota created
這個quota只會應用於擁有BestEffort QoS以及沒有設置有效期的pod上,這樣的pod只允許存在4個。
5.1 查看ResourceQuota
[root@master ~]# kubectl describe resourcequotas scoped-quota
resourcequota測試思路同cpu-and-mem和count-quota,這裏不再贅述。
本文所有腳本和配置文件已上傳github:https://github.com/loong576/k8s-Managing-pods-computational-resources.git