Vagrant + chef-soloでopsworksのrecipeをローカルで試す

Chefやcookbookについては過去のエントリで書きましたが、最近opsworksを使う機会があったので、その辺について書いてみようと。

opsworksAWSサービスでchefベースのサーバ構成ツール
opsworksが提供しているcookbookも使えるし、そのcookbookの一部をカスタマイズしたり、自分で作ったオリジナルのcookbookも登録して実行できる。

opsworksのコンソールから実行すればrecipeの実行はできるが、カスタマイズしたり新規で作ったcookbookを試す為に、ec2のインスタンスをポコポコ立ち上げるのも多少お金がかかるし、落とし忘れたら大きめの請求が来て悲しい気持ちになるので、ローカルで試せるものはなるべくローカルで試してみたい!

ということで、ローカルでrecipeを実行する為の、環境づくりや方法について説明していきます。
recipeを実行する先は自分のPCではなく、今流行(流行りに乗るのがだいぶ遅いけど)のVagrantを使います。
Vagrantについては詳しく説明しているサイトが他にもいっぱいあるので、詳しくはそちらを参照して下さい)


以下の説明はMac向けの説明となります。

VirtualBoxのインストール

VirtualBoxを以下のサイトからダウンロードして、インストールします。
https://www.virtualbox.org/wiki/Downloads

Vagrantのインストール

Vagrantを以下のサイトからダウンロードして、インストールします。
http://www.vagrantup.com/downloads.html

どちらもインストーラーなので、簡単ですね。

Vagrant仮想マシンを作る

ここからはターミナルを使って作業していきます。

どこか好きな所にディレクトリを作ってその中で作業します

$ mkdir ~/Documents/Vagrant
$ cd ~/Documents/Vagrant

今回はubuntuのイメージを使って作業するので、ubuntuのboxを作成します。
こちらのサイトに色々なイメージが公開されているので、使いたいものを選びます。
VirtualBox用を使うこと)

http://www.vagrantbox.es/

$ vagrant box add ubuntu12_04 http://cloud-images.ubuntu.com/vagrant/precise/current/precise-server-cloudimg-amd64-vagrant-disk1.box

VagrantFileを作ります

$ mkdir ubuntu
$ cd ubuntu
$ vagrant init ubuntu12_04

起動してみます

$ vagrant up

Bringing machine 'default' up with 'virtualbox' provider...
[default] Importing base box 'ubuntu12_04'...
[default] Matching MAC address for NAT networking...
[default] Setting the name of the VM...
[default] Clearing any previously set forwarded ports...
[default] Clearing any previously set network interfaces...
[default] Preparing network interfaces based on configuration...
[default] Forwarding ports...
[default] -- 22 => 2222 (adapter 1)
[default] Booting VM...
[default] Waiting for machine to boot. This may take a few minutes...
[default] Machine booted and ready!
[default] The guest additions on this VM do not match the installed version of
VirtualBox! In most cases this is fine, but in rare cases it can
prevent things such as shared folders from working properly. If you see
shared folder errors, please make sure the guest additions within the
virtual machine match the version of VirtualBox you have installed on
your host and reload your VM.

Guest Additions Version: 4.1.12
VirtualBox Version: 4.3
[default] Mounting shared folders...
[default] -- /vagrant

起動しました。

通常は、vagrant ssh仮想マシンに入れますが、後でrecipeを実行するときに不便なので、ssh hogehoge で入れるように設定します。

以下のコマンドsshのconfigに記載する情報を表示します

$ vagrant ssh-config

Host default
  HostName 127.0.0.1
  User vagrant
  Port 2222
  UserKnownHostsFile /dev/null
  StrictHostKeyChecking no
  PasswordAuthentication no
  IdentityFile /Users/hogehoge/.vagrant.d/insecure_private_key
  IdentitiesOnly yes
  LogLevel FATAL

表示された内容を~/.ssh/config に追記します

$ vi ~/.ssh/config

Host vagrant-ubuntu
  HostName 127.0.0.1
  User vagrant
  Port 2222
  UserKnownHostsFile /dev/null
  StrictHostKeyChecking no
  PasswordAuthentication no
  IdentityFile /Users/hogehoge/.vagrant.d/insecure_private_key
  IdentitiesOnly yes
  LogLevel FATAL

入れるか試します

$ ssh vagrant-ubuntu

