1. 程式人生 > >047.叢集管理-資源及配額管理

047.叢集管理-資源及配額管理

一 資源管理

1.1 資源排程機制

對於Kubernetes資源,有兩個重要引數:CPU Request與Memory Request。 通常在定義Pod時並沒有定義這兩個引數,此時Kubernetes會認為該Pod所需的資源很少,並可以將其排程到任何可用的Node上。因此,當叢集中的計算資源不很充足時,如果叢集中的Pod負載突然增大,就會使某個Node的資源嚴重不足。為了避免Node系統掛掉,該Node會選擇“清理”某些Pod來釋放資源,此時每個Pod都可能被“清理”。若其中某些Pod非常重要,比如與資料儲存相關的、與登入相關的、與查詢餘額相關的,需要在系統資源嚴重不足時,也得保障這些Pod的存活。 Kubernetes中該保障機制的核心如下:
  • 通過資源限額來確保不同的Pod只能佔用指定的資源。
  • 允許叢集的資源被超額分配,以提高叢集的資源利用率。
  • 為Pod劃分等級,確保不同等級的Pod有不同的服務質量(QoS),資源不足時,低等級的Pod會被清理,以確保高等級的Pod穩定執行。
Kubernetes叢集裡的節點提供的資源主要是計算資源,計算資源是可計量的能被申請、分配和使用的基礎資源,這使之區別於API資源(API Resources,例如Pod和Services等)。 當前Kubernetes叢集中的計算資源主要包括CPU、GPU及Memory,通常絕大多數常規應用不需要GPU資源。CPU與Memory是被Pod使用的,因此在配置Pod時可以通過引數CPU Request及Memory Request為其中的每個容器指定所需使用的CPU與Memory量,Kubernetes會根據Request的值去查詢有足夠資源的Node來排程此Pod,如果沒有相應的Node能滿足,則排程失敗。 通常,一個程式所使用的CPU與Memory是一個動態的量,確切地說,是一個範圍,跟它的負載密切相關:負載增加時,CPU和Memory的使用量也會增加。因此最準確的說法是,某個程序的CPU使用量為0.1個CPU~1個CPU,記憶體佔用則為500MB~1GB。對應到Kubernetes的Pod容器上,就是下面這4個引數:
  1. spec.container[].resources.requests.cpu
  2. spec.container[].resources.limits.cpu
  3. spec.container[].resources.requests.memory
  4. spec.container[].resources.limits.memory
其中,limits對應資源量的上限,即最多允許使用這個上限的資源量。由於CPU資源是可壓縮的,程序無論如何也不可能突破上限,因此設定起來比較容易。對於Memory這種不可壓縮資源來說,需要進行一定的規劃,若設定得小了,當程序在業務繁忙期試圖請求超過Limit限制的Memory時,此程序就會被Kubernetes殺掉。因此,Memory的Request與Limit的值需要結合程序的實際需求謹慎設定。

1.2 批量設定

若存在成百上千個不同的Pod,那麼先手動設定每個Pod的這4個引數,再檢查並確保這些引數的設定是否合理。比如不能出現記憶體超過2GB或者CPU佔據2個核心的Pod。最後需要手工檢查不同租戶(Namespace)下的Pod的資源使用量是否超過限額。 若上設定相對繁瑣複雜,為此,Kubernetes提供了另外兩個相關物件:LimitRange及ResourceQuota,前者解決request與limit引數的預設值和合法取值範圍等問題,後者則解決約束租戶的資源配額問題。叢集管理涉及計算資源管理(ComputeResources)、服務質量管理(QoS)、資源配額管理(LimitRange、ResourceQuota)等方面。 ResourceQoS解讀:若不設定CPU或Memory的Limit值,該Pod的資源使用量有一個彈性範圍,假設Pod A的Memory Request被設定為1GB,Node A當時空閒的Memory為1.2GB,符合Pod A的需求,因此Pod A被排程到Node A上。執行3天后,Pod A的訪問請求大增,記憶體需要增加到1.5GB,此時Node A的剩餘記憶體只有200MB,由於Pod A新增的記憶體已經超出系統資源,所以在這種情況下,Pod A就會被Kubernetes殺掉。沒有設定Limit的Pod,或者只設置了CPULimit或者MemoryLimit兩者之一的Pod,表面看都是很有彈性的,但實際上,相對於4個引數都被設定的Pod,是處於一種相對不穩定的狀態的,它們與4個引數都沒設定的Pod相比,只是穩定一點而已。

二 計算資源管理

2.1 Requests和Limits

以CPU為例,下圖顯示了未設定Limits和設定了Requests、Limits的CPU使用率的區別。
儘管Requests和Limits只能被設定到容器上,但是設定Pod級別的Requests和Limits能大大提高管理Pod的便利性和靈活性,因此在Kubernetes中提供了對Pod級別的Requests和Limits的配置。對於CPU和記憶體而言,Pod的Requests或Limits是指該Pod中所有容器的Requests或Limits的總和(對於Pod中沒有設定Requests或Limits的容器,該項的值被當作0或者按照叢集配置的預設值來計算)。

2.2 CPU和Memory計算

