Libral:一個提供資源和服務統一管理 API 的系統管理庫
作為繼承了 Unix 的傳統的 Linux 操作系統,其並沒有一個綜合的系統管理 API 介面,相反,管理操作是通過多種特定用途的工具和 API 來實現的,其每一個都有自己約定和特有的風格。這就使得編寫一個哪怕是簡單的系統管理任務的腳本也很困難、很脆弱。
舉個例子來說,改變 「app」 用戶的登錄 shell 要運行 usermod -s /sbin/nologin app
。這個命令通常沒有問題,只是當系統上沒有 「app」 用戶時就不行了。為了解決這個例外錯誤,具有創新精神的腳本編寫者也許要這樣寫:
grep -q app /etc/passwd
&& usermod -s /sbin/nologin app
|| useradd ... -s /sbin/nologin app
這樣,當 「app」 用戶存在於系統中時,會執行更改登錄 shell 的操作;而當此用戶不存在時,就會創建此用戶。不幸的是,這種編寫系統管理任務腳本的方式是不適合的:對於每一種資源來說都會有一套不同的工具,而且每個都有其不同的使用慣例;不一致性和經常出現的不完備的錯誤報告將會使錯誤的處理變得困難;再者也會因為工具自身的特性引發的故障而導致執行失敗。
實際上,以上所舉的例子也是不正確的:grep
並不是用來查找 「app」 用戶的,它只能在文件 /etc/passwd
的一些行中簡單的查找是否有字元串 「app」,在大多數情況下它或許可以工作,但是也可能會在最關鍵的時刻出錯。
很顯然,那些執行簡單任務的腳本管理工具,很難成為大型管理系統的基礎。認識到這一點,現有的配置管理系統,比如 Puppet、Chef 及 Ansible,圍繞基本的操作系統資源的管理竭盡全力的建立其內部 API 就是明智之舉。這些資源抽象是內部 API,其與所需的相應工具密切相關。但這不僅導致大量的重複性工作,也為嘗試一個新創新的管理工具設置了強大的障礙。
在創建虛擬機或者容器鏡像這一領域,這種障礙就變得非常明顯:比如在創建鏡像的過程中,就要麼需要回答關於它們的簡單問題,要麼需要對其進行簡單的更改才行。但是工具全都需要特別處理,那些所遇到的問題和更改需要用腳本逐個處理。因此,鏡像構建要麼依靠特定的腳本,要麼需要使用(和安裝)一個相當強大的配置管理系統。
Libral 將為管理工具和任務提供一個可靠的保證,通過對系統資源提供一個公用的管理 API,並使其可以通過命令行工具 ralsh
使用,它允許用戶按照相同的方法查詢和修改系統資源,並有可預見的錯誤報告。對以上的舉例來說,可以通過命令 ralsh -aq user app
檢查 「app」 用戶是否存在;通過 ralsh -aq package foo
檢查 「foo」 軟體包是否已經安裝;一般情況下,可以通過命令 ralsh -aq TYPE NAME
檢查 」NAME「 是否是 」TYPE「 類型的資源。類似的,要創建或更改已存在的用戶,可以運行:
ralsh user app home=/srv/app shell=/sbin/nologin
以及,要在文件 /etc/hosts
創建和修改條目,可以運行命令:
ralsh hostmyhost.example.com ip=10.0.0.1
host_aliases=myhost,apphost
以這種方式運行,「ralsh」 的使用者事實上完全隔離在那兩個命令內部的不同運行工作機制之外:第一個命令需要適當的調用命令 useradd
或者 usermod
,而第二個需要在 /etc/hosts
文件中進行編輯。而對於該用戶來說,他們似乎都採取同樣的模型:「確保資源處於我所需要的狀態。」
怎樣獲取和使用 Libral 呢?
Libral 可以在這個 git 倉庫找到並下載。其核心是由 C++ 編寫的,構建它的說明可以在該倉庫中找到,不過只是在你想要為 Libral 的 C++ 核心做貢獻的時候才需要看它。Libral 的網站上包含了一個 預構建的 tarball,可以用在任何使用 「glibc 2.12」 或者更高版本的 Linux 機器上。可以使用該 「tarball」 的內容進一步探究 ralsh ,以及開發新的提供者(provider),它使得 Libral 具備了管理新類型資源的能力。
在下載解壓 tarball 後,在目錄 ral/bin
下能找到 ralsh
命令。運行不需要任何參數的 ralsh
命令就會列舉出來 Libral 的所有資源類型。利用 --help
選項可以列印輸出關於 ralsh
的更多說明。
與配置管理系統的關係
知名的配置管理系統,如 Puppet、Chef 及 Ansible,解決了一些 Libral 所解決的同樣的問題。將 Libral 與它們的區分開的主要是它們所做工作和 Libral 不同。配置管理系統被構建來處理跨大量節點管理各種事物的多樣性和複雜性。而另一方面 Libral 旨在提供一個定義明確的低級別的系統管理 API ,獨立於任何特定的工具,可用於各種各樣的編程語言。
通過消除大型配置管理系統中包含的應用程序邏輯,Libral 從前面介紹里提及的簡單的腳本任務,到作為構建複雜的管理應用的構建塊,它在如何使用方面是非常靈活的。專註與這些基礎層面也使其保持很小,目前不到 2.5 MB,這對於資源嚴重受限的環境,如容器和小型設備來說是一個重要考慮因素。
Libral API
在過去的十年里,Libral API 是在實現配置管理系統的經驗下指導設計的,雖然它並沒有直接綁定到它們其中任何一個應用上,但它考慮到了這些問題,並規避了它們的缺點。
在 API 設計中四個重要的原則:
- 期望的狀態
- 雙向性
- 輕量級抽象
- 易於擴展
基於期望狀態的管理 API,舉個例子來說,用戶表示當操作執行後希望系統看起來是什麼狀態,而不是怎樣進入這個狀態,這一點什麼爭議。雙向性使得使用(讀、寫)相同的 API 成為可能,更重要的是,相同的資源可以抽象成讀取現有狀態和強制修改成這種狀態。輕量級抽象行為確保能容易的學習 API 並能快速的使用;過去在管理 API 上的嘗試過度加重了學習建模框架的使用者的負擔,其中一個重要的因素是他們的接受力缺乏。
最後,它必須易於擴展 Libral 的管理功能,這樣用戶可以教給 Libral 如何管理新類型的資源。這很重要,因為人們也許要管理的資源可能很多(而且 Libral 需要在適當時間進行管理),再者,因為即使是完全成熟的 Libral 也總是存在達不到用戶自定義的管理需求。
目前與 Libral API 進行交互的主要方式是通過 ralsh
命令行工具。它也提供了底層的 C++ API ,不過其仍處在不斷的演變當中,主要的還是為簡單的腳本任務做準備。該項目也提供了為 CRuby 提供語言綁定,其它語言也在陸續跟進。
未來 Libral 還將提供一個提供遠程 API 的守護進程,它可以做為管理系統的基礎服務,而不需要在管理節點上安裝額外的代理。這一點,加上對 Libral 管理功能的定製能力,可以嚴格控制系統的哪些方面可以管理,哪些方面要避免干擾。
舉個例子來說,一個僅限於管理用戶和服務的 Libral 配置會避免干擾到在節點上安裝的包。當前任何現有的配置管理系統都不可能控制以這種方式管理的內容;尤其是,需要對受控節點進行任意的 SSH 訪問也會將該系統暴露不必要的意外和惡意干擾。
Libral API 的基礎是由兩個非常簡單的操作構成的:「get」 用來檢索當前資源的狀態,「set」 用來設置當前資源的狀態。理想化地實現是這樣的,通過以下步驟:
provider.get(names) -> List[resource]
provider.set(List[update]) -> List[change]
「provider」 是要知道怎樣管理的一種資源的對象,就像用戶、服務、軟體包等等,Libral API 提供了一種查找特定資源的 管理器 的方法。
「get」 操作能夠接收資源名稱列表(如用戶名),然後產生一個資源列表,其本質來說是利用散列的方式列出每種資源的屬性。這個列表必須包含所提供名稱的資源,但是可以包含更多內容,因此一個簡單的 「get」 的實現可以忽略名稱並列出所有它知道的資源。
「set」 操作被用來設置所要求的狀態,並接受一個更新列表。每個更新可以包含 「update.is」,其表示當前狀態的資源,「update.should」 表示被資源所期望的狀態。調用 「set」 方法將會讓更新列表中所提到的資源成為 「update.should」 中指示的狀態,並列出對每個資源所做的更改。
在 ralsh
下,利用 ralsh user root
能夠重新獲得 「root」 用戶的當前狀態;默認情況下,這個命令會產生一個用戶可讀的輸出,就像 Puppet 中一樣,但是 ralsh
支持 --json
選項,可以生成腳本可以使用的 JSON 輸出。用戶可讀的輸出是:
# ralsh user root
user::useradd { 'root':
ensure => 'present',
comment => 'root',
gid => '0',
groups => ['root'],
home => '/root',
shell => '/bin/bash',
uid => '0',
}
類似的,用戶也可以用下面的形式修改:
# ralsh user root comment='The superuser'
user::useradd { 'root':
ensure => 'present',
comment => 'The superuser',
gid => '0',
groups => ['root'],
home => '/root',
shell => '/bin/bash',
uid => '0',
}
comment(root->The superuser)
ralsh
的輸出列出了 「root」 用戶的新狀態和被改變的 comment
屬性,以及修改了什麼內容(在這種情形下單指 comment
屬性)。下一秒運行相同的命令將產生同樣的輸出,但是不會提示修改,因為沒有需要修改的內容。
編寫 管理器
為 ralsh
編寫新的管理器(provider) 是很容易的,也花費不了多少工夫,但是這一步驟是至關重要的。正因為如此,ralsh
提供了大量的調用約定,使得可以根據管理器所能提供的能力而調整其實現複雜性成為可能。管理器可以使用遵循特定調用約定的外部腳本,也可以以 C++ 實現並內置到 Libral 裡面。到目前為止,有三種調用約定:
- simple 調用約定是編寫 shell 腳本用為管理器。
- JSON 調用約定意味著可以利用 Ruby 或者 Python 腳本語言編寫管理器。
- [內部 C++ API8 可以被用來實現原生的管理器。
強烈建議使用 「simple」 或者 「JSON」 調用約定開始開發管理器。GitHub 上的 simple.prov 文件包含了一個簡單的 shell 管理器框架,應該很容易的替換為你自己的管理器。python.prov 文件包含了利用 Python編寫的 JSON 管理器框架。
利用高級腳本語言編寫的管理器存在一個問題是,對於這些語言,在當前運行 Libral 的系統上需要包含所有的支持庫在內運行環境。在某些情況下,這不是一個障礙;舉例子來說,基於 「yum」 的包管理的管理器需要 Python 被安裝在當前的系統上,因為 「yum」 就是用 Python 開發的。
然而在很多時候,無法預期一種 Bourne shell(Bash)之外的設計語言能夠安裝到所有的管理系統上。通常,管理器的編寫者需要一個更加強大的腳本編譯環境是實際需要。然而事與願違,綁定一個完整的 Ruby 或 Python 作為解釋器來運行將會增加 Libral 的大小超出了實際使用環境對資源的限制。另一方面,通常選擇 Lua 或者 JavaScript 作為可嵌入的腳本編輯語言是不適應這種環境的,因為大多數的管理器的編寫者不熟悉他們,通常情況下需要做大量的工作才能滿足系統管理的實際需求。
Libral 綁定了一個 mruby 版本,一個小的、嵌入在 Ruby 的版本,提供給管理器的編寫者一個穩定的基礎以及功能強大的可實現的程序設計語言。mruby 是 Ruby 語言的一個完整實現,儘管其減少了大量的標準庫支持。與 Libral 綁定的 mruby 包含了 Ruby 用於腳本編輯管理任務的大多數的重要標準庫,其將基於管理器編寫者的需求隨著時間的推移得到加強。Libral 的 mruby 綁定了 API 適配器使編寫管理器更適合 JSON 約定,比如它包含了簡單的工具(如編譯修改結構體文件的 Augeas)來解決解析和輸出 JSON 的約定。mruby.prov 文件包含了利用 mruby 編寫的 JSON 管理器框架實例。
下一步工作
Libral 最關鍵的是下一步要使其增加廣泛的可用性——從 預編譯的 tarball 對於開發管理器的起步和深入是一個不錯的方法,但是 Libral 也需要打包到主流的發行版上,並在上面可以找到。同樣的,Libral 強大的功能取決於它附帶的 管理器的集合,及需要被擴展覆蓋一組核心管理功能。Libral 的網站上包含了一個 todo 列表列出了管理器的最迫切需求。
現在有多種方法能夠提高不同用途的 Libral 的可用性:從編寫更多程序語言的綁定,舉例來說,Python 或者 Go;到使 ralsh
更容易在 shell 腳本中使用,除了現有的可讀輸出和 JSON 輸出之外,可以很輕鬆的在 shell 腳本中格式化輸出。在大規模的管理中使用 Libral 也能夠在增加上面討論過的遠程 API 而得到改良,Libral 利用像 SSH 這樣的傳輸工具實現更好的支持批量安裝要求為各種架構提供預編譯的 tarball,並且腳本基於所發現的目標系統架構選擇正確的包。
Libral 和它的 API、它的性能能夠不斷地進化發展;一個有趣的可能性是為 API 增加提醒能力,這樣做可以向系統報告資源在超出它的範圍發生的變化。Libral 面臨的挑戰是保持小型化、輕量級和良好定義的工具,來對抗不斷增加的用例和管理性能——我希望每一個讀者都能成為這個挑戰之旅的一部分。
如果這讓你很好奇,我很想聽聽你的想法,可以用拉取請求的方式,也可以是增強請求方式,亦或者報告你對 ralsh 體驗經驗。
(題圖:Internet Archive Book Images,修改:Opensource.com. CC BY-SA 4.0)
作者簡介:
David Lutterkort - 戴維是一個 Puppet 的軟體工程師,他曾經參與的項目有 Direct Puppet 和最好的供給工具 Razor。他是 Puppet 最早的編著者之一,也是配置編輯工具 Augeas 的主要作者。
via: https://opensource.com/article/17/5/intro-libral-systems-management-library-linux
作者:David Lutterkort 譯者:stevenzdg988 校對:wxy
本文轉載來自 Linux 中國: https://github.com/Linux-CN/archive