K8s中CPU和Memory的資源管理

資源類型

在 Kubernetes 中,Pod 作為最小的原子調度單位,所有跟調度和資源管理相關的屬性都屬于 Pod。其中最常用的資源就是 CPU 和 Memory。

CPU 資源

在 Kubernetes 中,一個 CPU 等于 1 個物理 CPU 核或者一個虛擬核,取決于節點是一臺物理主機還是運行在某物理主機上的虛擬機。CPU 的請求是允許帶小數的,比如 0.5 等價于 500m,表示請求 500 millicpu 或 0.5 個 cpu 的意思,這樣 Pod 就會被分配 1 個 CPU 一半的計算能力。需要注意的是,Kubernetes 不允許設置精度小于 1m 的 CPU 資源。

Memory 資源

Memory 以 bytes 為單位,Kubernetes 支持使用 Ei、Pi、Ti、Gi、Mi、Ki(或者E、P、T、G、M、K)作為 bytes 的值。

其中 1Mi=1024*1024;1M=1000*1000,還要注意后綴的小寫情況,400m實際上請求的是 0.4 字節。

資源的請求和限制

在 Kubernetes 中,CPU 是一種可壓縮資源,當可壓縮資源不足時,Pod 會處于 Pending 狀態;而 Memory 是一種不可壓縮資源,當不可壓縮資源不足時,Pod 會因 OOM 而被殺掉。所以合理的請求和分配 CPU 和 Memory 資源,可以提高應用程序的性能。Pod 可以由多個 Container 組成,每個 Container 的資源配置通過累加,形成 Pod 整體的資源配置。

針對每個容器的資源請求和限制,可以通過以下字段設置:

  • spec.containers[].resources.limits.cpu

  • spec.containers[].resources.limits.memory

  • spec.containers[].resources.requests.cpu

  • spec.containers[].resources.requests.memory

下面是一個示例:

該 Pod 有兩個容器,每個容器請求的 CPU 和 Memory 都是 0.25 CPU 和 64 MiB,每個容器的資源限制都是 0.5 CPU 和 128 MiB,所以該 Pod 的資源請求為 0.5 CPU 和 128 MiB,資源限制為 1 CPU 和 256 MiB。

apiVersion: v1
kind: Pod
metadata:name: frontend
spec:containers:- name: appimage: images.my-company.example/app:v4resources:requests:memory: "64Mi"cpu: "250m"limits:memory: "128Mi"cpu: "500m"- name: log-aggregatorimage: images.my-company.example/log-aggregator:v6resources:requests:memory: "64Mi"cpu: "250m"limits:memory: "128Mi"cpu: "500m"

QoS模型

除了通過 limits 和 requests 限制和請求資源,Kubernetes 還會根據值的不同,為 Pod 設置優先級。當 Node 上的資源不足時,驅逐低優先級的 Pod,以保證更重要的 Pod 正常運行。這里就要介紹 Kubernetes 中的 QoS**(Quality of Service,服務質量)**。

QoS 類一共有三種:Guaranteed、Burstable 和 BestEffort。當一個 Node 耗盡資源時,Kubernetes 驅逐策略為:BestEffort Pod > Burstable Pod > Guaranteed Pod。

  • BestEffort:pod沒有設置requests和limit
  • Burstable:pod設置request和limit,但request<limit
  • Guaranteed:pod設置request和limit,并且request=limit

Guaranteed

判斷依據:

  • Pod 中的每一個 Container 都同時設置了 Memory limits 和 requests,且值相等

  • Pod 中的每一個 Container 都同時設置了 CPU limits 和 requests,且值相等

比如下面的 Pod 中,CPU 的請求和限制都為 0.7 CPU,Memory 的請求和限制都為 200 MiB。當該 Pod 創建后,它的 QoS Class 字段的值就是:Guaranteed。屬于該類型的 Pod 具有最嚴格的資源限制,且最不可能被驅逐。只有當獲取的資源超出 limits 值或沒有可被驅逐的 BestEffort Pod 或 Burstable Pod,這些 Pod 才會被殺死。