Welcome to Ubuntu 12.04.4 LTS (GNU/Linux 3.2.0-59-generic x86_64)

 * Documentation:  https://help.ubuntu.com/

  System information as of Sat Feb 22 00:24:13 UTC 2014

  System load:  0.0               Processes:           64
  Usage of /:   2.7% of 39.37GB   Users logged in:     0
  Memory usage: 10%               IP address for eth0: 10.0.2.15
  Swap usage:   0%

  Graph this data and manage this system at:
    https://landscape.canonical.com/

  Get cloud support with Ubuntu Advantage Cloud Guest:
    http://www.ubuntu.com/business/services/cloud

0 packages can be updated.
0 updates are security updates.

vagrant@vagrant-ubuntu-precise-64:~$

入れました!

仮想マシンの準備ができたので、仮想サーバから抜けて、先ほどのディレクトリ(~/Documents/Vagrant/ubuntu)に戻ります。

chef-soloのセットアップ

Macの方にknife-soloが必要なので、gemで入れます。

今回試したrubyの環境は、以下のとおりです

$ ruby -v
ruby 2.0.0p247 (2013-06-27 revision 41674) [universal.x86_64-darwin13]

$ gem -v
2.0.3

knife-soloをインストール

$ sudo gem install knife-solo

バージョンを確認すると

$ knife -v

Chef: 11.10.4

chef-repoを作る

cookbookなどを含めるディレクトリをknifeコマンドで作ります

$ knife solo init opsworks-test

WARNING: No knife configuration file found
Creating kitchen...
Creating knife.rb in kitchen...
Creating cupboards...

作成されたディレクトリに移動します

$ cd opsworks-test

ディレクトリ内に作られたファイルとかは以下の様な感じ

opsworks-test/
    .chef
    .gitignore
    cookbooks
    data_bags
    environments
    nodes
    roles
    site-cookbooks

cookbooksディレクトリは、opsworksのcookbookを置くので、一旦削除してgithub上のリポジトリをcookbooksとしてcloneします。

$ rm -rf cookbooks
$ git clone https://github.com/aws/opsworks-cookbooks.git cookbooks

一回、opsworksで用意されているcookbookを試してみます。

cookbookを実行するためには、対象の仮想マシンにchef-soloが入っている必要があります。
仮想マシンに入ってインストールしてもいいですが、以下のコマンドで必要な物をインストールすることが出来ます。

$ knife solo prepare vagrant-ubuntu

セットアップが完了すると、nodes/vagrant-ubuntu.jsonMac上に作られます。
ファイルの中身は、

{"run_list":[]}

となっているので、run_listに実行するrecipeを書きます。
(run_listにカンマ区切りで書けば複数のrecipeを実行することが出来ます)

$ vi nodes/vagrant-ubuntu.json

run_listにnginxを追加しました

{
  "run_list":[
      "nginx"
  ]
}

recipeを実行します

$ knife solo cook vagrant-ubuntu

ちゃんとnginxがインストールされたか見てみます。

$ ssh vagrant-ubuntu
$ ps aux | grep nginx

root      3456  0.0  0.2  62876  1336 ?        Ss   02:11   0:00 nginx: master process /usr/sbin/nginx
www-data  3457  0.0  0.3  63212  1912 ?        S    02:11   0:00 nginx: worker process
www-data  3458  0.0  0.3  63212  1912 ?        S    02:11   0:00 nginx: worker process
www-data  3459  0.0  0.3  63212  1912 ?        S    02:11   0:00 nginx: worker process
www-data  3460  0.0  0.3  63212  1912 ?        S    02:11   0:00 nginx: worker process
www-data  3461  0.0  0.3  63212  1912 ?        S    02:11   0:00 nginx: worker process
www-data  3462  0.0  0.3  63212  1912 ?        S    02:11   0:00 nginx: worker process
www-data  3463  0.0  0.3  63212  1912 ?        S    02:11   0:00 nginx: worker process
www-data  3464  0.0  0.3  63212  1912 ?        S    02:11   0:00 nginx: worker process
www-data  3465  0.0  0.3  63212  1912 ?        S    02:11   0:00 nginx: worker process
www-data  3466  0.0  0.3  63212  1912 ?        S    02:11   0:00 nginx: worker process
vagrant   3654  0.0  0.1   8108   928 pts/0    S+   02:12   0:00 grep --color=auto nginx

ちゃんと入ってました。

