一、問題描述
我司平臺研發(fā)的devops平臺底層采用k8s實現(xiàn),k8s自帶cadvisor進行集群指標收集,根據(jù)官網(wǎng),我們選用了container_memory_working_set_bytes
(容器的工作集使用量)作為內(nèi)存使用量的觀察項,但隨著后續(xù)使用過程中發(fā)現(xiàn)該指標上升到一定大小后就會維持不變,并不像應(yīng)用實際內(nèi)存使用量,沒出現(xiàn)波動;
來自kubernetes對該問題的討論(討論了5年多了):https://github.com/kubernetes/kubernetes/issues/43916
二、原因分析
??以下是建立在關(guān)閉swap交換分區(qū)的前提下分析
經(jīng)過一系列分析發(fā)現(xiàn)使用container_memory_working_set_bytes
不合理,應(yīng)該使用container_memory_rss
來表示應(yīng)用實際內(nèi)存使用量;
我最開始受cadvisor git問題欄中描述的影響,里面描述說:k8s kill pod時是根據(jù)該指標使用情況來判斷的,所以下意識認為該指標表示pod實際內(nèi)存使用量;官網(wǎng)說的沒有問題,container_memory_working_set_bytes
指標就是k8s來控制pod是否被kill的依據(jù)參考,但不代表container_memory_working_set_bytes
接近pod limit后就一定會被kill,這里涉及到下面要詳細分析的pod內(nèi)存分布情況;
-
獲取pod內(nèi)存記錄信息
在cadvisor中,采集應(yīng)用內(nèi)存信息具體實現(xiàn)實際是獲取docker cgroup中memory.stat
中的內(nèi)容,下面是通過cat /sys/fs/cgroup/memory/memory.stat
獲取到的pod內(nèi)存數(shù)據(jù):
cache 118784
rss 767553536
rss_huge 0
mapped_file 32768
swap 0
pgpgin 215484
pgpgout 28064
pgfault 388710
pgmajfault 0
inactive_anon 0
active_anon 767496192
inactive_file 32768
active_file 86016
unevictable 0
hierarchical_memory_limit 1073741824
hierarchical_memsw_limit 1073741824
total_cache 118784
total_rss 767553536
total_rss_huge 0
total_mapped_file 32768
total_swap 0
total_pgpgin 215484
total_pgpgout 28064
total_pgfault 388710
total_pgmajfault 0
total_inactive_anon 0
total_active_anon 767496192
total_inactive_file 32768
total_active_file 86016
total_unevictable 0
-
pod內(nèi)存記錄說明
上面獲取內(nèi)存記錄,主要關(guān)心total_cache
、total_rss
、total_inactive_anon
、total_active_anon
、total_inactive_file
、total_active_file
-
total_cache
:表示當(dāng)前pod緩存內(nèi)存量 -
total_rss
:表示當(dāng)前應(yīng)用進程實際使用內(nèi)存量 -
total_inactive_anon
:表示匿名不活躍內(nèi)存使用量 -
total_active_anon
:表示匿名活躍內(nèi)存使用量,jvm堆內(nèi)存使用量會被計算在此處
-
total_inactive_file
:表示不活躍文件內(nèi)存使用量 -
total_active_file
:表示活躍文件內(nèi)存使用量
- container_memory_working_set_bytes、container_memory_rss指標的詳細分析
?? 建議先查看最后附錄內(nèi)容,了解cadvisor中每個指標的意義,有助于幫助下面內(nèi)容理解。
- 容器當(dāng)前使用內(nèi)存量:
container_memory_usage_bytes
=total_cache
+total_rss
- 容器當(dāng)前使用緩存內(nèi)存:
total_cache
=total_inactive_file
+total_active_file
- container_memory_working_set_bytes=container_memory_usage_bytes - total_inactive_file為官方源代碼提供,帶入上面兩個公式,容器的工作集的等式可以拆解為:
container_memory_working_set_bytes
= container_memory_usage_bytes - total_inactive_file
= total_cache + total_rss - total_inactive_file
= total_inactive_file + total_active_file + total_rss - total_inactive_file
= total_active_file + total_rss
即:container_memory_working_set_bytes
= total_active_file
+ total_rss
,其中total_rss為應(yīng)用真實使用內(nèi)存量,正常情況下該指標數(shù)值穩(wěn)定,那為何該指標會持續(xù)上升而且一直維持很高呢?其實問題就出現(xiàn)在total_active_file
上;
Linux系統(tǒng)為了提高文件讀取速率,會劃分出來一部分緩存內(nèi)存,即cache內(nèi)存,這部分內(nèi)存有個特點,當(dāng)應(yīng)用需要進行io操作時,會向Linux申請一部分內(nèi)存,這部分內(nèi)存歸屬于操作系統(tǒng),當(dāng)應(yīng)用io操作完畢后,操作系統(tǒng)不會立即回收;
當(dāng)操作系統(tǒng)認為系統(tǒng)剩余內(nèi)存不足時(判斷依據(jù)未深究),才會主動回收這部分內(nèi)存。
這部分內(nèi)存屬于操作系統(tǒng),jvm無任何管理權(quán)限,故也不會把這部分內(nèi)存計算到JVM中。container_memory_working_set_bytes
指標升高一部分是應(yīng)用本身JVM內(nèi)存使用量增加,另一部分就是進行了io操作
,total_active_file
升高;該指標異常一般都是應(yīng)用進行了io相關(guān)操作。
模擬io操作
你可以在pod中創(chuàng)建一個大一點的日志文件,通過 cat 文件名 > /dev/null
將其加載到緩存內(nèi)存中,你會發(fā)現(xiàn)total_active_file升高并且不會被釋放;
刪除加載后的日志文件,模擬系統(tǒng)回收內(nèi)存操作,你會發(fā)現(xiàn)total_active_file降低;
或者執(zhí)行echo 3 > /proc/sys/vm/drop_caches
命令,前提是用戶有足夠權(quán)限文章來源:http://www.zghlxwxcb.cn/news/detail-608720.html
三、合理監(jiān)控
關(guān)心應(yīng)用使用內(nèi)存大小用container_memory_rss
;
排查pod為何被kill,關(guān)注container_memory_working_set_bytes
、total_active_file
、total_inactive_file
文章來源地址http://www.zghlxwxcb.cn/news/detail-608720.html
附錄 k8s pod container內(nèi)存指標說明
container_memory_cache表示容器使用的緩存內(nèi)存。
container_memory_mapped_file表示容器使用的映射文件內(nèi)存。
container_memory_rss表示容器的常駐內(nèi)存集(Resident Set Size),即實際使用的物理內(nèi)存量。
container_memory_swap表示容器使用的交換內(nèi)存量。
container_memory_usage_bytes表示容器當(dāng)前使用的內(nèi)存量,包括常駐內(nèi)存和緩存,**緩存部分往往會有很多處于空閑**。
container_memory_working_set_bytes表示容器的工作集,即容器當(dāng)前活躍使用的內(nèi)存量,不包括緩存。
container_memory_max_usage_bytes表示容器歷史上使用過的最大內(nèi)存量。
container_memory_failcnt表示容器內(nèi)存失敗計數(shù),即無法分配所需內(nèi)存的次數(shù)。
container_memory_failures_total表示容器內(nèi)存分配失敗的總次數(shù)。
到了這里,關(guān)于【k8s pod container內(nèi)存指標說明】的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!