導讀 | 作為繼承了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 提供了一种查找特定资源的管理器provider的方法。
“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” 或 “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 面臨的挑戰是保持小型化、輕量級和良好定義的工具,來對抗不斷增加的用例和管理效能——我希望每個讀者都能成為這個挑戰之旅的一部分。
以上是Libral 為系統資源和服務提供了一個統一的管理 API !的詳細內容。更多資訊請關注PHP中文網其他相關文章!