はじめに
今更感もありますが、標題の件をいじってみたのでメモしておきます。
こちらの內容をVagrantを使った方法に置き換えて、VirtualBoxとAWSの両方に適用してみることにしました。
使用したホストOS(ローカルPC)の環境は以下のとおりです。
- OS : MacOS X 10.9.5
- Vagrant : 1.6.5
- VirtualBox : 4.3.14
VirtualBoxで実行してみる
まずは、ローカルPCのVirtualBoxで仮想マシン起動・プロビジョニングをしてみます。
Vagrantfile作る
適当なディレクトリ作って、Vagrant設定を作成します。
boxは以前addしたものを使用しました。
確かbentoからaddしたboxなので、boxにはChef一式が入ってました。
vagrant init centos64-x64
ホストOS(ローカルPC)にChefインストール
knifeでレシピディレクトリ作りたいので、ホストOS(ローカルPC)にChef一式を入れます。
% curl -L https://www.opscode.com/chef/install.sh | sudo bash
レシピディレクトリ作成
% knife cookbook create apache2-take-simple -o .
recipes/defalut.rbとtemplates/default/index.html.erbを作成します。
package 'apache2' do
case node[ :platform ]
when 'redhat', 'centos'
package_name 'httpd'
when 'debian', 'ubuntu'
package_name 'apache2'
end
end
#
# set content
#
template 'index.html' do
case node[ :platform ]
when 'redhat', 'centos'
path '/var/www/html/index.html'
when 'debian', 'ubuntu'
path '/var/www/index.html'
end
source 'index.html.erb'
mode 0644
variables( { :fqdn => node[ :fqdn] } )
end
#
# set auto start and restart apache2
#
service 'apache2' do
case node[ :platform ]
when 'redhat', 'centos'
service_name 'httpd'
when 'debian', 'ubuntu'
service_name 'apache2'
end
action [ :enable, :start ]
end
Welcome to <%= @fqdn %>
provision設定追加
以下のように、Vagrantfileへprovision設定を追加します。
Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
# All Vagrant configuration is done here. The most common configuration
# options are documented and commented below. For a complete reference,
# please see the online documentation at vagrantup.com.
# Every Vagrant virtual environment requires a box to build off of.
config.vm.box = "centos64-x64"
config.vm.provision :chef_solo do |chef|
chef.cookbooks_path = "."
chef.run_list = "recipe[apache2-take-simple]"
end
end
vagrant up
vagrant up
で、仮想マシンが立ち上がります。
vagrant ssh
で仮想マシンに入って、設定ができている事を確認します。
- Apacheがサービス登録されていることを確認。
chkconfig --list httpd
- Apacheが起動していることを確認。
ps -aef | grep httpd
- htmlが正しく置換・配置されたことを確認。
curl 127.0.0.1
問題なく起動・設定できました。
AWS(EC2)で実行してみる
次はAWSへ適用してみます。
vagrant-awsプラグインを入れる
vagrant plugin install vagrant-aws
で、インストール開始。
完了後に追加されている事を確認してみます。
% vagrant plugin list
vagrant-aws (0.5.0)
vagrant-login (1.0.1, system)
vagrant-share (1.1.2, system)
ダミーのboxファイル追加
AMIを使うことになるのでboxはいらないけれど、何も指定しないとエラーになってしまうらしいので、ダミーのボックスを追加して使用します。
vagrant box add dummy https://github.com/mitchellh/vagrant-aws/raw/master/dummy.box
Vagrantfile作る
通常の手順と一緒です。
適当なディレクトリを掘って、そこに移動。
で、vagrant initすればOK。
% mkdir to_aws_sample
[naokienokido@Naoki-Enokido-no-MacBook-Pro] ~/Documents/vagrantDir
% cd to_aws_sample
[naokienokido@Naoki-Enokido-no-MacBook-Pro] ~/Documents/vagrantDir/to_aws_sample
% vagrant init
A `Vagrantfile` has been placed in this directory. You are now
ready to `vagrant up` your first virtual environment! Please read
the comments in the Vagrantfile as well as documentation on
`vagrantup.com` for more information on using Vagrant.
Vagrantfileを以下のように編集しました。
VAGRANTFILE_API_VERSION = "2"
Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
# All Vagrant configuration is done here. The most common configuration
# options are documented and commented below. For a complete reference,
# please see the online documentation at vagrantup.com.
# Every Vagrant virtual environment requires a box to build off of.
config.vm.box = "dummy"
config.vm.provider :aws do |aws, override|
aws.access_key_id = ENV['AWS_ACCESS_KEY_ID'] # AWSのアクセスキーID指定 同名で環境変数に設定されている前提
aws.secret_access_key = ENV['AWS_SECRET_ACCESS_KEY'] # AWSのシークレットアクセスキー指定 同名で環境変数に設定されている前提
aws.keypair_name = "vagrant-ec2" # 使用するKeyPairの名前を指定
override.ssh.username = "ec2-user" # sshするユーザ名を指定 ec2-user固定
override.ssh.private_key_path = "~/.ssh/vagrant-ec2.pem" # KeyPairからDLした鍵ファイルを指定
aws.instance_type = "t2.micro" # 使用するインスタンスタイプを指定
aws.region = "ap-northeast-1" # リージョン指定
aws.ami = "ami-35072834" # 使用するAMIのIDを指定
aws.subnet_id = "subnet-8ed6d9c8" # 使用するサブネットIDを指定
aws.private_ip_address = "10.0.1.11" # VPC内のローカルIPを指定
aws.security_groups = [ 'WEB-SG' ] # 適用するセキュリティグループを指定
end
end
アクセスキーIDとシークレットアクセスキーは、.zshrcに同名で環境変数として追加してあります。
vagrant up
上記Vagrantfileを使用して
vagrant up --provider=aws
でインスタンスを立ち上げてみます。
すると、こんなエラーが出ました。
The parameter as cannot be used with the parameter subnet
セキュリティグループをIDではなくて名前で指定してしまっていたのが原因だったので、修正します。
VAGRANTFILE_API_VERSION = "2"
Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
# All Vagrant configuration is done here. The most common configuration
# options are documented and commented below. For a complete reference,
# please see the online documentation at vagrantup.com.
# Every Vagrant virtual environment requires a box to build off of.
config.vm.box = "dummy"
config.vm.provider :aws do |aws, override|
aws.access_key_id = ENV['AWS_ACCESS_KEY_ID'] # AWSのアクセスキーID指定 同名で環境変数に設定されている前提
aws.secret_access_key = ENV['AWS_SECRET_ACCESS_KEY'] # AWSのシークレットアクセスキー指定 同名で環境変数に設定されている前提
aws.keypair_name = "vagrant-ec2" # 使用するKeyPairの名前を指定
override.ssh.username = "ec2-user" # sshするユーザ名を指定 ec2-user固定
override.ssh.private_key_path = "~/.ssh/vagrant-ec2.pem" # KeyPairからDLした鍵ファイルを指定
aws.instance_type = "t2.micro" # 使用するインスタンスタイプを指定
aws.region = "ap-northeast-1" # リージョン指定
aws.ami = "ami-35072834" # 使用するAMIのIDを指定
aws.subnet_id = "subnet-8ed6d9c8" # 使用するサブネットIDを指定
aws.private_ip_address = "10.0.1.11" # VPC内のローカルIPを指定
aws.security_groups = [ 'sg-fcaa6a99' ] # 適用するセキュリティグループをIDで指定
end
end
再度vagrant up --provider=aws
を実行し、AWSコンソールからインスタンスが立ち上がることを確認しました。
が、vagrant up
の実行が終わりません。
==> default: Waiting for SSH to become available...
というところで止まっているように見えます。
詳細を見るために、DEBUG指定でvagrant upしてみました。
VAGRANT_LOG=DEBUG vagrant up --provider=aws
色々ログが出ますが、以下のSSH接続のところでループしているのが分かりました。
DEBUG ssh: == Net-SSH connection debug-level log END ==
INFO retryable: Retryable exception raised: #<Errno::ECONNREFUSED: Connection refused - connect(2)>
INFO ssh: Attempting to connect to SSH...
INFO ssh: - Host: 10.0.1.11
INFO ssh: - Port: 22
INFO ssh: - Username: ec2-user
INFO ssh: - Password? false
INFO ssh: - Key Path: ["/Users/naokienokido/.ssh/vagrant-ec2.pem"]
DEBUG ssh: == Net-SSH connection debug-level log START ==
DEBUG ssh: D, [2014-10-15T10:32:56.841175 #10222] DEBUG -- net.ssh.transport.session[80762d68]: establishing connection to 10.0.1.11:22
Public DNSが設定できてない事が原因のようです。
そこで、以下の設定をVagrantfileに追加して、EIPが振られるようにします。
aws.elastic_ip = true
で、再度vagrant upすると、
INFO interface: Machine: error-exit ["Vagrant::Errors::VagrantError", "The following SSH command responded with a non-zero exit status.\nVagrant assumes that this means the command failed!\n\nmkdir -p '/vagrant'\n\nStdout from the command:\n\n\n\nStderr from the command:\n\nsudo: sorry, you must have a tty to run sudo\n"]
みたいなエラーが出るが、インスタンスの起動自体は成功しました。
ただ、/vagrantディレクトリの同期は失敗した状態です。
(前述のエラー通り、sudo指定での/vagrantディレクトリの作成に失敗している。)
sudoエラーの解消
前述のエラーの內容は、「tty経由ではないsudoは実行できない」という、よく見かけるやつです。
Amazon Linuxでは、requirettyはデフォルトで有効化されているようです。
(以前はそうではなかった?というのを何かで見たような気がします。)
解決策をググると、
「ゲストOSの/etc/sudoersを直接書き換えてrequirettyを無効化する」
という方法が結構引っかかってきますが、requirettyのそもそもの目的を考えると微妙な気がしました。
他の方法を探したところ、Vagrant1.4以降では以下のオプションを指定すれば解決しそうだったので、これをVagrantfileに追加します。
config.ssh.pty = true
これで再度vagrant upして、エラーが解消され、起動したインスタンス側に/vagrantディレクトリが作成され、Rsync Synced Folderとして機能していることが確認できました。
この時点で、Vagrantfileは以下のようになりました。
VAGRANTFILE_API_VERSION = "2"
Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
# All Vagrant configuration is done here. The most common configuration
# options are documented and commented below. For a complete reference,
# please see the online documentation at vagrantup.com.
# Every Vagrant virtual environment requires a box to build off of.
# config.vm.boot_timeout = 120
config.vm.box = "dummy" # dummyボックスを使用 実際はAMIを使用して仮想マシンが作成される
config.ssh.pty = true # Amazon Linuxでは/etc/sudoersでrequirettyが有効になっているためsudoエラーにならないように指定
config.vm.provider :aws do |aws, override|
aws.access_key_id = ENV['AWS_ACCESS_KEY_ID'] # AWSのアクセスキーID指定 同名で環境変数に設定されている前提
aws.secret_access_key = ENV['AWS_SECRET_ACCESS_KEY'] # AWSのシークレットアクセスキー指定 同名で環境変数に設定されている前提
aws.keypair_name = "vagrant-ec2" # 使用するKeyPairの名前を指定
override.ssh.username = "ec2-user" # sshするユーザ名を指定 ec2-user固定
override.ssh.private_key_path = "~/.ssh/vagrant-ec2.pem" # KeyPairからDLした鍵ファイルを指定
aws.instance_type = "t2.micro" # 使用するインスタンスタイプを指定
aws.region = "ap-northeast-1" # リージョン指定
aws.ami = "ami-35072834" # 使用するAMIのIDを指定
aws.subnet_id = "subnet-8ed6d9c8" # 使用するサブネットIDを指定
aws.private_ip_address = "10.0.1.11" # VPC内のローカルIPを指定
aws.elastic_ip = true # EIPを自動で割り当てる public subnet使用時はtrueにしておく必要がある
aws.security_groups = [ 'sg-fcaa6a99' ] # 適用するセキュリティグループをIDで指定
end
end
vagrant-omnibusプラグインを入れる
AMIにはChefは入っていないので、vagrant-omnibusプラグインを使ってインスタンス起動時にインストールするようにします。
vagrant plugin install vagrant-omnibus
で、インストール実行。
完了後に追加されている事を確認します。
% vagrant plugin list
vagrant-aws (0.5.0)
vagrant-login (1.0.1, system)
vagrant-omnibus (1.4.1)
vagrant-share (1.1.2, system)
Vagrantfileに以下を追加します。
config.omnibus.chef_version = :latest
vagrant provision
の都度で、最新のChefをインストールしてくれるようです。
レシピディレクトリ作成
ホストOSのVagrantfileが置いてあるディレクトリで、以下を実行。
% knife cookbook create apache2-take-simple -o .
recipes/defalut.rbとtemplates/default/index.html.erbは、VirtualBoxで実行したものをコピーしました。
Vagrantfileにprovisioning指定追加
Vagrantfileに、Virtualboxで実行した時と同じ設定を追加します。
VAGRANTFILE_API_VERSION = "2"
Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
# All Vagrant configuration is done here. The most common configuration
# options are documented and commented below. For a complete reference,
# please see the online documentation at vagrantup.com.
# Every Vagrant virtual environment requires a box to build off of.
# config.vm.boot_timeout = 120
config.vm.box = "dummy" # dummyボックスを使用 実際はAMIを使用して仮想マシンが作成される
config.ssh.pty = true # Amazon Linuxでは/etc/sudoersでrequirettyが有効になっているためsudoエラーにならないように指定
config.omnibus.chef_version = :latest # Chefをインストールする
config.vm.provider :aws do |aws, override|
aws.access_key_id = ENV['AWS_ACCESS_KEY_ID'] # AWSのアクセスキーID指定 同名で環境変数に設定されている前提
aws.secret_access_key = ENV['AWS_SECRET_ACCESS_KEY'] # AWSのシークレットアクセスキー指定 同名で環境変数に設定されている前提
aws.keypair_name = "vagrant-ec2" # 使用するKeyPairの名前を指定
override.ssh.username = "ec2-user" # sshするユーザ名を指定 ec2-user固定
override.ssh.private_key_path = "~/.ssh/vagrant-ec2.pem" # KeyPairからDLした鍵ファイルを指定
aws.instance_type = "t2.micro" # 使用するインスタンスタイプを指定
aws.region = "ap-northeast-1" # リージョン指定
aws.ami = "ami-35072834" # 使用するAMIのIDを指定
aws.subnet_id = "subnet-8ed6d9c8" # 使用するサブネットIDを指定
aws.private_ip_address = "10.0.1.11" # VPC内のローカルIPを指定
aws.elastic_ip = true # EIPを自動で割り当てる public subnet使用時はtrueにしておく必要がある
aws.security_groups = [ 'sg-fcaa6a99' ] # 適用するセキュリティグループをIDで指定
end
# chef-soloによるプロビジョニングの設定
config.vm.provision :chef_solo do |chef|
chef.cookbooks_path = "."
chef.run_list = "recipe[apache2-take-simple]"
end
end
再度 vagrant up
vagrant up --provider=aws
を実行すると、エラーが出ました。
==> default: Chef::Exceptions::Package
==> default: -------------------------
==> default: No version specified, and no candidate version available for apache2
==> default:
==> default: Resource Declaration:
==> default: ---------------------
==> default: # In /tmp/vagrant-chef-3/chef-solo-1/cookbooks/apache2-take-simple/recipes/default.rb
==> default:
==> default: 12: package 'apache2' do
==> default: 13: case node[ :platform ]
==> default: 14: when 'redhat', 'centos'
==> default: 15: package_name 'httpd'
==> default: 16: when 'debian', 'ubuntu'
==> default: 17: package_name 'apache2'
==> default: 18: end
==> default: 19: end
==> default:
==> default: Compiled Resource:
==> default: ------------------
==> default: # Declared in /tmp/vagrant-chef-3/chef-solo-1/cookbooks/apache2-take-simple/recipes/default.rb:12:in `from_file'
==> default:
==> default: package("apache2") do
==> default: action :install
==> default: retries 0
==> default: retry_delay 2
==> default: guard_interpreter :default
==> default: package_name "apache2"
==> default: timeout 900
==> default: cookbook_name :"apache2-take-simple"
==> default: recipe_name "default"
==> default: end
パッケージ名「apache2」でインストールが実行された事が原因です。
recipes/default.rbでplatform判定をしていますが、Amazon Linuxに該当する条件がないため、
package 'apache2'
で指定した名前がそのままパッケージ名として使用されています。
package 'apache2' do
case node[ :platform ]
when 'redhat', 'centos'
package_name 'httpd'
when 'debian', 'ubuntu'
package_name 'apache2'
end
end
Amazon Linuxを判定するためには「amazon」というplatform名が使えるらしいので、以下のようにコード修正しました。
package 'apache2' do
case node[ :platform ]
when 'redhat', 'centos', 'amazon'
package_name 'httpd'
when 'debian', 'ubuntu'
package_name 'apache2'
end
end
#
# set content
#
template 'index.html' do
case node[ :platform ]
when 'redhat', 'centos', 'amazon'
path '/var/www/html/index.html'
when 'debian', 'ubuntu'
path '/var/www/index.html'
end
source 'index.html.erb'
mode 0644
variables( { :fqdn => node[ :fqdn] } )
end
#
# set auto start and restart apache2
#
service 'apache2' do
case node[ :platform ]
when 'redhat', 'centos', 'amazon'
service_name 'httpd'
when 'debian', 'ubuntu'
service_name 'apache2'
end
action [ :enable, :start ]
end
これでvagrant up --provier=aws
を実行してもエラーが出なくなりました。
インスタンスが起動したらvagrant ssh
でインスタンスに入って、設定ができている事を確認してみます。
- Apacheがサービス登録されていることを確認。
chkconfig --list httpd
- Apacheが起動していることを確認。
ps -aef | grep httpd
- htmlが正しく置換・配置されたことを確認。
curl 127.0.0.1
- プラウザからPublic DNSを指定して、上記と同じ画面が開くことを確認。
全て問題なく設定されていました。
最終的にVagrantfileは以下のようになりました。
VAGRANTFILE_API_VERSION = "2"
Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
# All Vagrant configuration is done here. The most common configuration
# options are documented and commented below. For a complete reference,
# please see the online documentation at vagrantup.com.
# Every Vagrant virtual environment requires a box to build off of.
# config.vm.boot_timeout = 120
config.vm.box = "dummy" # dummyボックスを使用 実際はAMIを使用して仮想マシンが作成される
config.ssh.pty = true # Amazon Linuxでは/etc/sudoersでrequirettyが有効になっているためsudoエラーにならないように指定
config.omnibus.chef_version = :latest # Chefをインストールする
config.vm.provider :aws do |aws, override|
aws.access_key_id = ENV['AWS_ACCESS_KEY_ID'] # AWSのアクセスキーID指定 同名で環境変数に設定されている前提
aws.secret_access_key = ENV['AWS_SECRET_ACCESS_KEY'] # AWSのシークレットアクセスキー指定 同名で環境変数に設定されている前提
aws.keypair_name = "vagrant-ec2" # 使用するKeyPairの名前を指定
override.ssh.username = "ec2-user" # sshするユーザ名を指定 ec2-user固定
override.ssh.private_key_path = "~/.ssh/vagrant-ec2.pem" # KeyPairからDLした鍵ファイルを指定
aws.instance_type = "t2.micro" # 使用するインスタンスタイプを指定
aws.region = "ap-northeast-1" # リージョン指定
aws.ami = "ami-35072834" # 使用するAMIのIDを指定
aws.subnet_id = "subnet-8ed6d9c8" # 使用するサブネットIDを指定
aws.private_ip_address = "10.0.1.11" # VPC内のローカルIPを指定
aws.elastic_ip = true # EIPを自動で割り当てる public subnet使用時はtrueにしておく必要がある
aws.security_groups = [ 'sg-fcaa6a99' ] # 適用するセキュリティグループをIDで指定
end
# chef-soloによるプロビジョニングの設定
config.vm.provision :chef_solo do |chef|
chef.cookbooks_path = "."
chef.run_list = "recipe[apache2-take-simple]"
end
end
もっといい記述方法もありそうなので、追々改善していきたいと思います。
参考
以下を参考にさせていただきました。
ありがとうございました。
実施した內容の元
Vagrantの設定
AWS(EC2)での実行
vagrant-awsプラグインの公式ドキュメント:https://github.com/mitchellh/vagrant-aws
http://d.hatena.ne.jp/naoya/20130315/1363340698
http://www.ryuzee.com/contents/blog/6807
http://dqn.sakusakutto.jp/2013/10/the_following_settings_dont_exist_ssh_private_key_path_ssh_username.html
sudoエラー(tty指定)の辺り
http://j-caw.co.jp/blog/?p=1327
https://github.com/mitchellh/vagrant/issues/1482
http://www.1x1.jp/blog/2014/03/vagrant-rsync-synced-folder.html
platform判定の辺り