Speee DEVELOPER BLOG

Speee開発陣による技術情報発信ブログです。 メディア開発・運用、スマートフォンアプリ開発、Webマーケティング、アドテクなどで培った技術ノウハウを発信していきます!

vagrant-awsを日本で一番詳しく解説

こんにちは。ランチコンダクターです。

先日、第8回若手Webエンジニア交流会 #wakatewebにて 「vagrant-awsにプルリしたらマージされた話」をさせていただきました。

今回は、vagrant-awsの具体的な使い方をまとめてみます。

vagrant-awsとは

通常、VagrantVirtualBoxのコントローラーとして使われていると思いますが、バージョン1.1からプラグインを使用することにより、様々な仮想化技術に対応した仮想マシンのコントローラーとなりました。
vagrant-awsは、VagrantAWSを操作することができるようになるプラグインです。図で表すと以下のような感じになります。

AWSにて準備事項

事前準備としてAWS側での準備が必要なのですが、ここでは省略します。
とりあえず、以下を行っておけば最低限は大丈夫だと思います。

  • access_key_idをメモっておく
  • secret_access_keyをメモっておく
  • keypairを作成し、名前をメモっておく
  • 指定するsecurity_group名をメモっておく
  • sshのprivate_keyのダウンロードを行い、保持

vagrant-aws

事前準備

# vagrant aws プラグインのインストール
$ vagrant plugin install vagrant-aws
# ダミーのboxファイルを追加(Vagrantの起動にはBoxファイルが必ず必要なため)
$ vagrant box add dummy https://github.com/mitchellh/vagrant-aws/raw/master/dummy.box

vagrant-awsのVagrantfileを解説

VAGRANTFILE_API_VERSION = "2"

# 実行するShellScript
$script = <<SCRIPT
# 
echo 'Start ShellScript'
# タイムゾーンを日本に変更
sudo cp -p /usr/share/zoneinfo/Japan /etc/localtime
# AWSのVolumeのリサイズ(デフォルトだと8GBのため)
sudo resize2fs /dev/sda1
SCRIPT
Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
  # Box名(vagrant-awsでは使用はしないが指定しなくてはならない)
  config.vm.box = "dummy"

  # 同期するフォルダを選択(vagrant-awsでは常に同期される訳ではなく、provisionやupなどのコマンド実行時に同期される)
  config.vm.synced_folder "./", "/home/ec2-user/vagrant", disabled: true
  config.vm.provider :aws do |aws, override|
    # アクセスキー(リポジトリに入れたいので環境変数に保持)
    aws.access_key_id     = ENV['AWS_ACCESS_KEY_ID']
    # シークレットアクセスキー(リポジトリに入れたいので環境変数に保持)
    aws.secret_access_key = ENV['AWS_SECRET_ACCESS_KEY'] 
    # キー名
    aws.keypair_name = 'speee.key'
    # インスタンスタイプ(http://aws.amazon.com/jp/ec2/pricing/ を参照)
    aws.instance_type = "t1.micro"
    # リージョン(東京はap-northeast-1)
    aws.region = "ap-northeast-1"
    # アベイラビリティゾーン
    aws.availability_zone =  "ap-northeast-1c"
    # 使用するAMIのID
    aws.ami = "ami-c9562fc8"
    # セキュリティグループ(複数指定でor判定)
    aws.security_groups = ['web-server-group']
    # タグ
    aws.tags = {
      'Name' => 'web-server',
      'Description' => '詳細'
    }
    # Amazon Linuxの場合は最初からsudoできないので指定しておく
    aws.user_data = "#!/bin/sh\nsed -i 's/^.*requiretty/#Defaults requiretty/' /etc/sudoers\n"
    # EBSの指定が可能
    aws.block_device_mapping = [
      {
        # デバイス名
        'DeviceName' => "/dev/sda1",
        # 名称
        'VirtualName' => "v1",
        # ボリュームサイズ(GB単位)
        'Ebs.VolumeSize' => 10,
        # ターミネートした際に削除するかどうか
        'Ebs.DeleteOnTermination' => true,
        # EBSのタイプを指定      
        'Ebs.VolumeType' => 'standard',
        #'Ebs.VolumeType' => 'io1',
        # standardでIOPSを指定するとエラーが発生するので注意
        #'Ebs.Iops' => 1000
      }
    ]
    # -----
    # ここからはVPCを使用する際の設定
    # サブネットID(マネジメントコンソールから取得)
    #aws.subnet_id = 'サブネットID'
    # VPC内のローカルIPアドレスを指定
    #aws.private_id_address = '192.168.0.33'
    # 自動的にEIPを割り当てる場合(EIPの取得上限は5個のためそれ以上の指定はエラーとなる)
    # aws.elastic_ip = true
    # ELBを指定
    # aws.elb = "production-web"

    # -----
    # SSHのユーザー名を指定(Amazon Linuxはec2-user、ubuntuはubuntu、CentOSはroot)
    override.ssh.username = "ec2-user"
    # SSHのKeyのパスを指定
    override.ssh.private_key_path = "~/.ssh/speeekey.pem"
  end
  # シェルを実行
  config.vm.provision "shell", inline: $script

