ChefでEC2インスタンスの起動から初期設定までを行う

前回はChefのサーバとクライアントをインストールして、簡単なチュートリアルを試してみました。今回はより実践的な内容をやってみようと思います。

やること

chefとknifeを用いて、EC2インスタンスの起動と(ごく簡単な)設定を行う。

構成

  • chef-server: CentOS6 on EC2 (t1.micro)
  • 設定対象ノード: CentOS6 on EC2 (t1.micro)
    • knife-ec2を用いて起動〜設定までを行う対象 (chef-client)
  • workstation: CentOS6 on EC2 (t1.micro)
    • knifeコマンドを実行する端末(chef-client)

CentOS6はsuz-labさんが提供している ami-46902747 をベースに、カーネル以外のパッケージを最新にして AMI 化しておいたものを用いる。

事前準備

chef-server

手順は簡単。たったこれだけ。epelのリポジトリは最初から使えるようになっているので、無問題。

# yum install couchdb erlang rabbitmq-server libxml2-devel zlib-devel.x86_64 --enablrepo=epel
# rpm -Uvh http://rbel.frameos.org/rbel6
# yum install ruby ruby-devel ruby-ri ruby-rdoc ruby-shadow gcc gcc-c++ automake autoconf make curl dmidecode --enablerepo=rbel6
# yum install rubygem-chef-server --enablerepo=rbel6
# setup-chef-server.sh

workstation (chef-client)

インストール〜初期設定

knifeコマンドを実行したり、cookbookなどの編集を行うためのchef-client。こちらも簡単。
libxml2-develとlibxslt-develはknife-ec2をインストールするために必要となる。

# rpm -Uvh http://rbel.frameos.org/rbel6
# yum install rubygem-chef --enablerepo=epel,rbel6
# yum install ruby-devel libxml2-devel libxslt-devel --enablerepo=epel,rbel6
# gem install knife-ec2
# scp user@chef-server:/etc/chef/validation.pem /etc/chef/validation.pem
# vi /etc/chef/client.rb
chef_server_url 'http://chef-server:4000'
node_name       'matetsu-work'
# chef-client

ここで通常作業する一般ユーザに切り替える。

$ knife configure
$ sudo chmod 644 /etc/chef/client.pem
$ ln -s /etc/chef/client.pem ~/.chef/matetsu-work.pem

ここで、server-webuiにログインして、登録したクライアント(matetsu-work)にadmin権限を与えておく。

Cookbookなどの準備

knife-ec2でEC2インスタンスを操作できるようにACCESS KEYなどを設定する。
~/.chef/knife.rb に以下を設定する。

knife[:aws_access_key_id] = "hoge"
knife[:aws_secret_access_key] =  "fuga"

最終的にはRailsアプリを動かすところまでやりたいので、rails-quick-startを使うことにする。とりあえずはあるものをserverに上げてしまう。ただ、この rails-quick-start のリポジトリにあるのは、Ubuntuで動かすための設定なので、CentOSの場合は変更すべきところが何点かあるが、今は気にしない。

$ git clone git://github.com/opscode/rails-quick-start.git
$ knife cookbook upload -a -o ./cookbooks/
$ rake roles
$ knife data bag from file apps radiant.json

EC2インスタンス起動時に最初に実行するコマンド群を記述したbootstrapをubuntu用から、CentOS用に作り変える。

$ cp .chef/bootstrap/ubuntu10.04-gems-qs.erb .chef/bootstrap/centos6-chef.erb[]

内容は以下のような感じ。

bash -c '
<%= "export http_proxy=\"#{knife_config[:bootstrap_proxy]}\"" if knife_config[:bootstrap_proxy] -%>

if [ ! -f /usr/bin/chef-client ]; then
  rpm -Uvh http://rbel.frameos.org/rbel6
  yum install -y rubygem-chef ruby-devel libxml2-devel libxslt-devel wget --enablerepo=epel,rbel6
fi

mkdir -p /etc/chef

(
cat <<'EOP'
<%= validation_key %>
EOP
) > /tmp/validation.pem
awk NF /tmp/validation.pem > /etc/chef/validation.pem
rm /tmp/validation.pem

(
cat <<'EOP'
<%= config_content %>
EOP
) > /etc/chef/client.rb

(
cat <<'EOP'
<%= { "run_list" => @run_list }.to_json %>
EOP
) > /etc/chef/first-boot.json

<%= start_chef %>'

roleのbaseを今回必要なものだけに絞るためにコピーをする。

$ roles/base.rb roles/centos_base.rb

内容はこんな感じ。gitはgitパッケージのインストールで、build-essentialはgccなどの開発ツールパッケージのインストール。

name "centos_base"
description "Base role applied to all centos nodes."
run_list(
  "recipe[git]",
  "recipe[build-essential]"
)

ちなみに、レシピ build-essential の centos向けの設定を以下のように変えている。

when "centos","redhat","fedora"
  %w{gcc gcc-c++ make automake}.each do |pkg|
    package pkg do
      action :install
    end
  end
end

変更をserverに反映する。

$ knife cookbook upload -o ./cookbooks/ build-essential
$ rake roles
EC2インスタンスの起動から初期設定まで

準備したcookbookやroleを用いて、実際にEC2インスタンスの起動〜初期設定を行ってみる。これまた簡単。knife ec2コマンドで一発です。

$ knife ec2 server create -G [SECURITY_GROUP] -I [AMI_ID] -f [INSTANCE_KIND] -S [KEY_PAIR_NAME] -i [PRIVATE_KEY_FILE] -x [EC2_LOGIN_USER] -d [BOOTSTRAP_FILE] -r '[COMMA_SEPARATED_ROLES_OR_RECIPES]' --region [REGION_NAME] -Z [AZ_NAME]

これでAMIからEC2インスタンスを作成、bootstrapに記述された内容を実行、roleで指定されたレシピの実行が行われ、初期設定が完了した状態のノードが完成する。起動したインスタンスのIPなどは、server-webuiのnode一覧からも確認できますし、コマンド実行完了後に標準出力にも出力される。

こんな感じでコマンド一発で求める環境ができちゃうなんて、感動ですね。なんでもっと早く使っていなかったんだろう。

次は、railsアプリが動いている状態を作れるようにしたいと思います。