1. 程式人生 > 其它 >systemd --user程序CPU佔用高問題分析

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》