Update playbook to work on Vagrant, Digital Ocean, and AWS.

This commit is contained in:
Jeff Geerling
2014-11-12 11:25:18 -06:00
parent 2f7f10df58
commit fb5a98bbbe
8 changed files with 143 additions and 31 deletions
+18 -1
View File
@@ -43,7 +43,7 @@ After everything is booted and configured, visit http://varnish.dev/ (if you con
## Build and configure the servers (DigitalOcean)
Pre-suppositions: You have a DigitalOcean account, and you grabbed your v1 API Client ID and API Key from the account.
Pre-suppositions: You have a DigitalOcean account, and you have your v1 API Client ID and API Key from the account. Additionally, you have `dopy` and Ansible installed on your workstation (install `dopy` with `sudo pip install dopy`).
To build the droplets and configure them using Ansible, follow these steps (both from within this directory):
@@ -57,3 +57,20 @@ After everything is booted and configured, visit the IP address of the Varnish s
- Public IP addresses are used for all cross-droplet communication (e.g. PHP to MySQL/Memcached communication, MySQL master/slave replication). For better security and potentially a tiny performance improvement, you can use droplets' `private_ip_address` for cross-droplet communication.
- Hosting active or inactive droplets on DigitalOcean will incur hosting fees (normally $0.01 USD/hour for the default 512mb droplets used in this example). While the charges will be nominal (likely less than $1 USD for many hours of testing), it's important to destroy droplets you aren't actively using!
## Build and configure the servers (AWS)
Pre-suppositions: You have an Amazon Web Services account with a valid payment method configured, and you have your AWS Access Key and AWS Secret Key from your account. Additionally, you have `boto` and Ansible installed on your workstation (install `boto` with `sudo pip install boto`).
To build the droplets and configure them using Ansible, follow these steps (both from within this directory):
1. Set your AWS Access Key: `export AWS_ACCESS_KEY=[access key here]`
2. Set your AWS Secret Key: `export AWS_SECRET_KEY=[secret key here]`
3. Run `ansible-playbook provision.yml`.
After everything is booted and configured, visit the IP address of the Varnish server that was created in your AWS account in a browser, and refresh a few times to see that Varnish, Apache, PHP, Memcached, and MySQL are all working properly!
### Notes
- Public IP addresses are used for all cross-instance communication (e.g. PHP to MySQL/Memcached communication, MySQL master/slave replication). For better security and potentially a tiny performance improvement, you can use instances' `private_ip` for cross-instance communication.
- Hosting instances on AWS may incur hosting fees (unless all usage falls within AWS's first-year free tier limits). While the charges will be nominal (likely less than $1 USD for many hours of testing), it's important to destroy instances you aren't actively using!
+13 -5
View File
@@ -5,9 +5,6 @@ Vagrant.configure("2") do |config|
# Base VM OS configuration.
config.vm.box = "geerlingguy/centos6"
config.vm.provision "shell",
inline: "sudo iptables -F && service iptables save"
# Varnish.
config.vm.define "varnish" do |varnish|
varnish.vm.hostname = "varnish.dev"
@@ -29,7 +26,7 @@ Vagrant.configure("2") do |config|
www1.vm.network :private_network, ip: "192.168.2.3"
www1.vm.provision "shell",
inline: "sudo iptables -F && service iptables save && sudo yum update -y"
inline: "sudo yum update -y"
# VirtualBox.
www1.vm.provider :virtualbox do |v|
@@ -47,7 +44,7 @@ Vagrant.configure("2") do |config|
www2.vm.network :private_network, ip: "192.168.2.4"
www2.vm.provision "shell",
inline: "sudo iptables -F && service iptables save && sudo yum update -y"
inline: "sudo yum update -y"
# VirtualBox.
www2.vm.provider :virtualbox do |v|
@@ -102,5 +99,16 @@ Vagrant.configure("2") do |config|
v.customize ["modifyvm", :id, "--cpus", 1]
v.customize ["modifyvm", :id, "--ioapic", "on"]
end
# Run Ansible provisioner once for all VMs at the end.
memcached.vm.provision "ansible" do |ansible|
ansible.playbook = "configure.yml"
ansible.inventory_path = "inventories/vagrant/inventory"
ansible.limit = "all"
ansible.extra_vars = {
ansible_ssh_user: 'vagrant',
ansible_ssh_private_key_file: "~/.vagrant.d/insecure_private_key"
}
end
end
end
@@ -1,3 +1,11 @@
[vagrant]
192.168.2.2
192.168.2.3
192.168.2.4
192.168.2.5
192.168.2.6
192.168.2.7
[lamp-varnish]
192.168.2.2
@@ -5,28 +13,12 @@
192.168.2.3
192.168.2.4
[lamp-db]
192.168.2.5 mysql_replication_role=master mysql_server_id=1
192.168.2.6 mysql_replication_role=slave mysql_server_id=2
[a4d.lamp.db.1]
192.168.2.5
[lamp-db]
192.168.2.5
192.168.2.6
[lamp-memcached]
192.168.2.7
[lamp-varnish:vars]
ansible_ssh_user=vagrant
ansible_ssh_private_key_file=/Users/jgeerling/.vagrant.d/insecure_private_key
[lamp-www:vars]
ansible_ssh_user=vagrant
ansible_ssh_private_key_file=/Users/jgeerling/.vagrant.d/insecure_private_key
[lamp-db:vars]
ansible_ssh_user=vagrant
ansible_ssh_private_key_file=/Users/jgeerling/.vagrant.d/insecure_private_key
[lamp-memcached:vars]
ansible_ssh_user=vagrant
ansible_ssh_private_key_file=/Users/jgeerling/.vagrant.d/insecure_private_key
@@ -7,6 +7,7 @@
roles:
- geerlingguy.firewall
- geerlingguy.repo-epel
- geerlingguy.varnish
tasks:
@@ -1,3 +1,7 @@
vcl 4.0;
import directors;
{% for host in groups['lamp-www'] %}
backend www{{ loop.index }} {
.host = "{{ host }}";
@@ -5,14 +9,15 @@ backend www{{ loop.index }} {
}
{% endfor %}
director www random {
sub vcl_init {
new vdir = directors.random();
{% for host in groups['lamp-www'] %}
{ .backend = www{{ loop.index }}; .weight = 1; }
vdir.add_backend(www{{ loop.index }}, 1);
{% endfor %}
}
sub vcl_recv {
set req.backend = www;
set req.backend_hint = vdir.backend();
# For testing ONLY; we want to make sure load balancing is working correctly.
return (pass);
+7 -1
View File
@@ -1,3 +1,9 @@
---
- include: provisioners/digitalocean.yml
# Uncomment the provisioner you would like to use. For for Vagrant provisioning,
# use `vagrant up` instead of this playbook.
# - include: provisioners/digitalocean.yml
- include: provisioners/aws.yml
# Configure provisioned servers.
- include: configure.yml
+83
View File
@@ -0,0 +1,83 @@
---
- hosts: localhost
connection: local
gather_facts: false
vars:
instances:
- { name: a4d.lamp.varnish, ssh_key: "jeff_mba_home", group: "lamp-varnish", security_group: ["default", "a4d_lamp_http"] }
- { name: a4d.lamp.www.1, ssh_key: "jeff_mba_home", group: "lamp-www", security_group: ["default", "a4d_lamp_http"] }
- { name: a4d.lamp.www.2, ssh_key: "jeff_mba_home", group: "lamp-www", security_group: ["default", "a4d_lamp_http"] }
- { name: a4d.lamp.db.1, ssh_key: "jeff_mba_home", group: "lamp-db", security_group: ["default", "a4d_lamp_db"] }
- { name: a4d.lamp.db.2, ssh_key: "jeff_mba_home", group: "lamp-db", security_group: ["default", "a4d_lamp_db"] }
- { name: a4d.lamp.memcached, ssh_key: "jeff_mba_home", group: "lamp-memcached", security_group: ["default", "a4d_lamp_memcached"] }
security_groups:
- name: a4d_lamp_http
rules:
- { proto: tcp, from_port: 80, to_port: 80, cidr_ip: 0.0.0.0/0 }
- { proto: tcp, from_port: 22, to_port: 22, cidr_ip: 0.0.0.0/0 }
rules_egress: []
- name: a4d_lamp_db
rules:
- { proto: tcp, from_port: 3306, to_port: 3306, cidr_ip: 0.0.0.0/0 }
- { proto: tcp, from_port: 22, to_port: 22, cidr_ip: 0.0.0.0/0 }
rules_egress: []
- name: a4d_lamp_memcached
rules:
- { proto: tcp, from_port: 11211, to_port: 11211, cidr_ip: 0.0.0.0/0 }
- { proto: tcp, from_port: 22, to_port: 22, cidr_ip: 0.0.0.0/0 }
rules_egress: []
tasks:
- name: Configure EC2 Security Groups.
ec2_group:
name: "{{ item.name }}"
description: Example EC2 security group for A4D.
region: us-west-2
state: present
rules: "{{ item.rules }}"
rules_egress: "{{ item.rules_egress }}"
with_items: security_groups
- name: Provision EC2 instances.
ec2:
key_name: "{{ item.ssh_key | default('') }}"
instance_tags:
inventory_group: "{{ item.group | default('') }}"
inventory_host: "{{ item.name | default('') }}"
group: "{{ item.security_group | default('') }}"
instance_type: "{{ item.type | default('t2.micro')}}" # Falls within free tier
image: "{{ item.image | default('ami-11125e21') }}" # RedHat 6.5 x64 hvm
region: "{{ item.region | default('us-west-2') }}" # Oregon
wait: yes
wait_timeout: 500
exact_count: 1
count_tag:
inventory_group: "{{ item.group | default('') }}"
inventory_host: "{{ item.name | default('') }}"
register: created_instances
with_items: instances
- name: Add EC2 instances to their respective inventory groups.
add_host:
name: "{{ item.1.tagged_instances.0.public_ip }}"
groups: "aws,{{ item.1.item.group }},{{ item.1.item.name }}"
# You can dynamically add inventory variables per-host.
ansible_ssh_user: ec2-user
mysql_replication_role: "{{ 'master' if (item.1.item.name == 'a4d.lamp.db.1') else 'slave' }}"
mysql_server_id: "{{ item.0 }}"
when: item.1.instances is defined
with_indexed_items: created_instances.results
# Run some general configuration on all AWS hosts.
- hosts: aws
gather_facts: false
tasks:
- name: Wait for port 22 to become available.
local_action: "wait_for port=22 host={{ inventory_hostname }} search_regex=OpenSSH delay=3"
- name: Set selinux into 'permissive' mode.
selinux: policy=targeted state=permissive
sudo: yes
@@ -31,7 +31,7 @@
- name: Add DigitalOcean hosts to their respective inventory groups.
add_host:
name: "{{ item.1.droplet.ip_address }}"
groups: "{{ droplets[item.0].group }},{{ item.1.droplet.name }}"
groups: "digitalocean,{{ droplets[item.0].group }},{{ item.1.droplet.name }}"
# You can dynamically add inventory variables per-host.
ansible_ssh_user: root
mysql_replication_role: "{{ 'master' if (item.1.droplet.name == 'a4d.lamp.db.1') else 'slave' }}"