使用Vagrant + Ansible来启动和配置多个EC2实例
一条指令就能建立理想的环境,真是太令人开心了!我非常高兴!
开发环境和生产环境等有各种用途,但是在同时建立、运行和删除多个服务器时,Vagrant和配置管理工具非常方便。虽然有很多选择,如Chef、Puppet等,但为了方便地创建和使用定义文件,我们这次选择使用Ansible。
这次我们将启动5个实例,它们都是运行着相同应用程序但参考不同数据库的。我们将从已完成部署的AMI启动实例,并为每个主机更改配置文件。
创建一个Vagrantfile文件
请安装vagrant-aws插件,因为我们将使用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"
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
创建一个手册
我們要創建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最佳实践。
开始,结束
然后,在Vagrantfile所在的位置执行vagrant up –provide aws。要删除环境,使用vagrant destroy。如果需要,可以添加-f选项。
结束
我对于Vagrant和Ansible的协作方式阅读了文档,但仍然不太明白,因此为了自己整理了一下。果然,Ansible还是方便易用且实用的。