コマンド1発で理想の環境ができあがるとうれしいですよね!僕は、嬉しいです!!
開発環境や、本番環境など用途は色々ですが、同時にサーバーを幾つか建てて、動かして、削除する際にはVagrantと構成管理ツールが便利です。Chefとかpupetとか色々とありますが、手軽に定義ファイルを作って利用できるAnsibleを今回は利用します。
今回は、同じアプリケーションが動作しているけど参照しているDBが異なる5つのインスタンスの起動を行います。アプリケーションのデプロイが完了したamiからインスタンスを起動し、設定ファイルをホスト毎に切り替えます。
Vagrantfileを作る
EC2を利用するので、vagrant-awsプラグインを事前に入れておいてください。
# -*- 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|
access_key = ENV['AWS_ACCESS_KEY']
access_secret = ENV['AWS_SECRET_KEY']
config.vm.box = "dummy"
config.vm.box_url = "https://github.com/mitchellh/vagrant-aws/raw/master/dummy.box"
config.vm.define :ap1 do |ap1|
ap1.vm.provider :aws do |aws, override|
aws.access_key_id = access_key
aws.secret_access_key = access_secret
aws.keypair_name = "AWS_KEYPAIR_NAME"
aws.region = "ap-northeast-1"
aws.ami = "ami-xxxxxx"
aws.user_data = "#!/bin/bash\nexport TARGET_ENV=test;"
aws.availability_zone = "ap-northeast-1a"
aws.instance_type = "m1.small"
aws.security_groups = ["aws_security_group"]
override.ssh.username = "aws_user"
override.ssh.private_key_path = "~/.ssh/aws_private_key"
aws.tags = {
'Name' => 'ap01',
}
end
ap1.vm.provision "ansible" do |ansible|
ansible.groups = {
"ap1" => ["ap1"]
}
ansible.extra_vars = {
"db_host" => db_host,
"db_name" => "db_01"
}
ansible.playbook = "playbook.yaml"
end
end
config.vm.define :ap2 do |ap2|
ap2.vm.provider :aws do |aws, override|
aws.access_key_id = access_key
aws.secret_access_key = access_secret
aws.keypair_name = "AWS_KEYPAIR_NAME"
aws.region = "ap-northeast-1"
aws.ami = "ami-xxxxxx"
aws.user_data = "#!/bin/bash\nexport TARGET_ENV=test;"
aws.availability_zone = "ap-northeast-1a"
aws.instance_type = "m1.small"
aws.security_groups = ["aws_security_group"]
override.ssh.username = "aws_user"
override.ssh.private_key_path = "~/.ssh/aws_private_key"
aws.tags = {
'Name' => 'ap02',
}
end
ap2.vm.provision "ansible" do |ansible|
ansible.groups = {
"ap2" => ["ap2"]
}
ansible.extra_vars = {
"db_host" => db_host,
"db_name" => "db_02"
}
ansible.playbook = "playbook.yaml"
end
end
config.vm.define :ap3 do |ap3|
ap3.vm.provider :aws do |aws, override|
aws.access_key_id = access_key
aws.secret_access_key = access_secret
aws.keypair_name = "AWS_KEYPAIR_NAME"
aws.region = "ap-northeast-1"
aws.ami = "ami-xxxxxx"
aws.user_data = "#!/bin/bash\nexport TARGET_ENV=test;"
aws.availability_zone = "ap-northeast-1a"
aws.instance_type = "m1.small"
aws.security_groups = ["aws_security_group"]
override.ssh.username = "aws_user"
override.ssh.private_key_path = "~/.ssh/aws_private_key"
aws.tags = {
'Name' => 'ap03',
}
end
ap3.vm.provision "ansible" do |ansible|
ansible.groups = {
"ap3" => ["ap3"]
}
ansible.extra_vars = {
"db_host" => db_host,
"db_name" => "db_03"
}
ansible.playbook = "playbook.yaml"
end
end
config.vm.define :ap4 do |ap4|
ap4.vm.provider :aws do |aws, override|
aws.access_key_id = access_key
aws.secret_access_key = access_secret
aws.keypair_name = "AWS_KEYPAIR_NAME"
aws.region = "ap-northeast-1"
aws.ami = "ami-xxxxxx"
aws.user_data = "#!/bin/bash\nexport TARGET_ENV=test;"
aws.availability_zone = "ap-northeast-1a"
aws.instance_type = "m1.small"
aws.security_groups = ["aws_security_group"]
override.ssh.username = "aws_user"
override.ssh.private_key_path = "~/.ssh/aws_private_key"
aws.tags = {
'Name' => 'ap04',
}
end
ap4.vm.provision "ansible" do |ansible|
ansible.groups = {
"ap4" => ["ap4"]
}
ansible.extra_vars = {
"db_host" => db_host,
"db_name" => "db_04"
}
ansible.playbook = "playbook.yaml"
end
end
config.vm.define :ap5 do |ap5|
ap5.vm.provider :aws do |aws, override|
aws.access_key_id = access_key
aws.secret_access_key = access_secret
aws.keypair_name = "AWS_KEYPAIR_NAME"
aws.region = "ap-northeast-1"
aws.ami = "ami-xxxxxx"
aws.user_data = "#!/bin/bash\nexport TARGET_ENV=test;"
aws.availability_zone = "ap-northeast-1a"
aws.instance_type = "m1.small"
aws.security_groups = ["aws_security_group"]
override.ssh.username = "aws_user"
override.ssh.private_key_path = "~/.ssh/aws_private_key"
aws.tags = {
'Name' => 'ap05',
}
end
ap5.vm.provision "ansible" do |ansible|
ansible.groups = {
"ap5" => ["ap5"]
}
ansible.extra_vars = {
"db_host" => db_host,
"db_name" => "db_05"
}
ansible.playbook = "playbook.yaml"
end
end
end
playbookを作る
Ansibleの構成定義ファイル、playbookを作ります。yamlで書けるので新しいDSLを覚えたりしなくて良いよ!!ってのがウリらしいですね。
---
- name: Setup ecs
hosts: all
remote_user: aws_user
sudo: yes
tasks:
- name: upload config
template: src=config.ini dest=/var/www/Application/common/config/config.ini
- name: start httpd
service: name=httpd state=restarted enabled=yes
テンプレートを用意する
設定ファイルはテンプレートを利用し、Vagrantfileのansible.extra_values
でそれぞれ異なる値を代入しています。そのため、
database.host = {{ db_host }}
database.name = {{ db_name }}
{{}}
で囲った中身に変数が展開されます。
ファイルの配置
今回はこんな感じ。
├── Vagrantfile
├── config.ini
└── playbook.yaml
規模に応じてAnsible Best Practicesを採用したり。
起動、終了
あとは、Vagrantfileのある場所でvagrant up --provide aws
をやります。環境を消すにはvagrant destroy
。お好みで-f
も。
おわり
VagrantとAnsibleの連携方法がドキュメントを読んでてもよく分からなかったので自分用にまとめました。やっぱりAnsibleは手軽に使えて便利だなぁ。