CPU的Requests和Limits是通過CPU數(cpus)來度量的。CPU的資源值是絕對值,而不是相對值,比如0.1CPU在單核或多核機器上是一樣的,都嚴格等於0.1CPUcore。 Memory記憶體的Requests和Limits計量單位是位元組數。使用整數或者定點整數加上國際單位制來表示記憶體值。國際單位制包括十進位制的E、P、T、G、M、K、m,或二進位制的Ei、Pi、Ti、Gi、Mi、Ki。KiB與MiB是以二進位制表示的位元組單位,常見的KB與MB則是以十進位制表示的位元組單位,比如:
  • 1KB(KiloByte)= 1000Bytes = 8000Bits
  • 1KiB(KibiByte)= 2^10Bytes = 1024Bytes = 8192Bits
因此,128974848、129e6、129M、123Mi的記憶體配置是一樣的。 Kubernetes的計算資源單位是大小寫敏感的,因為m可以表示千分之一單位(milliunit),而M可以表示十進位制的1000,二者的含義不同;同理,小寫的k不是一個合法的資源單位。 示例1: [root@k8smaster01 study]# vi requests01.yaml
  1 apiVersion: v1
  2 kind: Pod
  3 metadata:
  4   name: frontend
  5 spec:
  6  continers:
  7  - name: db
  8    image: mysql
  9    resources:
 10      requests:
 11        memory: "64Mi"
 12        cpu: "250m"
 13      limits:
 14        memory: "128Mi"
 15        cpu: "500m"
 16  - name: wp
 17    image: wordpress
 18    resources:
 19      requests:
 20        memory: "64Mi"
 21        cpu: "250m"
 22      limits:
 23        memory: "128Mi"
 24        cpu: "500m"
 25 
解讀:如上所示,該Pod包含兩個容器,每個容器配置的Requests都是0.25CPU和64MiB(226 Bytes)記憶體,而配置的Limits都是0.5CPU和 128MiB(227 Bytes)記憶體。 這個Pod的Requests和Limits等於Pod中所有容器對應配置的總和,所以Pod的Requests是0.5CPU和128MiB(227 Bytes)記憶體,Limits是1CPU和256MiB(228 Bytes)記憶體。

2.3 Requests和Limits的Pod排程機制

當一個Pod建立成功時,Kubernetes排程器(Scheduler)會為該Pod選擇一個節點來執行。對於每種計算資源(CPU和Memory)而言,每個節點都有一個能用於執行Pod的最大容量值。排程器在排程時,首先要確保排程後該節點上所有Pod的CPU和記憶體的Requests總和,不超過該節點能提供給Pod使用的CPU和Memory的最大容量值。 例如,某個節點上的CPU資源充足,而記憶體為4GB,其中3GB可以執行Pod,而某Pod的Memory Requests為1GB、Limits為2GB,那麼在這個節點上最多可以執行3個這樣的Pod。假設該節點已經啟動3個此Pod例項,而這3個Pod的實際記憶體使用都不足500MB,那麼理論上該節點的可用記憶體應該大於1.5GB。但是由於該節點的Pod Requests總和已經達到節點的可用記憶體上限,因此Kubernetes不會再將任何Pod例項排程到該節點上。 注意:可能某節點上的實際資源使用量非常低,但是已執行Pod配置的Requests值的總和非常高,再加上需要排程的Pod的Requests值,會超過該節點提供給Pod的資源容量上限,這時Kubernetes仍然不會將Pod排程到該節點上。如果Kubernetes將Pod排程到該節點上,之後該節點上執行的Pod又面臨服務峰值等情況,就可能導致Pod資源短缺。

2.4 Requests和Limits機制

kubelet在啟動Pod的某個容器時,會將容器的Requests和Limits值轉化為相應的容器啟動引數傳遞給容器執行器(Docker或者rkt)。如果容器的執行環境是Docker,那麼會傳遞如下4個引數給Docker容器:
  • spec.container[].resources.requests.cpu
這個引數會轉化為core數(比如配置的100m會轉化為0.1),然後乘以1024,再將這個結果作為--cpu-shares引數的值傳遞給docker run命令。在docker run命令中,--cpu-share引數是一個相對權重值(RelativeWeight),這個相對權重值會決定Docker在資源競爭時分配給容器的資源比例。 舉例說明--cpu-shares引數在Docker中的含義:比如將兩個容器的CPU Requests分別設定為1和2,那麼容器在docker run啟動時對應的--cpu-shares引數值分別為1024和2048,在主機CPU資源產生競爭時,Docker會嘗試按照1∶2的配比將CPU資源分配給這兩個容器使用。 注意這個引數對於Kubernetes而言是絕對值,主要用於Kubernetes排程和管理;同時Kubernetes會將這個引數的值傳遞給docker run的--cpu-shares引數。--cpu-shares引數對於Docker而言是相對值,主要用於資源分配比例。
  • spec.container[].resources.limits.cpu
這個引數會轉化為millicore數(比如配置的1被轉化為1000,而配置的100m被轉化為100),將此值乘以100000,再除以1000,然後將結果值作為--cpu-quota引數的值傳遞給docker run命令。docker run命令中另外一個引數--cpu-period預設被設定為100000,表示Docker重新計量和分配CPU的使用時間間隔為100000μs(100ms)。 Docker的--cpu-quota引數和--cpu-period引數一起配合完成對容器CPU的使用限制:比如Kubernetes中配置容器的CPU Limits為0.1,那麼計算後--cpu-quota為10000,而--cpu-period為100000,這意味著Docker在100ms內最多給該容器分配10ms×core的計算資源用量,10/100=0.1core的結果與Kubernetes配置的意義是一致的。 注意:如果kubelet的啟動引數--cpu-cfs-quota被設定為true,那麼kubelet會強制要求所有Pod都必須配置CPU Limits(如果Pod沒有配置,則叢集提供了預設配置也可以)。從Kubernetes1.2版本開始,這個--cpu-cfs-quota啟動引數的預設值就是true。
  • spec.container[].resources.requests.memory
