[翻譯] 深入SaltStack

yinchuan發表於2013-04-12

[譯者注] 這是一篇發表在opencredo官網的博文,通過比較流行的Puppet和新發展起來的Salt,詳細地介紹了Salt的功能。在徵得原作者的同意後,翻譯出來,與大家分享。初次翻譯長文,請大家指點。 原文連結

深入SaltStack

Maartens Lourens.
於1月10日發表在opencredo.

對系統工程師來說,配置管理已經向前躍進了一大步. 系統配置的自動化不僅可預測,可重複, 還具有可管理性. 配置管理工具通常使用版本控制化的配置模板來描述基礎設施的目標狀態。憑藉版本控制化的配置,可以將環境回滾(或前滾)到前面(或後序)狀態;環境配置檔案的自動化管理也是持續性交付管道的必要特性。

CFEngine, Puppet和Chef(按年齡降序)是開源領域流行的配置管理工具。 我是一個Puppet的長期使用者, 與自定義的配置指令碼相比,它在系統自動化的組織性和可靠性方面帶來了巨大的提升。(我是在2009年作出這一次飛躍,與此相比, 以前的日子簡直是混亂不堪…).

雖然配置管理工具精於描述並達到想要的狀態, 但並不擅長動態地查詢或設定狀態. 這一點在狀態資源還沒有被納入配置管理時特別明顯。Llinux系統管理員的傳統解決辦法是ssh迴圈登陸節點列表並執行一堆命令。這不僅容易出錯, 且每一次迴圈都要開啟新的ssh會話,效率低下。想像一下要在1000臺機器上順序執行命令!更不用說網路安全,ssh金鑰和命令執行許可權的問題。這當然是一種可行的辦法,但缺少一種可管理的框架。

這就是命令編排工具產生的原因。這些工具旨在大量的節點上並行執行命令和實時操作。CFEngine, Puppet和Chef各自用不同的方法來解決命令編排問題。Puppet使用MCollective作為其武器,並將其整合到商業版中。

近來,我開始探索使用SaltStack來解決配置管理和命令編排這兩個問題。SaltStack開始於2011年,是一個相對較新的專案,但在系統管理員和DevOps工程師中擁有越來越多的粉絲。我將在本文中探討Salt作為前途光明的替代者,並與Puppet作比較以探索其特性。

安裝

創世之初,滿是空白和無序,黑暗籠罩著整個系統……然後神安裝了配置管理器,於是陽光普照!唯一的麻煩是,我們還需要安裝依賴……然後配置管理器本身還得被配置……並且有時事情會有那麼一點醜陋。

Salt在Ubuntu和CentOS上的安裝過程異常簡單,我相信在有安裝指南的別的系統也一樣 (Arch Linux, Debian, Fedora, RedHat, CentOS, FreeBSD, Gentoo, Windows, Solaris). YMMV. 典型安裝過程隱藏了不必要的細節配置,除非你需要修改他們。首先安裝salt master,然後安裝salt minions, 將minions指向master,安裝完成。如果salt master的主機名是"salt",都不需要將minions指向master,直接就可以執行。

然而, 如果你不是使用上面提到的發行版或作業系統, 你很可能需要捲起袖子自己手動安裝一些依賴。包括Python (>= 2.6 < 3.0), ZeroMQ, pyzmq, PyCrypto, msgpack-python和YAML的Python繫結.

另一方面, Puppet在多數基礎安裝時只依賴Ruby和Facter, 依賴帶來的麻煩顯著減少. 然而,Puppet的依賴列表可以進一步增加,包括augeas-libs, dmidecode, hiera, libselinux-ruby, pciutils, ruby-augeas, ruby-irb, ruby-rdoc, rubygem-json, ruby-shadow, rubygems. 這取決於Puppet的版本和你想要使用的功能。

我喜歡Salt包安裝的簡單明瞭。For the cases mentioned it is trivial to set up and get going. 如果你想親自安裝和配置的繁過程, 跟著安裝指南做即可。

If you are like me though and you prefer your provisioning and configuration all in one gift wrapped package, que Vagrant to the rescue and download this project by elasticdog on github.

配置管理

配置狀態

配置管理對Puppet來說是小菜一疊,對Salt又如何呢。讓我(高興的)驚訝的是,這件事簡單到令人髮指。和Puppet一樣,在Salt中可以描述系統的目標狀態。. Salt將其稱之為一個state, 配置模組是state模組。Salt的State模組檔案用YAML寫成,以.sls結尾。它們從功能上等同於Puppet模組的manifest檔案,後者用Puppet DSL寫成,以.pp結尾。

