kubelet架構(gòu)設(shè)計解析之Memory Manager

更多kubernetes文章:weiliang-ms/kubernetes-docs: kubernetes學(xué)習(xí)筆記 (github.com)

Memory Manager介紹說明

Memory Manager(譯為內(nèi)存管理器)是 kubelet 內(nèi)部的一個組件乙帮,旨在為 Guaranteed QoS 類型 pod 提供保證內(nèi)存(和大頁內(nèi)存)分配功能,該特性提供了幾種分配策略:

  1. 單 NUMA 策略:用于高性能和性能敏感的應(yīng)用程序
  2. 多 NUMA 策略:補充完善單 NUMA 策略無法管理的情況

也就是說鹰祸,只要 pod 所需的內(nèi)存量超過單個 NUMA 節(jié)點的容量,就會使用多 NUMA 策略跨多個 NUMA 節(jié)點提供保證的內(nèi)存。

在這兩種場景中,內(nèi)存管理器都使用提示生成協(xié)議為 pod 生成最合適的 NUMA 關(guān)聯(lián)沃疮,并將這些關(guān)聯(lián)提示提供給中央管理器(Topology Manager)。此外梅肤,內(nèi)存管理器確保 pod 請求的內(nèi)存從最小數(shù)量的 NUMA 節(jié)點分配司蔬。

從技術(shù)上講,單 NUMA 策略是多 NUMA 策略的一種特殊情況姨蝴,因此 kubernetes 開發(fā)團隊沒有為它們開發(fā)單獨的實現(xiàn)俊啼。

什么是NUMA?

早期的計算機左医,內(nèi)存控制器還沒有整合進 CPU授帕,所有的內(nèi)存訪問都需要經(jīng)過北橋芯片來完成同木。如下圖所示,CPU 通過前端總線(FSB跛十,F(xiàn)ront Side Bus)連接到北橋芯片彤路,然后北橋芯片連接到內(nèi)存——內(nèi)存控制器集成在北橋芯片里面。

d9353e066a4a2dc38861537a81c12c54.png

上面這種架構(gòu)被稱為 UMA(Uniform Memory Access, 一致性內(nèi)存訪問 ):總線模型保證了 CPU 的所有內(nèi)存訪問都是一致的芥映,不必考慮不同內(nèi)存地址之間的差異洲尊。

在 UMA 架構(gòu)下,CPU 和內(nèi)存之間的通信全部都要通過前端總線奈偏。而提高性能的方式坞嘀,就是不斷地提高 CPU、前端總線和內(nèi)存的工作頻率惊来。

由于物理條件的限制丽涩,不斷提高工作頻率的方式接近瓶頸。CPU 性能的提升開始從提高主頻轉(zhuǎn)向增加 CPU 數(shù)量(多核唁盏、多 CPU)内狸。越來越多的 CPU 對前端總線的爭用,使前端總線成為了瓶頸厘擂。為了消除 UMA 架構(gòu)的瓶頸昆淡,NUMA(Non-Uniform Memory Access, 非一致性內(nèi)存訪問)架構(gòu)誕生了:

e98800eca33964a548030826fdb689f4.png
  1. CPU 廠商把內(nèi)存控制器集成到 CPU 內(nèi)部,一般一個 CPU socket 會有一個獨立的內(nèi)存控制器刽严。
  2. 每個 CPU scoket 獨立連接到一部分內(nèi)存昂灵,這部分 CPU 直連的內(nèi)存稱為“本地內(nèi)存”。
  3. CPU 之間通過 QPI(Quick Path Interconnect) 總線進行連接舞萄。CPU 可以通過 QPI 總線訪問不和自己直連的“遠(yuǎn)程內(nèi)存”眨补。

和 UMA 架構(gòu)不同,在 NUMA 架構(gòu)下倒脓,內(nèi)存的訪問出現(xiàn)了本地和遠(yuǎn)程的區(qū)別:訪問遠(yuǎn)程內(nèi)存的延時會明顯高于訪問本地內(nèi)存撑螺。

什么是大頁內(nèi)存?

大頁內(nèi)存(HugePages)崎弃,有時也叫“大內(nèi)存頁”甘晤、“內(nèi)存大頁”、“標(biāo)準(zhǔn)大頁”饲做。計算機內(nèi)存以頁的形式分配給進程线婚。通常這些頁相當(dāng)小,這意味著消耗大量內(nèi)存的進程也將消耗大量的頁盆均。對于那些內(nèi)存操作非常頻繁的業(yè)務(wù)來說塞弊,大頁內(nèi)存可以有效的提高性能。簡而言之,通過啟用大頁內(nèi)存游沿,系統(tǒng)只需要處理較少的頁面映射表饰抒,從而減少訪問/維護它們的開銷!大頁內(nèi)存在數(shù)據(jù)庫服務(wù)器這樣的系統(tǒng)上特別有用奏候。像 MySQL 和 PostgreSQL 這樣的進程可以使用大頁內(nèi)存循集,以減少對 RAM 緩存的壓力。