這個引數值只提供給Kubernetes排程器作為排程和管理的依據,不會作為任何引數傳遞給Docker。
  • spec.container[].resources.limits.memory
這個引數值會轉化為單位為Bytes的整數,數值會作為--memory引數傳遞給docker run命令。如果一個容器在執行過程中使用了超出了其記憶體Limits配置的記憶體限制值,那麼它可能會被殺掉,如果這個容器是一個可重啟的容器,那麼之後它會被kubelet重新啟動。 因此對容器的Limits配置需要進行準確測試和評估。與記憶體Limits不同的是,CPU在容器技術中屬於可壓縮資源,因此對CPU的Limits配置一般不會因為偶然超標使用而導致容器被系統殺。

2.5 計算資源使用情況監控

Pod的資源用量會作為Pod的狀態資訊一同上報給Master。如果在叢集中配置了Heapster來監控叢集的效能資料,那麼還可以從Heapster中檢視Pod的資源用量資訊。

2.6 計算資源排程常見問題

  • Pod狀態為Pending,錯誤資訊為FailedScheduling
如果Kubernetes排程器在叢集中找不到合適的節點來執行Pod,那麼這個Pod會一直處於未排程狀態,直到排程器找到合適的節點為止。每次排程器嘗試排程失敗時,Kubernetes都會產生一個事件,我們可以通過下面這種方式來檢視事件的資訊: kubectl describe pod <podname>| grep -A 3 Events 如果一個或者多個Pod排程失敗且有這類錯誤,那麼可以嘗試以下幾種解決方法:
  1. 新增更多的節點到叢集中;
  2. 停止一些不必要的執行中的Pod,釋放資源;
  3. 檢查Pod的配置,錯誤的配置可能導致該Pod永遠無法被排程執行。比如整個叢集中所有節點都只有1CPU,而Pod配置的CPURequests為2,該Pod就不會被排程執行。
可以使用kubectl describe nodes命令來檢視叢集中節點的計算資源容量和已使用量: [root@k8smaster01 ~]# kubectl describe nodes k8snode01 超過可用資源容量上限(Capacity)和已分配資源量(Allocatedresources)差額的Pod無法執行在該Node上。
  • 容器被強行終止(Terminated)
如果容器使用的資源超過了它配置的Limits,那麼該容器可能會被強制終止。可以通過kubectl describe pod命令來確認容器是否因為這個原因被終止: kubectl describe pod Restart Count:5說明這個名為simmemleak的容器被強制終止並重啟了5次。可以在使用kubectl get pod命令時新增-o go-template=...格式引數來讀取已終止容器之前的狀態資訊: kubectl get pod -o go-template='{{range.status.containerStatuses}}{{"Container Name:"}}{{.name}}{{"\r\nLastate:"}}{{.lastState}}{{end}}' 可以看到這個容器因為reason:OOM Killed而被強制終止,說明這個容器的記憶體超過了限制(OutofMemory)。

三 資源配置範圍管理(LimitRange)

3.1 LimitRange

在預設情況下,Kubernetes不會對Pod加上CPU和記憶體限制,這意味著Kubernetes系統中任何Pod都可以使用其所在節點的所有可用的CPU和記憶體。通過配置Pod的計算資源Requests和Limits,可以限制Pod的資源使用,但對於Kubernetes叢集管理員而言,配置每一個Pod的Requests和Limits是煩瑣的,而且很受限制。更多時候,需要對叢集內Requests和Limits的配置做一個全侷限制。 常見的配置場景如下:
  1. 叢集中的每個節點都有2GB記憶體,叢集管理員不希望任何Pod申請超過2GB的記憶體:因為在整個叢集中都沒有任何節點能滿足超過2GB記憶體的請求。如果某個Pod的記憶體配置超過2GB,那麼該Pod將永遠都無法被排程到任何節點上執行。為了防止這種情況的發生,叢集管理員希望能在系統管理功能中設定禁止Pod申請超過2GB記憶體。
  2. 叢集由同一個組織中的兩個團隊共享,分別執行生產環境和開發環境。生產環境最多可以使用8GB記憶體,而開發環境最多可以使用512MB記憶體。叢集管理員希望通過為這兩個環境建立不同的名稱空間,併為每個名稱空間設定不同的限制來滿足這個需求。
  3. 使用者建立Pod時使用的資源可能會剛好比整個機器資源的上限稍小,而恰好剩下的資源大小非常尷尬:不足以執行其他任務但整個叢集加起來又非常浪費。因此,叢集管理員希望設定每個Pod都必須至少使用叢集平均資源值(CPU和記憶體)的20%,這樣叢集能夠提供更好的資源一致性的排程,從而減少了資源浪費。
針對這些需求,Kubernetes提供了LimitRange機制對Pod和容器的Requests和Limits配置進一步做出限制。
示例1: [root@k8smaster01 study]# kubectl create namespace limit-example #建立namespace [root@k8smaster01 study]# vi limits.yaml #建立limitrange
  1 apiVersion: v1
  2 kind: LimitRange
  3 metadata:
  4   name: mylimits
  5 spec:
  6   limits:
  7   - max:
  8       cpu: "4"
  9       memory: 2Gi
 10     min:
 11       cpu: 200m
 12       memory: 6Mi
 13     maxLimitRequestRatio:
 14       cpu: 3
 15       memory: 2
 16     type: Pod
 17   - default:
 18       cpu: 300m
 19       memory: 200Mi
 20     defaultRequest:
 21       cpu: 200m
 22       memory: 100Mi
 23     max:
 24       cpu: "2"
 25       memory: 1Gi
 26     min:
 27       cpu: 100m
 28       memory: 3Mi
 29     maxLimitRequestRatio:
 30       cpu: 5
 31       memory: 4
 32     type: Container
 33 