Salt在master的配置檔案中指定"file roots", 類似於Puppet的"module path", 但同時包含了模組根目錄和環境型別。舉例來說,在Salt中我們可以分別指定development和test環境配置檔案路徑. 注意base環境是必須存在的。

file_roots:
base:
- /srv/salt/
dev:
- /srv/salt/dev
prod:
- /srv/salt/prod

base環境必須包含Salt的入口top檔案(叫做top.sls).base定義了一個或多個環境,用正則來匹配節點,然後引用相應的Salt states. top檔案與Puppet的nodes檔案相似。(Puppet入口點是site檔案,在Salt中不需要).

假設有一個Salt master和兩個minions (由Elasticdog github提供),我想要在兩個minions上安裝mongodb。如果在預設的軟體倉庫中有mongodb包,只需要3步即可。

1, 在top.sls中指定節點。

dev:
'minion*.example.com':
- mongodb

2, 在dev/mongodb.sls中描述狀態:

mongodb:
pkg:
- installed

3, 傳遞狀態到salt minions:

# salt 'minion*' state.highstate -v
Executing job with jid 20121218102842533621
-------------------------------------------

minion1.example.com:
----------
State: - pkg
Name: mongodb
Function: installed
Result: True
Comment: Package mongodb installed
Changes: libicu: {'new': '3.6-5.16.1', 'old': ''}
mongodb: {'new': '1.6.4-1.el5', 'old': ''}
boost: {'new': '1.33.1-15.el5', 'old': ''}
js: {'new': '1.70-8.el5', 'old': ''}

minion2.example.com:
----------
State: - pkg
Name: mongodb
Function: installed
Result: True
Comment: Package mongodb installed
Changes: libicu: {'new': '3.6-5.16.1', 'old': ''}
mongodb: {'new': '1.6.4-1.el5', 'old': ''}
boost: {'new': '1.33.1-15.el5', 'old': ''}
js: {'new': '1.70-8.el5', 'old': ''}

配置描述檔案與Puppet非常相似。但格式差別很大。這是因為Puppet使用自己的ruby-like DSL, 而Salt使用YAML. 正是由於這點不同,造就了Salt state配置檔案在視覺上的簡潔性。YAML對人類可讀也容易被對映到資料結構, 非常適合做配置管理中的資源描述。這不是說Puppet DSL不清晰或不結構化- it is neither - 但很難勝過YAML. YAML可以快速寫成,在我的經驗看,比Puppet DSL要容易生成.

注意: 配置管理社群關於宣告配置的最佳方式一直存在爭論。部分人青睞於利用程式語言(比如說Ruby)的靈活性。Chef是其中的代表。Puppet處於中間地段。當使用現成的功能時,Puppet DSL非常強大。但要給配置開發者更大的能力,就必須使用內部的Ruby DSL。在波譜的另一端,Salt的簡單YAML狀態描述非常結構化。然而,Salt也支援渲染諸如JSON, Mako, Wempy和Jinja來擴充套件其能力, 在將來還會支援XML,原生Python及其他。

內建的state模組

我知道Salt是比Puppet近的專案, 我完全可以預料到不會有太多可用的內建模組。我錯了: Salt有大量的內建模組,包含Puppet中的大部分必要模組比如 cron, exec (Salt是cmd), file, group, host, mount, package (Salt中是pkg), service, ssh_authorized_key (Salt是ssh_auth)和user。

儘管如此, Puppet仍然具有部分優勢。比如, 我非常喜歡Puppet的Augeas模組。Augeas把內容當作value樹,允許你修改(而不是覆蓋)一個已存在的配置檔案。

雖然Salt有一個Augeas execution模組,但很不幸貌似沒有Augeas的state模組。雖然這樣,Salt也有一些自己特有的東西,比如針對git, hg和svn的內建state模組.

模板

Puppet具有開盒即用的模板系統。Puppet有file資源和template資源的概念,這些資源分佈在模組目錄結構的不同路徑下。在Salt中, files和templates在同一個位置。通過為template指令指定type來區分是template還是普通檔案資源, type可以是jinja, mako或wempy。好處是可以很容易為file資源增加邏輯。state檔案可能看起來像下面這樣:

