話題の記事

EC2のChef SandboxをVagrant+BerkShelfでさくっと作る

2013.04.24

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

ども、大瀧です。
社内でそこかしこから"Chefで〜"、"Chefが〜"と聞こえるようになってきました。来月、Chefについてお話しする機会なんてのも巡ってきたので、日頃からChefを触っておかねばと一念発起しました!

が、Chefの環境作るのって結構面倒なんですよね。そこで、最近EC2に対応したVagrantを使ってChefのお勉強環境(Sandbox)をさくっと作ってみます。例によって、説明はいっぱい書いてありますが、かいつまんで目を通して、ところどころのコマンドを実行していく感じで見ていただくのがいいと思います。

使ってみたツール

  • Chef Solo : Chefの実行方法はyamatoさんの記事にあるChef Server & Clientもありますが、今回はCookbookの勉強が目的なので、より簡単に構築できるChef Soloで行きます。
  • Berkshelf : ChefのCookbook管理ソフトウェア。Ruby(gems)のBundler、PHPのComposerと言った、LLのライブラリ管理ソフトウェアと同じ発想で、数あるChef Cookbookをうまーくコーディネートしてくれる(らしい)仕組みです。Chefの実行に必須というわけではありませんが、公開されているCookbookの賢いインポートができるので、Cookbookの写経、勉強するのに便利です。
  • Vagrant : 元はSun(現ORACLE)の仮想化ソフトウェア、Virtual Boxの仮想マシンを管理するためのツール。バージョン1.1でEC2&VPCに対応しました。Chef Soloとの連携機能があるので、1つの設定ファイルからEC2インスタンスの作成、起動とChef Soloの実行をコマンド一発で行えます。

1. AMI(EC2)のセットアップ

Chef Soloのインストール

まずは、Chef Solo(=Client)がインストール済みのAMIを準備します。今回はAmazon Linuxを使うので、公式のAMIからインスタンスを起動、SSH接続でec2-userでログインしChef Soloをインストールします。

[ec2-user@ip-XXX-XXX-XXX-XXX ~]$ curl -L https://www.opscode.com/chef/install.sh | sudo bash
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100  6471  100  6471    0     0   7930      0 --:--:-- --:--:-- --:--:-- 10337
Downloading Chef  for el...
Installing Chef
warning: /tmp/tmp.iHulWn0G/chef-.x86_64.rpm: Header V4 DSA/SHA1 Signature, key ID 83ef826a: NOKEY
Preparing...                ########################################### [100%]
   1:chef                   ########################################### [100%]
Thank you for installing Chef!
[ec2-user@ip-XXX-XXX-XXX-XXX ~]$ chef-solo -v
Chef: 11.4.0
[ec2-user@ip-XXX-XXX-XXX-XXX ~]$

sudoの設定変更

Amazon Linuxの初期設定では、Vagrantからsudoコマンドを実行できないようになっていますが、Chef Soloを実行するために必要です。あらかじめsudoの設定をvisudoコマンドで変更します。

[ec2-user@ip-XXX-XXX-XXX-XXX ~]$ sudo visudo
Defaults    requiretty
  ↓
#Defaults    requiretty

AMIの作成

セットアップしたEC2からAMIを作成します。

スクリーンショット 2013-04-24 13.50.59

2. Berkshelfのセットアップ

Berkshelfは、Vagrantを実行するPCにgemコマンドでインストールします。gemコマンドは、Rubyのライブラリ管理を行うRubyGemsに含まれるため、あらかじめRubyおよびRubyGemsをセットアップしておく必要があります。RubyGemsのインストールは、今回は割愛します。

vagrant_machine:~ $ sudo gem install berkshelf --no-ri --no-rdoc
Fetching: berkshelf-1.4.0.gem (100%)
Successfully installed berkshelf-1.4.0
1 gem installed
vagrant_machine:~ $

※ Berkshelfに依存するいくつかのgemがインストールされる場合もあります。rbenv環境の場合は、rbenv rehashの実行を忘れずに!

Berkshelfは、berksコマンドで動作します。

vagrant_machine:~ $ berks -v
Berkshelf (1.4.0)

Author:: Jamie Winsor (<reset@riotgames.com>)
Author:: Josiah Kiehl (<jkiehl@riotgames.com>)
Author:: Michael Ivey (<michael.ivey@riotgames.com>)
Author:: Justin Campbell (<justin.campbell@riotgames.com>)

Copyright 2012 Riot Games
         :

3. Vagrantのセットアップ

Vagrantのインストールは、以前はgemコマンドでしたが最近のバージョンではインストーラをダウンロード、実行します。今回は現時点で最新のバージョン1.2.1を使用します。OSX Mountain Lionで動作確認していますが、Windows版、Linux版もあります。

