使用 Chef 自動化部署一個 Web 服務器

使用 Chef 自動化部署一個 Web 服務器

隨着 DevOps 的流行,越來越多的工作被自動化處理。在搭建大規模的 IT 架構時,需要系統管理員夜以繼日地安裝配置服務器、調整各種參數等工作,直到Chef 的出現,將系統管理員從這種水深火熱的工作中解脫了出來,他們只需要編寫 Chef 腳本,描述出服務器所需要保持的狀態,然後運行腳本,服務器就配置好了。本文以配置一個 Web 服務器爲例,對 Chef 的概念和工作流程做一簡單介紹。

王 羣鋒, 軟件工程師,  IBM

2015 年 6 月 23 日

  • expand內容

在 IBM Bluemix 雲平臺上開發並部署您的下一個應用。

“這是一個最好的時代,也是一個最壞的時代。他們都在直奔天堂,而我們都在直奔相反的方向。”

90 後霸道總裁” 的超級課程表融資千萬美元、WhatsApp 被 Facebook 以 190 億美元收購……這個時代彷彿到處都充滿了機會。現在假設我們也決定放棄朝九晚五的工作,要開發出一款 Web 應用改變這個世界,順便當上總經理、出任 CEO、贏取白富美、走向人生巔峯。七拼八湊,我們的應用做出來了。它的架構非常簡單,如果非要描述的話,它的架構如圖 1 所示:

圖 1. 應用架構

應用架構

這麼簡單的應用,我們上網瀏覽一下資料,隨便租個服務器,安裝一個 Web 服務器,配置一下,應用順利上線。

幸福總是來得太快,很快我們的應用就火了。隨着訪問量的增大,我們需要單獨的數據庫服務器,一個都不夠,得來倆;應用服務器也不夠用了,再多添幾臺,上一個負載均衡;對數據庫的訪問又成了性能瓶頸,增加些數據庫緩存吧,最終,應用的架構變成了如下的樣子:

圖 2.    演進的應用架構

演進的應用架構

現在問題來了,面對如此複雜的架構,怎麼安裝和配置這些服務呢?Chef 就是用來解決這個問題的。

第一份“菜譜”(recipe)

讓我們暫且就此打住,先來看看怎麼使用 Chef。首先需要在一臺 Linux 機器上安裝Chef Development Kit。如果您實在找不到一臺 Linux 機器也沒有關係,可使用一個用於教學用途的在線虛擬機,該虛擬機上已經預裝了 Chef Development Kit,可以直接使用。

Recipe 是 Chef 中主要執行任務的地方,翻譯成中文是“菜譜”的意思。我們的第一份“菜譜”的主要功能是使用 Chef 生成一個文本文件,其內容爲:Hello Chef。讓我們先新建一個 chef-repo 目錄,用來存放“菜譜”,然後在該目錄下創建第一個“菜譜”:hello.rb,其內容如下:

清單 1. hello.rb
file 'motd' do
content 'Hello Chef’
end

在命令行中執行:chef-appy hello.rb,輸出如下:

圖 3. 輸出

輸出

可 以看到,命令執行後生成 motd 文件,該文件的內容爲字符串:Hello Chef。這就是我們的第一份“菜譜”,雖然簡單,但是卻概括了 Chef 的基本工作原理:使用一個 Ruby 文件,即“菜譜”描述服務器應有的狀態,然後執行 Chef 命令配置服務器。

您可嘗試再次執行 chef-appy hello.rb,Chef 會檢測到 motd 文件已經存在,且文件內容和“菜譜”中所描述的一致,因此不進行任何操作;您還可嘗試手動刪除 motd 文件,再次執行 chef-appy hello.rb 後,又重新生成了 motd 文件。這正是配置服務器所需要的,每次配置都能保證狀態一致。

當然,我們的第一份“菜譜”只是一道開胃小菜,下面我們看看如何使用 Chef 部署一個 Web 服務器。

部署 Web 服務器

部署一個 Web 服務器比生成一個文件複雜,但道理卻是相同的,讓我們先來看看代碼:

清單 2. webserver.rb
package 'httpd'
service 'httpd' do
    action [:start, :enable]
end

file '/var/www/html/index.html' do
  content '<html>
  <body>
    <h1>hello world</h1>
  </body>
</html>'
end

service 'iptables' do
  action :stop
end

這段代碼總共分成四部分:第一部分安裝 Apache HTTP Server;第二部分啓動 HTTP 服務;第三部分生成主頁面;第四部分停用 iptables 服務,這一步主要是因爲有些 Linux 安裝後,默認只打開 22 端口,其他端口是被禁止的,停用 iptables 服務後,就可以順利訪問 80 端口了,即 HTTP 協議所使用的端口。聰明的您朋友們,您能將這四部分和代碼對應起來嗎?

