天天看點

K8s:通過 Resource Quotas 限制命名空間對象建立數量和計算資源使用

作者:山河已無恙i

寫在前面

  • 分享一些 K8s 中資源配額管理 Resource Quotas 的筆記
  • 博文内容涉及: Resource Quotas(資源配額) 簡單介紹如何開啟 資源配額計算,存儲,對象資源配額 Demo配額作用域的簡單介紹
  • 了解不足小夥伴幫忙指正

投我以桃,報之以李。——《大雅·抑》

Resource Quotas 簡單介紹

在 k8s 中,容器、Pod 級别的的計算資源限制設定,可以通過定義 yaml 檔案時的 limits 和 requests 字段來做限制, 通過配置不同的 Limits 和 requests不但可以限制資源 , 還可以實作不同等級的 Qos,同時可以通過 LimitRange 來對命名空間内的所有 pod 計算資源配置做統一的限制管理。 那麼對于叢集級别命名空間的計算資源限制, k8s 提供了什麼解決方案? 對于對象數量又有什麼方式來進行限制,難道可以無限制的建立 pod、cm、svc 麼?

當然不是,對于叢集級别, k8s 可以通過 Resource Quotas 來實作叢集級别的資源配額,實作對每個命名空間的資源消耗總量提供限制。這裡的限制包括:

  • 限制命名空間中某種類型的 對象的總數目上限
  • 限制命名空間中的 Pod 可以使用的 計算資源的總上限

叢集管理者可以為每個命名空間建立一個或多個 Resource Quota 對象。

當使用者在命名空間下建立資源(如 Pod、Service 等)時,Kubernetes 的 配額系統 會跟蹤叢集的資源使用情況, 以確定使用的資源用量不超過 Resource Quota 中定義的 硬性資源限額。

如果資源建立或者更新請求 違反了配額限制,那麼該請求會報錯(HTTP 403 FORBIDDEN), 并在消息中給出有可能違反的限制。

不管是資源競争還是配額的修改,都不會影響已經建立的資源使用對象。

如果叢集中總的可用資源小于各命名空間中資源配額的總和,那麼可能會導緻資源競争。資源競争時,Kubernetes 系統會遵循先到先得的原則。

對于計算資源,這裡的 Resource Quota 和 LimitRange 職責并不重合,Resource Quota 限制命名空間 pod 總的用量(不考慮配額域),而 LimitRange 限制目前命名空間 中 每個 Pod 或者容器的計算資源。

啟用資源配額

當 API 伺服器 的指令行标志 --enable-admission-plugins= 中包含 ResourceQuota 時, 資源配額會被啟用。當命名空間中存在一個 ResourceQuota 對象時,對于該命名空間而言,資源配額就是開啟的。

如果需要開啟資源配額,需要在 修改 apiservice 元件靜态 pod 的 yaml 檔案 kube-apiserver.yaml

┌──[[email protected]]-[/etc/kubernetes/manifests]
└─$cat kube-apiserver.yaml  | grep -i  quota
    - --enable-admission-plugins=NodeRestriction,ResourceQuota
           

檢視目前命名空間的 資源配額

┌──[[email protected]]-[/etc/kubernetes/manifests]
└─$kubectl get resourcequotas  -A
No resources found
           

預設情況下,不指定 配額域 的情況,配額配置對目前命名空間有效,指定了配額域的情況,隻對配額域比對的資源有效。

計算資源配額

使用者可以對給定命名空間下的可被請求的 計算資源 總量進行限制。

如果命名空間下的計算資源 (如 cpu 和 memory)的配額被啟用, 則使用者必須為這些資源設定請求值(request)和限制值(limit),否則配額系統将拒絕 Pod 的建立。 可使用 LimitRanger 準入控制器來為沒有設定計算資源需求的 Pod 設定預設值。

┌──[[email protected]]-[~/ansible/quota]
└─$kubectl apply -f my-quota.yaml
resourcequota/object-quota-demo created
┌──[[email protected]]-[~/ansible/quota]
└─$kubectl describe  resourcequota object-quota-demo
Name:            object-quota-demo
Namespace:       liruilong-topo-namespace
Resource         Used   Hard
--------         ----   ----
limits.cpu       50m    6
limits.memory    100Mi  20Gi
requests.cpu     20m    4
requests.memory  50Mi   15Gi
           