vagrant01

Vagrantをインストールすると、vagrantコマンドを実行できるようになります。続いて、VagrantでEC2を管理するためにvagrant-awsプラグイン、berkshelfのCookbookをVagrantで読み込むためのvagrant-berkshelfプラグインをインストールします。

vagrant_machine:~ $ vagrant plugin install vagrant-aws
Installing the 'vagrant-aws' plugin. This can take a few minutes...
Installed the plugin 'vagrant-aws (0.2.2)'!
vagrant_machine:~ $ vagrant plugin install vagrant-berkshelf
Installing the 'vagrant-berkshelf' plugin. This can take a few minutes...
Installed the plugin 'vagrant-berkshelf (1.2.0)'!
vagrant_machine:~ $ vagrant plugin list
vagrant-aws (0.2.2)
vagrant-berkshelf (1.2.0)
vagrant_machine:~ $

Vagrantでは、管理する仮想マシン(今回はEC2インスタンス)のひな形をBoxとして管理します。EC2インスタンスの場合は、AMIをベースにするため、EC2用の空のBox(dummy)を使用します。ここで、dummy boxをインポートしておきます。既にdummy boxをインポート済みの場合は、他の適当なbox名で構いません。

vagrant_machine:~ $ vagrant box add dummy https://github.com/mitchellh/vagrant-aws/raw/master/dummy.box
Downloading or copying the box...
Extracting box...e: 0/s, Estimated time remaining: --:--:--)
Successfully added box 'dummy' with provider 'aws'!

Chef環境構築を一発実行!

材料がそろったので、1.のAMIをベースにBerkShelfでCookbookを選択、VagrantでEC2インスタンスを立ち上げ、Chef Soloを適用します。

Cookbook & Vagrantのひな形を作成

berksコマンドでCookbookのひな形を作成します。

vagrant_machine:~ $ berks cookbook sample-berkshelf
      create  sample-berkshelf/files/default
      create  sample-berkshelf/templates/default
      create  sample-berkshelf/attributes
      create  sample-berkshelf/definitions
      create  sample-berkshelf/libraries
      create  sample-berkshelf/providers
      create  sample-berkshelf/recipes
      create  sample-berkshelf/resources
      create  sample-berkshelf/recipes/default.rb
      create  sample-berkshelf/metadata.rb
      create  sample-berkshelf/LICENSE
      create  sample-berkshelf/README.md
      create  sample-berkshelf/Berksfile
      create  sample-berkshelf/chefignore
      create  sample-berkshelf/.gitignore
         run  git init from "./sample-berkshelf"
      create  sample-berkshelf/Gemfile
      create  sample-berkshelf/Vagrantfile
Using sample-berkshelf (0.1.0) at path: '/Users/XXXXXX/sample-berkshelf'

Cookbook名(今回はsample-berkshelf)のディレクトリが作成され、いくつかのひな形ファイルが作成されます。
今回の構成でいじるファイルをピックアップします。

  • Berksfile : Berkshelfの構成ファイル。ロードしたいCookbookを定義します。
  • Vagrantfile : Vagrantの構成ファイル。vagrantコマンドで作成することもできますが、Berkshelf向けの設定が入っているので、このあとEC2向けに修正・追加します。

Cookbookの作成、選択

EC2に適用するChefのCookbookを用意します。berksコマンドでひな形は作成済みなので、自前のRecipeを追加する感じです。また、Berksfileファイルに既存のCookbookを記述することで、Cookbookのインポートを行うこともできます。今回は、Opscodeのnginx Cookbookをインポートしてみます。

vagrant_machine:~ $ cd sample-berkshelf
vagrant_machine:~ $ vi Berksfile
site :opscode

metadata
cookbook 'nginx'

Cookbookのインポートは、RubyのBundlerと同様にberksコマンドを実行します。 BerkshelfでインポートしたCookbookは、~/.berkshelf/cookbooks/以下に配置されます。

vagrant_machine:~ $ berks
Installing nginx (1.4.0) from site: 'http://cookbooks.opscode.com/api/v1/cookbooks'
Installing bluepill (2.2.2) from site: 'http://cookbooks.opscode.com/api/v1/cookbooks'
Installing rsyslog (1.5.0) from site: 'http://cookbooks.opscode.com/api/v1/cookbooks'
Installing runit (0.16.2) from site: 'http://cookbooks.opscode.com/api/v1/cookbooks'
Installing build-essential (1.4.0) from site: 'http://cookbooks.opscode.com/api/v1/cookbooks'
Installing yum (2.2.0) from site: 'http://cookbooks.opscode.com/api/v1/cookbooks'
Installing apt (1.9.2) from site: 'http://cookbooks.opscode.com/api/v1/cookbooks'
Installing ohai (1.1.8) from site: 'http://cookbooks.opscode.com/api/v1/cookbooks'
vagrant_machine:~ $ ls ~/.berkshelf/cookbooks/
apt-1.9.2/             build-essential-1.4.0/ ohai-1.1.8/            runit-0.16.2/
bluepill-2.2.2/        nginx-1.4.0/           rsyslog-1.5.0/         yum-2.2.0/