這裏要注意的是,這四部分的順序非常重要,必須先安裝 Apache HTTP Server,然後啓動它,這一點也不難想象,我們手動配置服務器時不也如此嗎?

將 文件保存後,讓我們再來運行 sudo chef-appy webserver.rb,因爲腳本里包含安裝軟件包的操作,所以需要 root 權限,如果您不是以 root 賬號登錄(相信您不會真的這樣做吧?),務必在命令行前加 sudo,否則,Chef 會報錯。如果得到類似下面的輸出,就證明服務器配置成功,打開瀏覽器,輸入http://localhost,可以看到剛纔定製的主頁了吧?

圖 4. 輸出

輸出

然 而,作爲有“潔癖”的程序員,不難發現“菜譜”的第二部分好像混入了什麼奇怪的東西:一段 HTML 代碼。這段 HTML 代碼明顯和其他部分不協調,如果網頁再變得複雜點,這份“菜譜”會變得很難管理。因此,我們得想點什麼辦法,管理“菜譜”。方法就是“烹飪手冊” (cookbook)。

“烹飪手冊”(cookbook)

和真實的烹飪一樣,“烹飪手冊”是用來組織“菜譜”的,在“烹飪手冊”裏,不光可以定義各種“菜譜”,也可以定義一些屬性文件或模板,這些屬性文件或模板可以在“菜譜”裏直接引用。在實際工作中,我們往往使用的也是“烹飪手冊”,而不是一個個單獨的“菜譜”。

讓我們在當前目錄下新建一個文件夾 cookbooks,然後切換到該目錄,調用 chef generate cookbook learn_chef_httpd 會自動爲我們生成一個“烹飪手冊”。“烹飪手冊”的目錄結構如下:

圖 5. “烹飪手冊”目錄結構

“烹飪手冊”目錄結構

其中 recipes 目錄下的 default.rb 是默認的“菜譜”,讓我們將其中內容替換爲之前編寫的“菜譜”。

現 在我們要將原來“菜譜”中的 HTML 代碼移到一個外部文件中,使用 chef generate template learn_chef_httpd index.html 命令生成模板文件 index.html.erb,該文件被放置在 learn_chef_httpd/templates/default 目錄下。然後將該文件內容替換爲之前的 HTML,修改 default.rb,引用該模板,最終的“菜譜”變成了下面這個樣子:

清單 3. default.rb
package 'httpd'

service 'httpd' do
    action [:start, :enable]
end

template '/var/www/html/index.html' do
  source 'index.html.erb'
end

service 'iptables' do
  action :stop
end

在命令中執行 sudo chef-client --local-mode –runlist ‘recipe[learn_chef_httpd]’ ,打開瀏覽器,訪問http://localhost ,如果能正常訪問,那麼恭喜您完成了自己的第一個“烹飪手冊”!

真實環境下的 Chef

上 面的例子只是爲了展示如何編寫“菜譜”和“烹飪手冊”,真實環境下的 Chef 卻不是這樣工作的。在真實環境下,系統管理員在一臺電腦上編寫 Chef 腳本,然後使用上述方式調試,調試成功後,將腳本上傳至 Chef 服務器,我們從控制檯向 Chef 服務器發命令,Chef 服務器會將配置下發到各個待配置服務器,在每個服務器上運行 Chef,完成對服務器的配置。

圖 6.    Chef 原理

Chef 原理

爲此,我們需做三點準備:一臺用於編寫 Chef 腳本的電腦、一臺 Chef 服務器、很多待配置的服務器。我們已經有了一臺可以編寫 Chef 腳本的電腦,爲了方便學習,Chef 服務器可以選用Chef 官網提供的託管服務,另外需要幾臺待配置的服務器,記得不要在服務器上安裝 Chef,當我們配置這些服務器時,Chef 會自動在上面安裝所需的工具。

註冊成功 Chef 的託管服務後,先創建一個組織,然後下載與之對應的 Starter Kit,解壓到當前目錄,該工具是用來做認證的,有了它,纔可以從本地連接 Chef    服務器。現在讓我們刪除以前創建的“烹飪手冊”,轉而從 Chef 超市上 下載一個現成的手冊。Chef 超市是一個開發者交流“烹飪手冊”的地方,因爲配置服務器的很多操作都是通用的,所以人們把這些配置做成手冊,放在一個地方,大家都能使用。我們編寫 Chef 腳本,往往也是先上 Chef 超市去看看有沒有可用的手冊,如果有,直接拿過來,或者在此基礎上修改一下就能用,如果沒有,再考慮編寫自己的手冊。使用如下命令下載前面配置 Web 服務器的手冊:

