計算資源管理_Kubernetes中文社群
在Kubernetes,當配置Pod時,可以為每一個容器設定CPU和記憶體這些計算資源。當容器被指定資源請求後,排程器將能夠更好的決定將Pod部署在那一個Node上。
1、資源型別
在當前的Kubernetes版本中,計算資源有CPU和記憶體這兩種型別。CPU的基本單位是核(Core),記憶體的基本單位是位元組(byte)。CPU和記憶體統稱為“計算資源”。在Kubernetes中,計算資源是可以被請求、分配和消耗的可測量的數量。
Pod中的每一個容器都能夠通過如下的方式設定CPU和記憶體的資源:
- spec.containers[].resources.limits.cpu
- spec.containers[].resources.limits.memory
- spec.containers[].resources.requests.cpu
- spec.containers[].resources.requests.memory
雖然從根源上來說,requests和limits是在容器上進行設定的,但是在Pod級別上的設定會帶來更大的便利。Pod上的request/limit是Pod中各個容器request/limit的總和。
1.1 CPU資源
在Kubernetes中CPU資源通過cpu數量進行計算。如果容器的spec.containers[].resources.requests.cpu值為0.5,則表示它需要半個cpu。在Kubernetes中,如果spec.containers[].resources.requests.cpu值為0.1,則等價於spec.containers[].resources.requests.cpu值為100m。在kubernetes,設定CPU資源時,最小值為1m,也就是0.001。CPU資源是一個絕對值,而不是相對值,因此在單核,雙核或者48核機器上,0.1都表達是同一意思,即0.1個CPU core。
1.2 記憶體資源
在Kubernetes中,記憶體資源的計算單位為位元組數(byte),可以直接使用整型數字表達,也可以使用整數加國際單位制來表示。國際單位制包括:十進位制(E, P, T, G, M, K)和二進位制(Ei, Pi, Ti, Gi, Mi, Ki),其中:1KB(kilobyte)=1000bytes,1KiB(kibibyte)=2^10bytes=1024bytes。例如,以下代表大致相同的值:
128974848, 129e6, 129M, 123Mi
1.3 示例
下面的例子中擁有兩個容器的Pod,每一個容器的request是0.25 cpu和 64MiB 記憶體,每個容器的limit是0.5 cpu和128MiB 記憶體。因此,Pod的requst是0.5核cpu和128MiB記憶體,Pod的limit是1核cpu和256MiB記憶體。
apiVersion: v1 kind: Pod metadata: name: frontend spec: containers: - name: db image: mysql env: - name: MYSQL_ROOT_PASSWORD value: "password" resources: requests: memory: "64Mi" cpu: "250m" limits: memory: "128Mi" cpu: "500m" - name: wp image: wordpress resources: requests: memory: "64Mi" cpu: "250m" limits: memory: "128Mi" cpu: "500m"
2、基於資源的Pod排程
在建立一個Pod時,Kubernetes排程器將會為Pod選擇一個執行的Node。對於每一個Node來說,其都存在一個最大的資源能力(CPU和記憶體)。排程器在排程時,要確保Node上CPU和記憶體能夠滿足所有Pod對於計算資源的要求。
當kubelet啟動Pod中的容器時,它會將容器的request和limit作為引數傳遞給容器執行時。如果容器執行時使用的是docker:
- spec.containers[].resources.requests.cpu的值會被轉換為core,然後乘以1024,再將結果通過–cpu-shares引數的值傳遞給docker run命令。
- spec.containers[].resources.limits.cpu的值會被轉化為millicore,然後乘以100。結果值是作為容器在100微秒內能夠使用的CPU總量時間。預設的配額週期是100ms,最小的CPU配額是1ms。
- spec.containers[].resources.limits.memory被轉化為整數,在docker run命令中作為–memory欄位的值。
如果容器在執行過程中使用的記憶體超過了記憶體的limit,它將會被終止。同時如果此容器是可重啟的,則kubelet會在後續會重新啟動它。如果容器在執行過程中使用的記憶體超過了記憶體的request,則當Node記憶體不足時,它所在的Pod會被刪除。
與記憶體不同的是,在容器執行過程中如果使用了超過要求CPU,容器並不會被殺死。
3、監控計算資源使用情況
在Kubernetes中,計算資源的使用情況作為Pod狀態資訊的一部分被報告。另外,如果已經在叢集中配置了監控,也可以通過監控系統獲取Pod的資源使用情況。
4、問題處理
4.2 Pod的狀態為pending,事件資訊為failedScheduling
如果排程器無法為Pod找到合適的Node,則Pod會一直處於未排程的狀態。通過執行下面的命令能夠檢視資訊:
$ kubectl describe pod frontend | grep -A 3 Events
Events:
FirstSeen LastSeen Count From Subobject PathReason Message
36s 5s 6 {scheduler } FailedScheduling Failed for reason PodExceedsFreeCPU and possibly others
在上面的例子中,Pod名稱為fronted,由於Node的CPU資源不足,導致其無法被排程。同一如果記憶體不足的話也會導致Pod無法被排程。這裡錯誤的解決方案如下:
- 往叢集中新增新的Node;
- 終止不需要的Pod釋放資源,以為處於pengding狀態的Pod提供資源;
- 檢查Pod的配置,以保證Pod的資源要求不超過Node提供資源最大值。例如,如果叢集中所有的Node只提供了1核的CPU,如果Pod需要1.1核的CPU,則Pod將無法被排程。
通過執行如下的命令可以檢查Node所提供的計算資源:
$ kubectl describe nodes e2e-test-minion-group-4lw4 Name: e2e-test-minion-group-4lw4 [ ... lines removed for clarity ...] Capacity: cpu: 2 memory: 7679792Ki pods: 110 Allocatable: cpu: 1800m memory: 7474992Ki pods: 110 [ ... lines removed for clarity ...] Non-terminated Pods: (5 in total) Namespace Name CPU Requests CPU Limits Memory Requests Memory Limits --------- ---- ------------ ---------- --------------- ------------- kube-system fluentd-gcp-v1.38-28bv1 100m (5%) 0 (0%) 200Mi (2%) 200Mi (2%) kube-system kube-dns-3297075139-61lj3 260m (13%) 0 (0%) 100Mi (1%) 170Mi (2%) kube-system kube-proxy-e2e-test-... 100m (5%) 0 (0%) 0 (0%) 0 (0%) kube-system monitoring-influxdb-grafana-v4-z1m12 200m (10%) 200m (10%) 600Mi (8%) 600Mi (8%) kube-system node-problem-detector-v0.1-fj7m3 20m (1%) 200m (10%) 20Mi (0%) 100Mi (1%) Allocated resources: (Total limits may be over 100 percent, i.e., overcommitted.) CPU Requests CPU Limits Memory Requests Memory Limits ------------ ---------- --------------- ------------- 680m (34%) 400m (20%) 920Mi (12%) 1070Mi (14%)
4.2 容器被終止
如果應用資源的原因,容器被強行終止。可以通過執行下面的命令來檢查導致容器終止的原因
[12:54:41] $ kubectl describe pod simmemleak-hra99
Name: simmemleak-hra99
Namespace: default
Image(s): saadali/simmemleak
Node: kubernetes-node-tf0f/10.240.216.66
Labels: name=simmemleak
Status: Running
Reason:
Message:
IP: 10.244.2.75
Replication Controllers: simmemleak (1/1 replicas created)
Containers:
simmemleak:
Image: saadali/simmemleak
Limits:
cpu: 100m
memory: 50Mi
State: Running
Started: Tue, 07 Jul 2015 12:54:41 -0700
Last Termination State: Terminated
Exit Code: 1
Started: Fri, 07 Jul 2015 12:54:30 -0700
Finished: Fri, 07 Jul 2015 12:54:33 -0700
Ready: False
Restart Count: 5
Conditions:
Type Status
Ready False
Events:
FirstSeen LastSeen Count From SubobjectPath Reason Message
Tue, 07 Jul 2015 12:53:51 -0700 Tue, 07 Jul 2015 12:53:51 -0700 1 {scheduler } scheduled Successfully assigned simmemleak-hra99 to kubernetes-node-tf0f
Tue, 07 Jul 2015 12:53:51 -0700 Tue, 07 Jul 2015 12:53:51 -0700 1 {kubelet kubernetes-node-tf0f} implicitly required container POD pulled Pod container image "k8s.gcr.io/pause:0.8.0" already present on machine
Tue, 07 Jul 2015 12:53:51 -0700 Tue, 07 Jul 2015 12:53:51 -0700 1 {kubelet kubernetes-node-tf0f} implicitly required container POD created Created with docker id 6a41280f516d
Tue, 07 Jul 2015 12:53:51 -0700 Tue, 07 Jul 2015 12:53:51 -0700 1 {kubelet kubernetes-node-tf0f} implicitly required container POD started Started with docker id 6a41280f516d
Tue, 07 Jul 2015 12:53:51 -0700 Tue, 07 Jul 2015 12:53:51 -0700 1 {kubelet kubernetes-node-tf0f} spec.containers{simmemleak} created Created with docker id 87348f12526a
在上面的例子中,Restart Count: 5顯示了Pod中的容器simmemleak被終止和重啟了5次。
可以通過帶-o go-template=…引數的kubectl get pod 命令獲取已終止容器的狀態資訊:
[13:59:01] $ kubectl get pod -o go-template='{{range.status.containerStatuses}}{{"Container Name: "}}{{.name}}{{"\r\nLastState: "}}{{.lastState}}{{end}}' simmemleak-hra99 Container Name: simmemleak LastState: map[terminated:map[exitCode:137 reason:OOM Killed startedAt:2015-07-07T20:58:43Z finishedAt:2015-07-07T20:58:43Z containerID:docker://0e4095bba1feccdfe7ef9fb6ebffe972b4b14285d5acdec6f0d3ae8a22fad8b2]]
通過輸出的資訊,可以看出是由於reason:OOM Killed的原因,導致了容器被終止,這裡的OOM代表Out Of Memory。
參考資料
1.《Managing Compute Resources for Containers》地址:https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/