Vagrantfileの修正

Vagrantで管理するEC2インスタンスの設定を、Vagrantfileファイルに記述します。以下2点を修正します。

  • BerkshelfによるVirtualBox向けの設定が既にあるので、EC2用に書き換える
  • インスタンスに適用するChef Soloレシピを指定する

Vagrantバージョン1.2で、EC2インスタンスに接続するときのSSH構成の書き方が変わりました。バージョン1.1までの書き方では、vagrant sshコマンドがエラーになるので、注意してください。

vagrant_machine:~ $ vi Vagrantfile

項目が多かったので、diffの結果を貼付けます。

vagrant_machine:~ $ diff -u Vagrantfile.org Vagrantfile
--- Vagrantfile.org	2013-04-24 08:01:19.000000000 +0900
+++ Vagrantfile	2013-04-24 08:13:56.000000000 +0900
@@ -6,20 +6,20 @@
   # options are documented and commented below. For a complete reference,
   # please see the online documentation at vagrantup.com.

-  config.vm.hostname = "sample-berkshelf-berkshelf"
+  #config.vm.hostname = "sample-berkshelf-berkshelf"

   # Every Vagrant virtual environment requires a box to build off of.
-  config.vm.box = "Berkshelf-CentOS-6.3-x86_64-minimal"
+  config.vm.box = "dummy"

   # The url from where the 'config.vm.box' box will be fetched if it
   # doesn't already exist on the user's system.
-  config.vm.box_url = "https://dl.dropbox.com/u/31081437/Berkshelf-CentOS-6.3-x86_64-minimal.box"
+  #config.vm.box_url = "https://dl.dropbox.com/u/31081437/Berkshelf-CentOS-6.3-x86_64-minimal.box"

   # Assign this VM to a host-only network IP, allowing you to access it
   # via the IP. Host-only networks can talk to the host machine as well as
   # any other machines on the same network, but cannot be accessed (through this
   # network interface) by any external networks.
-  config.vm.network :private_network, ip: "33.33.33.10"
+  #config.vm.network :private_network, ip: "33.33.33.10"

   # Create a public network, which generally matched to bridged network.
   # Bridged networks make the machine appear as another physical device on
@@ -71,16 +71,28 @@
   # config.berkshelf.except = []

   config.vm.provision :chef_solo do |chef|
-    chef.json = {
-      :mysql => {
-        :server_root_password => 'rootpass',
-        :server_debian_password => 'debpass',
-        :server_repl_password => 'replpass'
-      }
-    }
+    # chef.json = {
+    #   :mysql => {
+    #     :server_root_password => 'rootpass',
+    #     :server_debian_password => 'debpass',
+    #     :server_repl_password => 'replpass'
+    #   }
+    # }

     chef.run_list = [
-        "recipe[sample-berkshelf::default]"
+        "recipe[nginx]"
     ]
   end
+  config.vm.provider :aws do |aws, override|
+    aws.access_key_id     = "<AWS_ACCESS_KEY>"
+    aws.secret_access_key = "<AWS_SECRET_ACCESS_KEY>"
+    aws.keypair_name = "<KeyPair>"
+    aws.instance_type = "t1.micro"
+    aws.region = "ap-northeast-1"
+    aws.ami = "ami-XXXXXXXX"
+    aws.security_groups = [ '<Security_Group>' ]
+
+    override.ssh.username = "ec2-user"
+    override.ssh.private_key_path = "<Your_SSH_Private_Key>.pem"
+  end
 end
vagrant_machine:~ $

インスタンスの作成、起動、Chef Soloの実行

準備ができたら、いよいよインスタンス作成&起動です。vagrant upコマンドの実行で、AMIからのEC2インスタンス作成、起動、Chef Soloの実行まで一気にやってくれます。うまくいけば結構感動モノです。