[root@k8smaster01 study]# kubectl create -f limits.yaml --namespace=limit-example #為Namespace“limit-example”建立LimitRange [root@k8smaster01 study]# kubectl get limitranges -n limit-example [root@k8smaster01 study]# kubectl describe limitranges mylimits -n limit-example 解讀:
  1. 不論是CPU還是記憶體,在LimitRange中,Pod和Container都可以設定Min、Max和MaxLimit/RequestsRatio引數。Container還可以設定Default Request和Default Limit引數,而Pod不能設定Default Request和DefaultLimit引數。
  2. 對Pod和Container的引數解釋如下:
    • Container的Min(如上圖100m和3Mi)是Pod中所有容器的Requests值下限;Container的Max(如上圖2和1Gi)是Pod中所有容器的Limits值上限;Container的Default Request(如上圖200m和100Mi)是Pod中所有未指定Requests值的容器的預設Requests值;Container的DefaultLimit(如上圖300m和200Mi)是Pod中所有未指定Limits值的容器的預設Limits值。對於同一資源型別,這4個引數必須滿足以下關係:Min ≤ Default Request ≤ Default Limit ≤ Max。
    • Pod的Min(如上圖200m和6Mi)是Pod中所有容器的Requests值的總和下限;Pod的Max(如上圖4和2Gi)是Pod中所有容器的Limits值的總和上限。當容器未指定Requests值或者Limits值時,將使用Container的Default Request值或者Default Limit值。
    • Container的Max Limit/Requests Ratio(如上圖5和4)限制了Pod中所有容器的Limits值與Requests值的比例上限;而Pod的MaxLimit/RequestsRatio(如上圖3和2)限制了Pod中所有容器的Limits值總和與Requests值總和的比例上限。
  1. 如果設定了Container的Max,那麼對於該類資源而言,整個叢集中的所有容器都必須設定Limits,否則無法成功建立。Pod內的容器未配置Limits時,將使用Default Limit的值(本例中的300mCPU和200MiB記憶體),如果也未配置Default,則無法成功建立。
  2. 如果設定了Container的Min,那麼對於該類資源而言,整個叢集中的所有容器都必須設定Requests。如果建立Pod的容器時未配置該類資源的Requests,那麼在建立過程中會報驗證錯誤。Pod裡容器的Requests在未配置時,可以使用預設值default Request(本例中的200mCPU和100MiB記憶體);如果未配置而又沒有使用預設值default Request,那麼會預設等於該容器的Limits;如果此時Limits也未定義,就會報錯。
  3. 對於任意一個Pod而言,該Pod中所有容器的Requests總和必須大於或等於6MiB,而且所有容器的Limits總和必須小於或等於1GiB;同樣,所有容器的CPU Requests總和必須大於或等於200m,而且所有容器的CPU Limits總和必須小於或等於2。
  4. Pod裡任何容器的Limits與Requests的比例都不能超過Container的MaxLimit/RequestsRatio;Pod裡所有容器的Limits總和與Requests的總和的比例不能超過Pod的MaxLimit/RequestsRatio。

[root@k8smaster01 study]# kubectl run nginx --image=nginx --replicas=1 --namespace=limit-example [root@k8smaster01 study]# kubectl get pods --namespace=limit-example NAME READY STATUS RESTARTS AGE nginx-7bb7cd8db5-mzcvb 1/1 Running 0 54s 解讀:名稱空間中LimitRange只會在Pod建立或者更新時執行檢查。如果手動修改LimitRange為一個新的值,那麼這個新的值不會去檢查或限制之前已經在該名稱空間中建立好的Pod。如果在建立Pod時配置的資源值(CPU或者記憶體)超過了LimitRange的限制,那麼該建立過程會報錯,在錯誤資訊中會說明詳細的錯誤原因。 [root@k8smaster01 study]# kubectl get pods nginx-7bb7cd8db5-mzcvb --namespace=limit-example -o yaml | grep resources -C 6 #檢視該Pod的resource
  1   uid: 5fd37e03-ea08-44f3-a2c7-30ad31c7ab4a
  2 spec:
  3   containers:
  4   - image: nginx
  5     imagePullPolicy: Always
  6     name: nginx
  7     resources:
  8       limits:
  9         cpu: 300m
 10         memory: 200Mi
 11       requests:
 12         cpu: 200m
 13         memory: 100Mi
 14 
解讀:由於該Pod未配置資源Requests和Limits,所以使用了namespace limit-example中的預設CPU和記憶體定義的Requests和Limits值。 [root@k8smaster01 study]# vi invalid-pod.yaml
  1 apiVersion: v1
  2 kind: Pod
  3 metadata:
  4   name: invalid-pod
  5 spec:
  6   containers:
  7   - name: kubernetes-serve-hostname
  8     image: gcr.azk8s.cn/google_containers/server_hostname
  9     resources:
 10       limits:
 11         cpu: "3"
 12         memory: 100Mi
 13 