/etc/myapp.conf:
file.managed:
- source: salt://files/myapp.conf
- mode: 644
- owner: root
- group: root
- template: jinja

注意最後一行, 指明被管理的檔案是一個jinja模板。

配置檔案可以使用jinja的語法來增加邏輯。舉例來說, 假設你的應用程式配置檔案中用到了主機名。再假設在Ubuntuh 只需要短主機名(hostname),在CentOS需要FQDN。這可以很容易地在模板檔案myapp.conf中指定:

{% if grains['os'] == 'Ubuntu' %}
host: {{ grains['host'] }}
{% elif grains['os'] == 'CentOS' %}
host: {{ grains['fqdn'] }}
{% endif %}

在CentOS節點minion1上結果檔案/etc/myapp.conf將包含以下內容

host: minion1.example.com

變數

Salt中的全域性變數不能在使用時定義。在對變數的支援方面Puppet更加直觀和靈活。在Salt中, 所有的變數儲存在單獨的位置。這樣做不夠靈活,但優勢是更有秩序。用Salt的話講,變數叫做"pillars"。pillars的位置在salt master的配置檔案中指定:

pillar_roots:
base:
- /srv/salt/pillar

和state檔案一樣, 首先建立一個top檔案,在其中可以引用相關的pillar模組。

base:
'*':
- packages

這個top檔案引用了名為packages.sls的state檔案, 其中包含將要安裝的軟體包的版本號的變數,如下所示:

mongodb: mongodb-1.6.4-1
httpd: httpd-2.2.3-65

宣告瞭兩個pillar, mongodb和httpd, 然後可以在state檔案中用如下方式引用:

pillar['mongodb']
pillar['httpd']

模擬執行(Dry run)

管理系統有點像駕駛飛機。如果不小心謹慎,將會是高風險的事情。假設我是一個雙翼飛機的駕駛員,將做一個危險的aerial manoeuvre, 我多半會希望能夠先模擬飛行。除非我像Red Baron一樣無所畏懼。無論如何,還好在執行Salt之前可以先做測試。你需要做的僅僅是將Test設定為True。

# salt 'minion1.example.com' state.highstate -v test=True

minion1.example.com:
----------
State: - file
Name: /etc/myapp.conf
Function: managed
Result: None
Comment: The following values are set to be changed:
newfile: /etc/myapp.conf

Changes:

總結

在配置管理方面,Salt在Puppet面前還是能夠站穩腳跟的。Salt安裝非常簡單,屬於簡單主義的開發風格, 功能豐富。總的來說,不需要過多的操作就可以完成事情。我發現的唯一問題是salt-master和minion之間的連線有時會無故斷掉。搜尋一番後,我發現其他人在Salt 0.10.5這個版本上也遇到了同樣的問題。希望這個問題在下一個版本中得到解決。

命令編排和遠端執行

MCollective

MCollective是 Puppet的命令編排解決方案。由R.I.Pienaar在PuppetLabs那幫人引起重視之前獨立開發完成。MCollective使用message broker (比如ActiveMQ)通過pub-sub匯流排來傳遞訊息, 可以並行通訊,這比用ssh快得多。這是一可以理解特定訊息併產生響應的框架。Puppet和MCollective現在可以在同一個框架下工作,同時提供完成配置管理和命令編排的功能。

先不管MCollective的優勢,有兩個負擔能夠打擊你的激情。第一,MCollective只是和Puppet鬆散整合,至少對社群版本來講是這樣 。MCollective有單獨的安裝包,獨立的配置檔案。另外你還需要安裝配置broker(比如ActiveMQ),來與MCollective一起工作. 雖然不難,但很繁瑣。最後,你還不得不自己解決生產環境中通訊渠道的安全問題。不幸的是,這個就有點困難。

