Vagrant 1.1 で EC2 を vagrant up

Vagrant 1.1 がリリースされました。 Vagrant は仮想サーバーのフロントエンドのツール、詳しくは Vagrant - naoyaのはてなダイアリー あたりを。

で、この 1.1 が 1.0 → 1.1 という割に結構大きなアップデートで新しく VMVirtualBox 以外のものが選択できるようになった。すなわち「VirtualBox のフロントエンド = Vagrant」から「各種仮想マシンのフロントエンド = Vagrant」という風にアップデートされた。

今回の 1.1 からVMを操作するproviderがプラグイン構造となり、VirtualBoxだけならず、公式で操作できる対象が増えました。

VMware Fusion以外はオープンソースで公開されています。

みんな「おっ」と反応するだろう点、その仮想マシンというのがローカルのみならず Amazon EC2 や Rackspace に対応してるじゃあーりませんか。vagrant up で EC2 インスタンスが立ちちあがるんですよ、胸熱!

これに伴いドキュメントも v.1.1 向けにアップデートされたようです。

v2 というタグがついているように、バージョンは v1.1 でも内部的には 2 という扱いみたい。

Version 1.1 での注意点

早速やってみますがその前に2点ほど

  • Vagrant の配布が rubygems ではなくなりパッケージ形式になった。gem install vagrant はもう古いから v1.1 使う場合は削除してパッケージ版を入れろ、とのことです
    • rubygems から gem install しても v1.0 系しか入らない
    • どうもパスの関係か何かで、例えば github + Bundler なかで入れた場合は動作が保証できないと警告が出る
  • Vagrantfile の書き方が少し変わった。具体的には Vagrant.configure("2") とバージョン番号を指定する。以前のように Vagrant::Config.run した場合は v1.0 系の後方互換モードになる

あたりに注意。

個人的にはあんまりシステムワイドなパスに入れたくないんだけど、まあしょうがない。というわけで

$ /usr/sbin/vagrant -v
Vagrant version 1.1.0

バージョン 1.1 でございます。

Vagrant で EC2 インスタンスを立ち上げる

ま、ほぼ README.md に書いてるとおりなんですけどね。結構はまったりもしたので、紹介しておこう。

まずは AWS Provider を入れる。プラグインです (もしかしたらこの作業必要ないのかもしれない)

$ vagrant plugin install vagrant-aws
$ vagrant plugin list
vagrant-aws (0.1.0)

EC2 を Provider に使う場合は OS のイメージはいらないけど、Box が何もないとだめなのでダミーのそれを box add しろ、ということだそうです。

$ vagrant box add dummy https://github.com/mitchellh/vagrant-aws/raw/master/dummy.box           
$ vagrant box list
Berkshelf-CentOS-6.3-x86_64-minimal (virtualbox)
base                                (virtualbox)
dummy                               (aws)

続けて Vagrantfile を調整していきましょう。

$ vagrant init

で作成して

Vagrant.configure("2") do |config|
  config.vm.box = "dummy"

  config.vm.provider :aws do |aws|
    aws.access_key_id     = ENV['AWS_ACCESS_KEY_ID']
    aws.secret_access_key = ENV['AWS_SECRET_ACCESS_KEY']
    aws.keypair_name = "naoya's keys"
    aws.ssh_username = "ec2-user"
    aws.ssh_private_key_path = "~/.ssh/aws-naoyaskeys.pem"
    aws.instance_type = "t1.micro"
    aws.region = "ap-northeast-1"
    aws.ami = "ami-a3af2ba2"
    aws.security_groups = [ 'webserver' ]
  end
end

と書く。

自分は AWSAPI キーはシェルの環境変数に入れてるのでそこから取ってます。

  • ssh_username などもちゃんと指定しないと良い感じに ssh はしてくれない
  • instance_type を指定しないとおもむろに m1.small が起ち上がったりして課金的につらい
  • security_groups を指定しないと対象が default になり、EC2 の default は ssh port が空いてないので嵌る

などなどあるので、ちょっと面倒ですが各種項目は丁寧にちゃんと設定しましょう。なお、config.vm.network あたりは今のところサポートしていないそうですが、VPC のアドレスを設定できる項目があるので問題ないでしょう。

これにて準備完了。vagrant up にございます。--provider=aws で Provider を選択するとよろしい。