什么是Guaranteed QoS pod蔗草?

Kubernetes 通過 服務(wù)質(zhì)量類(Quality of Service class咒彤,QoS class)定義了三種 pod 類型, Kubernetes 在 Node 資源不足時使用 QoS 類來就驅(qū)逐 Pod 作出決定:

  • Guaranteed: pod 中 每個容器 limits.cpu == requests.cpu && limits.memory== requests.memory. Guaranteed 類型 Pod 具有最嚴(yán)格的資源限制咒精,并且最不可能面臨驅(qū)逐镶柱。
  • Burstable: Pod 中至少一個容器有內(nèi)存或 CPU 的 request 或 limit 且非 Guaranteed
  • BestEffort: Pod 不滿足 GuaranteedBurstable 的判據(jù)條件模叙,即Pod 中的所有容器沒有設(shè)置內(nèi)存 limit 或內(nèi)存 request歇拆,也沒有設(shè)置 CPU limit 或 CPU request 。

三種 pod 優(yōu)先級:Guaranteed > Burstable > BestEffort

Memory Manager開發(fā)動機

  1. 為容器(同一 pod 內(nèi)的容器)提供最小數(shù)量的 NUMA 節(jié)點上有保證的內(nèi)存(和大頁內(nèi)存)分配范咨。
  2. 保證整個容器組(同一 pod 內(nèi)的容器)的內(nèi)存和大頁面與相同 NUMA 節(jié)點的關(guān)聯(lián)故觅。

內(nèi)存管理器的設(shè)計應(yīng)用對于性能敏感的程序、數(shù)據(jù)庫渠啊、虛擬化影響巨大:

由于數(shù)據(jù)庫(例如输吏,Oracle, PostgreSQL和MySQL)需要相對大量的內(nèi)存和大頁內(nèi)存,來相對有效地訪問大量數(shù)據(jù)替蛉。而為了減少由跨 NUMA 內(nèi)存訪問和共享引起的延遲贯溅,所有資源(CPU內(nèi)核、內(nèi)存躲查、大頁內(nèi)存和I/O設(shè)備)都應(yīng)該對齊到同一個 NUMA 節(jié)點它浅,這將極大地提高穩(wěn)定性和性能。

并且內(nèi)存數(shù)據(jù)庫(Redis等)具有更大的內(nèi)存需求镣煮,可以擴展到多個 NUMA 節(jié)點姐霍。這就產(chǎn)生了跨多個 NUMA 節(jié)點維持和管理內(nèi)存的需求。

Memory Manager架構(gòu)設(shè)計

494291e60e1bb7b73110b3735649231d.png

一旦 kubelet 請求 Guaranteed QoS 類型 pod 許可典唇,如上圖所示邮弹,拓?fù)涔芾砥鳎═opology Manager)就會向內(nèi)存管理器 (Memory Manager) 查詢 pod 中所有容器的內(nèi)存和大頁內(nèi)存的首選 NUMA 親和關(guān)系。

對于 pod 中的每個容器蚓聘,內(nèi)存管理器使用其內(nèi)部數(shù)據(jù)庫(即Node Map)計算關(guān)聯(lián)。Node Map 是一個對象盟劫,它負(fù)責(zé)跟蹤 Guaranteed QoS 類 Pod 中所有容器的內(nèi)存(和大頁內(nèi)存)的使用情況夜牡。一旦內(nèi)存管理器完成計算,它將結(jié)果返回給拓?fù)涔芾砥鳎员阃負(fù)涔芾砥骺梢杂嬎愠瞿膫€ NUMA 節(jié)點或一組 NUMA 節(jié)點最適合容器的內(nèi)存固定塘装。對 pod 中的所有容器執(zhí)行總體計算急迂,如果沒有容器被拒絕,則 kubelet 最終接收并部署該 pod蹦肴。

在 pod 接收階段僚碎,內(nèi)存管理器調(diào)用 Allocate() 方法并更新其 Node Map 對象。隨后內(nèi)存管理器調(diào)用 AddContainer() 方法并強制分配容器的內(nèi)存和大頁內(nèi)存阴幌,并限制到對應(yīng) NUMA 節(jié)點或 NUMA 節(jié)點組勺阐。最終通過CRI 接口更新控制組配置項(cpuset.mems項)。

