Kubernetes 給容器和Pod分配內存資源

這篇教程指導如何給容器分配申請的內存和內存限制。咱們保證讓容器得到足夠的內存 資源,可是不容許它使用超過限制的資源。node

Before you begin

You need to have a Kubernetes cluster, and the kubectl command-line tool must be configured to communicate with your cluster. If you do not already have a cluster, you can create one by using Minikube.git

你的集羣裏每一個節點至少必須擁有300M的內存。github

這個教程裏有幾個步驟要求Heapster , 可是若是你沒有Heapster的話,也能夠完成大部分的實驗,就算跳過這些Heapster 步驟,也不會有什麼問題。docker

檢查看Heapster服務是否運行,執行命令:api

kubectl get services --namespace=kube-system

若是Heapster服務正在運行,會有以下輸出:curl

NAMESPACE    NAME      CLUSTER-IP    EXTERNAL-IP  PORT(S)  AGE
kube-system  heapster  10.11.240.9   <none>       80/TCP   6d

建立一個命名空間

建立命名空間,以便你在實驗中建立的資源能夠從集羣的資源中隔離出來。ide

kubectl create namespace mem-example

配置內存申請和限制

給容器配置內存申請,只要在容器的配置文件裏添加resources:requests就能夠了。配置限制的話, 則是添加resources:limits。ui

本實驗,咱們建立包含一個容器的Pod,這個容器申請100M的內存,而且內存限制設置爲200M,下面 是配置文件:url

memory-request-limit.yaml 
apiVersion: v1
kind: Pod
metadata:
  name: memory-demo
spec:
  containers:
  - name: memory-demo-ctr
    image: vish/stress
    resources:
      limits:
        memory: "200Mi"
      requests:
        memory: "100Mi"
    args:
    - -mem-total
    - 150Mi
    - -mem-alloc-size
    - 10Mi
    - -mem-alloc-sleep
    - 1s

在這個配置文件裏,args代碼段提供了容器所需的參數。-mem-total 150Mi告訴容器嘗試申請150M 的內存。spa

建立Pod:

kubectl create -f https://k8s.io/docs/tasks/configure-pod-container/memory-request-limit.yaml --namespace=mem-example

驗證Pod的容器是否正常運行:

kubectl get pod memory-demo --namespace=mem-example

查看Pod的詳細信息:

kubectl get pod memory-demo --output=yaml --namespace=mem-example

這個輸出顯示了Pod裏的容器申請了100M的內存和200M的內存限制。

...
resources:
  limits:
    memory: 200Mi
  requests:
    memory: 100Mi
...

啓動proxy以便咱們能夠訪問Heapster服務:

kubectl proxy

在另一個命令行窗口,從Heapster服務獲取內存使用狀況:

curl http://localhost:8001/api/v1/proxy/namespaces/kube-system/services/heapster/api/v1/model/namespaces/mem-example/pods/memory-demo/metrics/memory/usage

這個輸出顯示了Pod正在使用162,900,000字節的內存,大概就是150M。這很明顯超過了申請 的100M,可是還沒達到200M的限制。

{
 "timestamp": "2017-06-20T18:54:00Z",
 "value": 162856960
}

刪除Pod:

kubectl delete pod memory-demo --namespace=mem-example

超出容器的內存限制

只要節點有足夠的內存資源,那容器就能夠使用超過其申請的內存,可是不容許容器使用超過其限制的 資源。若是容器分配了超過限制的內存,這個容器將會被優先結束。若是容器持續使用超過限制的內存, 這個容器就會被終結。若是一個結束的容器容許重啓,kubelet就會重啓他,可是會出現其餘類型的運行錯誤。

本實驗,咱們建立一個Pod嘗試分配超過其限制的內存,下面的這個Pod的配置文檔,它申請50M的內存, 內存限制設置爲100M。

memory-request-limit-2.yaml 
apiVersion: v1
kind: Pod
metadata:
  name: memory-demo-2
spec:
  containers:
  - name: memory-demo-2-ctr
    image: vish/stress
    resources:
      requests:
        memory: 50Mi
      limits:
        memory: "100Mi"
    args:
    - -mem-total
    - 250Mi
    - -mem-alloc-size
    - 10Mi
    - -mem-alloc-sleep
    - 1s

在配置文件裏的args段裏,能夠看到容器嘗試分配250M的內存,超過了限制的100M。

建立Pod:

kubectl create -f https://k8s.io/docs/tasks/configure-pod-container/memory-request-limit-2.yaml --namespace=mem-example

查看Pod的詳細信息:

kubectl get pod memory-demo-2 --namespace=mem-example

這時候,容器可能會運行,也可能會被殺掉。若是容器還沒被殺掉,重複以前的命令直至 你看到這個容器被殺掉:

NAME            READY     STATUS      RESTARTS   AGE
memory-demo-2   0/1       OOMKilled   1          24s

查看容器更詳細的信息:

kubectl get pod memory-demo-2 --output=yaml --namespace=mem-example

這個輸出顯示了容器被殺掉由於超出了內存限制。