[root@k8smaster01 study]# kubectl create -f invalid-pod.yaml --namespace=limit-example Error from server (Forbidden): error when creating "invalid-pod.yaml": pods "invalid-pod" is forbidden: maximum cpu usage per Container is 2, but limit is 3 解讀:建立該Pod,會出現系統報錯了,並且提供的錯誤原因為超過資源限制。 [root@k8smaster01 study]# vi limit-test-nginx.yaml
  1 apiVersion: v1
  2 kind: Pod
  3 metadata:
  4   name: limit-test-nginx
  5   labels:
  6     name: limit-test-nginx
  7 spec:
  8   containers:
  9   - name: limit-test-nginx
 10     image: nginx
 11     resources:
 12       limits:
 13         cpu: "1"
 14         memory: 512Mi
 15       requests:
 16         cpu: "0.8"
 17         memory: 250Mi
 18 
[root@k8smaster01 study]# kubectl create -f limit-test-nginx.yaml -n limit-example Error from server (Forbidden): error when creating "limit-test-nginx.yaml": pods "limit-test-nginx" is forbidden: memory max limit to request ratio per Pod is 2, but provided ratio is 2.048000 解讀:由於limit-test-nginx這個Pod的全部記憶體Limits總和與Requests總和的比例為512∶250,大於在LimitRange中定義的Pod的最大比率2(maxLimitRequestRatio.memory=2),因此建立失敗。 [root@k8smaster01 study]# vi valid-pod.yaml
  1 apiVersion: v1
  2 kind: Pod
  3 metadata:
  4   name: valid-pod
  5   labels:
  6     name: valid-pod
  7 spec:
  8   containers:
  9   - name: kubernetes-serve-hostname
 10     image: gcr.io/google_containers/serve_hostname
 11     resources:
 12       limits:
 13         cpu: "1"
 14         memory: 512Mi
 15 
[root@k8smaster01 study]# kubectl create -f valid-pod.yaml -n limit-example [root@k8smaster01 study]# kubectl get pods valid-pod -n limit-example -o yaml | grep resources -C 6 #檢視該Pod的資源資訊
  1   uid: 59e3d05a-8c09-479e-a3ad-1a4dbfd8e946
  2 spec:
  3   containers:
  4   - image: gcr.io/google_containers/serve_hostname
  5     imagePullPolicy: Always
  6     name: kubernetes-serve-hostname
  7     resources:
  8       limits:
  9         cpu: "1"
 10         memory: 512Mi
 11       requests:
 12         cpu: "1"
 13         memory: 512Mi
 14 
解讀:該Pod配置了明確的Limits和Requests,因此該Pod不會使用在namespace limit-example中定義的default和default Request。 注意:CPU Limits強制配置這個選項在Kubernetes叢集中預設是開啟的;除非叢集管理員在部署kubelet時,通過設定引數--cpucfs-quota=false來關閉該限制:如果叢集管理員希望對整個叢集中容器或者Pod配置的Requests和Limits做限制,那麼可以通過配置Kubernetes名稱空間中的LimitRange來達到該目的。在Kubernetes叢集中,如果Pod沒有顯式定義Limits和Requests,那麼Kubernetes系統會將該Pod所在的名稱空間中定義的LimitRange的default和default Requests配置到該Pod上。

四 資源服務質量管理(Resource QoS)

4.1 服務資源質量

Kubernetes會根據Pod的Requests和Limits配置來實現針對Pod的不同級別的資源服務質量控制(QoS)。在Kubernetes的資源QoS體系中,需要保證高可靠性的Pod可以申請可靠資源,而一些不需要高可靠性的Pod可以申請可靠性較低或者不可靠的資源。 容器的資源配置分為Requests和Limits,其中Requests是Kubernetes排程時能為容器提供的完全可保障的資源量(最低保障),而Limits是系統允許容器執行時可能使用的資源量的上限(最高上限)。Pod級別的資源配置是通過計算Pod內所有容器的資源配置的總和得出來的。 Kubernetes中Pod的Requests和Limits資源配置有如下特點:
  1. 如果Pod配置的Requests值等於Limits值,那麼該Pod可以獲得的資源是完全可靠的。
  2. 如果Pod的Requests值小於Limits值,那麼該Pod獲得的資源可分成兩部分:
    1. 完全可靠的資源,資源量的大小等於Requests值;
    2. 不可靠的資源,資源量最大等於Limits與Requests的差額,這份不可靠的資源能夠申請到多少,取決於當時主機上容器可用資源的餘量。
通過這種機制,Kubernetes可以實現節點資源的超售(OverSubscription),比如在CPU完全充足的情況下,某機器共有32GiB記憶體可提供給容器使用,容器配置為Requests值1GiB,Limits值為2GiB,那麼在該機器上最多可以同時執行32個容器,每個容器最多可以使用2GiB記憶體,如果這些容器的記憶體使用峰值能錯開,那麼所有容器都可以正常執行。超售機制能有效提高資源的利用率,同時不會影響容器申請的完全可靠資源的可靠性。

4.2 Requests和Limits限制機制

容器的資源配置滿足以下兩個條件:
  • Requests <= 節點可用資源
  • Requests <= Limits
Kubernetes根據Pod配置的Requests值來排程Pod,Pod在成功排程之後會得到Requests值定義的資源來執行;而如果Pod所在機器上的資源有空餘,則Pod可以申請更多的資源,最多不能超過Limits的值。Requests和Limits針對不同計算資源型別的限制機制存在差異。這種差異主要取決於計算資源型別是可壓縮資源還是不可壓縮資源。
  1. 可壓縮資源
