cookbook 概述
Chef 意為“廚房”,我們要做“菜”,自然需要有“菜譜”。事實上在 Chef 中分發到各服務器節點的不是“菜”,而是“菜譜”,服務器自己“做菜”,自己管理自己。
Cookbook 規定了在 Chef 中執行的操作順序,決定了應用的構建步驟。可以從市場中尋找一個 cookbook,市場地址:https://supermarket.chef.io/cookbooks/ 使用如下命令:
knife cookbook site install nginx
它會進行版本控制,在提交歷史中留下創建記錄。
如果不適用版本控制,則可以使用如下命令(不推薦):
knife cookbook site download nginx
在老的版本中,使用 knife 來與 Chef Server 進行交互,創建一個 cookbook 的命令是這樣的:
knife cookbook create first_cookbook
而在新版本中,創建的命令變為:
chef generate app first_cookbook
在 repo 的 cookbook 目錄下新建時,輸入如下命令:
chef generate first_cookbook
執行命令后,可以看到創建的目錄:
.
├── Berksfile
├── chefignore
├── LICENSE
├── metadata.rb
├── README.md
├── recipes
│ └── default.rb
├── spec
│ ├── spec_helper.rb
│ └── unit
│ └── recipes
│ └── default_spec.rb
└── test
└── smoke
└── default
└── default_test.rb
在新版本 Chef 中,不會自動生成所有目錄,一個 cookbook 內可能包含的目錄及作用參見文檔:https://docs.chef.io/cookbooks.html
接下來,我們創建一個部署 nginx 的 cookbook,在這里以 tengine 為例:
第一個 cookbook
首先,修改 recipes 目錄下的以 .rb
結尾的文件,該文件記錄了節點自身進行操作的步驟。
package 'pcre-devel' do
action :install
end
package 'openssl' do
action :install
end
package 'openssl-devel' do
action :install
end
上述腳本安裝了可能缺少的依賴包,這里 Chef 可以幫我們抹除平台差異,例如在 Ubuntu 平台使用 apt
和在 CentOS 使用 yum
的差異。
也可以一步安裝多個依賴包:
package %w(pcre-devel openssl openssl-devel)
action :install
end
這里可能產生的問題是,在不同的平台包名可能不同,對不同環境下依賴包的版本不同。當然,Chef 會考慮到這一點,這里不詳細展開,可以參閱文檔:https://docs.chef.io/resource_package.html
安裝完依賴后,就需要下載 tengine 源碼,並進行編譯操作。這一步用 shell 命令很方便,所以在 recipe 中也是可以定義一組 shell 命令的。在文件后追加如下行:
script 'install_tengine' do
interpreter 'bash'
user 'root'
cwd '/usr/local/src'
code <<-EOH
wget 'http://tengine.taobao.org/download/tengine-2.2.1.tar.gz'
tar -zxvf tengine-2.2.1.tar.gz -C /usr/local/src/
cd /usr/local/src/tengine-2.2.1/
./configure
make
make install
chkconfig nginx on
EOH
end
interpreter
參數指定了要以何種 shell 去運行,user
定義執行用戶,cwd
定義執行路徑。
隨后下載解壓,進行編譯安裝。
可以看到我們在定義的命令中啟用了 nginx 服務:
chkconfig nginx on
這里的問題在於,tengine 編譯后並不會生成定義服務的文件,因而需要我們手動添加服務,即:
創建 nginx 服務文件 -> 給定權限 -> 啟用服務
所以需要添加一個固定的文件,添加到節點中。在 cookbook 內,可以定義文件,文件中的內容一般是固定不變的。
在 script 'install_tengine' do
塊之前添加:
cookbook_file "/etc/init.d/nginx" do
source "nginx"
mode '0755'
owner 'root'
group 'root'
end
以本地文件 nginx 去添加到節點服務器的 /etc/init.d/nginx 內。其它參數顧名思義,cookbook 文件、權限、所有者及組。
新建一個 files/default 文件夾,在其中建立 nginx 文件,該文件定義了 nginx 服務,會被添加至 /etc/init.d/
文件夾。nginx 文件的內容可以自己去定義,也可以參考如下定義(來自 http://blog.51cto.com/benpaozhe/1760999):
#!/bin/bash
#writer:gaolixu
#chkconfig: 345 86 16
start(){
if [ -f /var/lock/subsys/tengine.lock ];then
echo "Tengine is already running: [ FAILED ]"
else
if /usr/local/nginx/sbin/nginx ;then
echo "Starting tengine: [ OK ]"
touch /var/lock/subsys/tengine.lock
else
echo "Starting tengine: [ FAILED ]"
fi
fi
}
stop(){
if [ -f /var/lock/subsys/tengine.lock ];then
if /usr/local/nginx/sbin/nginx -s quit ;then
echo "Stopping tengine: [ OK ]"
rm -rf /var/lock/subsys/tengine.lock
else
echo "Stopping tengine: [ FAILED ]"
fi
else
echo "Tengine not runing: [ FAILED ]"
fi
}
reload(){
if /usr/local/nginx/sbin/nginx -s reload ;then
echo "Reload tengine: [ OK ]"
else
echo "Reload tengine: [ FAILED ]"
fi
}
case $1 in
"start")
start
;;
"stop")
stop
;;
"restart")
stop
sleep 1
start
;;
"reload")
reload
;;
"status")
s=`pidof -s nginx`
[ "$s" ] && echo "Tengine(nginx) pid $s running!!" || echo "Tengine(nginx) not runging!"
;;
*)
echo "usage: $0 start|stop|restart|reload|status"
esac
現在,目錄結構應該是這樣的:
.
├── Berksfile
├── chefignore
├── files
│ └── default
│ └── nginx
├── LICENSE
├── metadata.rb
├── README.md
├── recipes
│ └── default.rb
├── spec
│ ├── spec_helper.rb
│ └── unit
│ └── recipes
│ └── default_spec.rb
└── test
└── smoke
└── default
└── default_test.rb
當安裝完添加服務后,當然希望它啟動:
service 'nginx' do
supports [:enable, :start, :status, :restart, :reload]
action :start
end
定義了 nginx 服務支持的命令和要執行的操作,對 service 的管理,參見:https://docs.chef.io/resource_service.html
同樣地,使用 Chef 內置的語法來管理 service,可以消除平台差異,並且可以支持更多的邏輯判斷操作,對服務的管理更加靈活。
現在就簡單的完成了一個 cookbook,現在來測試一下運行結果,在 chef-repo 文件夾下運行:
chef-client --local-mode --override-runlist first_cookbook
可以看到一堆命令輸出,若有報錯會中止!
命令結束后,驗證:
service nginx status
Tengine(nginx) pid 23776 running!!
可以看到,已經成功使用 cookbook 部署運行了 nginx。
不足
我們簡單的創建了一個 nginx 的 cookbook,並且在部署后實現了服務的自動啟動。但是往往在現實中會有不同的配置,簡單的使用默認配置當然不能滿足需求。這時,cookbook 中的 template
和 attributes
就派上用場了。下篇文章會使用模板變量結合一定的邏輯,來實現多樣化的配置管理需求。
-EOF-