Vagrant, vagrant-aws, vagrant-omnibus, Chef で Amazon EC2 インスタンスを生成し Apache と連携した Tomcat の Web アプリケーションをデプロイする.

スポンサーリンク

下記のコマンドを一発実行するだけで Amazon EC2 インスタンスを自動生成し,好きなアプリケーション (Apache, Tomcat) を yum でインストールし,その設定ファイルを編集した上でアプリケーションを起動し,さらに Tomcat のウェブアプリケーションをデプロイするなど.

vagrant up --provider=aws

ローカルの環境は Ubuntu 14.04 です.

事前準備

必要なソフトウェア

Ruby のインストールについてはこちら. Ubuntu 14.04 で rbenv, ruby-build を使用して Ruby のバージョンを管理する.

Vagrant, vagrant-aws, vagrant-omnibus, Chef, VirtualBox のインストールについてはこちら.Ubuntu 14.04 で VirtualBox, Vagrant, vagrant-aws, vagrant-omnibus, Chef のインストール

Access Key ID と Secret Access Key

AWS マネジメントコンソールにログインし,ユーザ名から Security Credentials を選択します.

Dashboard – Details – Your Security Credentials – Access Keys (Access Key ID and Secret Access Key) を選択します.
https://console.aws.amazon.com/iam/home?#security_credential

何も無い場合は,アクセスキーを Create New Access Key で作成します.Access Key ID と Secret Access Key を得ることができます.

インスタンスタイプの確認

東京リージョンの場合,AWS マネジメントコンソールの EC2 で Tokyo を選択し,Create Instance の Launch Instance ボタンを押します.Step 1: Choose an Amazon Machine Image (AMI) 画面に遷移します.

2014-05-08 時点,Free tier eligible な Amazon Linux は,”Amazon Linux AMI 2014.03.1 – ami-c9562fc8 (64-bit) / ami-c7562fc6 (32-bit)” となっています.例えば,64bit を使用したい場合,ami-c9562fc8 という文字列をメモしておきます.なお,Free tier eligible なのでマイクロインスタンス t1.micro です.

キーペア

AWS マネジメントコンソールの EC2 の NETWORK & SECURITY で Key Pairs を選択し,Create Key Pair ボタンを押してキーペアを作成しておきます.

ダウンロードした pem ファイルは,例えば Linux の場合は ~/.ssh に保存し,パーミッションを 400 にしておきます.キーペアの名前を tokyo.pem と設定した場合,

chmod 400 ~/.ssh/tokyo.pem

セキュリティグループ

AWS マネジメントコンソールの EC2 の NETWORK & SECURITY で Security Groups を選択し,Create Security Group ボタンを押して適切なセキュリティグループを作成しておきます.

Vagrant で EC2 インスタンスの作成

まず,Vagrant で EC2 インスタンスを作成するところまでやってみます.

vagrant-aws https://github.com/mitchellh/vagrant-aws を参考にします.

ダミーボックスで vagrant init

まず,ダミーのボックスを設定します.

vagrant box add dummy https://github.com/mitchellh/vagrant-aws/raw/master/dummy.box

適当な名前のディレクトリを作成し,そこで作業を実施します.

mkdir vagrant_aws_test
cd vagrant_aws_test
vagrant init

Vagrant ファイルが生成されます.

Vagrant ファイル

生成された 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"
  config.vm.box = "dummy"
  config.ssh.pty = true
  config.ssh.private_key_path = '/path/to/.ssh/tokyo.pem'
  config.ssh.username = "ec2-user"
  config.vm.synced_folder ".", "/vagrant", :disabled => true
  config.vm.provider :aws do |aws, override|
    aws.access_key_id = "Access Key ID"
    aws.secret_access_key = "Secret Access Key"
    aws.keypair_name = "キーペアの名前"

    aws.ami = "ami-c9562fc8"

    aws.instance_type = "t1.micro"
    # Tokyo region
    aws.region = "ap-northeast-1"  

    aws.security_groups = [ 'my_security_group' ]

    aws.tags = {
      'Name' => 'vagrant',
      'Description' => 'vagrant-aws testing'
    }

    override.ssh.username = "ec2-user"
    override.ssh.private_key_path = "/path/to/.ssh/tokyo.pem"
  end