apiVersion: v1
kind: Pod
metadata:name: qos-demonamespace: qos-example
spec:containers:- name: qos-demo-ctrimage: nginxresources:limits:memory: "200Mi"cpu: "700m"requests:memory: "200Mi"cpu: "700m"

需要注意的是,當 Pod 僅設置了 limits 沒有設置 requests 時,Kubernetes 會自動為它設置與 limits 相同的 requests 值。

Burstable

判斷依據:

  • 不滿足 Guaranteed 的判斷條件

  • 至少有一個 Container 設置了 requests

在下面的 Pod 中,Memory 的限制為 200 MiB,請求為 100 MiB。兩者不相等,所以被劃分為 Burstable。

如果不指定 limits 的值,那么默認 limits 等于 Node 容量,允許 Pod 靈活地使用資源。如果 Node 資源不足,導致 Pod 被驅逐,只有在 BestEffort Pod 被驅逐后,Burstable Pod 才會被驅逐。

apiVersion: v1
kind: Pod
metadata:name: qos-demo-2namespace: qos-example
spec:containers:- name: qos-demo-2-ctrimage: nginxresources:limits:memory: "200Mi"requests:memory: "100Mi"

BestEffort

判斷依據:

  • 不滿足 Guaranteed 或 Burstable 的判斷條件

  • 既沒有設置 limits,也沒有設置 requests

屬于 BestEffort 的 Pod,可以使用未分配給其他 QoS 類中的資源。如果 Node 有 16 核 CPU 可供使用,且已經為 Guaranteed Pod 分配了 4 核 CPU,那么 BestEffort Pod 可以隨意使用剩余的 12 核 CPU。

如果 Node 的資源不足,那么將首先驅逐 BestEffort Pod。

apiVersion: v1
kind: Pod
metadata:name: qos-demo-3namespace: qos-example
spec:containers:- name: qos-demo-3-ctrimage: nginx

限制范圍和資源配額

默認情況下,Kubernetes 中的容器可以使用的資源是沒有限制的。但是當多個用戶使用同一個集群時,可能會出現有人占用過量的資源,導致其他人無法正常使用集群的情況。

限制范圍和資源配額正是解決該問題的方法。其中限制范圍通過 LimitRange 對象,在命名空間級別下限制 Pod 中容器的資源使用量,在創建 Pod 時,自動設置 CPU 和 Memory 的請求和限制。資源配額通過 ResourceQuota 對象,對每個命名空間的資源總量進行限制,避免命名空間中的程序無限制地使用資源。

在下面的例子中,定義了一個 LimitRange 對象。在該命名空間創建的 Pod 將遵循以下條件:

  • 如果未指定 CPU 的 requests 和 limits,則均為 0.5 CPU

  • 如果只指定了 requests,則 limits 的值在 0.1 CPU 和 1 CPU 之間

  • 如果只指定了 limits,則 request 的值與 limits 相同,低于 0.1 CPU 的設為 0.1 CPU,高于 1 CPU 的設為 1 CPU。

  • 如果命名空間存在多個 LimitRange 對象,應用哪個默認值是不確定的

apiVersion: v1
kind: LimitRange
metadata:name: cpu-resource-constraint
spec:limits:- default: # 此處定義默認限制值cpu: 500mdefaultRequest: # 此處定義默認請求值cpu: 500mmax: # max 和 min 定義限制范圍cpu: "1"min:cpu: 100mtype: Container

需要注意的是,當只指定了 requests,沒有指定 limits 時,requests 的值大于 LimitRange 設置的 limits 的默認值,將導致 Pod 無法調度。

資源配額的流程如下:

  • 集群管理員為每個命名空間創建一個或多個 ResourceQuota 對象

  • 當用戶在命名空間下創建對象時,Kubernetes 的配額系統會跟蹤集群的資源使用情況,以確保使用的資源總量不超過 ResourceQuota 中的配額

  • 如果命名空間下的計算資源(CPU、Memory)被開啟,則用戶必須為 Pod 設置 limits 和 requests,否則系統將拒絕 Pod 的創建(或者使用 LimitRanger 解決)