Kubernetes目前支援的可壓縮資源是CPU。 Pod可以得到Pod的Requests配置的CPU使用量,而能否使用超過Requests值的部分取決於系統的負載和排程。不過由於目前Kubernetes和Docker的CPU隔離機制都是在容器級別隔離的,所以Pod級別的資源配置並不能完全得到保障;Pod級別的cgroups等待引入,以便於確保Pod級別的資源配置準確執行。 空閒CPU資源按照容器Requests值的比例分配。舉例說明:容器A的CPU配置為Requests 1 Limits 10,容器B的CPU配置為Request 2 Limits8,A和B同時執行在一個節點上,初始狀態下容器的可用CPU為3 cores,那麼A和B恰好得到在它們的Requests中定義的CPU用量,即1CPU和2CPU。如果A和B都需要更多的CPU資源,而恰好此時系統的其他任務釋放出1.5CPU,那麼這1.5 CPU將按照A和B的Requests值的比例1∶2分配給A和B,即最終A可使用1.5CPU,B可使用3CPU。 如果Pod使用了超過在Limits 10中配置的CPU用量,那麼cgroups會對Pod中的容器的CPU使用進行限流(Throttled);如果Pod沒有配置Limits 10,那麼Pod會嘗試搶佔所有空閒的CPU資源(Kubernetes從1.2版本開始預設開啟--cpu-cfs-quota,因此在預設情況下必須配置Limits)
  1. 不可壓縮資源
Kubernetes目前支援的不可壓縮資源是記憶體。 Pod可以得到在Requests中配置的記憶體。如果Pod使用的記憶體量小於它的Requests的配置,那麼這個Pod可以正常執行;如果Pod使用的記憶體量超過了它的Requests的配置,那麼這個Pod有可能被Kubernetes殺掉:比如Pod A使用了超過Requests而不到Limits的記憶體量,此時同一機器上另外一個Pod B之前只使用了遠少於自己的Requests值的記憶體,此時程式壓力增大,Pod B向系統申請的總量不超過自己的Requests值的記憶體,那麼Kubernetes可能會直接殺掉Pod A,而優先保障Pod B的Requests得到滿足;另外一種情況是Pod A使用了超過Requests而不到Limits的記憶體量,此時Kubernetes將一個新的Pod排程到這臺機器上,新的Pod需要使用記憶體,而只有Pod A使用了超過了自己的Requests值的記憶體,那麼Kubernetes也可能會殺掉Pod A來釋放記憶體資源。 如果Pod使用的記憶體量超過了它的Limits設定,那麼作業系統核心會殺掉Pod所有容器的所有程序中使用記憶體最多的一個,直到記憶體不超過Limits為止。

4.3 對排程策略的影響

Kubernetes的kubelet通過計算Pod中所有容器的Requests的總和來決定對Pod的排程。 不管是CPU還是記憶體,Kubernetes排程器和kubelet都會確保節點上所有Pod的Requests的總和不會超過在該節點上可分配給容器使用的資源容量上限。

4.4 服務質量等級(QoSClasses)

在一個超用(Over Committed,容器Limits總和大於系統容量上限)系統中,由於容器負載的波動可能導致作業系統的資源不足,最終可能導致部分容器被殺掉。在這種情況下,理想是優先殺掉那些不太重要的容器。Kubernetes將容器劃分成3個QoS等級來衡量重要程度: Guaranteed(完全可靠的)、Burstable(彈性波動、較可靠的)和BestEffort(盡力而為、不太可靠的),這三種優先順序依次遞減。 QoS等級和優先順序的關係從理論上來說,QoS級別應該作為一個單獨的引數來提供API,並由使用者對Pod進行配置,這種配置應該與Requests和Limits無關。但在當前版本的Kubernetes的設計中,為了簡化模式及避免引入太多的複雜性,QoS級別直接由Requests和Limits來定義。在Kubernetes中容器的QoS級別等於容器所在Pod的QoS級別,而Kubernetes的資源配置定義了Pod的如上三種QoS級別。
  1. Guaranteed
如果Pod中的所有容器對所有資源型別都定義了Limits和Requests,並且所有容器的Limits值都和Requests值全部相等(且都不為0),那麼該Pod的QoS級別就是Guaranteed。 注意:在這種情況下,容器可以不定義Requests,因為Requests值在未定義時預設等於Limits。 示例1:如下定義的PodQoS級別就是Guaranteed。
  1 containers:
  2   name: foo
  3     resources:
  4       limits:
  5         cpu: 10m
  6         memory: 1Gi
  7   name: bar
  8     resources:
  9       limits:
 10         cpu: 100m
 11         memory: 100Mi
 12 
解讀:如上未定義Requests值,所以其預設等於Limits值。 示例2:
  1 containers:
  2   name: foo
  3     resources:
  4       requests:
  5         cpu: 10m
  6         memory: 1Gi
  7       limits:
  8         cpu: 10m
  9         memory: 1Gi
 10   name: bar
 11     resources:
 12       requests:
 13         cpu: 10m
 14         memory: 1Gi
 15       limits:
 16         cpu: 100m
 17         memory: 100Mi
 18 
解讀:該定義的Requests和Limits的值完全相同。
  1. BestEffort
如果Pod中所有容器都未定義資源配置(Requests和Limits都未定義),那麼該Pod的QoS級別就是BestEffort。 示例3:
  1 containers:
  2   name: foo
  3     resources:
  4   name: bar
  5     resources:
  6 
解讀:該容器都未定義資源配置。
  1. Burstable
