簡介
此文主要講述如何定以容器的內存請求數和內存限制數。一個容器的運行必須保證內存大於容器請求的內存數,但是不能超過容器的限制數。
備注:此文檔參考官方文檔,並加以自己的理解。如有誤導性的內容,請批評指正。
創建命名空間
# kubectl create namespace mem-example
定義內存請求數和內存限制數
創建一個Pod,其中args塊中的--vm-bytes參數請求150MiB的內存。文件名:memory-request-limit.yaml
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"]
# kubectl apply -f /root/k8s-example/pods/memory-request-limit.yaml --namespace=mem-example
確認Pod 容器正在運行
# kubectl get pod memory-demo --output=yaml --namespace=mem-example
查看Pod詳情
# kubectl get pod memory-demo --output=yaml --namespace=mem-example
從結果可以看出,改Pod內存請求數200Mi,限制數100Mi
...
resources:
limits:
memory: 200Mi
requests:
memory: 100Mi
...
執行kubectl top命令,查看當前Pod好用了CPU和內存
# kubectl top pod memory-demo --namespace=mem-example
備注:執行kubectl top首先確保安裝metrics server,若沒有安裝可參考如下,需保證能下載k8s.gcr.io/metrics-server-amd64:v0.3.1鏡像:
# git clone https://github.com/kodekloudhub/kubernetes-metrics-server.git
# kubectl create -f kubernetes-metrics-server/
從kubectl top結果可以看出,當前Pod使用了150Mi字節內存,大於該Pod的請求值100MiB,小於該Pod的限制值200MiB:
NAME CPU(cores) MEMORY(bytes)
memory-demo 138m 150Mi
刪除該Pod
# kubectl delete pod memory-demo --namespace=mem-example
超過容器的內存限制
如果容器有更多的內存可以分配,則容器可以超過自定義的請求內存。如果容器需要的內存超過自定義的內存限制,則容器將會成為被終止的候選對象。如果容器持續消耗的內存大於自定義的內存限制,則容器被強制停止運行。容器被終止運行后,kubelet會重新啟動改容器。
創建一個分配的內存超過內存限制的Pod,如下配置,請求內存50MiB,限制內存100MiB。文件名:memory-request-limit-2.yaml
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"]
# kubectl apply -f /root/k8s-example/pods/memory-request-limit-2.yaml --namespace=mem-example
# kubectl get pod memory-demo-2 --namespace=mem-example
從結果可以看出,由於內存溢出,導致Pod直接被kill掉了。
# kubectl get pod memory-demo-2 --namespace=mem-example NAME READY STATUS RESTARTS AGE
memory-demo-2 0/1 OOMKilled 1 4s
查看Pod詳情
# kubectl get pod memory-demo-2 --output=yaml --namespace=mem-example
從結果可以看出,最后的狀態由於OOMKilled即Out Of Memory導致容器被kill
lastState:
terminated:
containerID: docker://0d4d5580e28df2a936f28cbef8580ac21c1014e1fad2814e28cfa28417bd3bb0
exitCode: 1
finishedAt: "2020-01-10T00:39:55Z"
reason: OOMKilled
startedAt: "2020-01-10T00:39:55Z"
刪除Pod
# kubectl delete pod memory-demo-2 --namespace=mem-example
定義內存請求大於節點內存的容器
內存請求數、內存限制數和容器相關聯,因此,對於Pod來說,設置合適的內存請求和限制非常有必要。Pod的內存請求數等於Pod內所有容器的內存請求數總和。Pod的內存限制數就是Pod內所有容器內存限制數總和。
Pod的調度是基於請求調度的。一個Pod運行於哪個Pod上取決於改Node是否能滿足該Pod的存請求。
在下面的聯系中,創建一個內存請求遠大於節點內存總數的Pod,下面的實例中定義的Pod內存請求數為1000GiB。文件名:memory-request-limit-3.yaml
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"]
# kubectl apply -f /root/k8s-example/pods/memory-request-limit-3.yaml --namespace=mem-example
查看容Pod狀態
# kubectl get pod memory-demo-3 --namespace=mem-example
NAME READY STATUS RESTARTS AGE
memory-demo-3 0/1 Pending 0 15s
查看Pod資源詳情
# kubectl describe pod memory-demo-3 --namespace=mem-example
從結果看,7個node節點沒有足夠的內存,由於我的是3個master節點高可用、4個node節點的k8s集群
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Warning FailedScheduling <unknown> default-scheduler 0/7 nodes are available: 7 Insufficient memory.
刪除名稱空間
內存單位
內存資源用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
沒有定義內存限制
如果沒有定義容器的內存限制,則適用以下情況之一:
- 容器對其使用的內存量沒有上限。容器可以使用其正在運行的節點上的所有可用內存,進而可以調用OOM Killer。此外,如果發生OOM Kill,則沒有資源限制的容器將有更大的機會被殺死。
- 運行在有默認內存限制的namespace中的容器,系統會自動為容器分配默認限制。集群管理員可以通過
LimitRange定義內存限制的值。
內存請求限制的原因
通過在集群中配置容器的內存請求和內存限制,可以合理的使用集群中node節點的內存資源。如果保證Pod的內存請求在合理值范圍內,則該Pod可以在集群中被合理的調度到合適的node節點上。
