以下の記事で、Vagrantを使った開発環境を作る手順はまとめたのですが、
本番環境側の構築方法をまとめていなかったので、
この記事で、chef+Berkshelfでサーバを自動構築する手順をまとめておきます。

MacOS上にVagrant+chef(knife)+Berkshelfで開発環境を作る手順
 http://takemikami.com/archives/1367

図の使い回しですが、
Knife Solo/Chef Solo/Berkshelfの役割は以下の通りになります。

Berkshelf:
 公開されているCookbookの取得
Knife Solo:
 ①各ノードへのChef Soloセットアップ
 ②各ノードへのCookbookの転送
 ③Chef Soloの起動
Chef Solo:
 レシピの実行(セットアップ実行)

この記事では、管理サーバをMacOSX、
各ノードをVMwareFusion上のCentOS6.4として説明します。
※AWS EC2などでも基本的な流れは同じになるはずです。

環境構築は次の流れで行います。

  1. Knife Soloのインストール
  2. CentOS6.4のセットアップ
  3. Knifeが利用できるようにCentOSの環境を設定
  4. BerkshelfにあるChefレシピの適用
  5. 自前Chefレシピの作成と適用

Knife Soloのインストール

# この手順は冒頭にリンクした記事と全く同じ(実際コピペ)です

MacOSX(管理サーバ側)で、
以下のコマンドで、Knife Soloの作業用ディレクトリを作成します。

$ mkdir ~/chef-repo

作業用ディレクトリに以下ファイルを作成します。

Gemfile

source 'https://rubygems.org'
gem 'chef'
gem 'knife-solo'
gem 'berkshelf'

Berksfile

site :opscode
cookbook 'nginx'

以下のコマンドで、KnifeSoloとBerkshelfをインストールします。

$ bundle install --path=vendor/bundle

以下のコマンドで、knifeのディレクトリ構成を作成します。

$ bundle exec knife solo init .

ここまでで、以下のような構成になります。
 + Berksfile
 + Gemfile
 + Gemfile.lock
 + cookbooks
 + data_bags
 + nodes
 + roles
 + site-cookbooks
 + vendor

ひとまず、このディレクトリ構成をgitにcommitしておきます。
# .gitignoreに「/vendor/」を追加しておいた方がよいです。

$ git init
$ git add .
$ git commit -a -m "initial commit"

以下のコマンドで、opscodeのリポジトリからnginxと依存するcookbookを取得します。

$ bundle exec berks --path=cookbooks

CentOS6.4のセットアップ

CentOSのサイトから近くのミラーを選んでminimalのISOイメージをダウンロードします。

CentOS
 http://www.centos.org
 ファイル:CentOS-6.4-x86_64-minimal.iso

VMware Fusionを起動し、ファイル→新規から新規仮想マシンを作成、
ダウンロードしたISOイメージをマウントしてインストールを行います。
ネットワークは有効にしておきます。

Knifeが利用できるようにCentOSの環境を設定

VMwareFusionから先ほどインストールしたCentOSを起動します。

MacOSX(管理サーバ側)からCentOS(対象ノード側)にSSH接続できるように、
rootユーザで以下のコマンドを実行し、CentOS側にユーザと公開鍵を追加します。

$ useradd <MacOSXでknifeSoloをインストールしたユーザ名> -G wheel
$ su - <MacOSXでknifeSoloをインストールしたユーザ名>
$ mkdir .ssh
$ chmod 700 .ssh
$ touch .ssh/authorized_keys
$ chmod 600 .ssh/authorized_keys

「.ssh/authorized_keys」に、
MacOSXの公開鍵「.ssh/id_rsa.pub」の内容を追記します。

# SSH認証用の鍵を未作成の場合は、
# MacOSX(管理サーバ側)で、「ssh-keygen -t rsa」コマンドを実行します。

作成したユーザがパスワード無しでroot化できるように、
rootユーザで「visudo」を実行し、次の行をコメントインし有効にします。

%wheel        ALL=(ALL)       NOPASSWD: ALL

BerkshelfにあるChefレシピの適用

MacOSX(管理サーバ側)で、
以下のコマンドを実行し、対象ノードにchefをインストールします。

