LoginSignup
22
24

More than 5 years have passed since last update.

Vagrant + Chef Soloで環境構築してみる

Last updated at Posted at 2014-10-15

はじめに

今更感もありますが、標題の件をいじってみたのでメモしておきます。

こちらの內容を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を作成します。

default.rb
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
index.html.erb
Welcome to <%= @fqdn %>

provision設定追加

以下のように、Vagrantfileへprovision設定を追加します。

Vagrantfile
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
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
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
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
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'

で指定した名前がそのままパッケージ名として使用されています。

default.rb
package 'apache2' do
  case node[ :platform ]
  when 'redhat', 'centos'
    package_name 'httpd'
  when 'debian', 'ubuntu'
    package_name 'apache2'
  end
end

Amazon Linuxを判定するためには「amazon」というplatform名が使えるらしいので、以下のようにコード修正しました。

default.rb
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
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判定の辺り

22
24
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
22
24