lastState:
   terminated:
     containerID: docker://65183c1877aaec2e8427bc95609cc52677a454b56fcb24340dbd22917c23b10f
     exitCode: 137
     finishedAt: 2017-06-20T20:52:19Z
     reason: OOMKilled
     startedAt: null

本實驗裏的容器能夠自動重啓,所以kubelet會再去啓動它。輸入多幾回這個命令看看它是怎麼 被殺掉又被啓動的:

kubectl get pod memory-demo-2 --namespace=mem-example

這個輸出顯示了容器被殺掉,被啓動,又被殺掉,又被啓動的過程:

stevepe@sperry-1:~/steveperry-53.github.io$ kubectl get pod memory-demo-2 --namespace=mem-example
NAME            READY     STATUS      RESTARTS   AGE
memory-demo-2   0/1       OOMKilled   1          37s
stevepe@sperry-1:~/steveperry-53.github.io$ kubectl get pod memory-demo-2 --namespace=mem-example
NAME            READY     STATUS    RESTARTS   AGE
memory-demo-2   1/1       Running   2          40s

查看Pod的歷史詳細信息:

kubectl describe pod memory-demo-2 --namespace=mem-example

這個輸出顯示了Pod一直重複着被殺掉又被啓動的過程:

... Normal  Created   Created container with id 66a3a20aa7980e61be4922780bf9d24d1a1d8b7395c09861225b0eba1b1f8511
... Warning BackOff   Back-off restarting failed container

查看集羣裏節點的詳細信息:

kubectl describe nodes

輸出裏面記錄了容器被殺掉是由於一個超出內存的情況出現:

Warning OOMKilling  Memory cgroup out of memory: Kill process 4481 (stress) score 1994 or sacrifice child

刪除Pod:

kubectl delete pod memory-demo-2 --namespace=mem-example

配置超出節點能力範圍的內存申請

內存的申請和限制是針對容器自己的,可是認爲Pod也有容器的申請和限制是一個頗有幫助的想法。 Pod申請的內存就是Pod裏容器申請的內存總和,相似的,Pod的內存限制就是Pod裏全部容器的 內存限制的總和。

Pod的調度策略是基於請求的,只有當節點知足Pod的內存申請時,纔會將Pod調度到合適的節點上。

在這個實驗裏,咱們建立一個申請超大內存的Pod,超過了集羣裏任何一個節點的可用內存資源。 這個容器申請了1000G的內存,這個應該會超過你集羣裏能提供的數量。

memory-request-limit-3.yaml 
apiVersion: v1
kind: Pod
metadata:
  name: memory-demo-3
spec:
  containers:
  - name: memory-demo-3-ctr
    image: vish/stress
    resources:
      limits:
        memory: "1000Gi"
      requests:
        memory: "1000Gi"
    args:
    - -mem-total
    - 150Mi
    - -mem-alloc-size
    - 10Mi
    - -mem-alloc-sleep
    - 1s

建立Pod:

kubectl create -f https://k8s.io/docs/tasks/configure-pod-container/memory-request-limit-3.yaml --namespace=mem-example

查看Pod的狀態:

kubectl get pod memory-demo-3 --namespace=mem-example

輸出顯示Pod的狀態是Pending,由於Pod不會被調度到任何節點,全部它會一直保持在Pending狀態下。

kubectl get pod memory-demo-3 --namespace=mem-example
NAME            READY     STATUS    RESTARTS   AGE
memory-demo-3   0/1       Pending   0          25s

查看Pod的詳細信息包括事件記錄

kubectl describe pod memory-demo-3 --namespace=mem-example

這個輸出顯示容器不會被調度由於節點上沒有足夠的內存:

Events:
  ...  Reason            Message
       ------            -------
  ...  FailedScheduling  No nodes are available that match all of the following predicates:: Insufficient memory (3).

內存單位

內存資源是以字節爲單位的,能夠表示爲純整數或者固定的十進制數字,後綴能夠是E, P, T, G, M, K, Ei, Pi, Ti, Gi, Mi, Ki.好比,下面幾種寫法表示相同的數值:alue:

128974848, 129e6, 129M , 123Mi

刪除Pod:

kubectl delete pod memory-demo-3 --namespace=mem-example

若是不配置內存限制

若是不給容器配置內存限制,那下面的任意一種狀況可能會出現:

  • 容器使用內存資源沒有上限,容器能夠使用當前節點上全部可用的內存資源。
  • 容器所運行的命名空間有默認內存限制,容器會自動繼承默認的限制。集羣管理員能夠使用這個文檔 LimitRange來配置默認的內存限制。

內存申請和限制的緣由

經過配置容器的內存申請和限制,你能夠更加有效充分的使用集羣裏內存資源。配置較少的內存申請, 可讓Pod跟任意被調度。設置超過內存申請的限制,能夠達到如下效果:

  • Pod能夠在負載高峯時更加充分利用內存。
  • 能夠將Pod的內存使用限制在比較合理的範圍。

清理

刪除命名空間,這會順便刪除命名空間裏的Pod。

kubectl delete namespace mem-example
相關文章
相關標籤/搜索