end

vagrant up

この Vagrant ファイルで up してみます.

vagrant up --provider=aws

作成した EC2 インスタンスへログイン

SSH で EC2 インスタンスにログインしてみます.

 
vagrant ssh

ログインできました.

WARNING: Nokogiri was built against LibXML version 2.8.0, but has dynamically loaded 2.9.1
[fog][WARNING] Unable to load the 'unf' gem. Your AWS strings may not be properly encoded.
Last login: ...

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

Amazon Linux AMI 2014.03 Release Notes
No packages needed for security; 24 packages available Run "sudo yum update" to apply all updates. [ec2-user@ip-172-xxx-xxx-xxx ~]$

作成した EC2 インスタンスの削除

EC2 インスタンスを削除したい場合は,vagrant destroy を実行します.

vagrant destroy

結果,

default: Are you sure you want to destroy the 'default' VM? [y/N] y
WARNING: Nokogiri was built against LibXML version 2.8.0, but has dynamically loaded 2.9.1
[fog][WARNING] Unable to load the 'unf' gem. Your AWS strings may not be properly encoded.
==> default: Terminating the instance...

Vagrant で EC2 インスタンスを作成し,Chef をインストール

Vagrant で EC2 インスタンスを作成し,そのインスタンスに Chef を自動インストールするところまでやってみます.

Vagrantfile に config.omnibus.chef_version = :latest という一文を追記するだけです.

# -*- mode: ruby -*-
# vi: set ft=ruby :

# Vagrantfile API/syntax version. Don't touch unless you know what you're doing!
VAGRANTFILE_API_VERSION = "2"
  config.vm.box = "dummy"
  config.ssh.pty = true
  config.ssh.private_key_path = '/path/to/.ssh/tokyo.pem'
  config.ssh.username = "ec2-user"
  config.vm.synced_folder ".", "/vagrant", :disabled => true
  config.vm.provider :aws do |aws, override|
    aws.access_key_id = "Access Key ID"
    aws.secret_access_key = "Secret Access Key"
    aws.keypair_name = "キーペアの名前"

    aws.ami = "ami-c9562fc8"

    aws.instance_type = "t1.micro"
    # Tokyo region
    aws.region = "ap-northeast-1"  

    aws.security_groups = [ 'my_security_group' ]

    aws.tags = {
      'Name' => 'vagrant',
      'Description' => 'vagrant-aws testing'
    }

    override.ssh.username = "ec2-user"
    override.ssh.private_key_path = "/path/to/.ssh/tokyo.pem"
  end
  config.omnibus.chef_version = :latest
end

vagrant up 後,EC2 インスタンスに SSH でログインし,chef-solo のパスを確認してみます.

which chef-solo

Vagrant で EC2 インスタンスを作成し,Chef をインストールし,ローカルで作成したレシピの実行

これが今回の最終的な目的となります.

Vagrantfile

ローカルにおける Chef のレシピを追記しています.ローカルで作成した Chef のレシピが自動で EC2 に転送され,EC2 上でレシピが実行されるようになります.

# -*- mode: ruby -*-
# vi: set ft=ruby :

