k8s 最佳實踐:處理內存碎片化

k8s 最佳實踐:處理內存碎片化

內存碎片化造成的危害

節點的內存碎片化嚴重,導致docker運行容器時,無法分到大的內存塊,導致start docker失敗。最終導致服務更新時,狀態一直都是啓動中

在長時間運行的Linux操作系統中,系統日誌有時會出現無法分配高階內存的報錯信息:

Aug  4 22:58:15 server1 kernel: : [69229257.683658] xenwatch: page allocation failure. order:4, mode:0xd0
Aug  4 22:58:15 server1 kernel: : [69229257.683665] Pid: 168, comm: xenwatch Tainted: GF          ---------------    2.6.32-358.23.2.el5.x86_64 #1
Aug  4 22:58:15 server1 kernel: : [69229257.683672] Call Trace:
Aug  4 22:58:15 server1 kernel: : [69229257.683688]  [<ffffffff8112723a>] ? __alloc_pages_nodemask+0x67a/0x8c0
Aug  4 22:58:15 server1 kernel: : [69229257.683697]  [<ffffffff8126082f>] ? number+0x2ff/0x330
Aug  4 22:58:15 server1 kernel: : [69229257.683706]  [<ffffffff81162260>] ? kmem_getpages+0x60/0x150

此時使用cat /proc/buddyinfo觀察內存order分配情況,可以看到內存碎片化嚴重(大量的低階內存頁,但是幾乎沒有高階內存頁)

#cat /proc/buddyinfo
Node 0, zone      DMA      2      2      2      1      2      1      1      0      0      0      2
Node 0, zone    DMA32  32995   4377    762    211    157    108     68     23      3      0      0
Node 0, zone   Normal 127146  68215   1614      0      0      0      0      0      0      0      1

處理的方法主要採用drop_caches(拋棄緩存),然後使用compact_memory合併低階內存頁來創造出足夠的高階內存頁。

方案1:drop_caches

Linux Kernel 2.6.16之後的內核提供了一個設置內核拋棄 頁緩存 和/或 目錄(dentry)和索引節點(inode)緩存,這樣可以釋放出大量內存。

  • 釋放頁緩存
echo 1 > /proc/sys/vm/drop_caches
  • 釋放目錄和索引節點緩存(inode and dentry cache)
echo 2 > /proc/sys/vm/drop_caches
  • 同時釋放 頁、目錄、索引節點緩存:
echo 3 > /proc/sys/vm/drop_caches

上述操作是無害的操作,並且智慧釋放完全沒有使用的內存對象。髒對象(dirty objects)將繼續被使用直到它們被寫入到磁盤中,所以內存髒對象不會被釋放。不過,如果在執行drop_caches之前執行sync指令,則會將髒對象刷新到磁盤中,這樣drop_caches操作會釋放出更多內存。

注意:drop_caches需要花費一些時間(在終端中可以看到大約幾十秒時間),此時再次使用cat /proc/buddyinfo可以看到立即出現了大量高階內存頁。

但是drop_caches這個觸發動作是一次性的,也就是說,並不因爲cat /proc/sys/vm/drop_caches時顯示輸出內容是3就表示系統不緩存內容。相反,一旦完成drop_caches,系統立即自動對後續內存對象進行緩存。所以要再次觸發緩存清理,需要再次執行 echo 3 > /proc/sys/vm/drop_caches

如果重複echo 3 > /proc/sys/vm/drop_caches不能再次釋放緩存,可以先嚐試echo 0 > /proc/sys/vm/drop_caches然後再執行echo 3 > /proc/sys/vm/drop_caches

方案2:compact_memory 內存整理

當內核編譯參數設置了CONFIG_COMPACTION,就會在/proc/sys/vm/compact_memory有入口文件。將1寫入到這個文件,則所有的zones就會進行壓縮,以便能夠儘可能地提供連續內存塊。對於需要分配大頁的時候這個功能非常重要,不過,進程會在需要時直接進行內存壓縮(compact memory)。

必要時候進行內存整理,開銷會比較大,會造成業務卡住一段時間(慎用):

echo 1 > /proc/sys/vm/compact_memory

實踐案例

  • 檢查系統缺乏高階內存
#cat /proc/buddyinfo
Node 0, zone      DMA      2      2      2      1      2      1      1      0      0      0      2
Node 0, zone    DMA32  32995   4377    762    211    157    108     68     23      3      0      0
Node 0, zone   Normal 127146  68215   1614      0      0      0      0      0      0      0      1
  • 執行緩存釋放
#echo 3 > /proc/sys/vm/drop_caches
  • 完成後檢查內存頁
#cat /proc/buddyinfo
Node 0, zone      DMA      2      2      2      1      2      1      1      0      0      0      2
Node 0, zone    DMA32  76826  65298  43784  20780   5272    616     90     32      4      0      0
Node 0, zone   Normal 524538 365499 176074  45644   4338    140      6      0      0      0      1
  • 然後執行內存壓縮
#echo 1 > /proc/sys/vm/compact_memory
  • 然後再次檢查內存頁分佈,可以看到逐漸出現更多的高階內存頁
#cat /proc/buddyinfo
Node 0, zone      DMA      2      2      2      1      2      1      1      0      0      0      2
Node 0, zone    DMA32  18217  13464   8621   4666   2654   2087   1609   1040    517    130      3
Node 0, zone   Normal 145048 131183  76864  38454  20405  11854   5149   1143     96      3      1
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章