kubernetes排程之資源配額
系列目錄
當多個使用者或者開發團隊共享一個有固定節點的的kubernetes叢集時,一個團隊或者一個使用者使用的資源超過他應當使用的資源是需要關注的問題,資源配額是管理員用來解決這個問題的一個工具.
資源配額,通過ResourceQuota
定義,提供了對某一名稱空間使用資源的總體約束.它即可以限制這個名稱空間下有多少個物件可以被建立,也可以限制對計算機資源使用量的限制(前面說到過,計算機資源包括cpu,記憶體,磁碟空間等資源)
資源配額通過以下類似方式工作:
不同的團隊在不同的名稱空間下工作.當前kubernetes並沒有強制這樣做,完全是自願的,但是kubernetes團隊計劃通過acl授權來達到強制這樣做.
管理員對每一個名稱空間建立一個
ResourceQuota(資源配額)
使用者在一個名稱空間下建立資源(例如pod,service等),配額系統跟蹤資源使用量來保證資源的使用不超過
ResourceQuota
定義的量.如果對一個資源的建立或者更新違反了資源配額約束,則請求會返回失敗,失敗的http狀態碼是
403 FORBIDDEN
並且有一條訊息來解釋哪個約束被違反.如果一個名稱空間下的計算機資源配額,比如CPU和記憶體被啟用,則使用者必須指定相應的資源申請或者限制的值,否則配額系統可能會阻止pod的建立.
資源配額在某一名稱空間下建立策略示例:
在一個有32G記憶體,16核cpu的叢集,讓團隊A使用20G記憶體和10核cpu,讓團隊B使用10G記憶體和4核cpu,剩餘的2G記憶體和2核cup預留以備進一步分配
限制
測試
名稱空間使用1核1G,讓生產
名稱空間使用剩下的全部資源
當叢集的容量小於所有名稱空間下配額總和時,將會出現資源競爭,這種情況下kubernetes將會基於先到先分配的原則進行處理
不論是資源競爭或者是資源配額的修改都不會影響已經建立的資源
啟用資源配額
很多kubernetes的發行版中資源配額支援預設是開啟的,當ResourceQuota
作為apiserver的--enable-admission-plugins=
的其中一個值時,資源配額被開啟.
當某一名稱空間包含ResourceQuota
物件時資源配額在這個名稱空間下生效.
計算機資源配額
你可以限制一個名稱空間下可以被申請的計算機資源的總和
kubernetes支援以下資源型別:
Resource Name | Description |
---|---|
cpu | Across all pods in a non-terminal state, the sum of CPU requests cannot exceed this value. |
limits.cpu | Across all pods in a non-terminal state, the sum of CPU limits cannot exceed this value. |
limits.memory | Across all pods in a non-terminal state, the sum of memory limits cannot exceed this value. |
memory | Across all pods in a non-terminal state, the sum of memory requests cannot exceed this value. |
requests.cpu | Across all pods in a non-terminal state, the sum of CPU requests cannot exceed this value. |
requests.memory | Across all pods in a non-terminal state, the sum of memory requests cannot exceed this value. |
擴充套件資源的資源配額
除了上面提到的,在kubernetes 1.10裡,添加了對擴充套件資源的配額支援
儲存資源配額
你可以限制某一名稱空間下的儲存空間總量的申請
此外,你也可以你也可以根據關聯的storage-class
來限制儲存空間資源的使用
Resource Name | Description |
---|---|
requests.storage | Across all persistent volume claims, the sum of storage requests cannot exceed this value. |
persistentvolumeclaims | The total number of persistent volume claims that can exist in the namespace. |
Across all persistent volume claims associated with the storage-class-name, the sum of storage requests cannot exceed this value. | |
Across all persistent volume claims associated with the storage-class-name, the total number of persistent volume claims that can exist in the namespace. |
例如,一個operator
想要想要使黃金和青銅單獨申請儲存空間,那麼這個operator
可以像如下一樣申請配額:
gold.storageclass.storage.k8s.io/requests.storage: 500Gi
bronze.storageclass.storage.k8s.io/requests.storage: 100Gi
在1.8版本里,對local ephemeral storage
配額的的支援被新增到alpha特徵裡.
Resource Name | Description |
---|---|
requests.ephemeral-storage | Across all pods in the namespace, the sum of local ephemeral storage requests cannot exceed this value. |
limits.ephemeral-storage | Across all pods in the namespace, the sum of local ephemeral storage limits cannot exceed this value. |
物件數量配額
1.9版本通過以下語法加入了對所有標準名稱空間資源型別的配額支援
count/<resource>.<group>
以下是使用者可能想要設定物件數量配額的例子:
count/persistentvolumeclaims
count/services
count/secrets
count/configmaps
count/replicationcontrollers
count/deployments.apps
count/replicasets.apps
count/statefulsets.apps
count/jobs.batch
count/cronjobs.batch
count/deployments.extensions
當使用count/*
型別資源配額,伺服器上存在的資源物件將都被控制.這將有助於防止伺服器儲存資源被耗盡.比如,如果儲存在伺服器上的secrets
資源物件過大,你可能會想要限制它的數量.過多的secrets
可能會導致伺服器無法啟動!你也可能會限制job
的數量以防一些設計拙劣的定時任務會建立過多的job以導致服務被拒絕
以下資源型別的限額是支援的
Resource Name | Description |
---|---|
configmaps | The total number of config maps that can exist in the namespace. |
persistentvolumeclaims | The total number of persistent volume claims that can exist in the namespace. |
pods | The total number of pods in a non-terminal state that can exist in the namespace. A pod is in a terminal state if .status.phase in (Failed, Succeeded) is true. |
replicationcontrollers | The total number of replication controllers that can exist in the namespace. |
resourcequotas | The total number of resource quotas that can exist in the namespace. |
services | The total number of services that can exist in the namespace. |
services.loadbalancers | The total number of services of type load balancer that can exist in the namespace. |
services.nodeports | The total number of services of type node port that can exist in the namespace. |
secrets | The total number of secrets that can exist in the namespace. |
例如,pod配額限制了一個名稱空間下非terminal
狀態的pod總數量.這樣可以防止一個使用者建立太多小的pod以至於耗盡叢集分配給pod的所有IP
配額範圍
每一個配額都可以包含一系列相關的範圍.配額只會在匹配列舉出的範圍的交集時才計算資源的使用.
當一個範圍被新增到配額裡,它將限制它支援的,屬於範圍的資源.指定的資源不在支援的集合裡時,將會導致驗證錯誤
Scope | Description |
---|---|
Terminating | Match pods where .spec.activeDeadlineSeconds >= 0 |
NotTerminating | Match pods where .spec.activeDeadlineSeconds is nil |
BestEffort | Match pods that have best effort quality of service. |
NotBestEffort | Match pods that do not have best effort quality of service. |
BestEffort
範圍限制配額只追蹤pods
資源
Terminating
,NotTerminating
和NotBestEffort
範圍限制配額追蹤以下資源:
cpu
limits.cpu
limits.memory
memory
pods
requests.cpu
requests.memory
每一個PriorityClass的資源配額
此特徵在1.12片本中為beta
pod可以以指定的優先順序建立.你可以通過pod的優先順序來控制pod對系統資源的使用,它是通過配額的spec下的scopeSelector
欄位產生效果的.
只有當配額spec的scopeSelector
選擇了一個pod,配額才會被匹配和消費
你在使用PriorityClass的配額的之前,需要啟用
ResourceQuotaScopeSelectors
以下示例建立一個配額物件,並且一定優先順序的pod會匹配它.
叢集中的pod有以下三個優先順序類之一:
low
,medium
,high
每個優先順序類都建立了一個資源配額
apiVersion: v1
kind: List
items:
- apiVersion: v1
kind: ResourceQuota
metadata:
name: pods-high
spec:
hard:
cpu: "1000"
memory: 200Gi
pods: "10"
scopeSelector:
matchExpressions:
- operator : In
scopeName: PriorityClass
values: ["high"]
- apiVersion: v1
kind: ResourceQuota
metadata:
name: pods-medium
spec:
hard:
cpu: "10"
memory: 20Gi
pods: "10"
scopeSelector:
matchExpressions:
- operator : In
scopeName: PriorityClass
values: ["medium"]
- apiVersion: v1
kind: ResourceQuota
metadata:
name: pods-low
spec:
hard:
cpu: "5"
memory: 10Gi
pods: "10"
scopeSelector:
matchExpressions:
- operator : In
scopeName: PriorityClass
values: ["low"]
使用kubectl create
來使用者以上yml檔案
kubectl create -f ./quota.yml
resourcequota/pods-high created
resourcequota/pods-medium created
resourcequota/pods-low created
使用kubectl describe quota
來檢視
kubectl describe quota
Name: pods-high
Namespace: default
Resource Used Hard
-------- ---- ----
cpu 0 1k
memory 0 200Gi
pods 0 10
Name: pods-low
Namespace: default
Resource Used Hard
-------- ---- ----
cpu 0 5
memory 0 10Gi
pods 0 10
Name: pods-medium
Namespace: default
Resource Used Hard
-------- ---- ----
cpu 0 10
memory 0 20Gi
pods 0 10
建立一個具有high
優先順序的pod,把以下內容儲存在high-priority-pod.yml
裡
apiVersion: v1
kind: Pod
metadata:
name: high-priority
spec:
containers:
- name: high-priority
image: ubuntu
command: ["/bin/sh"]
args: ["-c", "while true; do echo hello; sleep 10;done"]
resources:
requests:
memory: "10Gi"
cpu: "500m"
limits:
memory: "10Gi"
cpu: "500m"
priorityClassName: high
使用kubectl create
來應用
kubectl create -f ./high-priority-pod.yml
這時候再用kubectl describe quota
來檢視
Name: pods-high
Namespace: default
Resource Used Hard
-------- ---- ----
cpu 500m 1k
memory 10Gi 200Gi
pods 1 10
Name: pods-low
Namespace: default
Resource Used Hard
-------- ---- ----
cpu 0 5
memory 0 10Gi
pods 0 10
Name: pods-medium
Namespace: default
Resource Used Hard
-------- ---- ----
cpu 0 10
memory 0 20Gi
pods 0 10
scopeSelector
支援operator
欄位的以下值:
In
NotIn
Exist
DoesNotExist
配額資源的申請與限制
當分配計算機資源時,每一個容器可能會指定對cpu或者記憶體的申請或限制.配額可以配置為它們中的一個值
這裡是說配額只能是申請或者限制,而不能同時出現
如果配額指定了requests.cpu
或requests.memory
那麼它需要匹配的容器必須顯式指定申請這些資源.如果配額指定了limits.cpu
或limits.memory
,那麼它需要匹配的容器必須顯式指定限制這些資源
檢視和設定配額
kubectl支援建立,更新和檢視配額
kubectl create namespace myspace
cat <<EOF > compute-resources.yaml
apiVersion: v1
kind: ResourceQuota
metadata:
name: compute-resources
spec:
hard:
pods: "4"
requests.cpu: "1"
requests.memory: 1Gi
limits.cpu: "2"
limits.memory: 2Gi
requests.nvidia.com/gpu: 4
EOF
kubectl create -f ./compute-resources.yaml --namespace=myspace
cat <<EOF > object-counts.yaml
apiVersion: v1
kind: ResourceQuota
metadata:
name: object-counts
spec:
hard:
configmaps: "10"
persistentvolumeclaims: "4"
replicationcontrollers: "20"
secrets: "10"
services: "10"
services.loadbalancers: "2"
EOF
kubectl create -f ./object-counts.yaml --namespace=myspace
kubectl get quota --namespace=myspace
NAME AGE
compute-resources 30s
object-counts 32s
kubectl describe quota compute-resources --namespace=myspace
Name: compute-resources
Namespace: myspace
Resource Used Hard
-------- ---- ----
limits.cpu 0 2
limits.memory 0 2Gi
pods 0 4
requests.cpu 0 1
requests.memory 0 1Gi
requests.nvidia.com/gpu 0 4
kubectl describe quota object-counts --namespace=myspace
Name: object-counts
Namespace: myspace
Resource Used Hard
-------- ---- ----
configmaps 0 10
persistentvolumeclaims 0 4
replicationcontrollers 0 20
secrets 1 10
services 0 10
services.loadbalancers 0 2
kubectl通過count/<resource>.<group>
語法形式支援標準名稱空間物件數量配額
kubectl create namespace myspace
kubectl create quota test --hard=count/deployments.extensions=2,count/replicasets.extensions=4,count/pods=3,count/secrets=4 --namespace=myspace
kubectl run nginx --image=nginx --replicas=2 --namespace=myspace
kubectl describe quota --namespace=myspace
Name: test
Namespace: myspace
Resource Used Hard
-------- ---- ----
count/deployments.extensions 1 2
count/pods 2 3
count/replicasets.extensions 1 4
count/secrets 1 4
配額和叢集容量
ResourceQuotas
獨立於叢集的容量,它們通過絕對的單位表示.因此,如果你向叢集添加了節點,這並不會給叢集中的每個名稱空間賦予消費更多資源的能力.
有時候需要更為複雜的策略,比如:
把叢集中所有的資源按照比例分配給不同團隊
允許每個租戶根據需求增加資源使用,但是有一個總體的限制以防資源被耗盡
檢測名稱空間的需求,新增節點,增加配額
這些策略可以通過實現ResourceQuotas
來寫一個controller
用於監視配額的使用,並且通過其它訊號來調整每個名稱空間的配額
預設限制優先類消費
有時候我們可能希望一定優先級別的pod,例如cluster-services
應當被允許在一個名稱空間裡,當且僅當匹配的配額存在.
通過這種機制,operators可以限制一些高優先順序的類只能用於有限數量的名稱空間裡,並且不是所有的名稱空間都可以預設消費它們.
為了使以上生效,kube-apiserver標籤--admission-control-config-file
應當傳入以下配置檔案的路徑
apiVersion: apiserver.k8s.io/v1alpha1
kind: AdmissionConfiguration
plugins:
- name: "ResourceQuota"
configuration:
apiVersion: resourcequota.admission.k8s.io/v1beta1
kind: Configuration
limitedResources:
- resource: pods
matchScopes:
- scopeName: PriorityClass
operator: In
values: ["cluster-services"]
現在,cluster-services
型別的pod僅被允許執行在有匹配scopeSelector
的配額資源物件的名稱空間裡,例如
`yml scopeSelector: matchExpressions: - scopeName: PriorityClass operator: In values: ["cluster-services"]