下面的 ResourceQuota 定義了命名空間的資源限制:該命名空間中所有 Pod 的 CPU 總量不能超過 2,Pod 的 Memory 總量不能超過 2 GiB,PVC 的存儲總量不能超過 5 GiB,Pod 的數量不能超過 10 個。

apiVersion: v1
kind: ResourceQuota
metadata:name: example-quota
spec:hard:cpu: "2"memory: 2Gistorage: 5Gipods: "10"

CPU 管理器策略

默認情況下,kubelet 使用 CFS 配額 來對 Pod 的 CPU 進行約束。當 Node 上運行了很多 CPU 密集型任務時,Pod 可能會爭奪可用的 CPU 資源,工作負載可能會遷移到不同的 CPU 核,對上下文切換敏感的工作負載的性能會受到影響。為此,kubelet 提供了可選的 CPU 管理器策略。

管理策略

CPU 管理器目前有兩種策略:

  • None:默認策略

  • Static:允許為節點上具有整數型 CPU requests 的 Guaranteed Pod 賦予 CPU 親和性和獨占性。

此策略管理一個 CPU 共享池,該共享池最初包含節點上所有的 CPU 資源。可獨占性 CPU 資源數量等于 CPU 總量減去通過 kubeReserved 或 systemReserved 參數指定的 CPU 數量。這些參數指定的 CPU 供 BestEffort Pod、Burstable Pod 和 Guaranteed 中請求了非整數值 CPU 的 Pod 使用。只有那些請求了整數型 CPU 的 Guaranteed Pod,才會被分配獨占 CPU 資源。

上圖顯示了 CPU 管理器的結構。CPU 管理器使用contaimerRuntimeService接口的UpdateContainerResources方法來修改容器可以運行的 CPU。Manager 定期使用 cgroupfs 技術來與每個正在運行的容器的 CPU 資源的當前狀態進行協調。

使用場景

如果工作負載具有以下場景,那么通過使用該策略,操作系統在CPU之間進行上下文切換的次數大大減少,容器里應用的性能會得到大幅提升。

  • 對 CPU 節流敏感

  • 對上下文切換敏感

  • 對處理器換成未命中敏感

驗證策略

由于 CPU 管理器策略只能在 kubelet 生成新 Pod 時生效,所以簡單地從 "None" 更改為 "Static" 將不會對現有的 Pod 起作用。 因此,為了正確更改節點上的 CPU 管理器策略,可以執行以下步驟:

  1. 騰空節點

  2. 停止 kubelet

  3. 刪除舊的 CPU 管理器狀態文件。該文件的路徑默認為/var/lib/kubelet/cpu_manager_state。這將清除 CPUManager 維護的狀態,以便新策略設置的 cpu-sets 不會與之沖突

  4. 編輯 kubelet 配置/var/lib/kubelet/config.yml,以將 CPU 管理器策略更改為所需的值

  5. 啟動 kubelet

  6. 對需要更改其 CPU 管理器策略的每個節點重復此過程。

以下示例在config.yml添加了字段,如果該 Node 有 64 核,那么共享池將有 8 核,剩余的 56 核將用于指定了整數型 CPU 的 Guaranteed Pod。

systemReserved:cpu: "4"memory: "500m"
kubeReserved:cpu: "4"memory: "500m"
cpuManagerPolicy: "Static"

當重新啟動 kubelet 后,就會新建cpu_manager_state,"policyName" 字段將從 “None” 變為 “Static”。

{"policyName":"Static","defaultCpuSet":"","checksum":1353318690}

創建一個 calculate.yml,用來驗證 Static 策略是否真的生效。用 go 寫了一個可以并發計算 200000 以內的素數的程序 calculate_primes。指定部署在啟動了 Static 策略的 dc02-pff-500-5c24-cca-e881-3c40 節點上,并把 Pod 設置為 Guaranteed。

