譯者 | 劉濤
審校 | 重樓
以 Kubernetes、Nomad為代表的任何云托管的服務平臺(PaaS)提供了多種強大的功能。從擴展工作負載到保密管理再到部署策略,這些工作負載編排器已經(jīng)被優(yōu)化,以便以不同的方式對基礎結構進行擴展。
但是,運營者總是需要為最大化可擴展性付出代價嗎?有時,復雜性和抽象性的成本會超過它所帶來的益處。許多構建者更傾向于部署更簡單的架構,以便更容易管理。與跨容器主機集群的大規(guī)模微服務器集群相比,負載均衡器后面的兩臺虛擬專用服務器由一個大大簡化的堆棧來管理。當系統(tǒng)出現(xiàn)問題需要調(diào)試,或者需要維護升級時,組件越少,移動的部件越少,越容易管理,就可以更快產(chǎn)生回報。
許多現(xiàn)代Linux發(fā)行版的基礎是systemd(一個Linux系統(tǒng)的基本構建塊套件),systemd擁有一系列可以和容器編排器或 PaaS系統(tǒng)相媲美的強大功能。在本文中,我們將探討如何利用最新的systemd功能,以獲得類似于其他大型系統(tǒng)的許多能力,同時避免管理上的麻煩,并將任何普通的Linux服務器升級為一個非常強大的應用平臺。
Systemd入門知識
在單個主機上,編寫systemd.service文件是運行托管進程的理想方式。大多數(shù)時候,您甚至根本不需要更改應用程序:systemd支持各種不同類型的服務,并且可以相應地進行調(diào)整。
例如,考慮這個定義如何運行簡單Web服務的簡單.service:
請記住systemd服務的默認配置:
ExecStart= 必須是絕對路徑進程不應該派生到后臺運行,您可能需要用Envirnotallow=選項設置必要的環(huán)境變量。
當放入像/etc/systemd/system/webapp.service這樣的文件中時,這將創(chuàng)建一個可以用systemctl控制的服務:
- systemctl start webapp 將啟動該進程。
- systemctl status webapp 將顯示服務是否正在運行、運行時間、以及來自stderr和stdout的輸出,以及進程ID和其他信息。
- systemctl stop webapp 將結束該服務。
此外,所有打印到stderr和stdout的輸出將由journald(Linux系統(tǒng)中日志管理的一個系統(tǒng)守護進程)聚合并可通過系統(tǒng)日志(用journalctl)訪問,或具體使用--unit標志來進行目標定位:
因為journald默認會進行日志輪轉和存儲管理,通過journal收集日志是管理日志存儲的一個不錯的策略。
本文的其余部分將探討增強類似于此服務的選項。
保密信息
像Kubernetes這樣的容器編排器支持安全地注入保密信息:從安全數(shù)據(jù)存儲中提取值并公開給運行的工作負載。一些敏感數(shù)據(jù),比如API密鑰或口令,需要不同于環(huán)境變量或配置文件的處理方式,以避免無意暴露。
systemd的LoadCredential=選項支持從磁盤上的文件加載敏感值,并以安全的方式公開給運行的服務。像托管平臺遠程管理保密信息一樣,systemd將以不同于環(huán)境變量等值的方式處理這些敏感憑證,以確保它們的安全。
要向systemd服務注入保密信息,首先將包含保密值的文件放在文件系統(tǒng)上的路徑中。例如,要向.service單元公開API密鑰,可在/etc/credstore/api-key創(chuàng)建一個文件,并在重啟后永久保存該文件,或在/run/credstore/api-key創(chuàng)建一個文件,以避免永久保存該文件(路徑可以是任意的,但systemd會將這些credstore路徑視為默認值)。在任何一種情況下,您都應該使用諸如chmod 400 /etc/credstore/api-key之類的命令設置權限。
在.service文件的[Service]部分下,定義LoadCredential=選項,并傳遞兩個用冒號(:)分隔的值:憑證的名稱和路徑。例如,要調(diào)用/etc/credstore/api-key文件“令牌”,定義以下systemd服務選項:
當systemd啟動服務時,保密信息將在以下形式的路徑下公開給正在運行的服務${CREDENTIALS_DIRECTORY}/token,其中${CREDENTIALS_DIRECTORY}是由systemd填充的環(huán)境變量。您的應用程序代碼能夠讀取以這種方式定義的每個保密信息,以便在需要API令牌或密碼等安全值的庫或代碼中使用。例如,在Python中,您可以使用如下代碼讀取此保密信息:
然后,對于任何可能需要API令牌或密碼的庫,您可以將secret變量與保密信息的內(nèi)容一起使用。
重啟
像Nomad這樣的編排器還有一個功能,就是能自動重啟崩潰的工作負載。無論是由于未處理的應用程序錯誤還是其他原因,重新啟動失敗的應用程序都是非常有用的功能,它往往是設計一個有彈性的應用程序的首要防線。
Restart=systemd選項用來控制systemd是否會自動重啟正在運行的進程。此選項有幾個潛在的值,但對于基本服務,on-failure設置非常適合滿足大多數(shù)用例。
另一個需要考慮的設置是RestartSec=選項,它決定systemd重新啟動服務之前等待的時間。通常情況下,您應該自定義這個值以避免在緊密循環(huán)中再次出現(xiàn)服務失敗,并可能消耗過多的CPU時間在進程重啟上。像5秒這樣不會等太久的時間通常就足夠了。
最后,另外兩個選項決定了systemd在最終放棄之前會多么積極地嘗試重新啟動失敗的單元。StartLimitIntervalSec=和StartLimitBurst=將控制一個單元在給定時間段內(nèi)被允許啟動的次數(shù)。例如,以下設置:
它只允許一個單元在10秒內(nèi)嘗試啟動的次數(shù)最多為5次。如果配置的服務在10秒內(nèi)嘗試第6次啟動,systemd將停止嘗試重啟該單元并將其標記為failed。
結合所有這些設置,您可以為.service單元設置以下選項來配置自動重啟:
如果服務失?。匆馔馔顺?,例如使用了非0退出代碼),此配置將在等待一秒后重新啟動服務,如果在10秒內(nèi)嘗試啟動的服務超過了5次,則嘗試重新啟動服務將會終止。
強化服務
在容器中運行的主要好處之一是安全沙盒。通過將應用程序進程與底層操作系統(tǒng)分開,任何可能出現(xiàn)在服務中的漏洞都更難進化成全面的威脅。例如Docker(一種容器)運行時,通過cgroup和其他安全原語(security primitives)的組合來實現(xiàn)這一點。
您可以啟用多個systemd選項來強加類似的限制,這些限制有助于保護底層主機免受不可預測的工作負載行為的影響:
- ProtectSystem=可以限制對/boot和/usr等敏感系統(tǒng)路徑的寫入訪問。此選項的文檔枚舉了所有可用選項,但一般來說,將此選項設置為full是保護這些文件系統(tǒng)路徑的合理默認值。
- ProtectHome=可以將/home、/root和/run/user目錄設置為只讀read-only設置,或者當設置為true時,將它們作為空目錄載入到服務的文件系統(tǒng)中。除非您的應用程序特別需要訪問這些目錄,否則將其設置為true可以安全強化系統(tǒng)以防止對這些目錄的非法訪問。
- PrivateTmp=為配置的服務維護單獨的/tmp和/var/tmp,以便該服務和其他進程的臨時文件被保存為私有文件。除非進程有令人信服的理由通過臨時文件共享信息,那么這個選項就很有用了。
- NoNewPrivileges=是另一種安全和直接的方法 ,通過確保執(zhí)行的進程不需要提升其權限就可以強化服務。如果您不確定是否能夠使用其他強化選項,那么這種方法通常是使用問題最少的選項之一。
system.exec的操作手冊是一個有用的資源,可以為諸如服務等可執(zhí)行的工作負載提供不同的選項。
延伸閱讀
system的操作手冊內(nèi)容豐富,也非常實用。您可以了解所有可用于運行您自己應用程序的選項。無論您是運行諸如 webserver之類的持久服務,還是定期運行.timer單元來替換cron任務(Linux系統(tǒng)上的一個任務調(diào)度器),systemd文檔都可以提供有用的指導。
譯者介紹
劉濤,51CTO社區(qū)編輯,某大型央企系統(tǒng)上線檢測管控負責人。
原文標題:Micro-DevOps With Systemd: Supercharge Any Ordinary Linux Server,作者:Tyler