開始使用 Kubernetes 時,通常會忘記設定容器資源。 至此,足以保證Docker映像能夠運作並且可以部署到Kubernetes叢集。
但後來該應用程式需要與其他應用程式一起部署在生產叢集中。 為此,您需要為容器分配資源,並確保有足夠的資源來啟動和運行應用程序,並且其他正在運行的應用程式不會遇到問題。
團隊
計算資源
我們有兩種類型的資源,具有以下單位:
- 中央處理器 (CPU) - 核心;
- 記憶體 (MEM) - 位元組。
為每個容器指定資源。 在以下 Pod YAML 檔案中,您將看到一個資源部分,其中包含請求的資源和限制的資源:
- 請求的 Pod 資源 = 所有容器請求的資源總和;
- Pod 資源限制 = 所有 Pod 資源限制的總和。
apiVersion: v1
kind: Pod
metadata:
name: backend-pod-name
labels:
application: backend
spec:
containers:
— name: main-container
image: my-backend
tag: v1
ports:
— containerPort: 8080
resources:
requests:
cpu: 0.2 # REQUESTED CPU: 200m cores
memory: "1Gi" # REQUESTED MEM: 1Gi
limits:
cpu: 1 # MAX CPU USAGE: 1 core
memory: "1Gi" # MAX MEM USAGE: 1Gi
— name: other-container
image: other-app
tag: v1
ports:
— containerPort: 8000
resources:
requests:
cpu: "200m" # REQUESTED CPU: 200m cores
memory: "0.5Gi" # REQUESTED MEM: 0.5Gi
limits:
cpu: 1 # MAX CPU USAGE: 1 core
memory: "1Gi" # MAX MEM USAGE: 1Gi
請求的資源和有限的資源範例
領域 resources.requested
根據規範,Pod 是用來尋找所需節點的元素之一。 您已經可以為其規劃 Pod 部署。 如何找到合適的節點?
Kubernetes 由多個元件組成,包括主節點或主節點(Kubernetes Control Plane)。 主節點有幾個行程:kube-apiserver、kube-controller-manager 和 kube-scheduler。
kube-scheduler 程序負責檢查新建立的 Pod 並尋找與所有 Pod 請求相符的可能工作節點,包括要求的資源數量。 kube-scheduler 找到的節點清單已排序。 Pod 被調度到分數最高的節點。
紫色 Pod 將放置在哪裡?
在圖中您可以看到 kube-scheduler 應該會調度一個新的紫色 Pod。 Kubernetes 叢集包含兩個節點:A 和 B。如您所見,kube-scheduler 無法在節點 A 上調度 Pod - 可用(未要求)資源與紫色 Pod 的請求不符。 因此,紫色 Pod 請求的 1 GB 內存在節點 A 上不適合,因為可用記憶體為 0,5 GB。 但節點B有足夠的資源。 因此,kube-scheduler 判定紫色 Pod 的目的地是節點 B。
現在我們知道請求的資源如何影響運行 Pod 的節點的選擇。 但邊際資源的影響是什麼?
資源限制是CPU/MEM無法跨越的邊界。 但是,CPU 資源是靈活的,因此達到 CPU 限制的容器不會導致 Pod 退出。 相反,CPU 限制將開始。 如果達到 MEM 使用限制,容器將因 OOM-Killer 而停止,並在 RestartPolicy 設定允許的情況下重新啟動。
請求的資源和最大資源的詳細信息
Docker與Kubernetes之間的資源通信
解釋資源請求和資源限制如何運作的最佳方法是介紹 Kubernetes 和 Docker 之間的關係。 在上圖中,您可以看到 Kubernetes 欄位和 Docker 啟動標誌是如何關聯的。
記憶:要求和限制
containers:
...
resources:
requests:
memory: "0.5Gi"
limits:
memory: "1Gi"
如上所述,記憶體以位元組為單位。 基於 G
и Gi
,最重要的是要記住它們並不等同。 第一個是十進制,第二個是二進制。 就像k8s文件中提到的例子: 128974848
, 129e6
, 129M
, 123Mi
- 它們實際上是等效的。
庫伯內特選項 limits.memory
與旗幟相匹配 --memory
來自 Docker。 的情況下 request.memory
Docker 沒有箭頭,因為 Docker 不使用該欄位。 你可能會問,這還有必要嗎? 是的,需要。 正如我之前所說,這個領域對 Kubernetes 來說很重要。 根據其中的信息,kube-scheduler 決定在哪個節點上調度 Pod。
如果為請求設定的記憶體不足會發生什麼情況?
如果容器已達到請求記憶體的限制,則 Pod 會被放置在一組 Pod 中,當節點中記憶體不足時,這些 Pod 會停止。
如果您將記憶體限制設定得太低會發生什麼情況?
如果容器超過記憶體限制,它將因 OOM-Killed 而終止。 如果可能的話,將根據 RestartPolicy 重新啟動,預設值為 Always
.
如果不指定請求的記憶體會發生什麼?
Kubernetes 將採用該限制值並將其設為預設值。
如果不指定記憶體限制會發生什麼?
容器沒有任何限制;它可以使用任意多的記憶體。 如果他開始使用節點的所有可用內存,那麼 OOM 將殺死他。 如果可能的話,容器將根據 RestartPolicy 重新啟動。
如果不指定記憶體限制會發生什麼?
這是最糟的情況:調度程式不知道容器需要多少資源,這可能會導致節點出現嚴重問題。 在這種情況下,最好對命名空間設定預設限制(由 LimitRange 設定)。 沒有預設限制 - Pod 沒有限制,它可以使用任意多的記憶體。
如果請求的內存超過節點可以提供的內存,Pod 將不會被調度。 重要的是要記住這一點 Requests.memory
- 不是最小值。 這是對足以保持容器持續運行的內存量的描述。
通常建議設定相同的值 request.memory
и limit.memory
。 這可以確保 Kubernetes 不會將 Pod 調度到有足夠記憶體運行 Pod 但不足以運行它的節點上。 請記住:Kubernetes Pod 規劃僅考慮 requests.memory
和 limits.memory
不考慮。
CPU:請求和限制
containers:
...
resources:
requests:
cpu: 1
limits:
cpu: "1200m"
對CPU來說,一切都有點複雜。 回到 Kubernetes 和 Docker 的關係圖,可以看到 request.cpu
對應於 --cpu-shares
,而 limit.cpu
與旗幟相匹配 cpus
在 Docker 中。
Kubernetes 請求的 CPU 乘以 1024,即 CPU 週期的比例。 如果您想請求 1 個完整核心,則必須新增 cpu: 1
如上圖所示。
請求完整的核心(比例 = 1024)並不意味著您的容器會收到它。 如果您的主機只有一個核心,並且您正在執行多個容器,那麼所有容器必須在它們之間共用可用的 CPU。 這是怎麼發生的? 讓我們看一下圖片。
CPU 請求 - 單核心系統
讓我們假設您有一個運行容器的單核心主機系統。 媽媽(Kubernetes)烤了一個餡餅(CPU)並想把它分給孩子(容器)。 三個孩子想要整個派(比例 = 1024),另一個孩子想要半個派(512)。 媽媽為了公平起見,做了一個簡單的計算。
# Сколько пирогов хотят дети?
# 3 ребенка хотят по целому пирогу и еще один хочет половину пирога
cakesNumberKidsWant = (3 * 1) + (1 * 0.5) = 3.5
# Выражение получается так:
3 (ребенка/контейнера) * 1 (целый пирог/полное ядро) + 1 (ребенок/контейнер) * 0.5 (половина пирога/половина ядра)
# Сколько пирогов испечено?
availableCakesNumber = 1
# Сколько пирога (максимально) дети реально могут получить?
newMaxRequest = 1 / 3.5 =~ 28%
據計算,三個孩子將獲得核心的28%,而不是全部核心。 第四個孩子將獲得完整核心的 14%,而不是一半。 但如果你有一個多核心系統,情況就會有所不同。
CPU 請求 - 多核心 (4) 系統
在上圖中,您可以看到三個孩子想要一整個餡餅,一個想要半個。 由於媽媽烤了四個餡餅,所以她的每個孩子都想吃多少就吃多少。 在多核心系統中,處理器資源分佈在所有可用的處理器核心上。 如果一個容器被限制為少於一個完整的 CPU 核心,它仍然可以 100% 使用它。
簡化上述計算可以理解 CPU 如何在容器之間分配。 當然,除了容器本身之外,還有其他行程也會使用CPU資源。 當一個容器中的程序空閒時,其他容器可以使用其資源。 CPU: "200m"
對應於 CPU: 0,2
,這意味著一個核心的大約 20%。
現在讓我們談談 limit.cpu
。 Kubernetes 限制的 CPU 乘以 100。結果是容器每 100 µs 可以使用的時間量(cpu-period
).
limit.cpu
匹配 Docker 標誌 --cpus
。 這是舊的新組合 --cpu-period
и --cpu-quota
。 透過設定它,我們指示在限制開始之前容器可以最大使用多少可用CPU資源:
- CPU的 - 組合
cpu-period
иcpu-quota. cpus = 1.5
相當於設定cpu-period = 100000
иcpu-quota = 150000
; - CPU週期 - 時期
CPU CFS調度器 ,預設100微秒; - CPU配額 - 內在的微秒數
cpu-period
,它以容器為界。
如果安裝的 CPU 不足,會發生什麼事?
如果容器所需的數量超過其已安裝的數量,它將從其他進程中竊取 CPU。
如果您將 CPU 限制設定得太低會發生什麼情況?
由於CPU資源是可調的,因此會開啟節流。
如果不指定 CPU 請求會發生什麼?
與記憶體一樣,請求值等於限制。
如果不指定 CPU 限制會發生什麼?
容器將根據需要使用盡可能多的 CPU。 如果在命名空間中定義了預設 CPU 策略 (LimitRange),則此限制也適用於容器。
如果您不指定請求或 CPU 限制,會發生什麼情況?
與內存一樣,這是最壞的情況。 調度程序不知道您的容器需要多少資源,這可能會導致節點出現嚴重問題。 為了避免這種情況,您需要為命名空間設定預設限制(LimitRange)。
請記住:如果您要求的 CPU 多於節點可以提供的 CPU,則 Pod 將不會被調度。 Requests.cpu
- 不是最小值,而是足以啟動 Pod 並且正常工作的值。 如果應用程式不執行複雜的計算,最好的選擇是安裝 request.cpu <= 1
並根據需要啟動盡可能多的副本。
請求的資源的理想數量或資源限制
我們了解到計算資源的限制。 現在是時候回答這個問題了:「我的 Pod 需要多少資源才能運行應用程式而不出現任何問題? 理想的量是多少?
不幸的是,這些問題沒有明確的答案。 如果您不知道應用程式如何運作或需要多少 CPU 或內存,最好的選擇是為應用程式提供大量內存和 CPU,然後運行效能測試。
除了效能測試之外,還要在一週的監控中監控應用程式的行為。 如果圖表顯示您的應用程式消耗的資源少於您要求的資源,您可以減少要求的 CPU 或記憶體量。
舉個例子看看這個
結論
請求和限制資源有助於維持 Kubernetes 叢集的健康運作。 正確的限製配置可以最大限度地降低成本並保持應用程式始終運行。
簡而言之,有以下幾點要記住:
- 請求的資源是在啟動時(當 Kubernetes 計劃託管應用程式時)考慮的配置。 相反,限制資源在運行時非常重要——當應用程式已經在節點上運行時。
- 與記憶體相比,CPU 是一種受管制的資源。 如果沒有足夠的CPU,你的Pod將不會關閉並且節流機制將開啟。
- 請求的資源和資源限制不是最小值和最大值! 透過定義所請求的資源,您可以確保應用程式在運行時不會出現問題。
- 一個好的做法是將記憶體請求設定為等於記憶體限制。
- 好的安裝請求
CPU <=1
,如果應用程式不執行複雜的計算。 - 如果您要求的資源多於節點上可用的資源,則 Pod 將永遠不會調度到該節點。
- 若要確定請求的資源/資源限制的正確數量,請使用負載測試和監控。
我希望這篇文章可以幫助您理解資源限制的基本概念。 您將能夠將這些知識應用到您的工作中。
祝你好運!
還有什麼要讀的:
來源: www.habr.com