apiVersion: batch/v1
kind: Job
metadata:name: calculate-job
spec:template:metadata:name: calculate-jobspec:nodeName: ***containers:- name: calculate-containerimage: ubuntu:latestcommand: ["./calculate_primes", "2000000"]resources:limits:cpu: "5"memory: "100Mi"volumeMounts:- name: mix-storage-volumemountPath: ***volumes:- name: mix-storage-volumepersistentVolumeClaim:claimName: mix-storage-pvcrestartPolicy: NeverbackoffLimit: 0

查看 Pod 可以確認確實為 Guaranteed。

通過 taskset -cp PID 和 cat cpu_manager_state 可以查看 calculate_primes 進程使用了序號為 8-12 的5個 CPU,表明 Static 策略生效,程序可以獨占 CPU。

而使用 None 策略時,通過 taskset -cp PID 命令可以查看當前進程并不會獨占 CPU,而是在 64 個 CPU 間隨意切換。

CPU、Memory 限制和請求的最佳實踐

Natan Yellin 通過“口渴的探險家”和“披薩派對”的例子,給出了關于 CPU 、Memory 限制和請求的最佳實踐。

省略版

永遠設置 Memory limits == requests

絕不設置 CPU limits

口渴的探險家

在該故事中,CPU 就是水,CPU 饑餓就是死亡。A 和 B 在沙漠中旅行,他們有一個神奇的水瓶,每天可以產生 3 升水,每人每天需要 1 升水才能存活。

情景1:without limits, without requests

A 很貪婪,在 B 之前喝光了所有的水,導致 B 渴死。因為沒有限制和請求,所以 A 能喝掉所有的水,導致 CPU 饑餓。

情景2:with limits, with or without requests

A 和 B 都喝了 1 升水,但是 A 生病了,需要額外的水,B 不讓 A 喝,因為 A 的限制是每天 1 升水,所以 A 渴死了。當有 CPU 限制時,就可能發生這種情況,即使有很多資源,也無法使用。

情景3:without limits, with requests

這次輪到 B 生病了,需要額外的水,但是當喝到只剩 1 升水時停下了,因為 A 每天需要 1 升水。兩個人都活了下來。當沒有 CPU 限制但有請求時就會出現這種情況,一切正常。

用表格概括一下 limits 和 requests 的區別

PodCPU limitsNo CPU limits
CPU requests能使用的CPU 在 requests和limits之間無法使用更多的 CPU能夠使用 requests 指定的 CPU 數量多余的CPU也能用,不會造成浪費
No CPU requests能夠使用 limits 指定的 CPU 數量無法使用更多的 CPU隨意使用可能會耗盡節點資源

Kubernetes 給出了解釋:

Pod 保證能夠獲得所請求的 CPU 數量,如果沒有 limits,可能會使用多余的 CPU,但不會搶占其他正在運行任務的CPU。

披薩派對

想象一個披薩派對,每個人點 2 片,最多可以吃 4 片,相當于 requests = 2,limits = 4。但在訂購披薩的時候,是按每人 2 片的數量訂的。派對開始了,每張桌子都為坐下的人準備了 2 片披薩,誰都可以拿。但是在你準備吃的時候發現披薩沒有了,此時一個保鏢出來把正在吃披薩的另一個人擊倒,收集剩下的披薩(準確地說是也包括這個人吃過的披薩),給桌子上的其他人吃。并把剛才的那個人安排到另一張有更多披薩的桌子上。

當 Node 上的 Memory 不足時(OOM),就會出現這種情況。Pod 訪問不可用的 Memory,就會因 OOM 而被終止。如果客人只允許吃掉所訂購數量的披薩,即 requests = limits,那么大家都將相安無事。

總結

在 Kubernetes 中,CPU 和 Memory 資源的管理和分配是非常重要的。通過合理地分配和管理這些資源,可以確保 Kubernetes 集群的穩定性和可用性,提高應用程序的性能。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/75699.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/75699.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/75699.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