# Vagrantfile API/syntax version. Don't touch unless you know what you're doing!
VAGRANTFILE_API_VERSION = "2"
  config.vm.box = "dummy"
  config.ssh.pty = true
  config.ssh.private_key_path = '/path/to/.ssh/tokyo.pem'
  config.ssh.username = "ec2-user"
  config.vm.synced_folder ".", "/vagrant", :disabled => true
  config.vm.provider :aws do |aws, override|
    aws.access_key_id = "Access Key ID"
    aws.secret_access_key = "Secret Access Key"
    aws.keypair_name = "キーペアの名前"

    aws.ami = "ami-c9562fc8"

    aws.instance_type = "t1.micro"
    # Tokyo region
    aws.region = "ap-northeast-1"  

    aws.security_groups = [ 'my_security_group' ]

    aws.tags = {
      'Name' => 'vagrant',
      'Description' => 'vagrant-aws testing'
    }

    override.ssh.username = "ec2-user"
    override.ssh.private_key_path = "/path/to/.ssh/tokyo.pem"
  end
  config.omnibus.chef_version = :latest
  config.vm.provision :chef_solo do |chef|
    config.ssh.private_key_path = '/path/to/.ssh/tokyo.pem'
    config.ssh.username = "ec2-user"
    chef.cookbooks_path = "./cookbooks"
    chef.add_recipe "yum"
    chef.add_recipe "apache"
    chef.add_recipe "openjdk7"
    chef.add_recipe "tomcat7"
  end
end

Chef のレシピ作成

適当なパスに Chef 用のリポジトリを作成し,その下に Cookbooks を作成します.さらにその下に各 Cookbook を作成します.

cd /path/to/directory
knife cookbook create apache -o cookbooks

階層は下記の通り.

cookbooks/
  apache/
    attributes/
    difinitions/
    libraries/
    providers/
    recipes/
      default.rb
    templates
      default/
    CHANGELOG.md
    files/
      default/
    metadata.rb
    README.md
    resources/

Apache

Apache 用の Cookbook を作成します.

knife cookbook create apache -o cookbooks

そして,default.rb を例えば下記のように設定します.yum で Apache をインストールし,予め準備しておいた設定ファイルを適用させた上で Apache を起動します.デフォルトの設定ファイルに,後ほど Cookbook を作成する Tomcat との連携について追記しています.追記部分のみを別途設定ファイルとして準備してもよいと思います.

cookbooks/apache/recipes/default.rb

package "httpd" do
  action :install
end

cookbook_file "/etc/httpd/conf/httpd.conf" do
  mode 00644
end

service "httpd" do
  supports :status => true, :restart => true, :reload => true
  action [ :enable, :start ]
end

デフォルトに追記を行なった設定ファイルは,下記の場所に置いておきます.

cookbooks/apache/files/default/httpd.conf

追記内容は,例えば,

...
...
<Location /sample/>
  ProxyPass ajp://localhost:8009/sample/
</Location>

Java 7

OpenJDK 7 用の Cookbook を作成します.

knife cookbook create openjdk7 -o cookbooks

そして,default.rb を例えば下記のように設定します.yum で OpenJDK 7 をインストールします.

cookbooks/openjdk7/recipes/default.rb

package "java-1.7.0-openjdk" do
  action :install
end

Tomcat 7

Tomcat 7 用の Cookbook を作成します.

knife cookbook create tomcat7 -o cookbooks

デプロイする Web アプリケーションを sample.war とします.それを Cookbook の files/default に置いておきます.

cookbooks/tomcat7/files/default/sample.war

そして,default.rb を例えば下記のように設定します.Amazon Linux に yum で Tomcat 7 をインストールした場合,war ファイルは /var/lib/tomcat7/webapps にデプロイすることになります.

cookbooks/tomcat/recipes/default.rb

package "tomcat7" do
  action :install
end

cookbook_file "/var/lib/tomcat7/webapps/sample.war" do
  mode 00644
end

service "tomcat7" do
  action [ :enable, :start ]
  supports :status => true, :restart => true, :reload => true
end

yum

yum 用の Cookbook を作成します.

knife cookbook create yum -o cookbooks

そして,default.rb を例えば下記のように設定します.yum-fastestmirror をインストールした後に yum-update を実行します.

cookbooks/yum/recipes/default.rb

package "yum-fastestmirror" do
  action :install
end

execute "yum-update" do
#  user "root"
  command "yum -y update"
  action :run
end

vagrant up

vagrant up --provider=aws

vagrant up 終了後,EC2 の URI に接続してみます.今回の例だと,http://example.test/sample/ に接続し,Web アプリケーションが実行されれば OK です.

その他

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

Vagrantfile に config.ssh.pty = true を追記しておきます.