當一個Pod既不為Guaranteed級別,也不為BestEffort級別時,該Pod的QoS級別就是Burstable。Burstable級別的Pod包括兩種情況。
  • 第1種情況:Pod中的一部分容器在一種或多種資源型別的資源配置中定義了Requests值和Limits值(都不為0),且Requests值小於Limits值;
  • 第2種情況:Pod中的一部分容器未定義資源配置(Requests和Limits都未定義)。
注意:在容器未定義Limits時,Limits值預設等於節點資源容量的上限。 示例4:容器foo的CPURequests不等於Limits。
  1 containers:
  2   name: foo
  3     resources:
  4       requests:
  5         cpu: 5m
  6         memory: 1Gi
  7       limits:
  8         cpu: 10m
  9         memory: 1Gi
 10   name: bar
 11     resources:
 12       requests:
 13         cpu: 5m
 14         memory: 1Gi
 15       limits:
 16         cpu: 100m
 17         memory: 100Mi
 18 
示例5:容器bar未定義資源配置而容器foo定義了資源配置。
  1 containers:
  2   name: foo
  3     resources:
  4       requests:
  5         cpu: 10m
  6         memory: 1Gi
  7       limits:
  8         cpu: 10m
  9         memory: 1Gi
 10   name: bar
 11 
示例6:容器foo未定義CPU,而容器bar未定義記憶體。
  1 containers:
  2   name: foo
  3     resources:
  4       limits:
  5         memory: 1Gi
  6   name: bar
  7     resources:
  8       limits:
  9         cpu: 100m
 10 
示例7:容器bar未定義資源配置,而容器foo未定義Limits值。 containers: name: foo resources: requests: cpu: 5m memory: 1Gi name: bar

4.5 Kubernetes QoS的工作特點

Pod的CPU Requests無法得到滿足(比如節點的系統級任務佔用過多的CPU導致無法分配足夠的CPU給容器使用)時,容器得到的CPU會被壓縮限流。由於記憶體是不可壓縮的資源,所以針對記憶體資源緊缺的情況,會按照以下邏輯進行處理。
  1. BestEffort Pod的優先順序最低,在這類Pod中執行的程序會在系統記憶體緊缺時被第一優先殺掉。當然,從另外一個角度來看,BestEffort Pod由於沒有設定資源Limits,所以在資源充足時,它們可以充分使用所有的閒置資源。
  2. Burstable Pod的優先順序居中,這類Pod初始時會分配較少的可靠資源,但可以按需申請更多的資源。當然,如果整個系統記憶體緊缺,又沒有BestEffort容器可以被殺掉以釋放資源,那麼這類Pod中的程序可能會被殺掉。
  3. Guaranteed Pod的優先順序最高,而且一般情況下這類Pod只要不超過其資源Limits的限制就不會被殺掉。當然,如果整個系統記憶體緊缺,又沒有其他更低優先順序的容器可以被殺掉以釋放資源,那麼這類Pod中的程序也可能會被殺掉。

4.6 OOM計分系統

OOM(Out Of Memory)計分規則包括如下內容: OOM計分的計算方法為:計算程序使用記憶體在系統中佔的百分比,取其中不含百分號的數值,再乘以10的結果,這個結果是程序OOM的基礎分;將程序OOM基礎分的分值再加上這個程序的OOM分數調整值OOM_SCORE_ADJ的值,作為程序OOM的最終分值(除root啟動的程序外)。在系統發生OOM時,OOM Killer會優先殺掉OOM計分更高的程序。 程序的OOM計分的基本分數值範圍是0~1000,如果A程序的調整值OOM_SCORE_ADJ減去B程序的調整值的結果大於1000,那麼A程序的OOM計分最終值必然大於B程序,會優先殺掉A程序。 不論調整OOM_SCORE_ADJ值為多少,任何程序的最終分值範圍也是0~1000。在Kubernetes,不同QoS的OOM計分調整值規則如下所示。
QoS等級 oom_score_adj
Guaranteed -998
BestEffort 1000

相關推薦

047.叢集管理-資源配額管理

一 資源管理 1.1 資源排程機制 對於Kubernetes資源,有兩個重要引數:CPU Request與Memory Request。 通常在定義Pod時並沒有定義這兩個引數,此時Kubernetes會認為該Pod所需的資源很少,並可以將其排程到任何可用的Node上。因此,當叢集中的計算資源不很充足時,如果

Centos 磁盤管理配額管理

技術分享 寫入文件 卸載 掛載文件 2個 物理卷 51cto ado eba 實驗內容:一.添加兩塊硬盤,使用LVM做成VG01組,在該VG中新建兩個LV。二.將這兩個LV格式化為ext4/xfs,開機自動掛載到系統mnt1,mnt2目錄下。三.lv02開啟磁盤配額功能,用

實現Linux的LVM邏輯卷管理和磁碟配額管理

LVM邏輯卷管理 LVM是邏輯卷管理的簡稱,它是Linux環境下對磁碟分割槽管理的一種機制,實現檔案系統跨越不同磁碟和分割槽,工作原理是將若干個磁碟分割槽連線成一個整塊卷組,在卷組上隨意建立邏輯卷組,最後在邏輯卷組上建立檔案系統,管理員可以動態調整邏輯卷的大小,不會丟失現有的資料,通過建立LVM可以對磁碟進

【Linux】---基本的使用者管理命令系統管理操作

---------常用的使用者管理命令 ********建立一個使用者的命令:  1.useradd    beat ********需要為其設定一個密碼: 2.passwd    beat 預設建立的使用者在root許可權下的