內(nèi)存管理器為(且僅為) Guaranteed QoS類中的pod提供有保證的內(nèi)存分配矛双。

多NUMA節(jié)點保證內(nèi)存分配原理

主要思想是將一組 NUMA 節(jié)點視為一個獨立的單元渊抽,并由內(nèi)存管理器管理這些獨立的單元。

NUMA 節(jié)點組不能相交议忽。下面的圖舉例說明了一組不相交的 NUMA 組懒闷。圖中的組是不相交的,即:[0]栈幸,[1,2]愤估,[3]。必須遵守該規(guī)則速址,因為重疊的組基本上不能確保在多個 NUMA 節(jié)點上有保證的內(nèi)存分配玩焰。

cbdb8a7b6c255dbe9058f86e3fd08376.png

例如,以下組重疊壳繁,[0,1]震捣,[1,2]和[3],因為它們有一個以1為索引的公共 NUMA 節(jié)點闹炉。換句話說蒿赢,如果組重疊(比如:[0,1]和[1,2]),則[1,2]組的內(nèi)存資源可能會優(yōu)先被另一組([0,1])消耗渣触,[1,2]組可用內(nèi)存資源會被搶占羡棵。

節(jié)點映射(Node Map)

內(nèi)存管理器有一個內(nèi)部數(shù)據(jù)庫,即節(jié)點映射(Node Map)嗅钻,它包含內(nèi)存映射(Memory Map)皂冰。該數(shù)據(jù)庫用于記錄在 Guaranteed QoS 類中為已部署的容器保留的內(nèi)存。節(jié)點映射對象記錄 Node 對象中不相交的 NUMA-node組的動態(tài)配置养篓。注意秃流,實際上內(nèi)存映射提供了跟蹤內(nèi)存的計數(shù)器。因此柳弄,不應(yīng)該將映射理解為允許保留內(nèi)存范圍或連續(xù)內(nèi)存塊的映射舶胀。

在部署容器時,還使用映射來計算NUMA關(guān)聯(lián)。內(nèi)存管理器支持傳統(tǒng)內(nèi)存和各種可能大小的大頁內(nèi)存(例如2 MiB或1 GiB)嚣伐,節(jié)點向內(nèi)存管理器提供三種類型的內(nèi)存糖赔,即:常規(guī)內(nèi)存、hugepages-1Gi和hugepages-2Mi轩端。

在啟動時放典,內(nèi)存管理器為每個 NUMA 節(jié)點和各自的內(nèi)存類型初始化一個 Memory Table 集合,從而生成準(zhǔn)備使用的內(nèi)存映射對象基茵。

// MemoryTable 包含內(nèi)存信息 
type MemoryTable struct {  
    TotalMemSize uint64 `json:"total"`  
    SystemReserved uint64 `json:"systemReserved"`  
    Allocatable uint64 `json:"allocatable"`  
    Reserved uint64 `json:"reserved"`  Free uint64 `json:"free"` 
}  
// NodeState 包含 NUMA 節(jié)點關(guān)聯(lián)信息 
type NodeState struct {  
    // NumberOfAssignments contains a number memory assignments from this node  
    // When the container requires memory and hugepages it will increase number of assignments by two 
    NumberOfAssignments int `json:"numberOfAssignments"`  
    // MemoryTable 包含 NUMA 節(jié)點內(nèi)存關(guān)聯(lián)信息  
    MemoryMap map[v1.ResourceName] *MemoryTable `json:"memoryMap"`  
    // NodeGroups contains NUMA nodes that current NUMA node in group with them  
    // It means that we have container that pinned to the current NUMA node and all group nodes  
    Nodes []int `json:"nodes"` 
}  
// NodeMap 包含 每個 NUMA 節(jié)點的內(nèi)存信息. 
type NodeMap map[int] *NodeState

內(nèi)存映射(Memory Map)

內(nèi)存映射用于跟蹤每個 NUMA 節(jié)點的內(nèi)存使用情況奋构。內(nèi)存映射包含幾個計數(shù)器,用于跟蹤內(nèi)存使用情況耿导。存在以下等式:

Allocatable = TotalMemSize - SystemReserved
Free + Reserved = Allocatable

