社内向けの勉強会の環境としてEC2インスタンスを複数作成する機会があったので、Vagrantを使ってやってみました。
環境
- ワーク端末 : Mac OSX 10.9
- Vagrant : 1.6.1
- vagrant-aws : 0.4.1
1台のEC2インスタンスを起動する場合のVagrantfile
比較のために、1台のEC2インスタンス(Amazon Linux)を起動する場合のVagrantfileを記載します。 アクセスキーとシークレットアクセスキーは環境変数に設定してします。
# -*- mode: ruby -*-
# vi: set ft=ruby :
# Vagrantfile API/syntax version. Don't touch unless you know what you're doing!
VAGRANTFILE_API_VERSION = "2"
Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
config.vm.box = 'dummy'
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.region = 'ap-northeast-1'
aws.instance_type = 't1.micro'
# Amazon Linux AMI 2014.03.1(x64)
aws.ami = 'ami-c9562fc8'
aws.security_groups = ['Web Server']
aws.keypair_name = 'test1'
aws.tags = {
'Name' => 'test1'
}
override.ssh.username = 'ec2-user'
override.ssh.private_key_path = '~/.ssh/test1.pem'
end
end
2台のEC2インスタンスを起動する場合のVagrantfile
config.vm.define
メソッドを使います。引数には仮想マシン名と、その仮想マシンの設定のためのブロックを渡します。
仮想マシン設定のためのブロックは、上で書いた1台の仮想マシンを設定する場合のものと同一です。
複数のEC2インスタンスを起動する場合は、このconfig.vm.define
を台数分書くのが基本です。
boxは全インスタンスで共通のものを使うので、config.vm.define
の外側でconfig.vm.box = 'dummy'
を定義します。
(こうすることでconfig.vm.box
の設定が各config.vm.define
に継承されます。)
# -*- mode: ruby -*-
# vi: set ft=ruby :
# Vagrantfile API/syntax version. Don't touch unless you know what you're doing!
VAGRANTFILE_API_VERSION = "2"
Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
config.vm.box = 'dummy'
config.vm.define :test1 do |test1|
test1.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.region = 'ap-northeast-1'
aws.instance_type = 't1.micro'
# Amazon Linux AMI 2014.03.1(x64)
aws.ami = 'ami-c9562fc8'
aws.security_groups = ['Web Server']
aws.keypair_name = 'test1'
aws.tags = {
'Name' => 'test1'
}
override.ssh.username = 'ec2-user'
override.ssh.private_key_path = '~/.ssh/test1.pem'
end
end
config.vm.define :test2 do |test2|
test2.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.region = 'ap-northeast-1'
aws.instance_type = 't1.micro'
# Amazon Linux AMI 2014.03.1(x64)
aws.ami = 'ami-c9562fc8'
aws.security_groups = ['Web Server']
aws.keypair_name = 'test2'
aws.tags = {
'Name' => 'test2'
}
override.ssh.username = 'ec2-user'
override.ssh.private_key_path = '~/.ssh/test2.pem'
end
end
end
Vagrantfileの冗長性を排除
今回は全く同じ構成のEC2インスタンスを複数台起動したかったので、シーケンス番号部分を変数化しconfig.vm.define
を繰り返し定義する形としました。
# -*- mode: ruby -*-
# vi: set ft=ruby :
# Vagrantfile API/syntax version. Don't touch unless you know what you're doing!
VAGRANTFILE_API_VERSION = "2"
Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
config.vm.box = 'dummy'
#5台のEC2インスタンスを起動
(1..5).each do |num|
config.vm.define "test#{num}" do |node|
node.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.region = 'ap-northeast-1'
aws.instance_type = 't1.micro'
# Amazon Linux AMI 2014.03.1(x64)
aws.ami = 'ami-bb84c4ba'
aws.security_groups = ['Web Server']
aws.keypair_name = "test#{num}"
aws.tags = {
'Name' => "test#{num}"
}
override.ssh.username = 'ec2-user'
override.ssh.private_key_path = "~/.ssh/test#{num}.pem"
end
end
end
end
仮想マシンの制御
vagrant
コマンドにマシン名を渡せばOKです。例えばtest1
にsshで接続する場合は以下のようにコマンドを実行します。
$ vagrant ssh test1
仮想マシンの停止(halt)や削除(destroy)は、複数のマシンに対して実行できます。(仮想マシン名を指定しなかった場合は、全仮想マシンに対して処理が実行されます。)
$ vagrant halt test1 test2
【補足】Synced Foldersのエラー対応
Vagrantはvagrant up
時にリモートの仮想マシン上でmkdir -p '/vagrant'
コマンドを実行してSynced Foldersを
作成しますが、EC2のAmazon Linuxではsudoの実行にtty経由でのssh接続が必須となっているため、このsshでのリモートコマンド実行がエラーとなります。
(EC2インスタンスの起動自体は成功します。)
# エラー内容
The following SSH command responded with a non-zero exit status.
Vagrant assumes that this means the command failed!
mkdir -p '/vagrant'
Stdout from the command:
Stderr from the command:
sudo: sorry, you must have a tty to run sudo
対応として、一旦sshでEC2インスタンスにログインし、/etc/sudoers
の設定を変更しtty無しでのsudoの発行を許可します。
$ vagrant ssh test1
$ sudo visudo
# 以下をコメントアウトし全ユーザについてtty無しでのsudoの発行を許可する
Defaults requiretty
# または以下のように設定しec2-userのみtty無しでのsudoの発行を許可する
Defaults:ec2-user !requiretty
VagnrantからAmazon Linuxを頻繁に利用する場合は、この設定を行ったインスタンスからAMIを作成しておくと便利です。