kubernetes之計算機資源管理

系列目錄html

當你編排一個pod的時候,你也能夠可選地指定每一個容器須要多少CPU和多少內存(RAM).當容器請求特定的資源時,調度器能夠更好地根據資源請求來肯定把pod調度到哪一個節點上.當容器請求限制特定資源時,特定節點會以指定方式對容器的資源進行限制.node

對於資源請求和資源限制的區別,能夠查看QoSmysql

資源類型

CPU和RAM都是資源類型,資源類型有一個基本單位.CPU資源經過單位核數來指定,內存經過單位字節來指定.它們和api資源不一樣.api資源,例如pod和service是kubernetes api server能夠讀取和修改的對象.git

pod和容器的資源請求與資源限制

pod裏的每個容器均可以指一個或多個如下內容:sql

  • spec.containers[].resources.limits.cpudocker

  • spec.containers[].resources.limits.memoryapi

  • spec.containers[].resources.requests.cpubash

  • spec.containers[].resources.requests.memoryapp

儘管請求和限制只能經過單個的容器來指定,可是咱們一般說pod的資源請求和資源限制,這樣更方便.Pod對於某一特定資源的請求(或限制)是pod裏單個容器請求資源的和.frontend

CPU的意義

對cpu資源的請求和限制用單位cpu來衡量,一個cpu在kubernetes裏和如下任意一個是等價的:

  • 1 AWS vCPU

  • 1 GCP Core

  • 1 Azure vCore

  • 1 IBM vCPU

  • 在祼機因特爾超線程處理器上一個超線程

帶小數的請求也是容許的.一個指定spec.containers[].resources.requests.cpu值爲0.5的容器會被確保分配1個cpu的一半資源.值0.1和100m是等價的,能夠讀做100 millicpu,也有人讀做100 millicores,實際上意義是同樣的.請求資源的值爲0.1將會被api轉換爲100m,請求的精度比1m更小是不容許的,所以100m一個較優的選擇.CPU資源的請求老是絕對量,永遠不會是一個相對值,值是0.1時對於單核cpu,雙核cpu或者甚至48核cpu都是同樣的.

內存的意義

對內存資源的請求/限制用字節來衡量.你可使用一個純整數或者定點整數帶上E, P, T, G, M, K這些後綴,你也可使用2的冪次方的:Ei, Pi, Ti, Gi, Mi, Ki來表示,好比如下表示的量相等

128974848, 129e6, 129M, 123Mi

如下定義的pod包含兩個容器,每個都請求0.25cpu和64MiB (226 字節)的內存.每個都限制0.5cpu和128MIB內存.你能夠說pod請求0.5cpu和128MiB內存,限制1cpu和256MiB內存

前面說過,pod的資源請求/限制是pod裏的容器資源請求/限制的和

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"

kubernetes如何調度有資源請求的pod

當你建立一個pod,kubernetes會選擇一個節點來運行.對於每種資源類型,不管是cpu仍是內存,節點能夠提供給pod的都是有上限的.對於每種資源,調度器都會確保被調度的pod的請求的總和小於節點的承載能力.請注意即使節點上的cpu或者內存的使用率很是低,可是若是容量檢測失敗,調度器仍然可能拒絕把某一pod放到指定節點上.這確保後來資源使用增多時不會出現資源短缺的狀況.

有資源限制的pod如何運行

當kubelete啓動了pod的容器,它會把cpu和內存的限制傳入到容器的runtime裏

當使用的是docker時:

  • spec.containers[].resources.requests.cpu的值被轉換爲核數值,它也多是小數,乘1024.這個值和2二者較大的一個會被做爲--cpu-shares標識的值傳入docker run命令

  • spec.containers[].resources.limits.cpu被轉換爲millicore值而且乘以100.結果值是容器每100毫秒可用的cpu時間的總和.

注意默認的時間段配額是100毫秒,最小配額是1毫秒.

  • spec.containers[].resources.limits.memory被轉換爲整數,而後做爲--momory標識的值傳入docker run命令.

若是一個容器超過了它的資源限制,則它可能會被終止.若是它是可重啓的(根據pod編排時重啓策略),則kubelete會重啓它,就像對待其它運行時錯誤同樣.

一個容器可能會被容許或者不被容許超過超過它的cpu限制.可是超過cpu資源限制時它不會被殺掉.

問題處理

pod掛起,event消息是:failedScheduling

若是調度器找不到任何能夠放置pod的節點,pod一直是未調度狀態找到一個合適的節點.調度器每當找不到合適節點來放置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

上面的示例中,因爲節點的cpu資源不足,名稱爲frontend的pod調度失敗.相似的錯誤提示也多是因爲內存資源不足(PodExceedsFreeMemory).通常地,若是相似這樣的消息出現,能夠進行如下嘗試:

  • 集羣中添加更多節點

  • 終止一些非必須進程來爲掛起的pod騰出資源

  • 檢測確保pod小於node,好比節點的容量是cpu:1,若是pod請求的是cpu:1.1將永遠不會被調度.

你能夠經過kubectl describe nodes命令來查看節點的容量以及可分配的量:

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%)

經過上面的輸出,你能夠看到若是有一個pod請求或者 6.23Gi 內存,則它不適合調度到此節點上.

經過查看pods部分,你能夠看到你能夠看到哪些pod在本節點上佔用了資源

可供pod使用的資源數量小於節點的實際容量,這是由於系統守護進程按比例使用可用資源.allocatable字段裏的數量是pod實際可用的資源數量,詳情請查看可用資源

