systemd --user進程CPU佔用高問題分析

原文鏈接:https://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

接着,在第一個終端,執行如下命令過濾新產生的test3 用戶的systemd進程

$ top -bc |grep systemd

得到如下圖回顯,可知:1.9秒前產生了一個pid爲19178的systemd --user進程,此進程佔用了40.9%的CPU。

image.png

於是對接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進程進行跟蹤。

image.png

得到如下回顯:

 看這個進程是在不停的掃描磁盤。

關於這個問題,我在《google-cloud-kuberbetes-run-away-systemd-100-cpu-usage》一文中得到答案:

image.png

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 團隊給出如下優化方案:

image.png

 原文鏈接: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》

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章