上面的清單中 ,Used 為目前的計算資源情況,Hard 為配額情況。 配額機制所支援的資源類型

┌──[[email protected]]-[~/ansible/quota]
└─$cat my-quota.yaml
apiVersion: v1
kind: ResourceQuota
metadata:
  name: object-quota-demo
spec:
  hard:
    limits.cpu: '6'        #所有非終止狀态的 Pod,其 CPU 限額總量不能超過該值。
    limits.memory: '20Gi'  #所有非終止狀态的 Pod,其記憶體限額總量不能超過該值。
    requests.cpu: '4'        #所有非終止狀态的 Pod,其 CPU 需求總量不能超過該值。
    requests.memory: '15Gi'  #所有非終止狀态的 Pod,其記憶體需求總量不能超過該值。

    #hugepages-<size>        對于所有非終止狀态的 Pod,針對指定尺寸的巨頁請求總數不能超過此值。
    #cpu     與 requests.cpu 相同。
    #memory  與 requests.memory 相同。

           

存儲資源配額

使用者可以對給定命名空間下的存儲資源 總量進行限制。此外,還可以根據相關的存儲類(Storage Class)來限制存儲資源的消耗。

┌──[[email protected]]-[~/ansible/quota]
└─$kubectl get sc
NAME                   PROVISIONER             RECLAIMPOLICY   VOLUMEBINDINGMODE      ALLOWVOLUMEEXPANSION   AGE
local-path (default)   rancher.io/local-path   Delete          WaitForFirstConsumer   false                  84d
┌──[[email protected]]-[~/ansible/quota]
└─$
           

目前隻有一個預設的以本地存儲做的一個 SC,我們用來 Demo。

┌──[[email protected]]-[~/ansible/quota]
└─$kubectl apply  -f my-quota-sc.yaml
resourcequota/object-quota-sc-demo created
┌──[[email protected]]-[~/ansible/quota]
└─$kubectl describe  resourcequotas object-quota-sc-demo
Name:                                                          object-quota-sc-demo
Namespace:                                                     liruilong-topo-namespace
Resource                                                       Used  Hard
--------                                                       ----  ----
local-path.storageclass.storage.k8s.io/persistentvolumeclaims  0     3
local-path.storageclass.storage.k8s.io/requests.storage        0     10Gi
persistentvolumeclaims                                         0     50Gi
requests.storage                                               0     20Gi
┌──[[email protected]]-[~/ansible/quota]
└─$
           

具體可以限制的 存儲資源配額

┌──[[email protected]]-[~/ansible/quota]
└─$cat  my-quota-sc.yaml
apiVersion: v1
kind: ResourceQuota
metadata:
  name: object-quota-sc-demo
spec:
  hard:
    requests.storage: "20Gi"     #所有 PVC,存儲資源的需求總量不能超過該值。
    persistentvolumeclaims: "50Gi"  #在該命名空間中所允許的 PVC 總量。
    local-path.storageclass.storage.k8s.io/requests.storage: "10Gi"  #在所有與 <storage-class-name> 相關的持久卷申領中,存儲請求的總和不能超過該值 。
    local-path.storageclass.storage.k8s.io/persistentvolumeclaims: 3  #在與 storage-class-name 相關的所有持久卷申領中,命名空間中可以存在的持久卷申領總數
┌──[[email protected]]-[~/ansible/quota]
└─$
           

對象數量配額

可以使用以下文法對所有标準的、命名空間域的資源類型進行配額設定:

  • count/.:用于非核心(core)組的資源
  • count/:用于核心組的資源
kubectl create quota test --hard=count/deployments.apps=2,count/replicasets.apps=4,count/pods=3,count/secrets=4 --namespace=myspace
           

也可以直接通過 yaml 資源檔案的方式配置