容器終止

pod可能因爲資源不足被終止,你可使用kubectl describe pod來檢測pod是否因爲資源達到上限被殺死

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表示simmemleak容器停止而且被重啓了五次.

你能夠經過kubectl get pod加上-o go-template=...選項來獲取上次終止的容器的狀態

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(內存溢出)

Local ephemeral storage(本地暫存容量)

此功能在1.14版本中爲beta狀態

Kubernetes在1.8的版本中引入了一種相似於CPU,內存的新的資源模式:ephemeral-storage,而且在1.10的版本在kubelet中默認打開了這個特性。ephemeral-storage是爲了管理和調度Kubernetes中運行的應用的短暫存儲。在每一個Kubernetes的節點上,kubelet的根目錄(默認是/var/lib/kubelet)和日誌目錄(/var/log)保存在節點的主分區上,這個分區同時也會被Pod的EmptyDir類型的volume、容器日誌、鏡像的層、容器的可寫層所佔用。ephemeral-storage即是對這塊主分區進行管理,經過應用定義的需求(requests)和約束(limits)來調度和管理節點上的應用對主分區的消耗。

在節點上的kubelet啓動的時候,kubelet會統計當前節點的主分區的可分配的磁盤資源,或者你能夠覆蓋節點上kubelet的配置來自定義可分配的資源。在建立Pod時會根據存儲需求調度到知足存儲的節點,在Pod使用超過限制的存儲時會對其作驅逐的處理來保證不會耗盡節點上的磁盤空間。

若是運行時指定了別的獨立的分區,好比修改了docker的鏡像層和容器可寫層的存儲位置(默認是/var/lib/docker)所在的分區,將再也不將其計入ephemeral-storage的消耗。

對Local ephemeral storage的請求/限制

全部的container能夠指定如下一個或多個選項

  • spec.containers[].resources.limits.ephemeral-storage

  • spec.containers[].resources.requests.ephemeral-storage

ephemeral-storage資源的請求/限制經過字節來衡量.同上面內存的請求/限制方式同樣,這裏再也不細述.

好比如下pod包含兩個容器,每個都對Local ephemeral storage的請求爲2GiB,限制爲4GiB.此時,整個pod對資源的請求爲4GiB,對資源的限制爲8GiB

apiVersion: v1
kind: Pod
metadata:
  name: frontend
spec:
  containers:
  - name: db
    image: mysql
    env:
    - name: MYSQL_ROOT_PASSWORD
      value: "password"
    resources:
      requests:
        ephemeral-storage: "2Gi"
      limits:
        ephemeral-storage: "4Gi"
  - name: wp
    image: wordpress
    resources:
      requests:
        ephemeral-storage: "2Gi"
      limits:
        ephemeral-storage: "4Gi"

對有ephemeral-storage請求的pod如何調度

當你建立一個pod,kubernetes調度器選擇一個節點來運行它.每一個節點都有可供pod使用的最大Local ephemeral storage最大量,詳細信息請查看Node Allocatable

調度器保證被調度的容器資源總和小於節點的容量

帶有Local ephemeral storage的pod如何運行

對於容器級別的隔離,若是容器的可寫層( writable layer)和日誌(log)超出了容量限制,容器所在的pod將會被驅離;對於pod級別的隔離,若是pod裏全部容器使用的總Local ephemeral storage和pod的emptydir存儲卷超過限制,pod將會被驅離.

示例

apiVersion: v1
kind: Pod
metadata:
  name: teststorage
  labels:
    app: teststorage
spec:
  containers:
  - name: busybox
    image:  busybox
    command: ["bash", "-c", "while true; do dd if=/dev/zero of=$(date '+%s').out count=1 bs=10MB; sleep 1; done"] # 持續寫入文件到容器的rootfs中
    resources:
      limits:
        ephemeral-storage: 100Mi #定義存儲的限制爲100M
      requests:
        ephemeral-storage: 100Mi

測試這個Pod就能發如今容器寫入超過存儲限制時就會被驅逐掉了:

/tmp kubectl apply -f pod.yaml
pod "teststorage" created
  /tmp kubectl get pod -w
NAME          READY     STATUS              RESTARTS   AGE
teststorage   0/1       ContainerCreating   0          3s
teststorage   1/1       Running   0         7s
teststorage   0/1       Evicted   0         1m

查看kubernetes的pod的事件也能看到它是因爲超過了限制的ephemeral-storage被驅逐掉:

Events:
  Type     Reason                 Age   From               Message
  ----     ------                 ----  ----               -------
  Normal   Scheduled              2m    default-scheduler  Successfully assigned teststorage to minikube
  Normal   SuccessfulMountVolume  2m    kubelet, minikube  MountVolume.SetUp succeeded for volume "default-token-l7wp9"
  Normal   Pulling                2m    kubelet, minikube  pulling image "busybox"
  Normal   Pulled                 2m    kubelet, minikube  Successfully pulled image "busybox"
  Normal   Created                2m    kubelet, minikube  Created container
  Normal   Started                2m    kubelet, minikube  Started container
  Warning  Evicted                1m    kubelet, minikube  pod ephemeral local storage usage exceeds the total limit of containers {{104857600 0} {<nil>} 100Mi BinarySI}
  Normal   Killing                1m    kubelet, minikube  Killing container with id docker://busybox:Need to kill Pod
相關文章
相關標籤/搜索