解鎖 DeepSeek 與 Matlab:攻克科研難題的技術利刃

技術點目錄 第一章、MATLAB 2024b深度學習工具箱新特性簡介第二章、卷積神經網絡&#xff08;Convolutional Neural Network, CNN&#xff09;第三章、模型可解釋性與特征可視化Model Explanation and Feature Visualization第四章、遷移學習算法&#xff08;Transfer Learning…

藍橋杯_PCF8591

目錄 一 前言 二 引言 三 PCF8591介紹 &#xff08;1&#xff09;I2C通信 &#xff08;2&#xff09;原理圖中的8591 四 代碼層面 &#xff08;1&#xff09;根據題目所給的示范代碼&#xff0c;實現ADC 1 為什么需要返回值&#xff0c;同時返回值是unsigned char&#x…

Dify案例-接入飛書云文檔實現需求質量評估

dify接入飛書云文檔實現需求質量評估 1. 背景與目標2. 系統架構與流程2.1 整體架構圖2.2 核心流程2.3 dify工作流概覽 3. 實現細節3.1 文檔提取3.2 需求評估3.3 參數提取3.4 創建飛書云文檔 4. 難點總結4.1 提示詞編寫4.2 關聯飛書云文檔4.2.1 安裝飛書云文檔插件并關聯到飛書自…

機器視覺工程師的專業精度決定職業高度,而專注密度決定成長速度。低質量的合群,不如高質量獨處

在機器視覺行業&#xff0c;真正的技術突破往往誕生于深度思考與有效碰撞的辯證統一。建議采用「70%高質量獨處30%精準社交」的鉆石結構&#xff0c;構建可驗證的技術能力護城河。記住&#xff1a;你的專業精度決定職業高度&#xff0c;而專注密度決定成長速度。 作為機器視覺工…

字符串移位包含問題

字符串移位包含問題 #include <iostream> #include <algorithm> using namespace std; int main(){string a,b;cin>>a>>b;//誰長遍歷誰if(a.size()<b.size()) swap(a,b);//1-對整個字符串進行移位for(int i0; i<a.size(); i){//每次循環都將第一…

SQL 查詢執行順序

SQL 查詢的邏輯處理順序&#xff08;即 SQL 引擎解析和執行查詢的順序&#xff09;與書寫順序不同。以下是 SQL 查詢的完整執行順序&#xff1a; 1. 邏輯執行順序 FROM 和 JOIN - 確定數據來源表并執行連接操作 WHERE - 對行進行篩選 GROUP BY - 將數據分組 HAVING - 對分組…

核心知識——Spark核心數據結構:RDD

引入 通過前面的學習&#xff0c;我們對于Spark已經有一個基本的認識&#xff0c;并且搭建了一個本地的練習環境&#xff0c;因為本專欄的主要對象是數倉和數分&#xff0c;所以就不花大篇幅去寫環境搭建等內容&#xff0c;當然&#xff0c;如果感興趣的小伙伴可以留言&#x…

Spring Boot 嵌入式容器性能對決:Tomcat vs Undertow!

文章目錄 引言理論基礎嵌入式容器TomcatUndertow 實戰性能測試配置 Tomcat 和 Undertow創建測試控制器使用Jmeter壓測 總結 引言 在現代應用開發中&#xff0c;選擇合適的嵌入式容器對于提升應用的性能和響應性至關重要。Spring Boot 提供了多種嵌入式容器選項&#xff0c;其中…

計算機系統---GPU

硬件架構 核心處理器&#xff1a; 流處理器&#xff08;SP&#xff09;&#xff1a;是GPU進行計算的核心單元&#xff0c;數量眾多。例如&#xff0c;NVIDIA的高端GPU可能擁有數千個流處理器。它們可以并行執行大量的計算任務&#xff0c;如在圖形渲染中對每個頂點或像素進行獨…

【GPT寫代碼】動作視頻切截圖研究器