次は自分で作ったrecipeを実行できるようにします。

カスタムcookbookの実行

カスタムのcookbookは、site-cookbooksに配置します。

opsworksのコンソールでgitのリポジトリを指定している場合は、そのリポジトリをsite-cookbooksにcloneします。
例)

$ rm -rf site-cookbooks
$ git clone <カスタムリポジトリを指定> site-cookbooks

今回は、サンプルとしてnginxに以下の変更を加えます。

  • worker processを2つにする
  • access_logのフォーマットをltsvに変更

カスタムcookbookを置くディレクトリを作って、opsworksのcookbookからnginxのテンプレートをコピーします

$ mkdir -p site-cookbooks/nginx/templates/default
$ cp cookbooks/nginx/templates/default/nginx.conf.erb site-cookbooks/nginx/templates/default/nginx.conf.erb
$ cp cookbooks/nginx/templates/default/default-site.erb site-cookbooks/nginx/templates/default/default-site.erb

nginx.conf.erbを編集します

$ vi site-cookbooks/nginx/templates/default/nginx.conf.erb

〜〜〜
http {
   〜〜〜

  access_log    <%= node[:nginx][:log_dir] %>/access.log;

  log_format  ltsv  'time:$time_local\t'
                            'host:$remote_addr\t'
                            'request:$request\t'
                            'status:$status\t'
                            'size:$body_bytes_sent\t'
                            'referer:$http_referer\t'
                            'ua:$http_user_agent\t'
                            'reqtime:$request_time\t'
                            'upsttime:$upstream_response_time';

default-site.erbを編集します

$ vi site-cookbooks/nginx/templates/default/default-site.erb

server {
  listen   80;
  server_name  127.0.0.1;

  access_log  <%= node[:nginx][:log_dir] %>/localhost.access.log ltsv;

  location / {
    root   /var/www/nginx-default;
    index  index.html index.htm;
  }
}

recipeやtemplateで使われているattributeを上書く場合は、先ほどのnodes/vagrant-ubuntu.json に書きます。

$ vi nodes/vagrant-ubuntu.json

{
  "run_list":[
      "nginx"
  ],
  "nginx":{
    "worker_processes": 2
  }
}

実行します

$ knife solo cook vagrant-ubuntu

ちゃんと反映されたか確認します。

$ ssh vagrant-ubuntu
$ sudo service nginx restart
$ ps aux | grep nginx

root      5197  0.0  0.2  62876  1216 ?        Ss   02:45   0:00 nginx: master process /usr/sbin/nginx
www-data  5198  0.0  0.3  63212  1916 ?        S    02:45   0:00 nginx: worker process
www-data  5199  0.0  0.3  63212  1916 ?        S    02:45   0:00 nginx: worker process
vagrant   5201  0.0  0.1   8108   932 pts/0    S+   02:45   0:00 grep --color=auto nginx

worker processが2つになりました。

次にテンプレートが反映されたか確認するので、デフォルトのindex.htmlを用意します

$ sudo mkdir -p /var/www/nginx-default
$ sudo touch /var/www/nginx-default/index.html
$ curl -I http://localhost/

HTTP/1.1 200 OK
Server: nginx/1.1.19
Date: Sat, 22 Feb 2014 02:52:36 GMT
Content-Type: text/html
Content-Length: 0
Last-Modified: Sat, 22 Feb 2014 02:51:03 GMT
Connection: keep-alive
Accept-Ranges: bytes

ログを見ると

$ cat /var/log/nginx/localhost.access.log

time:22/Feb/2014:02:52:36 +0000	host:127.0.0.1	request:HEAD / HTTP/1.1	status:200	size:0	referer:-	ua:curl/7.22.0 (x86_64-pc-linux-gnu) libcurl/7.22.0 OpenSSL/1.0.1 zlib/1.2.3.4 libidn/1.23 librtmp/2.3	reqtime:0.000	upsttime:-

ちゃんと、ltsv形式になっています。

これで、opsworksのcookbookとカスタムcookbookを組み合わせたrecipeの実行がローカルでも出来るようになりました!
もう、EC2の料金を気にしなくても、recipeのテストが出来ますね。

仮想マシンなので、何度繰返してもvagrant destroyしてから、vagrant up すれば、いつでもまっさらな環境でテストできるのがいいですね。

次は、jenkinsと組み合わせてrecipeのテストにチャレンジしようと思います。