systemd --user程序CPU佔用高問題分析
1.問題由來
近期發現堡壘機環境有如下問題,systemd佔用大量cpu:
原文連結:https://www.cnblogs.com/yaohong/p/16046670.html
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 團隊給出如下優化方案:
原文連結:https://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。
原文連結:https://www.cnblogs.com/yaohong/p/16046670.html
五、參考文件
《systemd (簡體中文)》
《google-cloud-kuberbetes-run-away-systemd-100-cpu-usage》
《 原文連結:https://www.cnblogs.com/yaohong/p/16046670.html》