end

実際に使用する際の変更点は以下になります。

aws.access_key_id:AWSから取得したアクセスキーに変更、もしくは環境変数に設定※1
aws.secret_access_key:AWSから取得したシークレットアクセスキーに変更、もしくは環境変数に設定※1
aws.keypair_name:AWSにて作成したキーペア名に変更※1
aws.instance_type:任意のインスタンスに変更(試すだけならt1.microで問題無し)※1
aws.region:任意のリージョンを指定※1
aws.availability_zone:任意のアベイラビリティゾーンを指定※1
aws.ami:任意のAMIを指定※1
aws.security_groups:AWSにて作成したセキュリティグループを指定※1
aws.tags:タグを指定(タグに意味はありません)
aws.block_device_mapping:マッピングを行うデバイスを指定(EBSなど)
aws.subnet_id:VPCを使用する場合は指定
aws.private_id_address:VPCを使用する場合は指定
aws.elastic_ip:固定IPが必要な時に指定
override.ssh.username:OS毎に指定※1
override.ssh.private_key_path:プライベートKeyを配置しているローカルのPathを指定※1

※1:必須

実行

以下にて起動、破棄が行えます。

# EC2インスタンスの起動
$ vagrant up --provider=aws
# EC2インスタンスの破棄
$ vagrant destroy

vagrant実行時にデバッグログの出力を行う方法

以下のように、VAGRANT_LOG=debugをとすることにより、ログが多く出力されるので、問題が起こった際の解決がしやすくなります。

# vagrant up時にデバッグログを出力
$ VAGRANT_LOG=debug vagrant up
# vagrant destroy時にデバッグログを出力
$ VAGRANT_LOG=debug vagrant destroy

vagrant-awsをソースから実行するための手順

ソースを取得

$ git clone https://github.com/mitchellh/vagrant-aws
$ cd vagrant-aws

Gemfileを以下のように変更

source "https://rubygems.org"

gemspec

group :development do
  # We depend on Vagrant for development, but we don't add it as a
  # gem dependency because we expect to be installed within the
  # Vagrant environment itself using `vagrant plugin`.
  gem "vagrant", :git =&gt; "git://github.com/mitchellh/vagrant.git"
end

group :plugins do
  gem "vagrant-aws", path: "."
end

Gemのインストール

$ bundle
$ bundle exec rake

あとは先ほどのVagrantfileを配置し、「bundle exec vagrant up --provider=aws」を行えばec2インスタンスが起動されます。

# 起動
$ bundle exec vagrant up --provider=aws
# ターミネート
$ bundle exec vagrant destroy

ソースコードから実行した時のコマンド一覧(bundle execつけただけ)

# 起動
$ bundle exec vagrant up --provider=aws
# 終了
$ bundle exec vagrant destroy
# rsync(ローカルからEC2への一方通行のため、注意)
$ bundle exec vagrant rsync
# provision(rsyncしてからShellやChef等を実行)
$ bundle exec vagrant provision
# 再起動
$ bundle exec vagrant reload
# 停止
$ bundle exec vagrant halt

vagrant-awsAWSの操作はfogを使用しています。fogだけを使いたいときもvagrant-awsのコードはかなり参考になるとおもいます。
ちなみにvagrant-googleGoogle Compute Engineを操作)というプラグインもあります。vagrant-googleもfogを使用しているのでコードベースはかなり似ています(作者が同じなので当然ですが)。

Tips

AWSインスタンスIDを取得

# ※vagrant-awsにてvagrant up後
$ cat .vagrant/machines/default/aws/id
i-4ed31657

vagrant-awsを使う時にあると便利なプラグイン

vagrant-ami

このプラグインを使用することにより、vagrant-awsで作成したインスタンスのami化ができるようになります。

# インストール
$ vagrant plugin install vagrant-ami
# インスタンスをAMI化
$ vagrant create-ami --name my-ami-name --desc "My AMI" --tags role=test,environment=dev

最後に

Infrastructure as CodeとAWSを使ったImmutable Infrastructureを実現するためには、
AWSインスタンス起動 → Chef or Puppet or Ansibleを実行 → serverspecにてテストというフローを 繰り返し実行していくことになりますが、このフローを自作するのはそれなりの手間がかかります。
vagrant-awsや、その他のvagrantプラグインを組み合わせると、このフローをVagrantfileで管理でき、 かつ簡単に自動化できます。
また、インターフェイスが同じなので、Vagrantさえ知っていれば学習コストをある程度抑えられるのも 導入コストを抑えられるので良いですね。
機能の便利さの割に使われていないのが勿体無いと思っているので、皆さん、どんどん使いましょう!

vagrant-awsを使用してserverspecのテストを行う運用方法などについては
以下のスライドが参考になると思います。
DevOps + AWS #jawsug by Naoya Ito
KAIZEN platform Inc. における運用自動化 by Naoya Ito

日本一詳しくなかったらすみませんw

ありがとうございました。