MCollective的第二個問題是相對來講缺少一些自帶的功能。有很多現成的外掛可以下載安裝(https://github.com/puppetlabs/mcollective-plugins), 用Ruby寫自己的外掛也不是很複雜-不過想要立即使用的話,障礙比想像得要大。Nevertheless, given that the framework is solid and extensible, dabbling in Ruby plugins soon makes the real power of MCollective apparent.

Salt

另一方面,Salt生來就有命令編排的功能。最先設想的就是遠端執行技術,然後才新增的配置管理管理。Salt使用輕量的ZeroMQ來處理訊息。結果就是不需要單獨的安裝。裝好Salt後,配置管理和命令編排就可以工作了。毫不驚奇,Salt state模組和execution模組的命令在語法上類似,所以很直觀。再看Puppet和MCollective組合,各自使用不同的工具和語法結構,需要額外的時間去學習。

Salt遠端執行功能的可用性令人印象深刻。當前的線上文件列出了超過100個不同的內建excution模組-包括augeas!(所以augeas成為state模組只是時間上的問題).

舉個簡單的例子,看看通用的"cmd.run"模組和指令。這在你知道想要執行的命令卻又沒有現成的模組可用時非常有用,- 或者你僅僅想要快速地遠端執行命令。假設我想在所有節點上檢查執行的核心版本號:

[root@salt salt]# salt '*' cmd.run "uname -r"
minion1.example.com: 2.6.18-274.18.1.el5
minion2.example.com: 2.6.18-274.18.1.el5
salt.example.com: 2.6.18-274.18.1.el5

或者我想看看磁碟使用情況:

salt '*' cmd.run "df -h"

順便說一下, Salt有一個模組用來檢視磁碟用量以及其他磁碟相關的查詢:

salt '*' disk.usage

使用內建模組而不用cmd.run傳送shell命令的好處是,模組通常返回固定結構的資料。能夠以程式設計的方式用在自動化處理上。

有很多現成的execution模組來滿足通用的管理任務,比如apt, at, cp, cron, disk, extfs, file, hosts, iptables, mount, network, pam, parted, pkg, ps, selinux, shadow, ssh, and test. 也有大量的模組用於指定的軟體包和應用程式,比如apache, cassandra, djangomod, git, mongodb, mysql, nginx, nova, postgres, solr, sqlite3, 和tomcat.

甚至支援執行Puppet程式。

總結

毫無疑問,Salt遠端執行比Puppet加MCollective更優雅,附帶可用的功能更多。支援動態查詢和大規模的服務編排。要檢視完整的功能,請參考salt execution模組的文件。

附加功能

Dashboard

Puppet使用Puppet dashboard. Salt目前沒有圖形化的介面。我知道,我們都大愛命令列。不過,有時看到滿螢幕的綠色或是點點按鈕也是很愜意的。 認真的講,dashboard是獲得你所管理的節點網路state概覽的好工具。Salt的路線圖中沒有圖形介面,希望最終會出現。

Returners

Returners是minion向master返回資料時呼叫的模組。不將返回資料傳遞給salt master,而是呼叫Returner模組來將資料發給其他服務,通常是資料庫。Salt目前支援的returner,可以連線cassandra, mongo, redis和mysql. 也可以很容易的用Python指令碼為其他服務寫一個returner。

Salt Syndic

Salt文件將Salt Syndic描述為"一個可以構建Salt命令拓撲的強大工具“。實際意義上,Salt Syndic可以讓一個執行Syndic服務的Salt master連線到更高層的master。

假設你有多個不同的Salt環境,每個環境都有一個master。這些環境可能是特的雲或是有防火牆的網路。假設你想同時控制這幾個環境中的minions。你可以在想要控制的master主機上安裝Salt Syndic。Salt Syndic建立了傳輸介面,在最頂層的master看來,就像是控制了很多的minion,但配置狀態實際上是傳遞給了多個master。可以將其想像為軍隊的命令傳遞系統。

整合測試

有兩個採用現有測試框架的專案給Puppet增加測試功能,名字是cucumber-puppet (使用 Cucumber框架)和rspec-puppet (使用RSpec).

Salt採取的做法是通過一系列的整合類提供對整合測試的支援,roadmap中提到未來會使用Unittest2和pytest做單元測試。

自動化整合測試是持續性交付管道被忽視的領域,能有一些內建的支援是非常好的。這也是以後的博文中將探討的有趣領域

結論

我的目的是看看Salt Stack是否能做為配置管理和系統命令編排的解決方案。我的方法是與Puppet中最常用的功能作比較,以探索Salt的功能。結論是很耀眼的。Salt Stack不僅自帶了很多功能,且易於安裝,使用,擴充套件。 很明顯,Salt前途一片光明。

有用的連結

Saltstack主頁: http://saltstack.org
Salt下載: http://saltstack.org/download/
Salt在GitHub: https://github.com/saltstack/salt
Salt開發者部落格: http://red45.wordpress.com/

相關文章