Kubernetes 為容器和Pod分配內(nèi)存資源

2022-06-09 10:24 更新

為容器和 Pod 分配內(nèi)存資源

此頁面展示如何將內(nèi)存 請求 (request)和內(nèi)存 限制 (limit)分配給一個容器。 我們保障容器擁有它請求數(shù)量的內(nèi)存,但不允許使用超過限制數(shù)量的內(nèi)存。

在開始之前

你必須擁有一個 Kubernetes 的集群,同時你的 Kubernetes 集群必須帶有 kubectl 命令行工具。 建議在至少有兩個節(jié)點的集群上運行本教程,且這些節(jié)點不作為控制平面主機。 如果你還沒有集群,你可以通過 Minikube 構(gòu)建一個你自己的集群,或者你可以使用下面任意一個 Kubernetes 工具構(gòu)建:

要檢查版本,請輸入 ?kubectl version?。

你集群中的每個節(jié)點必須擁有至少 300 MiB 的內(nèi)存。

該頁面上的一些步驟要求你在集群中運行 metrics-server 服務。 如果你已經(jīng)有在運行中的 metrics-server,則可以跳過這些步驟。

如果你運行的是 Minikube,可以運行下面的命令啟用 metrics-server:

minikube addons enable metrics-server

要查看 metrics-server 或資源指標 API (?metrics.k8s.io?) 是否已經(jīng)運行,請運行以下命令:

kubectl get apiservices

如果資源指標 API 可用,則輸出結(jié)果將包含對 ?metrics.k8s.io? 的引用信息。

NAME
v1beta1.metrics.k8s.io

創(chuàng)建命名空間

創(chuàng)建一個命名空間,以便將本練習中創(chuàng)建的資源與集群的其余部分隔離。

指定內(nèi)存請求和限制 

要為容器指定內(nèi)存請求,請在容器資源清單中包含 ?resources:requests? 字段。 同理,要指定內(nèi)存限制,請包含 ?resources:limits?。

在本練習中,你將創(chuàng)建一個擁有一個容器的 Pod。 容器將會請求 100 MiB 內(nèi)存,并且內(nèi)存會被限制在 200 MiB 以內(nèi)。 這是 Pod 的配置文件:

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

配置文件的 ?args ?部分提供了容器啟動時的參數(shù)。 ?"--vm-bytes", "150M"? 參數(shù)告知容器嘗試分配 150 MiB 內(nèi)存。

開始創(chuàng)建 Pod:

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

驗證 Pod 中的容器是否已運行:

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

查看 Pod 相關(guān)的詳細信息:

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

輸出結(jié)果顯示:該 Pod 中容器的內(nèi)存請求為 100 MiB,內(nèi)存限制為 200 MiB。

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

運行 ?kubectl top? 命令,獲取該 Pod 的指標數(shù)據(jù):

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

輸出結(jié)果顯示:Pod 正在使用的內(nèi)存大約為 162,900,000 字節(jié),約為 150 MiB。 這大于 Pod 請求的 100 MiB,但在 Pod 限制的 200 MiB之內(nèi)。

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

刪除 Pod:

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

超過容器限制的內(nèi)存 

當節(jié)點擁有足夠的可用內(nèi)存時,容器可以使用其請求的內(nèi)存。 但是,容器不允許使用超過其限制的內(nèi)存。 如果容器分配的內(nèi)存超過其限制,該容器會成為被終止的候選容器。 如果容器繼續(xù)消耗超出其限制的內(nèi)存,則終止容器。 如果終止的容器可以被重啟,則 kubelet 會重新啟動它,就像其他任何類型的運行時失敗一樣。

在本練習中,你將創(chuàng)建一個 Pod,嘗試分配超出其限制的內(nèi)存。 這是一個 Pod 的配置文件,其擁有一個容器,該容器的內(nèi)存請求為 50 MiB,內(nèi)存限制為 100 MiB:

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 ?部分中,你可以看到容器會嘗試分配 250 MiB 內(nèi)存,這遠高于 100 MiB 的限制。

