Linux內存管理的機制
OOM Killer
在 Linux 系統里如果內存不足時,會殺死一個正在運行的進程來釋放一些內存,如果進程是容器處于OOM Killer 。
為什么還要去殺死正在運行的進程呢?
Linux允許進程申請超過實際物理內存上限的內存。因為 malloc() 申請的是內存的虛擬地址,系統只是給了程序一個地址范圍,并沒有得到真正的物理內存。
在發生 OOM 的時候,Linux 到底是根據什么標準來選擇被殺的進程呢?
在 Linux 內核里有一個 oom_badness() 函數,就是它定義了選擇進程的標準。
Memory Cgroup
限制cgroup 之中的進程所能使用的內存大小,Memory Cgroup 里都不會對內核的內存做限制(比如頁表,slab 等)。只限制用戶態相關的兩個內存類型,RSS(Resident Set Size) 和 Page Cache。
如何限制memory cgroup 的內存大小?
memory.limit_in_bytes:一個控制組里所有進程可使用內存的最大值
memory.oom_control,當控制組中的進程內存使用達到上限值時,這個參數能夠決定會不會觸發 OOM Killer
memory.swappiness,設置和顯示當前的swappiness
Linux 內存類型
內核需要分配內存給頁表,內核棧,還有 slab,也就是內核各種數據結構的 Cache Pool;
用戶態進程內存:
1:RSS 內存包含了進程的代碼段內存,棧內存,堆內存,共享庫的內存
2:文件讀寫的 Page Cache,是一種為了提高磁盤文件讀寫性能的機制。
Linux 的內存管理有一種內存頁面回收機制(page frame reclaim),會根據系統里空閑物理內存是否低于某個閾值(wartermark),來決定是否啟動內存的回收。內存回收的算法會根據不同類型的內存以及內存的最近最少用原則,就是 LRU(Least Recently Used)算法決定哪些內存頁面先被釋放。因為 Page Cache 的內存頁面只是起到 Cache 作用,自然是會被優先釋放的。
swap
Swap 是一塊磁盤空間,當內存寫滿的時候,就可以把內存中不常用的數據暫時寫到這個 Swap 空間上。
1、在容器中要用到 Swap,需要在宿主機節點上打開 Swap 空間
2、通過swappiness 參數值,在系統里有 Swap 空間之后,當系統需要回收內存的時候,是優先釋放 Page Cache 中的內存,還是優先釋放匿名內存
Kubernetes 管理內存機制
資源配額(Resource Quota): 資源配額可以設置命名空間中容器的內存使用限制。這可以幫助防止容器占用過多的內存資源,從而保護整個集群的穩定性。
資源限制(Resource Limit): 在容器的 PodSpec 中,可以設置容器的資源限制,包括內存限制。這樣可以確保容器不會使用超過限制的內存量。
內存請求和分配(Memory Requests and Allocation): 在容器的 PodSpec 中,可以設置容器的內存請求。這將告訴 Kubernetes 調度器容器所需的內存量。Kubernetes 調度器會根據節點的可用資源和容器的請求進行調度決策,以確保容器可以獲得足夠的內存。
內存回收(Memory Reclamation): Kubernetes 提供了內存回收機制來處理容器釋放未使用的內存。當容器不再需要內存時,Kubernetes 可以將其回收以供其他容器使用。
內存回收時的內存使用量的鎖定
1、保障 Pod 間內存回收的公平性,當整機內存資源緊張時,優先從內存超用(Usage > Request)的 Pod 中回收內存(Memory QoS 支持為這類Pod設置主動內存回收的水位線,將內存使用限制在水位線附近),約束破壞者以避免整機資源質量的下降。
2、當 Pod 的內存用量接近 Limit 時,優先在后臺異步回收一部分內存,緩解直接內存回收帶來的性能影響。
3、節點內存資源緊張時,優先保障 Guaranteed/Burstable Pod 的內存運行質量。Memory QoS 功能通過啟用全局最低水位線分級和內核 memcg QoS,當整機內存資源緊張時,優先從 BE 容器中回收內存,降低全局內存回收對 LS 容器的影響;也支持優先回收超用的的內存資源,保障內存資源的公平性。