Learn Chef Rally 學習筆記 part3 — 基本 cookbook 設定及使用
本文記錄 Learn Chef Rally 以下章節的學習歷程:
[Make your recipe more manageable]
本章節的開頭寫著:
KEY POINT: A cookbook provides structure to your recipes and enables you to more easily reference external files, such as our web server’s home page. In essence, a cookbook helps you stay organized.
意思是 cookbook 這東西可以幫助你保持 recipes 的結構化,並讓你能更輕鬆地調用外部檔案。
1. 新增 cookbook
進入 ~/chef-repo
開一個新資料夾 cookbooks
:
mkdir cookbooks
執行指令 chef generate cookbook
以產生一個叫 learn_chef_httpd
的 cookbook:
$ chef generate cookbook cookbooks/learn_chef_httpd
Generating cookbook learn_chef_httpd
- Ensuring correct cookbook file content
- Ensuring delivery configuration
- Ensuring correct delivery build cookbook content
Your cookbook is ready. Type `cd cookbooks/learn_chef_httpd` to enter it.
There are several commands you can run to get started locally developing and testing your cookbook.
Type `delivery local — help` to see a full list.
Why not start by writing a test? Tests for the default recipe are stored at:
test/recipes/default_test.rb
If you’d prefer to dive right in, the default recipe can be found at:
recipes/default.rb
先安裝一下 tree
這個套件,然後觀察 cookbooks
資料夾的結構:
$ sudo yum install tree -y
(略)
$ tree cookbooks
cookbooks
└── learn_chef_httpd
├── Berksfile
├── chefignore
├── metadata.rb
├── README.md
├── recipes
│ └── default.rb
├── spec
│ ├── spec_helper.rb
│ └── unit
│ └── recipes
│ └── default_spec.rb
└── test
└── recipes
└── default_test.rb
7 directories, 8 files
很好,跟本機執行結果跟教學長得一樣。 這邊有一個說明區塊,說 chef generate cookbook
指令其實還會生成一個隱藏資料夾 .delivery
,這個資料夾的用法在之後的 module 裡會說明,那我們就先不理它吧。
2. 新增 template
OMG 又來一個新的叫 template 的功能,好吧就照他說的下指令:
$ chef generate template cookbooks/learn_chef_httpd index.html
Recipe: code_generator::template
* directory[cookbooks/learn_chef_httpd/templates/default] action create
— create new directory cookbooks/learn_chef_httpd/templates/default
— restore selinux security context
* template[cookbooks/learn_chef_httpd/templates/index.html.erb] action create
— create new file cookbooks/learn_chef_httpd/templates/index.html.erb
— update content in file cookbooks/learn_chef_httpd/templates/index.html.erb from none to e3b0c4
(diff output suppressed by config)
— restore selinux security context
目前看起來是 chef 幫我們產生了一個 cookbooks/learn_chef_httpd/templates
的資料夾。用 tree
看一下目前的狀況:
$ tree cookbooks
cookbooks
└── learn_chef_httpd
├── Berksfile
├── chefignore
├── metadata.rb
├── README.md
├── recipes
│ └── default.rb
├── spec
│ ├── spec_helper.rb
│ └── unit
│ └── recipes
│ └── default_spec.rb
├── templates
│ ├── default
│ └── index.html.erb
└── test
└── recipes
└── default_test.rb
9 directories, 9 files
跟之前的差別的確是多了 templates 資料夾,進去看一下,default
是個資料夾,裡面是空的,index.html.erb
檔案也是空的。 接下來打開 index.html.erb
新增 html 內容,應該也是可以自由發揮:
<html>
<body>
<h1>Hello <a href=”https://www.verybuy.cc">VeryBuy</a></h1>
</body>
</html>
接著又有個說明區塊,說在實際應用上,這些網站的檔案比較有可能會是 .zip 或 .tar 這類 build 過的檔案。你可以把新的 web 檔案從外部 pull 下來,然後 deploy 到你的 web server 上。
3. 把 HTML template 加進 recipe
更新 cookbooks/learn_chef_httpd/recipes/default.rb
,打開之後發現裡面會有一些預設的註解內容,刪不刪應該都無所謂,加入下面幾行:
package 'httpd'service 'httpd' do
action [:enable, :start]
endtemplate '/var/www/html/index.html' do
source 'index.html.erb'
end
這裡出現了一個新的 resource 類型 template
。
仔細觀察一下語法,意思應該是我們要載入 template 到 /var/www/html/index.html
這個檔案中,內容是引用 index.html.erb
這個檔案。但問題是 index.html.erb
不是絕對路徑,又跟 default.rb
不在同一層目錄底下,而是在 templates
底下,有玄機,看來這個 source
不是吃一般所想的路徑,而是直接去抓 templates
底下的檔案?不知道,先繼續往下看吧。
4. 執行 cookbook
執行 chef-client
指令:
$ sudo chef-client --local-mode --runlist 'recipe[learn_chef_httpd]'
[2017-07-23T08:37:51+00:00] WARN: No config file found or specified on command line, using command line option
s.
Starting Chef Client, version 12.12.15
resolving cookbooks for run list: ["learn_chef_httpd"]
Synchronizing Cookbooks:
- learn_chef_httpd (0.1.0)
Installing Cookbook Gems:
Compiling Cookbooks...
Converging 3 resources
Recipe: learn_chef_httpd::default
* yum_package[httpd] action install (up to date)
* service[httpd] action enable (up to date)
* service[httpd] action start (up to date)
* template[/var/www/html/index.html] action create
- update content in file /var/www/html/index.html from 95172f to e3b0c4
--- /var/www/html/index.html 2017-07-22 11:49:46.214923159 +0000
+++ /var/www/html/.chef-index.html20170723-12981-cgfouc 2017-07-23 08:37:59.216236694 +0000
@@ -1,6 +1 @@
-<html>
- <body>
- <h1>Hello <a href="https://www.verybuy.cc">VeryBuy</a></h1>
- </body>
-</html>
- restore selinux security contextRunning handlers:
Running handlers complete
Chef Client finished, 1/4 resources updated in 08 seconds
這次的範例用了一個新的參數 --runlist
,用來一次跑多個 recipes。看起來語法是 recipe[cookbook的名稱]
,然後 chef 會自己去翻這個 cookbook 底下的 recipes
資料夾,但不知道是不是所有檔案都會被挖出來執行?看原文的語意應該是只會執行被指定的 recipe,但這邊卻又沒有特別指定。
底下解釋了,recipe[learn_chef_httpd]
等於 recipe[learn_chef_httpd::default]
的意思,也就是這個指令會去執行 default.rb
。
但我還是覺得沒有說得很清楚,只好自己來實驗一下,再加入另一個 recipe 到 recipes
資料夾裡,看它會不會被執行。新增一個檔案 cookbooks/learn_chef_httpd/recipes/test.rb
:
file '/tmp/test' do
content 'VeryBuy is good.'
end
然後再執行一次剛剛的 chef-client
指令:
$ sudo chef-client --local-mode --runlist 'recipe[learn_chef_httpd]'
[2017-07-23T08:55:13+00:00] WARN: No config file found or specified on command line, using command line options.
Starting Chef Client, version 12.12.15
resolving cookbooks for run list: ["learn_chef_httpd"]
Synchronizing Cookbooks:
- learn_chef_httpd (0.1.0)
Installing Cookbook Gems:
Compiling Cookbooks...
Converging 3 resources
Recipe: learn_chef_httpd::default
* yum_package[httpd] action install (up to date)
* service[httpd] action enable (up to date)
* service[httpd] action start (up to date)
* template[/var/www/html/index.html] action create (up to date)Running handlers:
Running handlers complete
Chef Client finished, 0/4 resources updated in 04 seconds
看起來我的 test.rb
並沒有被執行,用 more
檢查一下:
$ more /tmp/test
/tmp/test: 沒有此一檔案或目錄
沒錯,並不是 recipes
底下的所有檔案都會被執行,不寫清楚的話就是只去執行預設的 recipe: recipes/default.rb
。
我想以後遇到這種情況似乎還是把完整的 recipe[learn_chef_httpd::default]
寫清楚會比較好理解,以免新手混淆。
結論
咦?已經來到 Conclusion 了?那我的 test.rb
要怎麼跟 default.rb
一起在同一行指令裡被執行?居然沒有說,只丟了一個 run-list 連結就棄我而去了。可惡,只好點開來看一下:
A run-list must be in one of the following formats: fully qualified, cookbook, or default. Both roles and recipes must be in quotes, for example:
'role[NAME]'
or
'recipe[COOKBOOK::RECIPE]'
Use a comma to separate roles and recipes when adding more than one item the run-list:
'recipe[COOKBOOK::RECIPE],COOKBOOK::RECIPE,role[NAME]'
用 ,
分隔 COOKBOOK::RECIPE 就對了,感覺連 recipe[]
都可以不用加?來試試看:
$ sudo chef-client --local-mode --runlist 'learn_chef_httpd::default,learn_chef_httpd::test'
(略)
resolving cookbooks for run list: ["learn_chef_httpd::default", "learn_chef_httpd::test"]
(略)
Recipe: learn_chef_httpd::default
(略)
Recipe: learn_chef_httpd::test
* file[/tmp/test] action create
- create new file /tmp/test
- update content in file /tmp/test from none to 3a126d
--- /tmp/test 2017-07-23 09:13:04.429963485 +0000
+++ /tmp/.chef-test20170723-13711-1a8d0i7 2017-07-23 09:13:04.429963485 +0000
@@ -1 +1,2 @@
+VeryBuy is good.
- restore selinux security context
(略)
看起來不錯,再用 more
檢查一下:
$ more /tmp/test
VeryBuy is good.
可以確認 test.rb
順利地被執行囉!
不過 run-list 的文件裡還提到了一個 role[NAME]
的東西,目前還不知道是啥鬼但有點在意,先放在心上。
正港的結論
這個 Conclusion 不是這個章節的小結而是整個 module 的總結:
- 我們學到了 Chef 是如何以測試及修復系統的方式,讓整個系統能保持在我們想要的樣子。我們一開始直接拿 recipe 來執行,爾後利用 cookbook 來使得程式碼能更有組織性。
- 當我們有很多 cookbooks 的時候,我們可以利用 run-list 來一次執行多個 recipes,並且能按照我們想要的順序去執行。
- 這裡的 web server cookbook 範例你大概不太可能拿來用在你的 production 環境,只有你自己知道你的需求是什麼,Chef 會提供你必要的工具幫助你達到目的。
- 你可以繼續實驗一下這個 module 學到的東西,當你玩夠了的時候請往下一個 module Manage a node 前進,你將學到如何從你的工作站遠端管理另一台 server (Chef 將稱之為 node)。
測驗
What does a cookbook do?
- It includes recipes and external information and makes them easier to manage.
- It includes only external information, such as templates, and makes them easier to manage.
- It includes only recipes and makes them easier to manage.
What is a run-list?
- A run-list specifies which recipes to run.
- A run-list specifies which recipes to run and they order in which to run them.
- A run-list specifies which cookbooks to run.
What does test and repair mean?
- Chef applies changes only when they are necessary.
- Chef always applies changes and then tests to see if they are correct.
- Chef repairs incorrect states and then tests to see if they are now correct.
答案是 1, 2, 1。
[指令及語法整理]
1. 新增 cookbook:
chef generate cookbook COOKBOOK_PATH
例:
chef generate cookbook cookbooks/learn_chef_httpd
2. 在 cookbook 中新增 template:
chef generate template COOKBOOK_PATH TEMPLATE_NAME
例:
chef generate template cookbooks/learn_chef_httpd index.html
但產出的 template 檔案不會叫 index.html
而叫做 index.html.erb
3. 用 run-list 一次執行多個 recipes:
$ sudo chef-client --local-mode --runlist 'recipe[COOKBOOK::RECIPE],COOKBOOK::RECIPE'
例:
$ sudo chef-client --local-mode --runlist 'recipe[learn_chef_httpd::default],learn_chef_httpd::test'
4. recipe 中使用 template:
template 'FILE_PATH' do
source 'TEMPLATE_FILE_NAME'
end
例:
template '/var/www/html/index.html' do
source 'index.html.erb'
end
其中 index.html.erb
會在 cookbook 中的 templates
資料夾內。