windows資源管理ie監聽

Okay, it’s been a while since we set aside our Little Program to learn a bit about connection points and using dispatch interfaces as connection p

kubernetes實戰(九):k8s叢集動態儲存管理GlusterFS容器化GlusterFS擴容

1、準備工作   所有節點安裝GFS客戶端 yum install glusterfs glusterfs-fuse -y   如果不是所有節點要部署GFS管理服務,就在需要部署的節點上打上標籤 [[email protected] ~]# kubectl label node k8s-nod

dubbo管理控制檯整合zookeeper叢集部署

參考 http://www.mamicode.com/info-detail-168312.html http://blog.csdn.net/rangqiwei/article/details/19398301 1、下載dubbo控制檯管理war包 http://

kubernetes資源配額管理

參考:https://kubernetes.io/docs/concepts/policy/resource-quotas/ 當叢集有多個使用者或者團隊時,一個重要的問題就是資源的公平分配。 資源配置就是管理員用來解決類似問題的工具。 通過定義ResourceQuota

048.叢集管理-資源限制實踐

一 實踐規劃 1.1 實踐需求 本實驗通過資源配額和資源配置範圍的配合來控制一個名稱空間的資源使用。 叢集管理員根據叢集使用者的數量來調整叢集配置,以達到這個目的:能控制特定名稱空間中的資源使用量,最終實現叢集的公平使用和成本控制。 需要實現的功能如下: 限制執行狀態的Pod的計算資源用量。 限制持久儲存

SQL server數據庫的在server 2008R2上的安裝基本管理

server 數據庫 SQL server數據庫的在server 2008R2上的安裝及基本管理(一)選擇SQL的數據庫的鏡像文件雙擊setup.ext 執行安裝程序這裏選擇安裝項,並選擇全新安裝安裝的環境監測全部通過因為這裏是使用的破解版的鏡像,所以會自動生成密鑰再一次檢測安裝環境

effective C++ 讀書筆記 條款14 以對象管理資源

effect virt 什麽 con pin 構造 ostream pos sha 如果我們使用一個投資行為的程序庫: #include "stdafx.h" #include <iostream> #include <memory> using

初始化管理IPweb界面

cisco 密碼 ios ip 以 Cisco Catalyst 3560G-24TS Switch 為例初始化管理IPenable configure terminal interface vlan 1 ip address IP地址 掩碼 no shutdown初始化web界面登陸enab

Linux學習筆記——目錄、文件管理命令常用選項

linux 目錄文件管理 linux目錄文件管理命令 目錄管理命令:ls 、 cd 、 pwd 、mkdir、 rmdir 、tree文件管理命令:touch、 stat 、file、 rm 、cp、 mv 、nan目錄管理#ls 列出列表格式ls [OPTION]... [FILE]...

Linux服務安全管理第八周作業【Linux微職位】

加密解密技術;ca;dns1、詳細描述一次加密通訊的過程,結合圖示最佳。一次完整的加密通訊過程如下:通訊的雙方需要事先協商好單向加密算法,並交換各自的公鑰發送端加密過程1、發送端先用單向加密算法計算出數據的特征碼2、發送端用自己的私鑰加密特征碼,生成數字簽名,並將該數字簽名附加在數據之後3、發送端生成一個臨時

Linux 自學筆記——內核管理初步編譯

linux kernel 內核管理 編譯內核 Linux Kernel: 內核設計體系:單內核、微內核; 內核的組成部分: 1.Kernel:內核核心,一般為bzimage,通常位於/boot目錄,名稱為vmlinuz-VERSION-release

Linux服務安全管理第九周作業【Linux微職位】

http1、請描述一次完整的http請求處理過程;(1)建立或處理連接:接收請求或拒絕請求;(2)接收請求:接收來自於網絡上的主機請求報文中對某特定資源的一次請求的過程;(3)處理請求:對請求報文進行解析,獲取客戶端請求的資源及請求方法等相關信息;(4)訪問資源:獲取請求報文中請求的資源;(5)構建響應報文:

2.3-用戶管理

用戶及組管理用戶和組管理 資源分配: Authentication:認證 Authorization:授權 Accouting(Audition):審計 token:只驗證密碼,不驗證用戶的機制 認證(identity):密碼和用戶名雙重驗證Linu

第4天【文件管理、管道、用戶管理、用戶權限管理

std 有效 i/o 屏幕 顯示行數 私有 文本處理 txt $path Bash的I/o重定向及管道 管道:使用豎杠符號‘|’表示,用於將前面命令的命名輸出結果作為命名後的操作對象。 重定向輸出:使用大於符號”>”表示,前面的命令成功執行以後,其屏幕輸出結果將保存到

linux中磁盤配額管理

用戶 r文件 管理 linu 文件 ges off 磁盤空間 fst 一,磁盤管理的概念: Linux系統是多用戶任務操作系統,在使用系統時,會出現多用戶共同使用一個磁盤的情況,如果其中少數幾個用戶占用了大量的磁盤空間,勢必壓縮其他用戶的磁盤的空間和使用權限。因此,系統管理

linux進程作業管理

進程、任務1、cpu指令級別: cpu環0級別:存放只能系統調用的指令 cpu環3級別:存放只能用戶調用的指令2、操作系統組成:(廣義) 計算機硬件、kernel(操作系統:system call,只能系統調用,比較底層)、庫調用(library call,為用戶編程提供接口)、應用程序。所