Chefに入門(3) 〜Webサーバ立ち上げ〜


[入門Chef Solo](http://www.amazon.co.jp/%E5%85%A5%E9%96%80Chef-Solo-Infrastructure-as-Code-ebook/dp/B00BSPH158)の勉強3回目です。
Webサーバ(nginx)を立ち上げてみます。

## cookbook作成

新規にcookbookを作ります。

```Bash:
vagrant@precise64:~/chef-repo$ knife cookbook create nginx -o cookbooks
** Creating cookbook nginx
** Creating README for cookbook: nginx
** Creating CHANGELOG for cookbook: nginx
** Creating metadata for cookbook: nginx
```
## レシピ編集

レシピファイル`cookbooks/nginx/recipes/default.rb`を編集してnginxをインストール、実行するための記述を行います。`nginx.conf`をerbテンプレートとして用意しておき、レシピにそれを使うように書いておくとテンプレートが`nginx.conf`として指定パスに配置されます。

```default.rb
#
# Cookbook Name:: nginx
# Recipe:: default
#
# Copyright 2013, YOUR_COMPANY_NAME
#
# All rights reserved - Do Not Redistribute
#
package "nginx" do
        action :install
end

service "nginx" do
        supports:status=>true,:restart=> true,:reload=>true
        action [:enable,:start]
end

template "nginx.conf" do
        path "/etc/nginx/nginx.conf"
        source "nginx.conf.erb"
        owner "root"
        group "root"
        mode 0644
        notifies :reload,'service[nginx]'
end
```
##テンプレートファイル作成
テンプレートファイル`cookbooks/nginx/templates/default/nginx.conf.erb`を作成します。

```nginx.conf.erb
user nginx;
worker_processes 1;
error_log /var/log/nginx/error.log;
pid     /var/run/nginx.pid;

events {
        worker_connections 1024;
}

http {
        include /etc/nginx/mime.types;
        default_type application/octet-stream;

        server {
                listen  <%=node['nginx']['port'] %>;
                server_name localhost;
                location / {
                        root /usr/share/nginx/html;
                        index index.html index.htm;
                }
        }
}
```
<% 〜 %>は変数展開要のタグです。この変数部分は実行時に指定するJSONファイル(後述)に記述することができるみたいです。こうすることにより、ポートはChef実行時にテンプレートに手を入れることなく切り替えることができます。

JSONファイルは以下のようにしました。
"nginx"ノードの"port"属性に 80 番を指定しています。
これで、`nginx.conf`展開時に先ほどの変数タグ部分が 80 に置き換えられます。

```nginx.json
{
        "nginx":{
                "port":80
        },

        "run_list":[
                "nginx"
        ]
}
```

## 実行
先ほどのJSONファイルを指定して実行します。

```
vagrant@precise64:~/chef-repo$ sudo chef-solo -c config.rb -j ./nginx.json
Starting Chef Client, version 11.6.2
Compiling Cookbooks...
Converging 3 resources
Recipe: nginx::default
  * package[nginx] action install
================================================================================
Error executing action `install` on resource 'package[nginx]'
================================================================================


Chef::Exceptions::Exec
----------------------
apt-get -q -y install nginx=1.1.19-1ubuntu0.1 returned 100, expected 0


Resource Declaration:
---------------------
# In /home/vagrant/chef-repo/cookbooks/nginx/recipes/default.rb

  9: package "nginx" do
 10: 	action :install
 11: end
 12: 



Compiled Resource:
------------------
# Declared in /home/vagrant/chef-repo/cookbooks/nginx/recipes/default.rb:9:in `from_file'

package("nginx") do
  action [:install]
  retries 0
  retry_delay 2
  package_name "nginx"
  version "1.1.19-1ubuntu0.1"
  cookbook_name :nginx
  recipe_name "default"
end



[2013-10-19T18:49:18-07:00] ERROR: Running exception handlers
[2013-10-19T18:49:18-07:00] ERROR: Exception handlers complete
[2013-10-19T18:49:18-07:00] FATAL: Stacktrace dumped to /tmp/chef-solo/chef-stacktrace.out
Chef Client failed. 0 resources updated
[2013-10-19T18:49:18-07:00] FATAL: Chef::Exceptions::ChildConvergeError: Chef run process exited unsuccessfully (exit code 1)
```
エラーが出ています。
ググったところ、[似たようなQA](http://stackoverflow.com/questions/8937351/chef-isnt-running-the-apt-apt-get-update-recipe-apt-returns-100)が見つかりました。
nginxの指定バージョンがaptのリスト上に見つからないのが原因なので、先に`$sudo apt-get update`してリストを更新しておけばいいですよ、という感じです。

上記コマンド実行後に再挑戦。

```
vagrant@precise64:~/chef-repo$ sudo chef-solo -c config.rb -j ./nginx.json
Starting Chef Client, version 11.6.2
Compiling Cookbooks...
Converging 3 resources
Recipe: nginx::default
  * package[nginx] action install
    - install version 1.1.19-1ubuntu0.2 of package nginx

  * service[nginx] action enable (up to date)
  * service[nginx] action start
    - start service service[nginx]

  * template[nginx.conf] action create
    - update content in file /etc/nginx/nginx.conf from 38154b to 406356
        --- /etc/nginx/nginx.conf	2012-03-28 19:50:24.000000000 -0700
        +++ /tmp/chef-rendered-template20131019-6018-1tfg5gj	2013-10-19 19:22:46.336623985 -0700
        @@ -1,95 +1,23 @@
        -user www-data;
        -worker_processes 4;
        -pid /var/run/nginx.pid;
        +user nginx;
        +worker_processes 1;
        +error_log /var/log/nginx/error.log
        +pid	/var/run/nginx.pid;
         
        -events {
        -	worker_connections 768;
        -	# multi_accept on;
        +events{
        +	worker_connections 1024;
         }
 （省略）
```
今度はうまく入りました。
nginx.confがテンプレート(+JSONのAttribute)で指定した内容で置き換わっていることが分かります。
タイポとのバトルがありましたので細かいログは省略してます。

ホストのブラウザ等からこのVMの80番ポートにアクセスすると、nginxのスタートページ(Welcome to nginx！)が表示されることが確認できます。