Free = Allocatable - Reserved 
Reserved = Allocatable - Free
  • TotalMemSize 的值由 cadvisor 為每種內(nèi)存類型(常規(guī)內(nèi)存声怔、hugepages-1Gi等)提供給內(nèi)存管理器。TotalMemSize 的值是恒定的舱呻,表示 NUMA 節(jié)點上可用的特定類型內(nèi)存的總(最大)容量醋火。
  • SystemReserved 由 systemReserved 配置項設(shè)置,表示預(yù)留給系統(tǒng)服務(wù)的資源大邢渎馈(如kubelet芥驳、其他系統(tǒng)服務(wù))
  • Reserved 表示 Guaranteed QoS 類型 pod 中為容器預(yù)留的保證內(nèi)存總量

啟動階段內(nèi)存映射

下圖展示了節(jié)點啟動后不久的內(nèi)存映射(常規(guī)內(nèi)存):

c357405af6a01e955f2a463a6ae49bec.png

SystemReserved 的值是由 kubelet 啟動參數(shù)預(yù)先配置。SystemReserved 在運行時保持不變茬高,因此Allocatable在運行時也是不變的兆旬。

55a3a970d493e648ffb8a7eb087d8b67.png

SystemReserved 表示系統(tǒng)預(yù)留的內(nèi)存大小,用于系統(tǒng)怎栽,即內(nèi)核丽猬、操作系統(tǒng)守護進程和核心節(jié)點組件,如 kubelet (kubelet守護進程)熏瞄。

運行階段內(nèi)存映射

下圖中脚祟,容器A和容器B實際消耗的內(nèi)存(紅色色塊、紫色色塊)少于內(nèi)存管理器保留的(保證內(nèi)存)內(nèi)存大星恳(紅色虛線框由桌、紫色虛線框),所以對于兩個容器來說邮丰,它們的內(nèi)存消耗都低于它們的內(nèi)存限制(limits.memroy)行您,并且容器正常運行。

4addad022a750b7e090709c110479bf4.png

當(dāng) kubernetes 節(jié)點發(fā)生 OOM 時(cgroups內(nèi)存限制剪廉、hard-eviction-treshold 等)娃循,由 kubelet、系統(tǒng)內(nèi)核(linux oom killer)進行處理斗蒋,而非由內(nèi)存管理器處理淮野。

工作方式

下面展示內(nèi)存管理器如何管理不同 QoS 類(Guaranteed, bestefort /Burstable)中的 pod捧书,以及內(nèi)存管理器如何動態(tài)管理(創(chuàng)建或刪除) NUMA 節(jié)點的非相交組。

多NUMA節(jié)點

  1. 創(chuàng)建 pod1 骤星,其中 pod1 內(nèi)存配額為15G,且 requests.memory == limits.memory (即Guaranteed QoS 類型pod)
6759d05b90743f45b3643d3f17a00a21.png

內(nèi)存管理器隨后創(chuàng)建 名為 group1 的組爆哑,group1 包含 NUMA 節(jié)點與 pod1洞难,同時更新 pod1 控制組cpuset.mems 參數(shù)[[0,1], 15G]

d9b4f785b0c5c48d801bedd56ef4a412.png
  1. 創(chuàng)建 pod2 ,其中 pod2 內(nèi)存配額為5G揭朝,且 requests.memory == limits.memory (即Guaranteed QoS 類型pod)

盡管 group1剩余內(nèi)存(5G)滿足 Pod2 內(nèi)存需求(5G)队贱,但由于 group1 是多 NUMA 節(jié)點,集群節(jié)點中存在能滿足 pod2 內(nèi)存需求的單 NUMA 節(jié)點(假設(shè)存在), 所以 pod2 準(zhǔn)入請求將被拒絕潭袱。

c2e38ddc40092f98e6b08b87bb44f8bd.png
  1. 當(dāng) pod3 (非Guaranteed QoS類型)嘗試加入 group1 時柱嫌,將被放行 。這是為什么呢屯换?

因為內(nèi)存管理器只管理 Guaranteed QoS類型 Pod编丘,對于非Guaranteed QoS類型Pod一律放行準(zhǔn)入。

d4231713e4a303117c85bb2739819e73.png

由于 pod3 是非Guaranteed QoS類型 pod 彤悔, pod3 內(nèi)存使用有可能會超過 5G 時嘉抓,當(dāng)出現(xiàn)這種情況時將會將觸發(fā) OOM。這種 OOM 情況有兩種處理機制:

  • kubelet 觸發(fā) pod 驅(qū)逐機制晕窑,進而釋放出更多可用內(nèi)存
  • 觸發(fā)linux OOM killer抑片,優(yōu)先 kill 低優(yōu)先級進程(如:BestEffort/QoS、Burstable/QoS類型 pod)

兩種機制優(yōu)先級:kubelet > linux OOM killer