創(chuàng)建 Pod:

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

查看 Pod 相關(guān)的詳細信息:

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

此時,容器可能正在運行或被殺死。重復前面的命令,直到容器被殺掉:

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

獲取容器更詳細的狀態(tài)信息:

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

輸出結(jié)果顯示:由于內(nèi)存溢出(OOM),容器已被殺掉:

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

本練習中的容器可以被重啟,所以 kubelet 會重啟它。 多次運行下面的命令,可以看到容器在反復的被殺死和重啟:

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

輸出結(jié)果顯示:容器被殺掉、重啟、再殺掉、再重啟……:

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

查看關(guān)于該 Pod 歷史的詳細信息:

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

輸出結(jié)果顯示:該容器反復的在啟動和失?。?/p>

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

查看關(guān)于集群節(jié)點的詳細信息:

kubectl describe nodes

輸出結(jié)果包含了一條練習中的容器由于內(nèi)存溢出而被殺掉的記錄:

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

超過整個節(jié)點容量的內(nèi)存

內(nèi)存請求和限制是與容器關(guān)聯(lián)的,但將 Pod 視為具有內(nèi)存請求和限制,也是很有用的。 Pod 的內(nèi)存請求是 Pod 中所有容器的內(nèi)存請求之和。 同理,Pod 的內(nèi)存限制是 Pod 中所有容器的內(nèi)存限制之和。

Pod 的調(diào)度基于請求。只有當節(jié)點擁有足夠滿足 Pod 內(nèi)存請求的內(nèi)存時,才會將 Pod 調(diào)度至節(jié)點上運行。

在本練習中,你將創(chuàng)建一個 Pod,其內(nèi)存請求超過了你集群中的任意一個節(jié)點所擁有的內(nèi)存。 這是該 Pod 的配置文件,其擁有一個請求 1000 GiB 內(nèi)存的容器,這應該超過了你集群中任何節(jié)點的容量。

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

創(chuàng)建 Pod:

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

查看 Pod 狀態(tài):

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

輸出結(jié)果顯示:Pod 處于 PENDING 狀態(tài)。 這意味著,該 Pod 沒有被調(diào)度至任何節(jié)點上運行,并且它會無限期的保持該狀態(tài):

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

查看關(guān)于 Pod 的詳細信息,包括事件:

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

輸出結(jié)果顯示:由于節(jié)點內(nèi)存不足,該容器無法被調(diào)度:

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

內(nèi)存單位

內(nèi)存資源的基本單位是字節(jié)(byte)。你可以使用這些后綴之一,將內(nèi)存表示為 純整數(shù)或定點整數(shù):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

如果你沒有指定內(nèi)存限制 

如果你沒有為一個容器指定內(nèi)存限制,則自動遵循以下情況之一:

  • 容器可無限制地使用內(nèi)存。容器可以使用其所在節(jié)點所有的可用內(nèi)存, 進而可能導致該節(jié)點調(diào)用 OOM Killer。 此外,如果發(fā)生 OOM Kill,沒有資源限制的容器將被殺掉的可行性更大。
  • 運行的容器所在命名空間有默認的內(nèi)存限制,那么該容器會被自動分配默認限制。 集群管理員可用使用 LimitRange 來指定默認的內(nèi)存限制。

內(nèi)存請求和限制的目的 

通過為集群中運行的容器配置內(nèi)存請求和限制,你可以有效利用集群節(jié)點上可用的內(nèi)存資源。 通過將 Pod 的內(nèi)存請求保持在較低水平,你可以更好地安排 Pod 調(diào)度。 通過讓內(nèi)存限制大于內(nèi)存請求,你可以完成兩件事:

  • Pod 可以進行一些突發(fā)活動,從而更好的利用可用內(nèi)存。
  • Pod 在突發(fā)活動期間,可使用的內(nèi)存被限制為合理的數(shù)量。

清理 

刪除命名空間。下面的命令會刪除你根據(jù)這個任務創(chuàng)建的所有 Pod:

kubectl delete namespace mem-example


以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號