$ vagrant up --provider=aws
Bringing machine 'default' up with 'aws' provider...
[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-a3af2ba2
[default]  -- Region: ap-northeast-1
[default]  -- Keypair: naoya's keys
[default]  -- Security Groups: ["webserver"]
[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/naoya/vagrant/ec2berks/ => /vagrant

インスタンスがこれで起ち上がる。

$ vagrant ssh
vagrant ssh
Last login: Fri Mar 15 08:52:46 2013 from …

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

https://aws.amazon.com/amazon-linux-ami/2012.09-release-notes/
There are 11 security update(s) out of 20 total update(s) available

きたわー。public DNS を覚えなくても ssh できるのが地味に嬉しい。

$ vagrant destroy

これでインスタンスが Terminate されます。vagrant halt だとおそらくサスペンドではないかと思います。

Chef でプロビジョニング

EC2 インスタンスVagrant で立ち上げられる、というだけだとまあそこまで旨みは感じられないのですが例えば複数 VM をまとめて作成する マルチVM 機能を使ったり Chef や Puppet などのプロビジョニングツールと連携して vagrant up 時にプロビジョニングも走らせてしまう・・・という Vagrant の付加機能を使っていくと、EC2 を Vagrant で管理する意味が出てくる。

Chef Solo でプロビジョニング、やってみましょう。

Vagrant.configure("2") do |config|
  config.vm.box = "dummy"
  config.ssh.username = "ec2-user" # これないとこける

  config.vm.provider :aws do |aws|
    # さっきと同じ
  end

  # プロビジョニングの設定
  config.vm.provision :chef_solo do |chef|
    chef.add_recipe "sandbox"
  end
end

という具合。Chef Solo を使う場合例によって rsync + ssh でレシピ転送と chef-solo 実行を行うようですが、その際に config.ssh.username を指定しとかないと vagrant ユーザーで操作しようとして落ちます。えらくはまって vagrant のソース読むはめに・・・。

あとはいつもどおりプロビジョニングの設定をしてやる。上記の chef オブジェクトはほぼ、Chef Solo の JSON ファイルに記述する Node Object 相当です。

クックブックの配置場所は Vagrantfile のあるパスの cookbooks ディレクトリが暗黙に期待されている。

$ tree
.
├── Vagrantfile
└── cookbooks
    └── sandbox

ので Vagrantfile のある場所で

$ knife cookbook create sandbox -o cookbooks

で作成する。

ここでは試しに Template を使って Ohai からEC2関連の値を取得したファイルを書き出してみよう。

# recipes/default.rb
template "/tmp/vagrant_test.txt" do
  mode 0644
end
# templates/default/vagrant_test_txt.erb
<%= node[:ec2][:ami_id] %>
<%= node[:ec2][:instance_type] %>
<%= node[:ec2][:placement_availability_zone] %>

すでに vagrant up 済みなのときプロビジョニングだけ適用するには vagrant provision です。

$ vagrant provision
[default] Rsyncing folder: /Users/naoya/vagrant/ec2berks/ => /vagrant
[default] Rsyncing folder: /Users/naoya/vagrant/ec2berks/cookbooks/ => /tmp/vagrant-chef-1/chef-solo-1/cookbooks
[default] Running provisioner: VagrantPlugins::Chef::Provisioner::ChefSolo...
Generating chef JSON and uploading...
Running chef-solo...
[2013-03-15T08:52:35+00:00] INFO: *** Chef 10.18.2 ***
…
$ vagrant ssh
$ cat /tmp/vagrant_test.txt
ami-a3af2ba2
t1.micro
ap-northeast-1a

はい、上手に焼けました。

というわけで EC2 インスタンスVagrant で操作できるようになった。やってみると、例えば EC2 インスタンスを立ち上げるスクリプトを書いて knife-solo で Chef Solo を流しているみたいなものなのでそこまで「すげえ!」という話ではないのかもしれないけれど、Vagrantfile に「インスタンスの状態」を記述して管理できる点、プロビジョナーとセットにすれば統一された EC2 上の試験環境の配布が楽になる点など、常用してもいいかなというポイントはちらほらあるように思いました。

逆にマルチVMやプロビジョニング連携を使わないとなると、そんなに嬉しいかどうか。自分で EC2 インスタンス立ち上げスクリプトを書いたりしなくていい、というくらいですかね。今後 Vagrant Sahara などのプラグインとちゃんと連携していくかどうかとかも気になるところではあります。

以上、Vagrant 1.1 キャッチアップでした。え、Chef の使い方とか良く分からない? なるほどそれでは

入門Chef Solo - Infrastructure as Code
伊藤直也 (2013-03-11)
売り上げランキング: 14

をおすすめしておきますね。