┌──[[email protected]]-[~/ansible/quota]
└─$kubectl apply  -f my-quota-objects.yaml
resourcequota/object-quota-count-demo created
┌──[[email protected]]-[~/ansible/quota]
└─$kubectl describe   resourcequotas object-quota-count-demo
Name:                   object-quota-count-demo
Namespace:              liruilong-topo-namespace
Resource                Used  Hard
--------                ----  ----
configmaps              1     10
persistentvolumeclaims  0     5
pods                    4     15
replicationcontrollers  0     10
resourcequotas          3     5
secrets                 4     7
services                0     5
services.loadbalancers  0     5
services.nodeports      0     5
           

對象數量配額對應的 yaml 檔案

┌──[[email protected]]-[~/ansible/quota]
└─$cat my-quota-objects.yaml
apiVersion: v1
kind: ResourceQuota
metadata:
  name: object-quota-count-demo
spec:
  hard:
    configmaps: 10  #在該命名空間中允許存在的 ConfigMap 總數上限。
    persistentvolumeclaims: 5  #在該命名空間中允許存在的 PVC 的總數上限。
    pods: 15    #在該命名空間中允許存在的非終止狀态的 Pod 總數上限。Pod 終止狀态等價于 Pod 的 .status.phase in (Failed, Succeeded) 為真。
    replicationcontrollers: 10  #在該命名空間中允許存在的 ReplicationController 總數上限。
    resourcequotas: 5  #在該命名空間中允許存在的 ResourceQuota 總數上限。
    services: 5        #在該命名空間中允許存在的 Service 總數上限。
    services.loadbalancers: 5  #在該命名空間中允許存在的 LoadBalancer 類型的 Service 總數上限。
    services.nodeports: 5      #在該命名空間中允許存在的 NodePort 類型的 Service 總數上限。
    secrets: 7  #在該命名空間中允許存在的 Secret 總數上限。
           

資源配額将整個叢集中的資源總量做了一個靜态劃分,但它并沒有對叢集中的節點做任何限制:不同命名空間中的 Pod 仍然可以運作在同一個節點上,如果期望 pod 均勻的分布到不同的 工作節點,需要考慮使用 pod 的拓撲分布限制來實作。

配額作用域

上面的配額配置中,預設情況下對整個命名空間有效,實際上每個配額都有一組相關的 scope(作用域),配額隻會對作用域内的資源生效。 配額機制僅統計所列舉的作用域的交集中的資源用量。

當一個作用域被添加到配額中後,它會對作用域相關的資源數量作限制。 如配額中指定了允許(作用域)集合之外的資源,會導緻驗證錯誤。

  • Terminating :比對所有 spec.activeDeadlineSeconds 不小于 0 的 Pod。
  • NotTerminating :比對所有 spec.activeDeadlineSeconds 是 nil 的 Pod。
  • BestEffort : 比對所有 Qos 是 BestEffort 的 Pod。
  • NotBestEffort : 比對所有 Qos 不是 BestEffort 的 Pod。
  • PriorityClass :比對所有引用了所指定的優先級類的 Pods。

activeDeadlineSeconds 表示 Pod 可以運作的最長時間,達到設定的該值後,Pod 會自動停止,BestEffort 表示 Qos 的三個等級中等級最低的一個,盡力而為的,不太可靠的,

┌──[[email protected]]-[~/ansible/quota]
└─$kubectl apply  -f my-quota-objects-scop.yaml
resourcequota/object-quota-count-scop-demo created
┌──[[email protected]]-[~/ansible/quota]
└─$kubectl describe  resourcequotas  object-quota-count-scop-demo
Name:       object-quota-count-scop-demo
Namespace:  liruilong-topo-namespace
Resource    Used  Hard
--------    ----  ----
pods        2     15
┌──[[email protected]]-[~/ansible/quota]
└─$cat  my-quota-objects-scop.yaml
apiVersion: v1
kind: ResourceQuota
metadata:
  name: object-quota-count-scop-demo
spec:
  hard:
    pods: 15    #在該命名空間中允許存在的非終止狀态的 Pod 總數上限。Pod 終止狀态等價于 Pod 的 .status.phase in (Failed, Succeeded) 為真。
  scopeSelector:
    matchExpressions:
    - operator: Exists
      scopeName: BestEffort

┌──[[email protected]]-[~/ansible/quota]
└─$
           

博文參考

https://kubernetes.io/zh-cn/docs/concepts/policy/resource-quotas/