2021-05-12 14:32:11
CentOS 7 之systemd管理
CentOS系統啟動流程:
POST --> Boot Sequence --> Bootloader --> kernel + initramfs(initrd) --> rootfs --> /sbin/init
innit程式:
CentOS 5:SysV init
CetnOS 6: Upstart
CentOS 7 : Systemd
Systemd新特性:
系統Sys V init和LSB init scripts相容
系統引導時實現服務並行啟動;採用socket / D-Bus activation等技術啟動服務;為了減少系統啟動時間,systemd的目標是:盡可能啟動更少的進程;盡可能將更多的進程並行啟動;
按需啟用進程;Systemd可以提供按需啟動的能力,只有在某個服務被真正請求的時候才啟動它。當該服務結束,systemd可以關閉它,等待下次需要時再次啟動它。
能夠對系統進行快照和恢復;
啟動掛載點和自動掛載點的管理:
Systemd自助管理系統上的掛載點,以便能夠在系統啟動時自動掛載它們。且相容/etc/fstab檔案;
實現事務依賴關係管理:
systemd 維護一個"事務一致性"的概念,保證所有相關的服務都可以正常啟動而不會出現互相依賴,以至於死鎖的情況。
基於內生依賴關係定義服務控制邏輯;
system利用Linux核心的特性即CGroup來完成進程跟蹤的任務。當停止服務時,通過查詢CGroup,systemd可以確保找到所有的相關進程,從而乾淨地停止服務;
紀錄檔服務:systemd自帶紀錄檔服務journald,該紀錄檔服務的設計初衷是克服現有的syslog服務的缺點。
System的基本概念
單元的概念:
系統初始化需要做的事情非常多。需要啟動後台服務,比如啟動 SSHD 服務;需要做設定工作,比如掛載檔案系統。這個過程中的每一步都被 systemd 抽象為一個設定單元,即 unit。可以認為一個服務是一個設定單元;一個掛載點是一個設定單元;一個交換分割區的設定是一個設定單元;等等。systemd 將設定單元歸納為以下一些不同的型別。然而,systemd 正在快速發展,新功能不斷增加。所以設定單元型別可能在不久的將來繼續增加。
•service:代表一個後台服務進程,比如MySQLd。這是常用的一類;
•socket:此類設定單元封裝系統和網際網路中的一個通訊端。當下,systemd支援流式、封包和連續包的AF_INET、AF_INET6、AF_UNIX socket。每一個通訊端設定單元都有一個相應的服務設定單元 。相應的服務在第一個"連線"進入通訊端時就會啟動(例如:nscd.socket 在有新連線後便啟動 nscd.service)。
•device :此類設定單元封裝一個存在於 Linux 裝置樹中的裝置。每一個使用 udev 規則標記的裝置都將會在 systemd 中作為一個裝置設定單元出現。
•mount :此類設定單元封裝檔案系統結構層次中的一個掛載點。Systemd 將對這個掛載點進行監控和管理。比如可以在啟動時自動將其掛載;可以在某些條件下自動解除安裝。Systemd 會將/etc/fstab 中的條目都轉換為掛載點,並在開機時處理。
•automount :此類設定單元封裝系統結構層次中的一個自掛載點。每一個自掛載設定單元對應一個掛載設定單元 ,當該自動掛載點被存取時,systemd 執行掛載點中定義的掛載行為。
•swap: 和掛載設定單元類似,交換設定單元用來管理交換分割區。使用者可以用交換設定單元來定義系統中的交換分割區,可以讓這些交換分割區在啟動時被啟用。
•target :此類設定單元為其他設定單元進行邏輯分組。它們本身實際上並不做什麼,只是參照其他設定單元而已。這樣便可以對設定單元做一個統一的控制。這樣就可以實現大家都已經非常熟悉的執行級別概念。比如想讓系統進入圖形化模式,需要執行許多服務和設定命令,這些操作都由一個個的設定單元表示,將所有這些設定單元組合為一個目標(target),就表示需要將這些設定單元全部執行一遍以便進入目標所代表的系統執行狀態。 (例如:multi-user.target 相當於在傳統使用 SysV 的系統中執行級別 3)
•timer:定時器設定單元用來定時觸發使用者定義的操作,這類設定單元取代了 atd、crond 等傳統的定時服務。
•snapshot :與 target 設定單元相似,快照是一組設定單元。它儲存了系統當前的執行狀態。
依賴關係:
雖然 systemd 將大量的啟動工作解除了依賴,使得它們可以並行啟動。但還是存在有些任務,它們之間存在天生的依賴,不能用"通訊端啟用"(socket activation)、D-Bus activation 和 autofs 三大方法來解除依賴(三大方法詳情見後續描述)。比如:掛載必須等待掛載點在檔案系統中被建立;掛載也必須等待相應的物理裝置就緒。為了解決這類依賴問題,systemd 的設定單元之間可以彼此定義依賴關係。
Systemd 用設定單元定義檔案中的關鍵字來描述設定單元之間的依賴關係。比如:unit A 依賴 unit B,可以在 unit B 的定義中用"require A"來表示。這樣 systemd 就會保證先啟動 A 再啟動 B。
Systemd事務:
Systemd 能保證事務完整性。Systemd 的事務概念和資料庫中的有所不同,主要是為了保證多個依賴的設定單元之間沒有環形參照。 存在迴圈依賴,那麼 systemd 將無法啟動任意一個服務。此時systemd 將會嘗試解決這個問題,因為設定單元之間的依賴關係有兩種:required是強依賴;want 則是弱依賴,systemd 將去掉 wants 關鍵字指定的依賴看看是否能打破迴圈。如果無法修復,systemd會報錯。
Systemd 能夠自動檢測和修復這類設定錯誤,極大地減輕了管理員的排錯負擔。
Target和執行級別:
systemd 用目標(target)替代了執行級別的概念,提供了更大的靈活性,如您可以繼承一個已有的目標,並新增其它服務,來建立自己的目標。下表列舉了 systemd 下的目標和常見 runlevel 的對應關係:
CentOS7/RHEL7 systemd詳解 http://www.linuxidc.com/Linux/2015-04/115937.htm
為什麼systemd會被如此迅速的採用? http://www.linuxidc.com/Linux/2014-08/105789.htm
systemd 與 sysVinit 彩版對照表 http://www.linuxidc.com/Linux/2014-09/106455.htm
太有用了!用systemd命令來管理Linux系統! http://www.linuxidc.com/Linux/2014-09/106490.htm
淺析 Linux 初始化 init 系統,第 3 部分: Systemd http://www.linuxidc.com/Linux/2014-12/110383.htm
Systemd 的並行啟動原理
如前所述,在 Systemd 中,所有的服務都併行啟動,比如Avahi、D-Bus、livirtd、X11、HAL 可以同時啟動。乍一看,這似乎有點兒問題,比如 Avahi 需要syslog 的服務,Avahi 和syslog 同時啟動,假設 Avahi 的啟動比較快,所以syslog 還沒有準備好,可是 Avahi 又需要記錄紀錄檔,這豈不是會出現問題?
Systemd 的開發人員仔細研究了服務之間相互依賴的本質問題,發現所謂依賴可以分為三個具體的型別,而每一個型別實際上都可以通過相應的技術解除依賴關係。
•並行啟動原理之一:解決 socket 依賴
絕大多數的服務依賴是通訊端依賴。比如服務A 通過一個通訊端埠S1 提供自己的服務,其他的服務如果需要服務A,則需要連線S1。因此如果服務A 尚未啟動,S1就不存在,其他的服務就會得到啟動錯誤。所以傳統地,人們需要先啟動服務A,等待它進入就緒狀態,再啟動其他需要它的服務。Systemd認為,只要我們預先把S1 建立好,那麼其他所有的服務就可以同時啟動而無需等待服務A 來建立S1 了。如果服務A 尚未啟動,那麼其他進程向S1 傳送的服務請求實際上會被Linux 作業系統快取,其他進程會在這個請求的地方等待。一旦服務A 啟動就緒,就可以立即處理快取的請求,一切都開始正常執行。
那麼服務如何使用由 init 進程建立的通訊端呢?
Linux 作業系統有一個特性,當進程呼叫fork 或者exec 建立子進程之後,所有在父進程中被開啟的檔案控制代碼(file descriptor) 都被子進程所繼承。通訊端也是一種檔案控制代碼,進程A 可以建立一個通訊端,此後當進程A 呼叫 exec 啟動一個新的子進程時,只要確保該通訊端的close_on_exec 標誌位被清空,那麼新的子進程就可以繼承這個通訊端。子進程看到的通訊端和父進程建立的通訊端是同一個系統通訊端,就彷佛這個通訊端是子進程自己建立的一樣,沒有任何區別。
這個特性以前被一個叫做 inetd 的系統服務所利用。Inetd 進程會負責監控一些常用通訊端埠,比如Telnet,當該埠有連線請求時,inetd才啟動 telnetd 進程,並把有連線的通訊端傳遞給新的telnetd 進程進行處理。這樣,當系統沒有telnet 用戶端連線時,就不需要啟動telnetd 進程。Inetd可以代理很多的網路服務,這樣就可以節約很多的系統負載和記憶體資源,只有當有真正的連線請求時才啟動相應服務,並把通訊端傳遞給相應的服務進程。
和 inetd 類似,systemd 是所有其他進程的父進程,它可以先建立所有需要的通訊端,然後在呼叫exec 的時候將該通訊端傳遞給新的服務進程,而新進程直接使用該通訊端進行服務即可。
•並行啟動原理之二:解決 D-Bus 依賴
D-Bus 是 desktop-bus 的簡稱,是一個低延遲、低開銷、高可用性的進程間通訊機制。它越來越多地用於應用程式之間通訊,也用於應用程式和作業系統核心之間的通訊。很多現代的服務進程都使用D-Bus取代通訊端作為進程間通訊機制,對外提供服務。比如簡化Linux 網路設定的NetworkManager 服務就使用D-Bus 和其他的應用程式或者服務進行互動:郵件用戶端軟體evolution 可以通過D-Bus 從NetworkManager 服務獲取網路狀態的改變,以便做出相應的處理。
D-Bus 支援所謂"busactivation"功能。如果服務A 需要使用服務 B 的 D-Bus 服務,而服務 B 並沒有執行,則 D-Bus 可以在服務 A 請求服務 B 的 D-Bus 時自動啟動服務 B。而服務 A 發出的請求會被 D-Bus 快取,服務 A 會等待服務 B 啟動就緒。利用這個特性,依賴D-Bus 的服務就可以實現並行啟動。
•並行啟動原理之三??解決檔案系統依賴
系統啟動過程中,檔案系統相關的活動是最耗時的,比如掛載檔案系統,對檔案系統進行磁碟檢查(fsck),磁碟配額檢查等都是非常耗時的操作。在等待這些工作完成的同時,系統處於空閒狀態。那些想使用檔案系統的服務似乎必須等待檔案系統初始化完成才可以啟動。但是systemd 發現這種依賴也是可以避免的。
Systemd 參考了 autofs 的設計思路,使得依賴檔案系統的服務和檔案系統本身初始化兩者可以並行工作。autofs可以監測到某個檔案系統掛載點真正被存取到的時候才觸發掛載操作,這是通過核心automounter 模組的支援而實現的。比如一個open()系統呼叫作用在"/misc/cd/file1"的時候,/misc/cd 尚未執行掛載操作,此時 open()呼叫被掛起等待,Linux 核心通知 autofs,autofs 執行掛載。這時候,控制權返回給open()系統呼叫,並正常開啟檔案。
Systemd 整合了 autofs 的實現,對於系統中的掛載點,比如/home,當系統啟動的時候,systemd 為其建立一個臨時的自動掛載點。在這個時刻/home真正的掛載裝置尚未啟動好,真正的掛載操作還沒有執行,檔案系統檢測也還沒有完成。可是那些依賴該目錄的進程已經可以並行啟動,他們的open()操作被內建在systemd 中的autofs 捕獲,將該open()呼叫掛起(可中斷睡眠狀態)。然後等待真正的掛載操作完成,檔案系統檢測也完成後,systemd將該自動掛載點替換為真正的掛載點,並讓open()呼叫返回。由此,實現了那些依賴於檔案系統的服務和檔案系統本身同時並行啟動。
當然對於"/"根目錄的依賴實際上一定還是要序列執行,因為systemd 自己也存放在/之下,必須等待系統根目錄掛載檢查好。
不過對於類似/home 等掛載點,這種並行可以提高系統的啟動速度,尤其是當/home是遠端的 NFS 節點,或者是加密盤等,需要耗費較長的時間才可以準備就緒的情況下,因為並行啟動,這段時間內,系統並不是完全無事可做,而是可以利用這段空餘時間做更多的啟動進程的事情,總的來說就縮短了系統啟動時間。
更多詳情見請繼續閱讀下一頁的精彩內容: http://www.linuxidc.com/Linux/2015-09/122973p2.htm
相關文章