cgroup有個memory子系統,有兩組對應的文件,一組帶 memsw ,另一組不帶。
# docker ps -a
# cd /sys/fs/cgroup/memory/docker/4b5619ac3b906a44e0babb27eaf7252a8b3533878be4652909b3443da6affe7a/
# ls | grep memory
memory.failcnt
memory.limit_in_bytes
memory.usage_in_bytes
memory.max_usage_in_bytes
memory.memsw.failcnt
memory.memsw.limit_in_bytes
memory.memsw.max_usage_in_bytes
memory.memsw.usage_in_bytes
memory.soft_limit_in_bytes
memory.oom_control
memory.use_hierarchy
memory.swappiness
memory.stat
帶 memsw 的表示虛擬內存,不帶 memsw 的僅包括物理內存。其中,limit_in_bytes 是用來限制內存使用的,其他的則是統計報告。
memory.memsw.limit_in_bytes:內存+swap空間使用的總量限制。
memory.limit_in_bytes:內存使用量限制。
memory.memsw.limit_in_bytes 必須大於或等於 memory.limit_in_byte。
要解除內存限制,把對應的值設為 -1 即可。
這種方式限制進程內存占用會有個風險。當進程試圖占用的內存超過限制時,會觸發 oom ,導致進程直接被殺,從而造成可用性問題。即使關閉控制組的 oom killer,在內存不足時,進程雖然不會被殺,但是會長時間進入 D 狀態(等待系統調用的不可中斷休眠),並被放到 OOM-waitqueue 等待隊列中, 仍然導致服務不可用。因此,用 memory.limit_in_bytes 或 memory.memsw.limit_in_bytes 限制進程內存占用僅應當作為一個保險,避免在進程異常時耗盡系統資源。如,預期一組進程最多會消耗 1G 內存,那么可以設置為 1.5G 。這樣在發生內存泄露等異常情況時,可以避免造成更嚴重問題。
memory.oom_control:內存超限之后的 oom 行為控制。
查看oom killer設置:
# cat memory.oom_control
oom_kill_disable 1
under_oom 0
關閉oom killer:
設置 oom_kill_disable 為 1。(0 為開啟)
在 memory 子系統中,還有一個 memory.soft_limit_in_bytes 。和 memory.limit_in_bytes 的差異是,這個限制並不會阻止進程使用超過限額的內存,只是在系統內存足夠時,會優先回收超過限額的內存,使之向限定值靠攏。
usage_in_bytes、max_usage_in_bytes、failcnt 則分別對應 當前使用量,最高使用量和發生的缺頁次數(申請內存失敗的次數)。
memory子系統中還有一個很重要的設置是 memory.use_hierarchy 這是個布爾開關,默認為 0。此時不同層次間的資源限制和使用值都是獨立的。當設為 1 時,子控制組進程的內存占用也會計入父控制組,並上溯到所有 memory.use_hierarchy = 1 的祖先控制組。這樣一來,所有子孫控制組的進程的資源占用都無法超過父控制組設置的資源限制。同時,在整個樹中的進程的內存占用達到這個限制時,內存回收也會影響到所有子孫控制組的進程。這個值只有在還沒有子控制組時才能設置。之后在其中新建的子控制組默認的 memory.use_hierarchy 也會繼承父控制組的設置。
memory.swappiness 則是控制內核使用交換區的傾向的。值的范圍是 0 – 100。值越小,越傾向使用物理內存。設為 0 時,只有在物理內存不足時才會使用交換區。默認值是系統全局設置: /proc/sys/vm/swappiness 。
memory.stat 就是內存使用情況報告了。包括當前資源總量、使用量、換頁次數、活動頁數量等等。