vagrant_machine:~ $ vagrant up --provider=aws
Bringing machine 'default' up with 'aws' provider...
[Berkshelf] Updating Vagrant's berkshelf: '/Users/XXXXXX/.berkshelf/vagrant/berkshelf-20130424-2472-weucfz'
[Berkshelf] Using sample-berkshelf (0.1.0) at path: '/Users/XXXXXX/Vagrants/sample-berkshelf'
[Berkshelf] Using nginx (1.4.0)
[Berkshelf] Using bluepill (2.2.2)
[Berkshelf] Using rsyslog (1.5.0)
[Berkshelf] Using runit (0.16.2)
[Berkshelf] Using build-essential (1.4.0)
[Berkshelf] Using yum (2.2.0)
[Berkshelf] Using apt (1.9.2)
[Berkshelf] Using ohai (1.1.8)
[default] Warning! The AWS provider doesn't support any of the Vagrant
high-level network configurations (`config.vm.network`). They
will be silently ignored.
[default] Launching an instance with the following settings...
[default]  -- Type: t1.micro
[default]  -- AMI: ami-XXXXXXXX
[default]  -- Region: ap-northeast-1
[default]  -- Keypair: XXXXXX
[default]  -- Security Groups: ["XXXXXX"]
[default] Waiting for instance to become "ready"...
[default] Waiting for SSH to become available...
[default] Machine is booted and ready for use!
[default] Rsyncing folder: /Users/XXXXXX/Vagrants/sample-berkshelf/ => /vagrant
[default] Rsyncing folder: /Users/XXXXXX/.berkshelf/vagrant/berkshelf-20130424-2472-weucfz/ => /tmp/vagrant-chef-1/chef-solo-1/cookbooks
[default] Running provisioner: chef_solo...
Generating chef JSON and uploading...
Running chef-solo...
[2013-04-24T04:58:43+00:00] INFO: *** Chef 11.4.4 ***
[2013-04-24T04:58:46+00:00] INFO: Setting the run_list to ["recipe[nginx]"] from JSON
[2013-04-24T04:58:46+00:00] INFO: Run List is [recipe[nginx]]
[2013-04-24T04:58:46+00:00] INFO: Run List expands to [nginx]
[2013-04-24T04:58:46+00:00] INFO: Starting Chef Run for ip-10-130-91-13.ap-southeast-1.compute.internal
[2013-04-24T04:58:46+00:00] INFO: Running start handlers
[2013-04-24T04:58:46+00:00] INFO: Start handlers complete.
  : (以下、Chef Soloの実行結果がつづく)
vagrant_machine:~ $

EC2インスタンスへのSSH接続は、vagrant sshコマンドでいけます。Opscodeのnginx Recipeは、Nginxのインストールと設定ファイルの配置を行うようなので、EC2インスタンスに構成済みかどうか、それぞれ確認してみます。

vagrant_machine:~ $ vagrant ssh
Last login: Wed Apr 24 04:47:23 2013 from XXXXXXXXXXXXX

       __|  __|_  )
       _|  (     /   Amazon Linux AMI
      ___|\___|___|

https://aws.amazon.com/amazon-linux-ami/2013.03-release-notes/
There are 10 security update(s) out of 17 total update(s) available
Run "sudo yum update" to apply all updates.
[ec2-user@ip-XXX-XXX-XXX-XXX ~]$ rpm -q nginx
nginx-1.2.7-2.8.amzn1.x86_64
[ec2-user@ip-XXX-XXX-XXX-XXX ~]$ ls /etc/nginx/
conf.d        fastcgi.conf.default  fastcgi_params.default  koi-win     mime.types.default  nginx.conf.default  scgi_params.default  sites-enabled  uwsgi_params.default
fastcgi.conf  fastcgi_params        koi-utf                 mime.types  nginx.conf          scgi_params         sites-available      uwsgi_params   win-utf
[ec2-user@ip-XXX-XXX-XXX-XXX ~]$ exit
vagrant_machine:~ $

ちゃんと入ってますね。

Cookbookを追加した、Recipeをいじった、というときはvagrant provisionコマンドでChef Soloを再実行できます。Recipeで試行錯誤するときにはvagrant provisionvagrant sshがメインになると思います。

後片付け

一通りいじって"疲れた"とか"飽きてきた"ときには、EC2インスタンスを削除(Terminate)しちゃいましょう。これもvagrant destroyコマンドで一発です。

vagrant_machine:~ $ vagrant destroy
[default] Terminating the instance...

Vagrantには、vagrant haltという仮想マシンをシャットダウンするコマンドもあるのですが、現状EC2インスタンスでは動きません。Chefの実験環境で使う分には、手元にCookbookも残りますし、インスタンスをTerminateする運用でさほど困らないのでは、と思います。

まとめ

今回はChefの実験環境としてCookbookを管理するBerkshelfと、EC2インスタンスを管理するVagrantを組み合わせて使ってみました。
ちょっと欲張っていろんなツールを引っ張ってきましたが、Chefの実験環境としてはまずまずのものになっているのではないでしょうか。みなさんのChef力向上の一歩になると幸いです。