$ bundle exec knife solo prepare <対象のIPアドレス>
Bootstrapping Chef...
※途中省略※
Thank you for installing Chef!
Generating node config 'nodes/<対象のIPアドレス>.json'...

nodesの下に「<対象のIPアドレス>.json」というファイルができるので、
このファイルを以下のように編集します。

{"run_list":["recipe[nginx]"]}

次のコマンドを実行し、Chefレシピの適用を行います。

$ bundle exec knife solo cook <対象のIPアドレス>
Running Chef on <対象のIPアドレス>...
Checking Chef version...
Installing Berkshelf cookbooks to 'cookbooks'...
※途中省略※
Recipe: nginx::default
* service[nginx] action start
- start service service[nginx]

* service[nginx] action reload
- reload service service[nginx]

Chef Client finished, 22 resources updated

CentOS(対象ノード側)にログインして以下のコマンドを実行すると、
nginxがセットアップされている事が確認できます。

$ ps -ef | grep nginx

しかし、この時点では、
iptableの設定でポート80のアクセスがブロックされているため、
MacOSXからSafariで対象ノードのnginxにアクセスしようとしてもできないはずです。

次に、自前のレシピを作成しiptableの設定をコントロールしてみます。

自前Chefレシピの作成と適用

MacOSX(管理サーバ側)で、
以下のコマンドを実行し、mycookbookというcookbookを作成します。

$ bundle exec knife cookbook create mycookbook -o site-cookbooks/
** Creating cookbook mycookbook
** Creating README for cookbook: mycookbook
** Creating CHANGELOG for cookbook: mycookbook
** Creating metadata for cookbook: mycookbook

site-cookbooks/mycookbook配下に、以下のディレクトリができます。
 + attributes
 + definitions
 + files
 + libraries
 + providers
 + recipes
 + resources
 + templates

mycookbook配下にポート開放用のレシピを作成します。
iptablesの設定ファイルと適用スクリプトの2ファイルです。

site-cookbooks/mycookbook/files/default/iptables

# Firewall configuration written by system-config-firewall
# Manual customization of this file is not recommended.
*filter
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
-A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
-A INPUT -p icmp -j ACCEPT
-A INPUT -i lo -j ACCEPT
-A INPUT -m state --state NEW -m tcp -p tcp --dport 22 -j ACCEPT
-A INPUT -m state --state NEW -m tcp -p tcp --dport 80 -j ACCEPT
-A INPUT -j REJECT --reject-with icmp-host-prohibited
-A FORWARD -j REJECT --reject-with icmp-host-prohibited
COMMIT

site-cookbooks/mycookbook/recipes/nginx-port.rb

cookbook_file "/etc/sysconfig/iptables" do
source "iptables"
owner "root"
group "root"
mode "600"
end
service "iptables" do
supports :status => true, :restart => true, :reload => true
action [ :enable, :restart ]
end

対象ノードのjsonファイルを変更して、作成したレシピが適用されるようにします。

nodes/<対象のIPアドレス>.json

{"run_list":["recipe[nginx]","recipe[mycookbook::nginx-port]"]}

次のコマンドを実行し、Chefレシピの適用を行います。

$ bundle exec knife solo cook <対象のIPアドレス>
Running Chef on <対象のIPアドレス>...
Checking Chef version...
Installing Berkshelf cookbooks to 'cookbooks'...
※途中省略※
Recipe: mycookbook::nginx-port
* cookbook_file[/etc/sysconfig/iptables] action create (up to date)
* service[iptables] action enable (up to date)
* service[iptables] action restart
- restart service service[iptables]

Chef Client finished, 2 resources updated

これで、MacOSXからSafariで対象ノードのnginxにアクセスすると
「Welcome to nginx on EPEL!」
というページが表示されているはずです。

このように、
『レシピの修正』と『「knife solo cook」でのレシピ適用』を繰り返してレシピ開発、
そして、完成したレシピを
本番サーバに適用という流れで、環境構築を行う事になると思います。
# さらに言えばアプリケーション開発者は、
# そのレシピをVagrant upした環境で開発とテストを実施ですね。。