目錄 背景源代碼 end 背景 用python寫一個windows環境運行的動作視頻切截圖研究器&#xff0c;用路徑瀏覽的方式指定待處理的視頻文件&#xff0c;然后點擊分析按鈕&#xff0c;再預覽區域顯示視頻預覽畫面&#xff0c;然后拖動時間軸&#xff0c;可以在預覽區域刷新顯示相應的…

在 .NET 8 中使用自定義令牌身份驗證掌握 SignalR Hub 安全性

最近在練習做一個 Web 開發項目&#xff0c;需要使用 WebSockets 傳輸數據&#xff0c;實現實時通信。這是一個 React.js 項目&#xff0c;后端是 .NET。 雖然 MSDN 提供了出色的頂級文檔&#xff0c;但它通常缺少高級用例所需的低級細節。 一種這樣的場景是使用自定義令牌對…

[2018][note]用于超快偏振開關和動態光束分裂的all-optical有源THz超表——

前言 類型 太赫茲 + 超表面 太赫茲 + 超表面 太赫茲+超表面 期刊 O p e n A c c e s s Open Access Open

家里網絡訪問Github有時候打不開,解決辦法

1、修改Hosts文件修改法 通過DNS查詢工具&#xff08;如&#xff09;獲取最新GitHub域名解析IP修改系統hosts文件&#xff08;路徑&#xff1a;C:\Windows\System32\drivers\etc\hosts&#xff09;&#xff0c;添加&#xff1a;20.205.243.166 github.com 20.27.177.113 github…

MyBatis操作數據庫(1)

1. MyBatis 簡介 MyBatis 是一款持久層框架&#xff0c;簡化了 JDBC 的復雜操作&#xff0c;通過配置和映射文件將 Java 對象與數據庫表關聯。核心優勢&#xff1a; 自動管理資源&#xff1a;無需手動關閉連接、釋放資源。 動態 SQL&#xff1a;支持參數綁定、條件查詢等。 …

ModuleNotFoundError: No module named ‘matplotlib_inline‘

ModuleNotFoundError: No module named matplotlib_inline 1. ModuleNotFoundError: No module named matplotlib_inline2. matplotlib-inlineReferences 如果你在普通的 Python 腳本或命令行中運行代碼&#xff0c;那么不需要 matplotlib_inline&#xff0c;因為普通的 Python…

SSL證書自動化管理(ACME協議)工作流程介紹

SSL證書自動化管理&#xff08;ACME協議&#xff09;是一種用于自動化管理SSL/TLS證書的協議&#xff0c;以下是其詳細介紹&#xff1a; 一、ACME協議概述 ACME協議由互聯網安全研究小組&#xff08;ISRG&#xff09;設計開發&#xff0c;旨在實現SSL證書獲取流程的自動化。通…

基于FPGA的特定序列檢測器verilog實現,包含testbench和開發板硬件測試

目錄 1.課題概述 2.系統測試效果 3.核心程序與模型 4.系統原理簡介 5.完整工程文件 1.課題概述 本課題采用基于偽碼匹配相關峰檢測的方式實現基于FPGA的特定序列檢測器verilog實現,包含testbench和開發板硬件測試。 2.系統測試效果 仿真測試 當檢測到序列的時候&#xf…

#管理Node.js的多個版本

在 Windows 11 上管理 Node.js 的多個版本&#xff0c;最方便的方法是使用 nvm-windows&#xff08;Node Version Manager for Windows&#xff09;。它允許你輕松安裝、切換和管理多個 Node.js 版本。 &#x1f4cc; 方法 1&#xff1a;使用 nvm-windows&#xff08;推薦 ?&a…

【已解決】Webstorm 每次使用 git pull/push 都要輸入令牌/密碼登錄

解決辦法&#xff1a;勾上【使用憑據幫助程序】&#xff08;英文&#xff1a;Use credential helper&#xff09;

大模型架構記錄13【hr agent】

一 Function calling 函數調用 from dotenv import load_dotenv, find_dotenvload_dotenv(find_dotenv())from openai import OpenAI import jsonclient OpenAI()# Example dummy function hard coded to return the same weather # In production, this could be your back…