systemd –user進程CPU佔用高問題分析
- 2022 年 3 月 25 日
- 筆記
- 雲計算-k8s, 服務端-Docker, 服務端-Linux
原文鏈接://www.cnblogs.com/yaohong/p/16046670.html,轉載需經同意。
1.問題由來
近期發現堡壘機環境有如下問題,systemd佔用大量cpu:
2.問題定位
2.1.什麼是systemd
咋們可以先從systemd這個進程入手分析這個問題:
根據文檔《systemd (簡體中文)》文檔,我們可知如下圖資訊:
作用:
systemd 會給每個用戶生成一個 systemd 實例,用戶可以在這個實例下管理服務,啟動、停止、啟用以及禁用他們自己的單元。
工作原理:
「從 systemd 226 版本開始,/etc/pam.d/system-login 默認配置中的 pam_systemd 模組會在用戶首次登錄的時候, 自動運行一個 systemd --user 實例。 只要用戶還有會話存在,這個進程就不會退出;用戶所有會話退出時,進程將會被銷毀。」。
根據上面這段話,我們可以猜測:ssh登錄時可以創建systemd進程,ssh退出登錄時可以銷毀systemd –user進程。
懷著這個猜測,我們進行下面的研究分析。
2.2.systemd進程怎麼產生的
首先,我們在第一個終端,執行下面的命令創建test3用戶:
$ groupadd test3 $ useradd -g test3 -m -d /home/test3 -s /bin/bash test3 $ passwd test3
然後,在第二個終端,執行ssh登錄test3
$ ssh [email protected]
接著,在第一個終端,執行如下命令過濾新產生的test3 用戶的systemd進程
$ top -bc |grep systemd
得到如下圖回顯,可知:1.9秒前產生了一個pid為19178的systemd --user進程,此進程佔用了40.9%的CPU。
於是對接systemd進程創建得出如下結論:
systemd版本大於226(centos7為219、ubuntu1604為229),ssh 登錄會產生登錄用戶對應的systemd進程。
2.3.systemd進程為何沒有被銷毀
既然ssh登錄會產生systemd進程,那退出ssh登錄應該會銷毀對應systemd進程。
於是,我們在2.2中的第二個窗口執行 exit
退出ssh連接。
$ exit
然後,再執行如下命令,發現沒有test3用戶的systemd進程了。
$ top -bc | grep systemd
至此,我們對systemd進程的退出也有了了解:退出ssh連接即可銷毀對應systemd進程
。
但,為什麼我們看到的騰訊雲環境上systemd進程一直沒有被銷毀?
此時我想到了 非正常退出ssh連接
,
如2.1章節,在第二個終端,執行ssh登錄test3,再如下圖直接點「X」
直接關閉窗口,
然後,在第一個終端,執行如下命令過濾新產生的test3 用戶的systemd進程
$ top -bc |grep systemd
test3用戶的systemd進程還存在,驚訝!!!
於是分別做如下操作對systemd進程關閉做測試,並得出相應結論:
- 1.xshell連內部vmware上虛擬機環境,點「X」號關閉窗口,對應systemd進程正常銷毀;
- 2.web端連公司堡壘機上的雲主機環境,點「X」號關閉窗口,對應systemd進程不能被銷毀;
- 3.web端通過部門內部運維平台連接內部虛擬機環境,點「X」號關閉窗口,對應systemd進程不能被銷毀;
於是對於systemd進程銷毀得出如下結論:
web端連接的虛擬機終端,直接點「X」號關閉窗口,登錄用戶對應的systemd進程都不能被銷毀,exit命令退出終端登錄可以銷毀,Xshell無此問題。
2.4.systemd進程吃CPU的原因
關於進程跟蹤我們很容易想到strace命令。
我們對2.1章節中創建的test3的systemd進程進行跟蹤。
得到如下回顯:
看這個進程是在不停的掃描磁碟。
關於這個問題,我在《google-cloud-kuberbetes-run-away-systemd-100-cpu-usage》一文中得到答案:
Docker在17.03和18.09版本之間的變化導致了大量的systemd活動,無論在pod中執行了什麼。同時,只要runc發生change,它導致所有mount units被重新載入,作為執行存活探針的一部分。
於是針對這個猜想,我看了下k8s同一集群中systemd正常與異常的節點:
1.正常節點:
# cat /proc/mounts |wc 120 720 46377
2.異常節點:
# cat /proc/mounts |wc 1017 6102 341121
於是瞬間也有了結論:
systemd 進程cpu使用率太高是因為mount掛載點太多,mount有更新後,通過dbus通知到systemd重新遍歷所有mount, 遍歷操作比較耗cpu。
同時,既然說到和docker版本有關係,我便針對性找了兩個有差異的環境做docker版本對不:
- 1.ubuntu1604+mount掛載多+systemd正常環境
- 2.ubuntu1604+mount掛載多+systemd異常環境
由上圖我們發行,環境1中mount掛載為1537個,比環境2中mount掛載為1028個更高但是沒出現systemd吃cpu問題,可知系統相同情況下和docker版本有關。
對於什麼情況下出現systemd佔用高,我們得出如下結論:
systemd版本大於226(ubuntu1604為229)+docker版本為19.03.14,無論runc做了什麼操作,dbus會通知systemd重新遍歷 mount,遍歷mout過多(cat /proc/mounts |wc命令查看)會導致systemd進程吃CPU。
三、解決方案
1.不使用web終端連接systemd版本大於226,docker>=19.03.14的環境,可以使用比如xshell連接。
2.針對runc活動導致systemd進程吃CPU問題,google GKE 團隊給出如下優化方案:
原文鏈接://www.cnblogs.com/yaohong/p/16046670.html
四、總結
1.systemd進程如何被創建:systemd版本大於226(centos7為219、ubuntu1604為229),ssh 登錄會產生登錄用戶對應的systemd –user進程。
2.systemd進程為何未被銷毀:web端連接的虛擬機終端,直接點「X」號關閉窗口,登錄用戶對應的systemd進程都不能被銷毀,exit命令退出終端登錄可以銷毀,Xshell無此問題。
3.systemd進程為何吃cpu:systemd版本大於226(ubuntu1604為229)+docker版本為19.03.14,無論runc做了什麼操作,dbus會通知systemd重新遍歷 mount,如果遍歷mount過多(cat /proc/mounts |wc命令查看,700個會吃30%CPU,1000個會吃50%左右CPU)就會導致systemd進程吃CPU。
原文鏈接://www.cnblogs.com/yaohong/p/16046670.html
五、參考文檔
《systemd (簡體中文)》
《google-cloud-kuberbetes-run-away-systemd-100-cpu-usage》
《 原文鏈接://www.cnblogs.com/yaohong/p/16046670.html》