84c2e984bf83d24b716b2cda0a7474bc.png

單NUMA節(jié)點

  1. 創(chuàng)建 pod4 杨赤,其中 pod4 內(nèi)存配額為2G敞斋,且 requests.memory == limits.memory (即Guaranteed QoS 類型pod)
9159d18e2a8c5eed903c4d469a0f052b.png

內(nèi)存管理器隨后創(chuàng)建 名為 group2 的組,group2 包含 NUMA 節(jié)點與 pod4

  1. 創(chuàng)建 pod5 疾牲,其中 pod5內(nèi)存配額為6G植捎,且 requests.memory == limits.memory (即Guaranteed QoS 類型pod)

由于group2仍有8G可用內(nèi)存,pod5將被加入到group2

3eebb8fbf6649aace8dfd28e3eda82e2.png
  1. 創(chuàng)建 pod6 说敏,其中 pod6內(nèi)存配額為3G鸥跟,且 requests.memory == limits.memory (即Guaranteed QoS 類型pod),由于group2僅有2G可用內(nèi)存,pod6將被加入到group3
4eda3a20244e06c86e5898891e5bd253.png
  1. 創(chuàng)建 pod7 盔沫,其中 pod6內(nèi)存配額為8G医咨,且 requests.memory == limits.memory (即Guaranteed QoS 類型pod),由于group3僅有7G可用內(nèi)存,pod7準(zhǔn)入請求將被拒絕架诞。(盡管group2 + group3 剩余容量之和滿pod7拟淮,但無法跨group)
8df74f9f9fe46659fd56a18a7259a626.png

參考資料

  1. 每個程序員都應(yīng)該知道的 CPU 知識:NUMA
  2. pod qos
  3. how-to-enable-hugepages-on-linux
  4. memory-manager
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市谴忧,隨后出現(xiàn)的幾起案子很泊,更是在濱河造成了極大的恐慌角虫,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,277評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件委造,死亡現(xiàn)場離奇詭異戳鹅,居然都是意外死亡,警方通過查閱死者的電腦和手機昏兆,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,689評論 3 393
  • 文/潘曉璐 我一進店門枫虏,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人爬虱,你說我怎么就攤上這事隶债。” “怎么了跑筝?”我有些...
    開封第一講書人閱讀 163,624評論 0 353
  • 文/不壞的土叔 我叫張陵死讹,是天一觀的道長。 經(jīng)常有香客問我曲梗,道長赞警,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,356評論 1 293
  • 正文 為了忘掉前任稀并,我火速辦了婚禮仅颇,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘碘举。我一直安慰自己忘瓦,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 67,402評論 6 392
  • 文/花漫 我一把揭開白布引颈。 她就那樣靜靜地躺著耕皮,像睡著了一般。 火紅的嫁衣襯著肌膚如雪蝙场。 梳的紋絲不亂的頭發(fā)上凌停,一...
    開封第一講書人閱讀 51,292評論 1 301
  • 那天,我揣著相機與錄音售滤,去河邊找鬼罚拟。 笑死,一個胖子當(dāng)著我的面吹牛完箩,可吹牛的內(nèi)容都是我干的赐俗。 我是一名探鬼主播,決...
    沈念sama閱讀 40,135評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼弊知,長吁一口氣:“原來是場噩夢啊……” “哼阻逮!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起秩彤,我...
    開封第一講書人閱讀 38,992評論 0 275
  • 序言:老撾萬榮一對情侶失蹤叔扼,失蹤者是張志新(化名)和其女友劉穎事哭,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體瓜富,經(jīng)...
    沈念sama閱讀 45,429評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡鳍咱,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,636評論 3 334
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了食呻。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片流炕。...
    茶點故事閱讀 39,785評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖仅胞,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情剑辫,我是刑警寧澤干旧,帶...
    沈念sama閱讀 35,492評論 5 345
  • 正文 年R本政府宣布,位于F島的核電站妹蔽,受9級特大地震影響椎眯,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜胳岂,卻給世界環(huán)境...
    茶點故事閱讀 41,092評論 3 328
  • 文/蒙蒙 一编整、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧乳丰,春花似錦掌测、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,723評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至什燕,卻和暖如春粘勒,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背屎即。 一陣腳步聲響...
    開封第一講書人閱讀 32,858評論 1 269
  • 我被黑心中介騙來泰國打工技俐, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留暂刘,地道東北人谣拣。 一個月前我還...
    沈念sama閱讀 47,891評論 2 370
  • 正文 我出身青樓,卻偏偏與公主長得像列肢,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子跨晴,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,713評論 2 354