knife cookbook site download learn_chef_httpd

將下載後的手冊解壓到 cookbooks 目錄,刪除壓縮包:

tar -zxvf learn_chef_httpd-0.1.0.tar.gz -C cookbooks
rm learn_chef_httpd*.tar.gz

接下來將該手冊上傳至 Chef 服務器,即我們剛纔註冊的 Chef 託管服務:

knife cookbook upload learn_chef_httpd

打 開託管服務控制檯,在 Policy 選項卡下就能看見剛剛上傳成功的“烹飪手冊”。接下來我們要做的工作是告訴 Chef 服務器來幫我們讓服務器自舉,這一步會通過 SSH 登錄到待配置的服務器,下載並安裝 Chef,然後下載執行剛剛上傳到 Chef 服務器上的“烹飪手冊”。該操作只在第一次配置服務器時需要,自舉成功後,以後就再不需要自舉了:

knife bootstrap `address` --ssh-user `user` --ssh-password '`password`' \
--sudo --use-sudo-password --node-name node1 \
--run-list 'recipe[learn_chef_httpd]'

將其中的`address`、`user`、`password`替換爲待配置服務器的真實地址、用戶名和密碼。打開瀏覽器,輸入服務器地址,看看是否能訪問定製的主頁?

獲取服務器信息

Chef 不光可以管理服務器,同時服務器將自己的信息上傳至 Chef 服務器。使用如下命令查看當前組織裏被管理的服務器:

knife node list

使用如下命令查看服務器信息,包括服務器的 IP 地址、機器名、操作系統等信息:

knife node show node1

有了這些信息後,我們可以重新修改模板,讓其顯示給定服務器的信息:

清單 4. index.html.erb
<html>
<body>
<h1>hello from <%= node['fqdn'] %></h1>
</body>
</html>

再將“烹飪手冊”上傳至 Chef 服務器,然後使用如下命令配置服務器:

knife ssh `address` 'sudo chef-client' --manual-list \
--ssh-user `user` --ssh-password '`password`'

同理,將`address`、`user`、`password`替換爲待配置服務器的真實地址、用戶名和密碼。打開瀏覽器,輸入服務器地址,看看改動是否生效?

只要一臺服務器配置成功,我們便可以用同樣的方法配置幾十臺、上百臺。而且一旦配置發生變化,我們只需修改腳本,所有服務器便可以獲得相同的更新,這個時候,Chef 的威力就顯示出來了。

chef 還是 knife?

細 心的您可能會注意到,上面的命令,一些是 chef *****,一些卻是 knife *****。初次接觸 Chef,很容易被這些命令搞混。這裏有一個簡單的規則:本地執行的命令以 chef 打頭,需要遠程連接到 Chef 服務器或待配置服務器的命令以 knife 打頭。

最後,讓我們再複習一遍本文中所使用到的命令:

  1. 運行“菜譜”

    chef-appy hello.rb
  2. 使用 Chef 生成“烹飪手冊”

    chef generate cookbook learn_chef_httpd
  3. 使用 Chef 生成模板

    chef generate template learn_chef_httpd index.html
  4. 使用 Chef 運行“烹飪手冊”

    chef-client --local-mode –runlist ‘recipe[learn_chef_httpd]’
  5. 從 Chef 超市下載“烹飪手冊”

    knife cookbook site download learn_chef_httpd
  6. 向 Chef 服務器上傳“烹飪手冊”

    knife cookbook upload learn_chef_httpd
  7. 服務器自舉

    knife bootstrap `address` --ssh-user `user` --ssh-password '`password`' \
    --sudo --use-sudo-password --node-name node1 \
    --run-list 'recipe[learn_chef_httpd]'
  8. 獲取當前組織下的服務器列表

    knife node list
  9. 顯示服務器信息

    knife node show node1
  10. 使用 Chef 遠程運行“烹飪手冊”,配置服務器

    knife ssh `address` 'sudo chef-client' --manual-list \
     --ssh-user `user` --ssh-password '`password`'

結束語

隨 着雲計算和 DevOps 技術的發展,有人斷言系統管理員和 DBA 會面臨失業,未來的雲計算公司和數據庫公司只會僱傭少數系統管理員和 DBA 管理他們的 IT 基礎設施和數據庫。雖然作者不大讚成“機器替代人工”這一觀點,但提早下手,學點東西總不是壞事,所謂技多不壓身嘛。

Chef 能夠實現服務器配置的自動化,在 DevOps 運動中佔有重要的位置。本文通過一個配置 Web 服務器的例子,一步步引導大家如何使用 Chef。希望您讀完本文,能編寫出自己的第一個“烹飪手冊”。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章