1-1 分配內存資源給容器和POD

這一小節講解如何分配內存請求和對一個容器做內存限制。一個容器被保證擁有足夠的內存可以處理請求,但是也不允許使用超過限制的內存。

開始之前

需要擁有一個k8s集羣

需要安裝好一個kubectl 工具,並且能夠與集羣通信。

如果沒有準備好,你可以使用minikube或者使用以下的練習場地。

https://www.katacoda.com/courses/kubernetes/playground

http://labs.play-with-k8s.com/

可以使用以下命令,檢測版本

kubectl version

集羣中的每個節點,至少擁有300MB的內存。

本文中的一些步驟要求你在集羣中有運行 metrics-server 的服務,如果你沒有運行,你可以跳過這些步驟。

如果你使用的是minikube ,你可以使用以下命令來啓用:

minikube addons enable metrics-server

檢查 metrics-server是否運行,或者其它提供 metrics api 資源 (metrics.k8s.io),你可以使用以下的命令

kubectl get apiservices

如果 metrics api 資源是可用的,會響應以下內容:

NAME
v1beta1.metrics.k8s.io

創建命名空間

創建命名空間來保證當前的測試環境和集羣的其它環境的隔離的。

定義一個內存請求和內存限制

定義一個內存請求:
resources:requests

定義一個內存限制:
resources:limits

在這個練習中,你創建了一個POD包含一個容器,容器申請了100MB的內存,並且設置了200MB內存限制。

apiVersion: v1
kind: Pod
metadata:
name: memory-demo
namespace: mem-example
spec:
containers:
name: memory-demo-ctr
image: polinux/stress
resources:
limits:
memory: "200Mi"
requests:
memory: "100Mi"
command: ["stress"]
args: ["--vm", "1", "--vm-bytes", "150M", "--vm-hang", "1"]

args是 提供容器啓動的參數。

"--vm-bytes", "150M" 告訴容器分配多少內存

創建一個POD

kubectl create -f https://k8s.io/examples/pods/resource/memory-request-limit.yaml --namespace=mem-example

驗證POD是否運行

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

查看POD的詳細信息,並輸出到yaml

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

獲取POD的技術指標
kubectl top pod memory-demo --namespace=mem-example

顯示的內存大小是 162,900,000 bytes ,大約是150MB,大於分配的100MB內存,小於200MB的內存限制。

NAME CPU(cores) MEMORY(bytes)
memory-demo <something> 162856960

刪除POD

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

配置容器的內存限制

如果節點有足夠的內存,那麼容器就可以執行內存的分配請求。但是一個容器不允許使用
超出它的限制的內存。如果一個容器分配的內存超出了它的限制,該容器成爲了被停止的候選人。
如果一個容器持續的使用超過自己內存限制的情況,該容器會被停止。如果一個停止的容器
能夠被重啓,和其它的運行錯誤一樣,kubelet也會去重啓它。

在這個練習中,你可以嘗試創建一個POD,並且分配超出它限制的內存。
以下爲創建一個POD,擁有一個容器,分配50MB的內存,並且設置了100MB的內存限制

apiVersion: v1
kind: Pod
metadata:
name: memory-demo-2
namespace: mem-example
spec:
containers:

  • name: memory-demo-2-ctr
    image: polinux/stress
    resources:
    requests:
    memory: "50Mi"
    limits:
    memory: "100Mi"
    command: ["stress"]
    args: ["--vm", "1", "--vm-bytes", "250M", "--vm-hang", "1"]

    在 args 選項,我們嘗試分配了250MB的內存,超過了我們設置的100MB限制。

創建POD

kubectl create -f https://k8s.io/examples/pods/resource/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

這個輸出顯示容器被殺掉的原因是因爲內存不足(OOM)

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

下面的輸出顯示容器被殺掉,重啓,再次被殺掉,再次重啓等等

kubectl get pod memory-demo-2 --namespace=mem-example
NAME READY STATUS RESTARTS AGE
memory-demo-2 0/1 OOMKilled 1 37s

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

以下是容器不斷啓動和失敗的事件信息
... 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,內存的請求大於集羣中任意節點的容量。以下爲創建一個
POD擁有一個容器,要求1000GB的內存,超過了集羣中的任意節點的內存容量。

apiVersion: v1
kind: Pod
metadata:
name: memory-demo-3
namespace: mem-example
spec:
containers:

  • name: memory-demo-3-ctr
    image: polinux/stress
    resources:
    limits:
    memory: "1000Gi"
    requests:
    memory: "1000Gi"
    command: ["stress"]
    args: ["--vm", "1", "--vm-bytes", "150M", "--vm-hang", "1"]

創建POD
kubectl create -f https://k8s.io/examples/pods/resource/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).

內存單元

內存的資源是用bytes來衡量。你可以用普通整數或者帶小數點的整數來表達內存容量。

後綴爲E, P, T, G, M, K, Ei, Pi, Ti, Gi, Mi, Ki.

例如下面的值:

128974848, 129e6, 129M , 123Mi

刪除POD
kubectl delete pod memory-demo-3 --namespace=mem-example

如果你沒有定義內存限制

如果你沒有設置內存限制,以下的情況將被適用:

  1. 容器沒有內存的上限邊界。容器能夠使用節點的所有可用內存。
  2. 容器運行的命名空間有默認的內存限制,容器將被自動分配這個默認的限制。集羣管理員
    可用使用 LimitRange 來定義內存限制的默認值。

內存請求和限制的動機

在運行的集羣中對容器進行內存的分配和限制,可以使集羣的內存資源使用效率更高。
保持POD的內存請求較低,這樣POD可以有機會可以被調度。設置內存限制比內存分配更好,
你可以完成以下的兩件事情:

    POD 可能存在對內存的爆發性需求
    POD內存容量的爆發可以被限制在合理的區間。

清除

清除命名空間。刪除以上練習創建的所有POD

kubectl delete namespace mem-example

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章