From b0db889baa5184bfdc2879f32521306012063451 Mon Sep 17 00:00:00 2001 From: Graham Taylor Date: Thu, 7 Jan 2016 13:01:03 +0000 Subject: [PATCH 1/4] #594 - add terraform scripts for AWS private VPC with coreOS --- bootstrap/aws/config-default.sh | 11 +- bootstrap/aws/util.sh | 2 +- playbooks/coreos-bootstrap.yml | 4 +- roles/mesos/templates/mesos-slave.service.j2 | 2 +- site.yml | 2 +- terraform/aws-public/provider.tf | 1 - terraform/aws/aws-vpc.tf | 20 ++- terraform/aws/bastion-server.tf | 25 ++-- terraform/aws/cloud-config.yml.tpl | 19 +++ terraform/aws/etcd_discovery_url.txt | 0 terraform/aws/mesos-masters.tf | 38 +++--- terraform/aws/mesos-slaves.tf | 62 ++++----- terraform/aws/private-subnet.tf | 6 +- terraform/aws/public-subnet.tf | 9 +- terraform/aws/security_groups.tf | 41 +++--- terraform/aws/terraform.tfvars.example | 7 - terraform/aws/variables.tf | 134 +++---------------- 17 files changed, 148 insertions(+), 235 deletions(-) create mode 100644 terraform/aws/cloud-config.yml.tpl create mode 100644 terraform/aws/etcd_discovery_url.txt delete mode 100644 terraform/aws/terraform.tfvars.example diff --git a/bootstrap/aws/config-default.sh b/bootstrap/aws/config-default.sh index 305e3ad3..42f9b2e8 100644 --- a/bootstrap/aws/config-default.sh +++ b/bootstrap/aws/config-default.sh @@ -15,16 +15,9 @@ export TF_VAR_STATE_ROOT="${APOLLO_ROOT}/terraform/aws" export ANSIBLE_SSH_ARGS="-F ${APOLLO_ROOT}/terraform/${APOLLO_PROVIDER}/ssh.config -q" -# Terraform mappings needs to be statically passed as -var parameters -# so no really needed to export them. Exporting for consitency. -export TF_VAR_atlas_artifact_master=${TF_VAR_atlas_artifact_master:-capgemini/apollo-ubuntu-14.04-amd64} -export TF_VAR_atlas_artifact_slave=${TF_VAR_atlas_artifact_slave:-capgemini/apollo-ubuntu-14.04-amd64} -export TF_VAR_atlas_artifact_version_master=${TF_VAR_atlas_artifact_version_master:-20} -export TF_VAR_atlas_artifact_version_slave=${TF_VAR_atlas_artifact_version_slave:-20} - export TF_VAR_region=${TF_VAR_region:-eu-west-1} -export TF_VAR_master_size=${TF_VAR_master_size:-m3.medium} -export TF_VAR_slave_size=${TF_VAR_slave_size:-m3.medium} +export TF_VAR_master_instance_type=${TF_VAR_master_instance_type:-m3.medium} +export TF_VAR_slave_instance_type=${TF_VAR_slave_instance_type:-m3.medium} export TF_VAR_slaves=${TF_VAR_slaves:-1} export TF_VAR_availability_zones=${TF_VAR_availability_zones:-'eu-west-1a,eu-west-1b,eu-west-1c'} export TF_VAR_public_subnet_availability_zone=${TF_VAR_public_subnet_availability_zone:-'eu-west-1a'} diff --git a/bootstrap/aws/util.sh b/bootstrap/aws/util.sh index 5dfa8d91..68ff6bb9 100644 --- a/bootstrap/aws/util.sh +++ b/bootstrap/aws/util.sh @@ -40,7 +40,7 @@ ansible_ssh_config() { ControlMaster auto ControlPath ~/.ssh/mux-%r@%h:%p ControlPersist 30m - User ubuntu + User core IdentityFile $TF_VAR_private_key_file UserKnownHostsFile /dev/null EOF diff --git a/playbooks/coreos-bootstrap.yml b/playbooks/coreos-bootstrap.yml index 7643b712..c69b2b18 100644 --- a/playbooks/coreos-bootstrap.yml +++ b/playbooks/coreos-bootstrap.yml @@ -1,12 +1,12 @@ - name: bootstrap coreos hosts - hosts: all + hosts: all:!role=bastion gather_facts: False roles: - coreos_bootstrap - coreos_timezone - name: Install docker-py - hosts: all + hosts: all:!role=bastion gather_facts: False tasks: - pip: diff --git a/roles/mesos/templates/mesos-slave.service.j2 b/roles/mesos/templates/mesos-slave.service.j2 index 6b7c55d6..ead50aa7 100644 --- a/roles/mesos/templates/mesos-slave.service.j2 +++ b/roles/mesos/templates/mesos-slave.service.j2 @@ -17,7 +17,7 @@ ExecStart=/usr/bin/docker run --rm --name mesos_slave \ -p {{ mesos_slave_port }}:{{ mesos_slave_port }} \ -v /sys:/sys \ -v /proc:/host/proc:ro \ --v /lib/libgcrypt.so.20:/lib/libgcrypt.so.20:ro \ +-v /lib/libgcrypt.so:/lib/libgcrypt.so:ro \ -v /lib/libsystemd.so.0:/lib/libsystemd.so.0:ro \ -v /lib/libpthread.so.0:/lib/libpthread.so.0:ro \ -v /lib64/libdevmapper.so.1.02:/lib/libdevmapper.so.1.02:ro \ diff --git a/site.yml b/site.yml index e3898b95..67274990 100644 --- a/site.yml +++ b/site.yml @@ -1,6 +1,6 @@ --- - hosts: all:!role=bastion - gather_facts: no + gather_facts: False tasks: - name: Wait for ssh port to become available from bastion server. wait_for: diff --git a/terraform/aws-public/provider.tf b/terraform/aws-public/provider.tf index 8f31c33e..92059c40 100644 --- a/terraform/aws-public/provider.tf +++ b/terraform/aws-public/provider.tf @@ -4,7 +4,6 @@ provider "aws" { region = "${var.region}" } -# Define our vpc resource "aws_vpc" "default" { cidr_block = "${var.vpc_cidr_block}" enable_dns_support = true diff --git a/terraform/aws/aws-vpc.tf b/terraform/aws/aws-vpc.tf index 36a529a3..389eaa33 100644 --- a/terraform/aws/aws-vpc.tf +++ b/terraform/aws/aws-vpc.tf @@ -1,12 +1,28 @@ provider "aws" { access_key = "${var.access_key}" secret_key = "${var.secret_key}" - region = "${var.region}" + region = "${var.region}" } -/* Define our vpc */ resource "aws_vpc" "default" { cidr_block = "${var.vpc_cidr_block}" enable_dns_support = true enable_dns_hostnames = true } + +resource "aws_key_pair" "deployer" { + key_name = "${var.key_name}" + public_key = "${file(var.ssh_public_key)}" +} + +# Generate an etcd URL for the cluster +resource "template_file" "etcd_discovery_url" { + filename = "/dev/null" + provisioner "local-exec" { + command = "curl https://discovery.etcd.io/new?size=${var.masters + var.slaves} > ${var.etcd_discovery_url_file}" + } + # This will regenerate the discovery URL if the cluster size changes + vars { + size = "${var.masters + var.slaves}" + } +} diff --git a/terraform/aws/bastion-server.tf b/terraform/aws/bastion-server.tf index 6ed2204c..d2345c10 100644 --- a/terraform/aws/bastion-server.tf +++ b/terraform/aws/bastion-server.tf @@ -1,20 +1,11 @@ -resource "aws_key_pair" "deployer" { - key_name = "${var.key_name}" - public_key = "${file(var.key_file)}" -} - -/* - Terraform module to get the current set of publicly available ubuntu AMIs. - https://github.com/terraform-community-modules/tf_aws_ubuntu_ami -*/ +# Bastion server module "ami_bastion" { - source = "github.com/terraform-community-modules/tf_aws_ubuntu_ami/ebs" - region = "${var.region}" - distribution = "trusty" + source = "github.com/terraform-community-modules/tf_aws_ubuntu_ami/ebs" + region = "${var.region}" + distribution = "trusty" instance_type = "${var.bastion_instance_type}" } -/* NAT/VPN server */ resource "aws_instance" "bastion" { ami = "${module.ami_bastion.ami_id}" instance_type = "${var.bastion_instance_type}" @@ -28,8 +19,8 @@ resource "aws_instance" "bastion" { role = "bastion" } connection { - user = "ubuntu" - key_file = "${var.private_key_file}" + user = "ubuntu" + private_key = "${var.ssh_private_key}" } provisioner "remote-exec" { inline = [ @@ -53,8 +44,8 @@ resource "aws_instance" "bastion" { } } -/* NAT elastic IP */ +# Bastion elastic IP resource "aws_eip" "bastion" { instance = "${aws_instance.bastion.id}" - vpc = true + vpc = true } diff --git a/terraform/aws/cloud-config.yml.tpl b/terraform/aws/cloud-config.yml.tpl new file mode 100644 index 00000000..4cc6a1c2 --- /dev/null +++ b/terraform/aws/cloud-config.yml.tpl @@ -0,0 +1,19 @@ +#cloud-config + +coreos: + etcd2: + # $public_ipv4 and $private_ipv4 are populated by the cloud provider + advertise-client-urls: http://$public_ipv4:2379 + initial-advertise-peer-urls: http://$private_ipv4:2380 + listen-client-urls: http://0.0.0.0:2379,http://0.0.0.0:4001 + listen-peer-urls: http://$private_ipv4:2380,http://$private_ipv4:7001 + # Discovery is populated by Terraform + discovery: ${etcd_discovery_url} + fleet: + public-ip: "$public_ipv4" + units: + - name: etcd2.service + command: start + - name: fleet.service + command: start +manage_etc_hosts: localhost diff --git a/terraform/aws/etcd_discovery_url.txt b/terraform/aws/etcd_discovery_url.txt new file mode 100644 index 00000000..e69de29b diff --git a/terraform/aws/mesos-masters.tf b/terraform/aws/mesos-masters.tf index f9061fe9..2e25e5cc 100644 --- a/terraform/aws/mesos-masters.tf +++ b/terraform/aws/mesos-masters.tf @@ -1,28 +1,34 @@ -/* Base packer build we use for provisioning master instances */ -resource "atlas_artifact" "mesos-master" { - name = "${var.atlas_artifact.master}" - type = "aws.ami" - version = "${var.atlas_artifact_version.master}" +module "master_amitype" { + source = "github.com/terraform-community-modules/tf_aws_virttype" + instance_type = "${var.master_instance_type}" } -/* Mesos master instances */ -resource "aws_instance" "mesos-master" { - /* - We had to hardcode the amis list in variables.tf file creating amis map because terraform doesn't - support interpolation in the way which could allow us to replaced the region dinamically. - We need to remember to update the map every time when we build a new artifact on atlas. - Similar issue related to metada_full is mentioned here: - https://github.com/hashicorp/terraform/issues/732 - */ +module "master_ami" { + source = "github.com/terraform-community-modules/tf_aws_coreos_ami" + region = "${var.region}" + channel = "${var.coreos_channel}" + virttype = "${module.master_amitype.prefer_hvm}" +} + +resource "template_file" "master_cloud_init" { + filename = "cloud-config.yml.tpl" + depends_on = ["template_file.etcd_discovery_url"] + vars { + etcd_discovery_url = "${file(var.etcd_discovery_url_file)}" + size = "${var.masters + var.slaves}" + } +} - instance_type = "${var.instance_type.master}" - ami = "${lookup(var.amis, var.region)}" +resource "aws_instance" "mesos-master" { + instance_type = "${var.master_instance_type}" + ami = "${module.master_ami.ami_id}" count = "${var.masters}" key_name = "${aws_key_pair.deployer.key_name}" source_dest_check = false subnet_id = "${element(aws_subnet.private.*.id, count.index)}" security_groups = ["${aws_security_group.default.id}"] depends_on = ["aws_instance.bastion", "aws_internet_gateway.public"] + user_data = "${template_file.master_cloud_init.rendered}" tags = { Name = "apollo-mesos-master-${count.index}" role = "mesos_masters" diff --git a/terraform/aws/mesos-slaves.tf b/terraform/aws/mesos-slaves.tf index 62860a76..cdeba684 100644 --- a/terraform/aws/mesos-slaves.tf +++ b/terraform/aws/mesos-slaves.tf @@ -1,65 +1,67 @@ -/* Base packer build we use for provisioning slave instances */ -resource "atlas_artifact" "mesos-slave" { - name = "${var.atlas_artifact.slave}" - type = "aws.ami" - version = "${var.atlas_artifact_version.slave}" +module "slave_amitype" { + source = "github.com/terraform-community-modules/tf_aws_virttype" + instance_type = "${var.slave_instance_type}" } -/* Mesos slave instances */ -resource "aws_instance" "mesos-slave" { - /* - We had to hardcode the amis list in variables.tf file creating amis map because terraform doesn't - support interpolation in the way which could allow us to replaced the region dinamically. - We need to remember to update the map every time when we build a new artifact on atlas. - Similar issue related to metada_full is mentioned here: - https://github.com/hashicorp/terraform/issues/732 - */ +module "slave_ami" { + source = "github.com/terraform-community-modules/tf_aws_coreos_ami" + region = "${var.region}" + channel = "${var.coreos_channel}" + virttype = "${module.slave_amitype.prefer_hvm}" +} - instance_type = "${var.instance_type.slave}" - ami = "${lookup(var.amis, var.region)}" +resource "template_file" "slave_cloud_init" { + filename = "cloud-config.yml.tpl" + depends_on = ["template_file.etcd_discovery_url"] + vars { + etcd_discovery_url = "${file(var.etcd_discovery_url_file)}" + size = "${var.masters + var.slaves}" + } +} + +resource "aws_instance" "mesos-slave" { + instance_type = "${var.slave_instance_type}" + ami = "${module.slave_ami.ami_id}" count = "${var.slaves}" key_name = "${aws_key_pair.deployer.key_name}" source_dest_check = false subnet_id = "${element(aws_subnet.private.*.id, count.index)}" security_groups = ["${aws_security_group.default.id}"] depends_on = ["aws_instance.bastion", "aws_internet_gateway.public", "aws_instance.mesos-master"] + user_data = "${template_file.master_cloud_init.rendered}" tags = { Name = "apollo-mesos-slave-${count.index}" role = "mesos_slaves" } - ebs_block_device { - device_name = "/dev/sda1" - volume_size = "${var.slave_block_device.volume_size}" - delete_on_termination = true - } } -/* Load balancer */ +# Load balancer resource "aws_elb" "app" { - name = "apollo-mesos-elb" - subnets = ["${aws_subnet.public.*.id}"] + name = "apollo-mesos-elb" + subnets = ["${aws_subnet.public.*.id}"] security_groups = ["${aws_security_group.default.id}", "${aws_security_group.web.id}"] listener { - instance_port = 80 + instance_port = 80 instance_protocol = "http" - lb_port = 80 - lb_protocol = "http" + lb_port = 80 + lb_protocol = "http" } + # traefik health check health_check { healthy_threshold = 2 unhealthy_threshold = 2 timeout = 3 - target = "HTTP:34180/haproxy_status" + target = "HTTP:8888/health" interval = 30 } - instances = ["${aws_instance.mesos-slave.*.id}"] + instances = ["${aws_instance.mesos-slave.*.id}"] cross_zone_load_balancing = true } resource "aws_proxy_protocol_policy" "http" { - load_balancer = "${aws_elb.app.name}" + load_balancer = "${aws_elb.app.name}" instance_ports = ["80"] } diff --git a/terraform/aws/private-subnet.tf b/terraform/aws/private-subnet.tf index 3f3e5c54..7efecba2 100644 --- a/terraform/aws/private-subnet.tf +++ b/terraform/aws/private-subnet.tf @@ -1,4 +1,4 @@ -/* Private subnet */ +# Private subnet resource "aws_subnet" "private" { vpc_id = "${aws_vpc.default.id}" count = "${length(split(",", var.availability_zones))}" @@ -11,11 +11,10 @@ resource "aws_subnet" "private" { } } -/* Routing table for private subnet */ resource "aws_route_table" "private" { vpc_id = "${aws_vpc.default.id}" route { - cidr_block = "0.0.0.0/0" + cidr_block = "0.0.0.0/0" instance_id = "${aws_instance.bastion.id}" } tags { @@ -23,7 +22,6 @@ resource "aws_route_table" "private" { } } -/* Associate the routing table to private subnet */ resource "aws_route_table_association" "private" { count = "${length(split(",", var.availability_zones))}" subnet_id = "${element(aws_subnet.private.*.id, count.index)}" diff --git a/terraform/aws/public-subnet.tf b/terraform/aws/public-subnet.tf index f406dbe2..97b777e2 100644 --- a/terraform/aws/public-subnet.tf +++ b/terraform/aws/public-subnet.tf @@ -1,9 +1,8 @@ -/* Internet gateway for the public subnet */ +# Public subnet resource "aws_internet_gateway" "public" { vpc_id = "${aws_vpc.default.id}" } -/* Public subnet */ resource "aws_subnet" "public" { vpc_id = "${aws_vpc.default.id}" availability_zone = "${var.public_subnet_availability_zone}" @@ -15,7 +14,6 @@ resource "aws_subnet" "public" { } } -/* Routing table for public subnet */ resource "aws_route_table" "public" { vpc_id = "${aws_vpc.default.id}" route { @@ -28,11 +26,10 @@ resource "aws_route_table" "public" { } resource "aws_main_route_table_association" "public" { - vpc_id = "${aws_vpc.default.id}" - route_table_id = "${aws_route_table.public.id}" + vpc_id = "${aws_vpc.default.id}" + route_table_id = "${aws_route_table.public.id}" } -/* Associate the routing table to public subnet */ resource "aws_route_table_association" "public" { subnet_id = "${aws_subnet.public.id}" route_table_id = "${aws_route_table.public.id}" diff --git a/terraform/aws/security_groups.tf b/terraform/aws/security_groups.tf index 0cac70fc..df6fef35 100644 --- a/terraform/aws/security_groups.tf +++ b/terraform/aws/security_groups.tf @@ -1,8 +1,7 @@ -/* Default security group */ resource "aws_security_group" "default" { - name = "default-apollo-mesos" + name = "default-apollo-mesos" description = "Default security group that allows inbound and outbound traffic from all instances in the VPC" - vpc_id = "${aws_vpc.default.id}" + vpc_id = "${aws_vpc.default.id}" ingress { from_port = "0" @@ -23,37 +22,36 @@ resource "aws_security_group" "default" { } } -/* Security group for the bastion server */ resource "aws_security_group" "bastion" { - name = "bastion-apollo-mesos" + name = "bastion-apollo-mesos" description = "Security group for bastion instances that allows SSH and VPN traffic from internet" - vpc_id = "${aws_vpc.default.id}" + vpc_id = "${aws_vpc.default.id}" ingress { - from_port = 22 - to_port = 22 - protocol = "tcp" + from_port = 22 + to_port = 22 + protocol = "tcp" cidr_blocks = ["0.0.0.0/0"] } ingress { - from_port = 1194 - to_port = 1194 - protocol = "udp" + from_port = 1194 + to_port = 1194 + protocol = "udp" cidr_blocks = ["0.0.0.0/0"] } egress { - from_port = 80 - to_port = 80 - protocol = "tcp" + from_port = 80 + to_port = 80 + protocol = "tcp" cidr_blocks = ["0.0.0.0/0"] } egress { - from_port = 443 - to_port = 443 - protocol = "tcp" + from_port = 443 + to_port = 443 + protocol = "tcp" cidr_blocks = ["0.0.0.0/0"] } @@ -62,16 +60,15 @@ resource "aws_security_group" "bastion" { } } -/* Security group for web traffic */ resource "aws_security_group" "web" { name = "web-apollo-mesos" description = "Security group that allows web traffic from the internet" vpc_id = "${aws_vpc.default.id}" ingress { - from_port = 80 - to_port = 80 - protocol = "tcp" + from_port = 80 + to_port = 80 + protocol = "tcp" cidr_blocks = ["0.0.0.0/0"] } diff --git a/terraform/aws/terraform.tfvars.example b/terraform/aws/terraform.tfvars.example deleted file mode 100644 index 351f68a7..00000000 --- a/terraform/aws/terraform.tfvars.example +++ /dev/null @@ -1,7 +0,0 @@ -access_key = "aws_access_key_jfldajlkdfja;ds" -secret_key = "aws_secret_key_jkfldajskfja;klkfjdsa" -atlas_token = "atlas_token_v-31xdELrnLSns-HgbmJy1eXztv_z69zMvQ2xyJ8" -region = "eu-west-1" -key_name = "your-key-name" -key_file = "some/path/to/file.pem" -zone_id = "FAKEZONEID" diff --git a/terraform/aws/variables.tf b/terraform/aws/variables.tf index b3440a2f..36d7c056 100644 --- a/terraform/aws/variables.tf +++ b/terraform/aws/variables.tf @@ -1,116 +1,18 @@ -variable "access_key" { - description = "The aws access key." - default = "" -} - -variable "secret_key" { - description = "The aws secret key." - default = "" -} - -variable "key_name" { - description = "The aws ssh key name." - default = "Apollo" -} - -variable "key_file" { - description = "The ssh public key for using with the cloud provider." - default = "" -} - -variable "private_key_file" { - description = "The ssh public key for using with the cloud provider." - default = "" -} - -variable "atlas_infrastructure" { - description = "The Atlas infrastructure project to join." - default = "capgemini/infrastructure" -} - -variable "region" { - description = "The AWS region to create resources in." - default = "eu-west-1" -} - -variable "public_subnet_availability_zone" { - description = "Public availability zone." - default = "" -} - -variable "availability_zones" { - description = "AWS availability zones list separated by ','" - default = "" -} - -variable "vpc_cidr_block" { - description = "Cidr block for the VPC." - default = "10.0.0.0/16" -} - -variable "public_subnet_cidr_block" { - description = "CIDR for public subnet" - default = "10.0.0.0/24" -} - -variable "slaves" { - description = "The number of slaves." - default = "1" -} - -variable "masters" { - description = "The number of masters." - default = "3" -} - -variable "slave_block_device" { - description = "Block device for OSD." - default = { - volume_size = 30 - } -} - -variable "instance_type" { - default = { - master = "m3.medium" - slave = "m3.medium" - } -} - -variable "bastion_instance_type" { - default = "t2.micro" -} - -variable "atlas_artifact" { - default = { - master = "capgemini/apollo-ubuntu-14.04-amd64" - slave = "capgemini/apollo-ubuntu-14.04-amd64" - } -} - -variable "atlas_artifact_version" { - default = { - master = "20" - slave = "20" - } -} - -variable "docker_version" { - description = "Docker version" - default = "1.9.0-0~trusty" -} - -/* Remember to update the list every time when you build a new artifact on atlas */ -variable "amis" { - default = { - ap-northeast-1 ="ami-d6def0b8" - ap-southeast-1 ="ami-7923e31a" - ap-southeast-2 ="ami-f492ca97" - eu-central-1 ="ami-e2938e8e" - eu-west-1 ="ami-c10aacb2" - sa-east-1 ="ami-64e66208" - us-east-1 ="ami-3f91dd55" - us-west-1 ="ami-697f1709" - us-west-2 ="ami-62726f03" - } -} +variable "access_key" {} +variable "secret_key" {} +variable "key_name" { default = "Apollo" } +variable "ssh_public_key" {} +variable "ssh_private_key" {} +variable "region" { default = "eu-west-1" } +variable "availability_zones" { default = "eu-west-1a,eu-west-1b,eu-west-1c" } # availability zones list separated by , +variable "vpc_cidr_block" { default = "10.0.0.0/16" } +variable "public_subnet_cidr_block" { default = "10.0.0.0/24" } +variable "public_subnet_availability_zone" { default = "eu-west-1a" } +variable "coreos_channel" { default = "stable" } +variable "etcd_discovery_url_file" { default = "etcd_discovery_url.txt" } +variable "slaves" { default = "1" } +variable "masters" { default = "3" } +variable "master_instance_type" { default = "m3.medium" } +variable "slave_instance_type" { default = "m3.medium" } +variable "bastion_instance_type" { default = "t2.micro" } +variable "docker_version" { default = "1.9.1-0~trusty" } From 1ba6e7d43022e458f1773629a52e3dc556276494 Mon Sep 17 00:00:00 2001 From: Graham Taylor Date: Thu, 7 Jan 2016 17:18:19 +0000 Subject: [PATCH 2/4] Initial modularisation of aws-public --- terraform/aws-public/elb.tf | 31 ------- terraform/aws-public/elb/main.tf | 45 +++++++++++ terraform/aws-public/etcd_discovery_url.txt | 1 + terraform/aws-public/keypair/main.tf | 14 ++++ terraform/aws-public/main.tf | 81 +++++++++++++++++++ terraform/aws-public/mesos-masters.tf | 8 +- terraform/aws-public/mesos-slaves.tf | 8 +- terraform/aws-public/outputs.tf | 12 --- terraform/aws-public/provider.tf | 29 ------- terraform/aws-public/public-subnet.tf | 40 --------- .../main.tf} | 19 +++-- terraform/aws-public/variables.tf | 6 +- terraform/aws/aws-vpc.tf | 2 +- terraform/aws/mesos-masters.tf | 2 +- terraform/aws/mesos-slaves.tf | 2 +- 15 files changed, 168 insertions(+), 132 deletions(-) delete mode 100644 terraform/aws-public/elb.tf create mode 100644 terraform/aws-public/elb/main.tf create mode 100644 terraform/aws-public/keypair/main.tf create mode 100644 terraform/aws-public/main.tf delete mode 100644 terraform/aws-public/outputs.tf delete mode 100644 terraform/aws-public/provider.tf delete mode 100644 terraform/aws-public/public-subnet.tf rename terraform/aws-public/{security_groups.tf => sg-all-traffic/main.tf} (55%) diff --git a/terraform/aws-public/elb.tf b/terraform/aws-public/elb.tf deleted file mode 100644 index 164659c0..00000000 --- a/terraform/aws-public/elb.tf +++ /dev/null @@ -1,31 +0,0 @@ -resource "aws_elb" "web" { - name = "${var.elb_name}" - - subnets = ["${aws_subnet.public.*.id}"] - - security_groups = ["${aws_security_group.default.id}"] - - listener { - instance_port = 80 - instance_protocol = "http" - lb_port = 80 - lb_protocol = "http" - } - - # Traefik health check - health_check { - healthy_threshold = 2 - unhealthy_threshold = 2 - timeout = 3 - target = "HTTP:8888/health" - interval = 30 - } - - instances = ["${aws_instance.mesos-slave.*.id}"] - cross_zone_load_balancing = true -} - -resource "aws_proxy_protocol_policy" "http" { - load_balancer = "${aws_elb.web.name}" - instance_ports = ["80"] -} diff --git a/terraform/aws-public/elb/main.tf b/terraform/aws-public/elb/main.tf new file mode 100644 index 00000000..3776b4eb --- /dev/null +++ b/terraform/aws-public/elb/main.tf @@ -0,0 +1,45 @@ +variable "elb_name" { default = "apollo-elb" } +variable "backend_port" { default = "80"} +variable "backend_protocol" { default = "http" } +variable "health_check_target" { default = "HTTP:8888/health" } +variable "instances" {} +variable "subnets" {} +variable "security_groups" {} + +resource "aws_elb" "elb" { + name = "${var.elb_name}" + cross_zone_load_balancing = true + subnets = ["${split(\",\", var.subnets)}"] + security_groups = ["${split(\",\",var.security_groups)}"] + instances = ["${split(\",\", var.instances)}"] + + listener { + instance_port = "${var.backend_port}" + instance_protocol = "${var.backend_protocol}" + lb_port = 80 + lb_protocol = "http" + } + + # Traefik health check + health_check { + healthy_threshold = 2 + unhealthy_threshold = 2 + timeout = 3 + target = "${var.health_check_target}" + interval = 30 + } + + tags { + Name = "${var.elb_name}" + } +} + +resource "aws_proxy_protocol_policy" "http" { + load_balancer = "${aws_elb.elb.name}" + instance_ports = ["80"] +} + +# outputs +output "elb_id" { value = "${aws_elb.elb.id}" } +output "elb_name" { value = "${aws_elb.elb.name}" } +output "elb_dns_name" { value = "${aws_elb.elb.dns_name}" } diff --git a/terraform/aws-public/etcd_discovery_url.txt b/terraform/aws-public/etcd_discovery_url.txt index e69de29b..5eaac65a 100644 --- a/terraform/aws-public/etcd_discovery_url.txt +++ b/terraform/aws-public/etcd_discovery_url.txt @@ -0,0 +1 @@ +https://discovery.etcd.io/365f729dcd00529b8a181c72a4c66f6a \ No newline at end of file diff --git a/terraform/aws-public/keypair/main.tf b/terraform/aws-public/keypair/main.tf new file mode 100644 index 00000000..d7199807 --- /dev/null +++ b/terraform/aws-public/keypair/main.tf @@ -0,0 +1,14 @@ +# input variables +variable "short_name" { default = "apollo" } +variable "public_key_filename" { default = "~/.ssh/id_rsa_aws.pub" } + +# SSH keypair for the instances +resource "aws_key_pair" "default" { + key_name = "${var.short_name}" + public_key = "${file(var.public_key_filename)}" +} + +# output variables +output "keypair_name" { + value = "${aws_key_pair.default.key_name}" +} diff --git a/terraform/aws-public/main.tf b/terraform/aws-public/main.tf new file mode 100644 index 00000000..8975e501 --- /dev/null +++ b/terraform/aws-public/main.tf @@ -0,0 +1,81 @@ +provider "aws" { + access_key = "${var.access_key}" + secret_key = "${var.secret_key}" + region = "${var.region}" +} + +resource "aws_vpc" "default" { + cidr_block = "${var.vpc_cidr_block}" + enable_dns_support = true + enable_dns_hostnames = true + lifecycle { + create_before_destroy = true + } +} + +# ssh keypair for instances +module "aws-keypair" { + source = "./keypair" + + public_key_filename = "${var.public_key_file}" +} + +# internet gateway +module "igw" { + source = "github.com/terraform-community-modules/tf_aws_igw" + + name = "public" + vpc_id = "${aws_vpc.default.id}" +} + +# public subnets +module "public_subnet" { + source = "github.com/terraform-community-modules/tf_aws_public_subnet" + + name = "public" + cidrs = "10.0.1.0/24,10.0.2.0/24,10.0.3.0/24" + azs = "${var.availability_zones}" + vpc_id = "${aws_vpc.default.id}" + igw_id = "${module.igw.igw_id}" +} + +# security group to allow all traffic in and out of the instances +module "sg-default" { + source = "./sg-all-traffic" + + vpc_id = "${aws_vpc.default.id}" +} + +module "elb" { + source = "./elb" + + security_groups = "${module.sg-default.security_group_id}" + instances = "${join(\",\", aws_instance.mesos-slave.*.id)}" + subnets = "${module.public_subnet.subnet_ids}" +} + +# Generate an etcd URL for the cluster +resource "template_file" "etcd_discovery_url" { + template = "/dev/null" + provisioner "local-exec" { + command = "curl https://discovery.etcd.io/new?size=${var.masters + var.slaves} > ${var.etcd_discovery_url_file}" + } + # This will regenerate the discovery URL if the cluster size changes + vars { + size = "${var.masters + var.slaves}" + } +} + +# outputs +output "master.1.ip" { + value = "${aws_instance.mesos-master.0.public_ip}" +} +output "master_ips" { + value = "${join(",", aws_instance.mesos-master.*.public_ip)}" +} +output "slave_ips" { + value = "${join(",", aws_instance.mesos-slave.*.public_ip)}" +} +output "elb.hostname" { + value = "${module.elb.elb_dns_name}" +} diff --git a/terraform/aws-public/mesos-masters.tf b/terraform/aws-public/mesos-masters.tf index 8d2f3cea..4c4540dd 100644 --- a/terraform/aws-public/mesos-masters.tf +++ b/terraform/aws-public/mesos-masters.tf @@ -11,7 +11,7 @@ module "master_ami" { } resource "template_file" "master_cloud_init" { - filename = "cloud-config.yml.tpl" + template = "cloud-config.yml.tpl" depends_on = ["template_file.etcd_discovery_url"] vars { etcd_discovery_url = "${file(var.etcd_discovery_url_file)}" @@ -23,10 +23,10 @@ resource "aws_instance" "mesos-master" { instance_type = "${var.master_instance_type}" ami = "${module.master_ami.ami_id}" count = "${var.masters}" - key_name = "${aws_key_pair.deployer.key_name}" - subnet_id = "${element(aws_subnet.public.*.id, count.index)}" + key_name = "${module.aws-keypair.keypair_name}" + subnet_id = "${element(split(",", module.public_subnet.subnet_ids), count.index)}" source_dest_check = false - security_groups = ["${aws_security_group.default.id}"] + security_groups = ["${module.sg-default.security_group_id}"] user_data = "${template_file.master_cloud_init.rendered}" tags = { Name = "apollo-mesos-master-${count.index}" diff --git a/terraform/aws-public/mesos-slaves.tf b/terraform/aws-public/mesos-slaves.tf index 3468213d..41294b84 100644 --- a/terraform/aws-public/mesos-slaves.tf +++ b/terraform/aws-public/mesos-slaves.tf @@ -11,7 +11,7 @@ module "slave_ami" { } resource "template_file" "slave_cloud_init" { - filename = "cloud-config.yml.tpl" + template = "cloud-config.yml.tpl" depends_on = ["template_file.etcd_discovery_url"] vars { etcd_discovery_url = "${file(var.etcd_discovery_url_file)}" @@ -23,10 +23,10 @@ resource "aws_instance" "mesos-slave" { instance_type = "${var.slave_instance_type}" ami = "${module.slave_ami.ami_id}" count = "${var.slaves}" - key_name = "${aws_key_pair.deployer.key_name}" - subnet_id = "${element(aws_subnet.public.*.id, count.index)}" + key_name = "${module.aws-keypair.keypair_name}" + subnet_id = "${element(split(",", module.public_subnet.subnet_ids), count.index)}" source_dest_check = false - security_groups = ["${aws_security_group.default.id}"] + security_groups = ["${module.sg-default.security_group_id}"] depends_on = ["aws_instance.mesos-master"] user_data = "${template_file.slave_cloud_init.rendered}" tags = { diff --git a/terraform/aws-public/outputs.tf b/terraform/aws-public/outputs.tf deleted file mode 100644 index f2768e16..00000000 --- a/terraform/aws-public/outputs.tf +++ /dev/null @@ -1,12 +0,0 @@ -output "master.1.ip" { - value = "${aws_instance.mesos-master.0.public_ip}" -} -output "master_ips" { - value = "${join(",", aws_instance.mesos-master.*.public_ip)}" -} -output "slave_ips" { - value = "${join(",", aws_instance.mesos-slave.*.public_ip)}" -} -output "elb.hostname" { - value = "${aws_elb.web.dns_name}" -} diff --git a/terraform/aws-public/provider.tf b/terraform/aws-public/provider.tf deleted file mode 100644 index 92059c40..00000000 --- a/terraform/aws-public/provider.tf +++ /dev/null @@ -1,29 +0,0 @@ -provider "aws" { - access_key = "${var.access_key}" - secret_key = "${var.secret_key}" - region = "${var.region}" -} - -resource "aws_vpc" "default" { - cidr_block = "${var.vpc_cidr_block}" - enable_dns_support = true - enable_dns_hostnames = true -} - -# SSH keypair for the instances -resource "aws_key_pair" "deployer" { - key_name = "${var.key_name}" - public_key = "${file(var.key_file)}" -} - -# Generate an etcd URL for the cluster -resource "template_file" "etcd_discovery_url" { - filename = "/dev/null" - provisioner "local-exec" { - command = "curl https://discovery.etcd.io/new?size=${var.masters + var.slaves} > ${var.etcd_discovery_url_file}" - } - # This will regenerate the discovery URL if the cluster size changes - vars { - size = "${var.masters + var.slaves}" - } -} diff --git a/terraform/aws-public/public-subnet.tf b/terraform/aws-public/public-subnet.tf deleted file mode 100644 index 8164bd1c..00000000 --- a/terraform/aws-public/public-subnet.tf +++ /dev/null @@ -1,40 +0,0 @@ -# Internet gateway for the public subnet -resource "aws_internet_gateway" "public" { - vpc_id = "${aws_vpc.default.id}" -} - -# Public subnet -resource "aws_subnet" "public" { - vpc_id = "${aws_vpc.default.id}" - count = "${length(split(",", var.availability_zones))}" - availability_zone = "${element(split(",", var.availability_zones), count.index)}" - cidr_block = "10.0.${count.index}.0/24" - map_public_ip_on_launch = true - depends_on = ["aws_internet_gateway.public"] - tags { - Name = "public" - } -} - -# Routing table for public subnet -resource "aws_route_table" "public" { - vpc_id = "${aws_vpc.default.id}" - route { - cidr_block = "0.0.0.0/0" - gateway_id = "${aws_internet_gateway.public.id}" - } - tags { - Name = "main" - } -} - -resource "aws_main_route_table_association" "public" { - vpc_id = "${aws_vpc.default.id}" - route_table_id = "${aws_route_table.public.id}" -} - -# Associate the routing table to public subnet -resource "aws_route_table_association" "public" { - subnet_id = "${element(aws_subnet.public.*.id, count.index)}" - route_table_id = "${aws_route_table.public.id}" -} diff --git a/terraform/aws-public/security_groups.tf b/terraform/aws-public/sg-all-traffic/main.tf similarity index 55% rename from terraform/aws-public/security_groups.tf rename to terraform/aws-public/sg-all-traffic/main.tf index 5a17e017..5f98ee2e 100644 --- a/terraform/aws-public/security_groups.tf +++ b/terraform/aws-public/sg-all-traffic/main.tf @@ -1,8 +1,12 @@ -# Default security group +variable "security_group_name" { default = "default-apollo-mesos" } +variable "vpc_id" {} +variable "source_cidr_block" { default = "0.0.0.0/0" } + +# Security group that allows all traffic everywhere resource "aws_security_group" "default" { - name = "default-apollo-mesos" + name = "${var.security_group_name}" description = "Default security group that allows all traffic" - vpc_id = "${aws_vpc.default.id}" + vpc_id = "${var.vpc_id}" # Allows inbound and outbound traffic from all instances in the VPC. ingress { @@ -17,7 +21,7 @@ resource "aws_security_group" "default" { from_port = "0" to_port = "0" protocol = "-1" - cidr_blocks = ["0.0.0.0/0"] + cidr_blocks = ["${var.source_cidr_block}"] } # Allows all outbound traffic. @@ -25,9 +29,14 @@ resource "aws_security_group" "default" { from_port = 0 to_port = 0 protocol = "-1" - cidr_blocks = ["0.0.0.0/0"] + cidr_blocks = ["${var.source_cidr_block}"] } tags { Name = "apollo-mesos-default-security-group" } } + +# output variables +output "security_group_id" { + value = "${aws_security_group.default.id}" +} diff --git a/terraform/aws-public/variables.tf b/terraform/aws-public/variables.tf index 56ab70ca..16c57ee5 100644 --- a/terraform/aws-public/variables.tf +++ b/terraform/aws-public/variables.tf @@ -1,14 +1,12 @@ variable "access_key" {} variable "secret_key" {} -variable "key_name" { default = "deployer"} -variable "key_file" {} +variable "public_key_file" { default = "~/.ssh/id_rsa_aws.pub" } variable "region" { default = "eu-west-1" } -variable "availability_zones" { default = "" } # zones list separated by , +variable "availability_zones" { default = "eu-west-1a,eu-west-1b,eu-west-1c" } variable "coreos_channel" { default = "stable" } variable "etcd_discovery_url_file" { default = "etcd_discovery_url.txt" } variable "masters" { default = "3" } variable "master_instance_type" { default = "m3.medium" } variable "slaves" { default = "1" } variable "slave_instance_type" { default = "m3.medium" } -variable "elb_name" { default = "apollo-elb" } variable "vpc_cidr_block" { default = "10.0.0.0/16" } diff --git a/terraform/aws/aws-vpc.tf b/terraform/aws/aws-vpc.tf index 389eaa33..9c00e500 100644 --- a/terraform/aws/aws-vpc.tf +++ b/terraform/aws/aws-vpc.tf @@ -17,7 +17,7 @@ resource "aws_key_pair" "deployer" { # Generate an etcd URL for the cluster resource "template_file" "etcd_discovery_url" { - filename = "/dev/null" + template = "/dev/null" provisioner "local-exec" { command = "curl https://discovery.etcd.io/new?size=${var.masters + var.slaves} > ${var.etcd_discovery_url_file}" } diff --git a/terraform/aws/mesos-masters.tf b/terraform/aws/mesos-masters.tf index 2e25e5cc..5591e084 100644 --- a/terraform/aws/mesos-masters.tf +++ b/terraform/aws/mesos-masters.tf @@ -11,7 +11,7 @@ module "master_ami" { } resource "template_file" "master_cloud_init" { - filename = "cloud-config.yml.tpl" + template = "cloud-config.yml.tpl" depends_on = ["template_file.etcd_discovery_url"] vars { etcd_discovery_url = "${file(var.etcd_discovery_url_file)}" diff --git a/terraform/aws/mesos-slaves.tf b/terraform/aws/mesos-slaves.tf index cdeba684..22477133 100644 --- a/terraform/aws/mesos-slaves.tf +++ b/terraform/aws/mesos-slaves.tf @@ -11,7 +11,7 @@ module "slave_ami" { } resource "template_file" "slave_cloud_init" { - filename = "cloud-config.yml.tpl" + template = "cloud-config.yml.tpl" depends_on = ["template_file.etcd_discovery_url"] vars { etcd_discovery_url = "${file(var.etcd_discovery_url_file)}" From b6cb1cb5ea31e88c2764ee0f7a33a9d6ce70dcc2 Mon Sep 17 00:00:00 2001 From: Graham Taylor Date: Thu, 7 Jan 2016 18:22:51 +0000 Subject: [PATCH 3/4] Update AWS terraform plans to re-use modules across each other --- .gitignore | 3 +- .../aws/{ => private-cloud}/config-default.sh | 2 +- bootstrap/aws/{ => private-cloud}/util.sh | 0 .../public-cloud}/config-default.sh | 9 +- .../{aws-public => aws/public-cloud}/util.sh | 0 terraform/aws-public/etcd_discovery_url.txt | 1 - terraform/aws-public/variables.tf | 12 --- terraform/aws/aws-vpc.tf | 28 ------ terraform/{aws-public => aws}/elb/main.tf | 0 terraform/{aws-public => aws}/keypair/main.tf | 0 terraform/aws/outputs.tf | 18 ---- .../aws/{ => private-cloud}/bastion-server.tf | 9 +- .../bin/ovpn-client-config | 0 .../aws/{ => private-cloud}/bin/ovpn-init | 0 .../{ => private-cloud}/bin/ovpn-new-client | 0 .../aws/{ => private-cloud}/bin/ovpn-start | 0 .../private-cloud}/cloud-config.yml.tpl | 0 .../etcd_discovery_url.txt | 0 terraform/aws/private-cloud/main.tf | 85 +++++++++++++++++++ .../aws/{ => private-cloud}/mesos-masters.tf | 6 +- .../aws/{ => private-cloud}/mesos-slaves.tf | 37 +------- .../aws/{ => private-cloud}/private-subnet.tf | 4 +- .../{ => private-cloud}/security_groups.tf | 28 +----- .../{ => public-cloud}/cloud-config.yml.tpl | 0 .../aws/public-cloud/etcd_discovery_url.txt | 1 + .../{aws-public => aws/public-cloud}/main.tf | 19 ++++- .../public-cloud}/mesos-masters.tf | 0 .../public-cloud}/mesos-slaves.tf | 0 terraform/aws/public-subnet.tf | 36 -------- .../sg-all-traffic/main.tf | 4 +- terraform/aws/variables.tf | 18 ---- 31 files changed, 122 insertions(+), 198 deletions(-) rename bootstrap/aws/{ => private-cloud}/config-default.sh (94%) rename bootstrap/aws/{ => private-cloud}/util.sh (100%) rename bootstrap/{aws-public => aws/public-cloud}/config-default.sh (61%) rename bootstrap/{aws-public => aws/public-cloud}/util.sh (100%) delete mode 100644 terraform/aws-public/etcd_discovery_url.txt delete mode 100644 terraform/aws-public/variables.tf delete mode 100644 terraform/aws/aws-vpc.tf rename terraform/{aws-public => aws}/elb/main.tf (100%) rename terraform/{aws-public => aws}/keypair/main.tf (100%) delete mode 100644 terraform/aws/outputs.tf rename terraform/aws/{ => private-cloud}/bastion-server.tf (84%) rename terraform/aws/{ => private-cloud}/bin/ovpn-client-config (100%) rename terraform/aws/{ => private-cloud}/bin/ovpn-init (100%) rename terraform/aws/{ => private-cloud}/bin/ovpn-new-client (100%) rename terraform/aws/{ => private-cloud}/bin/ovpn-start (100%) rename terraform/{aws-public => aws/private-cloud}/cloud-config.yml.tpl (100%) rename terraform/aws/{ => private-cloud}/etcd_discovery_url.txt (100%) create mode 100644 terraform/aws/private-cloud/main.tf rename terraform/aws/{ => private-cloud}/mesos-masters.tf (84%) rename terraform/aws/{ => private-cloud}/mesos-slaves.tf (51%) rename terraform/aws/{ => private-cloud}/private-subnet.tf (90%) rename terraform/aws/{ => private-cloud}/security_groups.tf (63%) rename terraform/aws/{ => public-cloud}/cloud-config.yml.tpl (100%) create mode 100644 terraform/aws/public-cloud/etcd_discovery_url.txt rename terraform/{aws-public => aws/public-cloud}/main.tf (73%) rename terraform/{aws-public => aws/public-cloud}/mesos-masters.tf (100%) rename terraform/{aws-public => aws/public-cloud}/mesos-slaves.tf (100%) delete mode 100644 terraform/aws/public-subnet.tf rename terraform/{aws-public => aws}/sg-all-traffic/main.tf (90%) delete mode 100644 terraform/aws/variables.tf diff --git a/.gitignore b/.gitignore index 1267ca16..db76b2cb 100644 --- a/.gitignore +++ b/.gitignore @@ -17,6 +17,7 @@ inventory/terraform.py tests/spec/*/*runtime_spec.rb contrib-plugins/* vault-security.yaml -terraform/*/.terraform +terraform/**/.terraform roles/coreos_bootstrap roles/coreos_timezone +terraform/aws-public/etcd_discovery_url.txt diff --git a/bootstrap/aws/config-default.sh b/bootstrap/aws/private-cloud/config-default.sh similarity index 94% rename from bootstrap/aws/config-default.sh rename to bootstrap/aws/private-cloud/config-default.sh index 42f9b2e8..9e2e411d 100644 --- a/bootstrap/aws/config-default.sh +++ b/bootstrap/aws/private-cloud/config-default.sh @@ -11,7 +11,7 @@ export TF_VAR_key_file=${TF_VAR_key_file:-$HOME/.ssh/apollo_aws_rsa} export TF_VAR_key_name=${TF_VAR_key_name:-apollo} # Overrides default folder in Terraform.py inventory. -export TF_VAR_STATE_ROOT="${APOLLO_ROOT}/terraform/aws" +export TF_VAR_STATE_ROOT="${APOLLO_ROOT}/terraform/${APOLLO_PROVIDER}" export ANSIBLE_SSH_ARGS="-F ${APOLLO_ROOT}/terraform/${APOLLO_PROVIDER}/ssh.config -q" diff --git a/bootstrap/aws/util.sh b/bootstrap/aws/private-cloud/util.sh similarity index 100% rename from bootstrap/aws/util.sh rename to bootstrap/aws/private-cloud/util.sh diff --git a/bootstrap/aws-public/config-default.sh b/bootstrap/aws/public-cloud/config-default.sh similarity index 61% rename from bootstrap/aws-public/config-default.sh rename to bootstrap/aws/public-cloud/config-default.sh index 54e9131d..e902c2d1 100644 --- a/bootstrap/aws-public/config-default.sh +++ b/bootstrap/aws/public-cloud/config-default.sh @@ -6,19 +6,12 @@ export ATLAS_INFRASTRUCTURE=${ATLAS_INFRASTRUCTURE:-capgemini/apollo} export TF_VAR_access_key=${TF_VAR_access_key:?"Need to set TF_VAR_access_key non-empty"} export TF_VAR_secret_key=${TF_VAR_secret_key:?"Need to set TF_VAR_secret_key non-empty"} -export TF_VAR_key_file=${TF_VAR_key_file:-$HOME/.ssh/apollo_aws_rsa} -export TF_VAR_key_name=${TF_VAR_key_name:-deployer} # Overrides default folder in Terraform.py inventory. -export TF_VAR_STATE_ROOT="${APOLLO_ROOT}/terraform/aws-public" +export TF_VAR_STATE_ROOT="${APOLLO_ROOT}/terraform/${APOLLO_PROVIDER}" export ANSIBLE_SSH_ARGS="-F ${APOLLO_ROOT}/terraform/${APOLLO_PROVIDER}/ssh.config -q" export TF_VAR_region=${TF_VAR_region:-eu-west-1} -export TF_VAR_master_instance_type=${TF_VAR_master_instance_type:-m3.medium} -export TF_VAR_slave_instance_type=${TF_VAR_slave_instance_type:-m3.medium} -export TF_VAR_slaves=${TF_VAR_slaves:-1} -export TF_VAR_availability_zones=${TF_VAR_availability_zones:-'eu-west-1a,eu-west-1b,eu-west-1c'} - export APOLLO_consul_dc=${APOLLO_consul_dc:-$TF_VAR_region} export APOLLO_mesos_cluster_name=${APOLLO_mesos_cluster_name:-$TF_VAR_region} diff --git a/bootstrap/aws-public/util.sh b/bootstrap/aws/public-cloud/util.sh similarity index 100% rename from bootstrap/aws-public/util.sh rename to bootstrap/aws/public-cloud/util.sh diff --git a/terraform/aws-public/etcd_discovery_url.txt b/terraform/aws-public/etcd_discovery_url.txt deleted file mode 100644 index 5eaac65a..00000000 --- a/terraform/aws-public/etcd_discovery_url.txt +++ /dev/null @@ -1 +0,0 @@ -https://discovery.etcd.io/365f729dcd00529b8a181c72a4c66f6a \ No newline at end of file diff --git a/terraform/aws-public/variables.tf b/terraform/aws-public/variables.tf deleted file mode 100644 index 16c57ee5..00000000 --- a/terraform/aws-public/variables.tf +++ /dev/null @@ -1,12 +0,0 @@ -variable "access_key" {} -variable "secret_key" {} -variable "public_key_file" { default = "~/.ssh/id_rsa_aws.pub" } -variable "region" { default = "eu-west-1" } -variable "availability_zones" { default = "eu-west-1a,eu-west-1b,eu-west-1c" } -variable "coreos_channel" { default = "stable" } -variable "etcd_discovery_url_file" { default = "etcd_discovery_url.txt" } -variable "masters" { default = "3" } -variable "master_instance_type" { default = "m3.medium" } -variable "slaves" { default = "1" } -variable "slave_instance_type" { default = "m3.medium" } -variable "vpc_cidr_block" { default = "10.0.0.0/16" } diff --git a/terraform/aws/aws-vpc.tf b/terraform/aws/aws-vpc.tf deleted file mode 100644 index 9c00e500..00000000 --- a/terraform/aws/aws-vpc.tf +++ /dev/null @@ -1,28 +0,0 @@ -provider "aws" { - access_key = "${var.access_key}" - secret_key = "${var.secret_key}" - region = "${var.region}" -} - -resource "aws_vpc" "default" { - cidr_block = "${var.vpc_cidr_block}" - enable_dns_support = true - enable_dns_hostnames = true -} - -resource "aws_key_pair" "deployer" { - key_name = "${var.key_name}" - public_key = "${file(var.ssh_public_key)}" -} - -# Generate an etcd URL for the cluster -resource "template_file" "etcd_discovery_url" { - template = "/dev/null" - provisioner "local-exec" { - command = "curl https://discovery.etcd.io/new?size=${var.masters + var.slaves} > ${var.etcd_discovery_url_file}" - } - # This will regenerate the discovery URL if the cluster size changes - vars { - size = "${var.masters + var.slaves}" - } -} diff --git a/terraform/aws-public/elb/main.tf b/terraform/aws/elb/main.tf similarity index 100% rename from terraform/aws-public/elb/main.tf rename to terraform/aws/elb/main.tf diff --git a/terraform/aws-public/keypair/main.tf b/terraform/aws/keypair/main.tf similarity index 100% rename from terraform/aws-public/keypair/main.tf rename to terraform/aws/keypair/main.tf diff --git a/terraform/aws/outputs.tf b/terraform/aws/outputs.tf deleted file mode 100644 index 0cc99010..00000000 --- a/terraform/aws/outputs.tf +++ /dev/null @@ -1,18 +0,0 @@ -output "vpc_cidr_block.ip" { - value = "${aws_vpc.default.cidr_block}" -} -output "bastion.ip" { - value = "${aws_eip.bastion.public_ip}" -} -output "master.1.ip" { - value = "${aws_instance.mesos-master.0.private_ip}" -} -output "master_ips" { - value = "${join(",", aws_instance.mesos-master.*.private_ip)}" -} -output "slave_ips" { - value = "${join(",", aws_instance.mesos-slave.*.private_ip)}" -} -output "elb.hostname" { - value = "${aws_elb.app.dns_name}" -} diff --git a/terraform/aws/bastion-server.tf b/terraform/aws/private-cloud/bastion-server.tf similarity index 84% rename from terraform/aws/bastion-server.tf rename to terraform/aws/private-cloud/bastion-server.tf index d2345c10..d4ae6886 100644 --- a/terraform/aws/bastion-server.tf +++ b/terraform/aws/private-cloud/bastion-server.tf @@ -9,10 +9,9 @@ module "ami_bastion" { resource "aws_instance" "bastion" { ami = "${module.ami_bastion.ami_id}" instance_type = "${var.bastion_instance_type}" - subnet_id = "${aws_subnet.public.id}" - security_groups = ["${aws_security_group.default.id}", "${aws_security_group.bastion.id}"] - depends_on = ["aws_internet_gateway.public", "aws_key_pair.deployer"] - key_name = "${aws_key_pair.deployer.key_name}" + subnet_id = "${module.vpc.public_subnets}" + security_groups = ["${module.sg-default.security_group_id}", "${aws_security_group.bastion.id}"] + key_name = "${module.aws-keypair.keypair_name}" source_dest_check = false tags = { Name = "apollo-mesos-bastion" @@ -20,7 +19,7 @@ resource "aws_instance" "bastion" { } connection { user = "ubuntu" - private_key = "${var.ssh_private_key}" + private_key = "${var.private_key_file}" } provisioner "remote-exec" { inline = [ diff --git a/terraform/aws/bin/ovpn-client-config b/terraform/aws/private-cloud/bin/ovpn-client-config similarity index 100% rename from terraform/aws/bin/ovpn-client-config rename to terraform/aws/private-cloud/bin/ovpn-client-config diff --git a/terraform/aws/bin/ovpn-init b/terraform/aws/private-cloud/bin/ovpn-init similarity index 100% rename from terraform/aws/bin/ovpn-init rename to terraform/aws/private-cloud/bin/ovpn-init diff --git a/terraform/aws/bin/ovpn-new-client b/terraform/aws/private-cloud/bin/ovpn-new-client similarity index 100% rename from terraform/aws/bin/ovpn-new-client rename to terraform/aws/private-cloud/bin/ovpn-new-client diff --git a/terraform/aws/bin/ovpn-start b/terraform/aws/private-cloud/bin/ovpn-start similarity index 100% rename from terraform/aws/bin/ovpn-start rename to terraform/aws/private-cloud/bin/ovpn-start diff --git a/terraform/aws-public/cloud-config.yml.tpl b/terraform/aws/private-cloud/cloud-config.yml.tpl similarity index 100% rename from terraform/aws-public/cloud-config.yml.tpl rename to terraform/aws/private-cloud/cloud-config.yml.tpl diff --git a/terraform/aws/etcd_discovery_url.txt b/terraform/aws/private-cloud/etcd_discovery_url.txt similarity index 100% rename from terraform/aws/etcd_discovery_url.txt rename to terraform/aws/private-cloud/etcd_discovery_url.txt diff --git a/terraform/aws/private-cloud/main.tf b/terraform/aws/private-cloud/main.tf new file mode 100644 index 00000000..1599ec7e --- /dev/null +++ b/terraform/aws/private-cloud/main.tf @@ -0,0 +1,85 @@ +variable "access_key" {} +variable "secret_key" {} +variable "public_key_file" { default = "~/.ssh/id_rsa_aws.pub" } +variable "private_key_file" { default = "~/.ssh/id_rsa_aws.pem" } +variable "region" { default = "eu-west-1" } +variable "availability_zones" { default = "eu-west-1a,eu-west-1b,eu-west-1c" } +variable "vpc_cidr_block" { default = "10.0.0.0/16" } +variable "coreos_channel" { default = "stable" } +variable "etcd_discovery_url_file" { default = "etcd_discovery_url.txt" } +variable "masters" { default = "3" } +variable "master_instance_type" { default = "m3.medium" } +variable "slaves" { default = "1" } +variable "slave_instance_type" { default = "m3.medium" } +variable "bastion_instance_type" { default = "t2.micro" } +variable "docker_version" { default = "1.9.1-0~trusty" } + +provider "aws" { + access_key = "${var.access_key}" + secret_key = "${var.secret_key}" + region = "${var.region}" +} + +module "vpc" { + source = "github.com/terraform-community-modules/tf_aws_vpc" + + name = "default" + + cidr = "${var.vpc_cidr_block}" + private_subnets = "10.0.1.0/24,10.0.2.0/24,10.0.3.0/24" + public_subnets = "10.0.101.0/24,10.0.102.0/24,10.0.103.0/24" + + azs = "${var.availability_zones}" +} + +# ssh keypair for instances +module "aws-keypair" { + source = "../keypair" + + public_key_filename = "${var.public_key_file}" +} + +# security group to allow all traffic in and out of the instances in the VPC +module "sg-default" { + source = "../sg-all-traffic" + + vpc_id = "${module.vpc.vpc_id}" +} + +module "elb" { + source = "../elb" + + security_groups = "${module.sg-default.security_group_id}" + instances = "${join(\",\", aws_instance.mesos-slave.*.id)}" + subnets = "${module.vpc.public_subnets}" +} + +# Generate an etcd URL for the cluster +resource "template_file" "etcd_discovery_url" { + template = "/dev/null" + provisioner "local-exec" { + command = "curl https://discovery.etcd.io/new?size=${var.masters + var.slaves} > ${var.etcd_discovery_url_file}" + } + # This will regenerate the discovery URL if the cluster size changes + vars { + size = "${var.masters + var.slaves}" + } +} + +# outputs +output "bastion.ip" { + value = "${aws_eip.bastion.public_ip}" +} +output "master.1.ip" { + value = "${aws_instance.mesos-master.0.private_ip}" +} +output "master_ips" { + value = "${join(",", aws_instance.mesos-master.*.private_ip)}" +} +output "slave_ips" { + value = "${join(",", aws_instance.mesos-slave.*.private_ip)}" +} +/* +output "elb.hostname" { + value = "${module.elb.elb_dns_name}" +}*/ diff --git a/terraform/aws/mesos-masters.tf b/terraform/aws/private-cloud/mesos-masters.tf similarity index 84% rename from terraform/aws/mesos-masters.tf rename to terraform/aws/private-cloud/mesos-masters.tf index 5591e084..dea45d85 100644 --- a/terraform/aws/mesos-masters.tf +++ b/terraform/aws/private-cloud/mesos-masters.tf @@ -23,11 +23,11 @@ resource "aws_instance" "mesos-master" { instance_type = "${var.master_instance_type}" ami = "${module.master_ami.ami_id}" count = "${var.masters}" - key_name = "${aws_key_pair.deployer.key_name}" + key_name = "${module.aws-keypair.keypair_name}" source_dest_check = false subnet_id = "${element(aws_subnet.private.*.id, count.index)}" - security_groups = ["${aws_security_group.default.id}"] - depends_on = ["aws_instance.bastion", "aws_internet_gateway.public"] + security_groups = ["${module.sg-default.security_group_id}"] + depends_on = ["aws_instance.bastion"] user_data = "${template_file.master_cloud_init.rendered}" tags = { Name = "apollo-mesos-master-${count.index}" diff --git a/terraform/aws/mesos-slaves.tf b/terraform/aws/private-cloud/mesos-slaves.tf similarity index 51% rename from terraform/aws/mesos-slaves.tf rename to terraform/aws/private-cloud/mesos-slaves.tf index 22477133..8b2de1fb 100644 --- a/terraform/aws/mesos-slaves.tf +++ b/terraform/aws/private-cloud/mesos-slaves.tf @@ -23,45 +23,14 @@ resource "aws_instance" "mesos-slave" { instance_type = "${var.slave_instance_type}" ami = "${module.slave_ami.ami_id}" count = "${var.slaves}" - key_name = "${aws_key_pair.deployer.key_name}" + key_name = "${module.aws-keypair.keypair_name}" source_dest_check = false subnet_id = "${element(aws_subnet.private.*.id, count.index)}" - security_groups = ["${aws_security_group.default.id}"] - depends_on = ["aws_instance.bastion", "aws_internet_gateway.public", "aws_instance.mesos-master"] + security_groups = ["${module.sg-default.security_group_id}"] + depends_on = ["aws_instance.bastion", "aws_instance.mesos-master"] user_data = "${template_file.master_cloud_init.rendered}" tags = { Name = "apollo-mesos-slave-${count.index}" role = "mesos_slaves" } } - -# Load balancer -resource "aws_elb" "app" { - name = "apollo-mesos-elb" - subnets = ["${aws_subnet.public.*.id}"] - security_groups = ["${aws_security_group.default.id}", "${aws_security_group.web.id}"] - - listener { - instance_port = 80 - instance_protocol = "http" - lb_port = 80 - lb_protocol = "http" - } - - # traefik health check - health_check { - healthy_threshold = 2 - unhealthy_threshold = 2 - timeout = 3 - target = "HTTP:8888/health" - interval = 30 - } - - instances = ["${aws_instance.mesos-slave.*.id}"] - cross_zone_load_balancing = true -} - -resource "aws_proxy_protocol_policy" "http" { - load_balancer = "${aws_elb.app.name}" - instance_ports = ["80"] -} diff --git a/terraform/aws/private-subnet.tf b/terraform/aws/private-cloud/private-subnet.tf similarity index 90% rename from terraform/aws/private-subnet.tf rename to terraform/aws/private-cloud/private-subnet.tf index 7efecba2..671e277d 100644 --- a/terraform/aws/private-subnet.tf +++ b/terraform/aws/private-cloud/private-subnet.tf @@ -1,6 +1,6 @@ # Private subnet resource "aws_subnet" "private" { - vpc_id = "${aws_vpc.default.id}" + vpc_id = "${module.vpc.vpc_id}" count = "${length(split(",", var.availability_zones))}" availability_zone = "${element(split(",", var.availability_zones), count.index)}" cidr_block = "10.0.${count.index+1}.0/24" @@ -12,7 +12,7 @@ resource "aws_subnet" "private" { } resource "aws_route_table" "private" { - vpc_id = "${aws_vpc.default.id}" + vpc_id = "${module.vpc.vpc_id}" route { cidr_block = "0.0.0.0/0" instance_id = "${aws_instance.bastion.id}" diff --git a/terraform/aws/security_groups.tf b/terraform/aws/private-cloud/security_groups.tf similarity index 63% rename from terraform/aws/security_groups.tf rename to terraform/aws/private-cloud/security_groups.tf index df6fef35..eb02a46f 100644 --- a/terraform/aws/security_groups.tf +++ b/terraform/aws/private-cloud/security_groups.tf @@ -1,31 +1,7 @@ -resource "aws_security_group" "default" { - name = "default-apollo-mesos" - description = "Default security group that allows inbound and outbound traffic from all instances in the VPC" - vpc_id = "${aws_vpc.default.id}" - - ingress { - from_port = "0" - to_port = "0" - protocol = "-1" - self = true - } - - egress { - from_port = "0" - to_port = "0" - protocol = "-1" - self = true - } - - tags { - Name = "apollo-mesos-default-vpc" - } -} - resource "aws_security_group" "bastion" { name = "bastion-apollo-mesos" description = "Security group for bastion instances that allows SSH and VPN traffic from internet" - vpc_id = "${aws_vpc.default.id}" + vpc_id = "${module.vpc.vpc_id}" ingress { from_port = 22 @@ -63,7 +39,7 @@ resource "aws_security_group" "bastion" { resource "aws_security_group" "web" { name = "web-apollo-mesos" description = "Security group that allows web traffic from the internet" - vpc_id = "${aws_vpc.default.id}" + vpc_id = "${module.vpc.vpc_id}" ingress { from_port = 80 diff --git a/terraform/aws/cloud-config.yml.tpl b/terraform/aws/public-cloud/cloud-config.yml.tpl similarity index 100% rename from terraform/aws/cloud-config.yml.tpl rename to terraform/aws/public-cloud/cloud-config.yml.tpl diff --git a/terraform/aws/public-cloud/etcd_discovery_url.txt b/terraform/aws/public-cloud/etcd_discovery_url.txt new file mode 100644 index 00000000..c8c8c34f --- /dev/null +++ b/terraform/aws/public-cloud/etcd_discovery_url.txt @@ -0,0 +1 @@ +https://discovery.etcd.io/fafb16ac572cae5895c6523e7b3bd640 \ No newline at end of file diff --git a/terraform/aws-public/main.tf b/terraform/aws/public-cloud/main.tf similarity index 73% rename from terraform/aws-public/main.tf rename to terraform/aws/public-cloud/main.tf index 8975e501..60d023dd 100644 --- a/terraform/aws-public/main.tf +++ b/terraform/aws/public-cloud/main.tf @@ -1,3 +1,16 @@ +variable "access_key" {} +variable "secret_key" {} +variable "public_key_file" { default = "~/.ssh/id_rsa_aws.pub" } +variable "region" { default = "eu-west-1" } +variable "availability_zones" { default = "eu-west-1a,eu-west-1b,eu-west-1c" } +variable "coreos_channel" { default = "stable" } +variable "etcd_discovery_url_file" { default = "etcd_discovery_url.txt" } +variable "masters" { default = "3" } +variable "master_instance_type" { default = "m3.medium" } +variable "slaves" { default = "1" } +variable "slave_instance_type" { default = "m3.medium" } +variable "vpc_cidr_block" { default = "10.0.0.0/16" } + provider "aws" { access_key = "${var.access_key}" secret_key = "${var.secret_key}" @@ -15,7 +28,7 @@ resource "aws_vpc" "default" { # ssh keypair for instances module "aws-keypair" { - source = "./keypair" + source = "../keypair" public_key_filename = "${var.public_key_file}" } @@ -41,13 +54,13 @@ module "public_subnet" { # security group to allow all traffic in and out of the instances module "sg-default" { - source = "./sg-all-traffic" + source = "../sg-all-traffic" vpc_id = "${aws_vpc.default.id}" } module "elb" { - source = "./elb" + source = "../elb" security_groups = "${module.sg-default.security_group_id}" instances = "${join(\",\", aws_instance.mesos-slave.*.id)}" diff --git a/terraform/aws-public/mesos-masters.tf b/terraform/aws/public-cloud/mesos-masters.tf similarity index 100% rename from terraform/aws-public/mesos-masters.tf rename to terraform/aws/public-cloud/mesos-masters.tf diff --git a/terraform/aws-public/mesos-slaves.tf b/terraform/aws/public-cloud/mesos-slaves.tf similarity index 100% rename from terraform/aws-public/mesos-slaves.tf rename to terraform/aws/public-cloud/mesos-slaves.tf diff --git a/terraform/aws/public-subnet.tf b/terraform/aws/public-subnet.tf deleted file mode 100644 index 97b777e2..00000000 --- a/terraform/aws/public-subnet.tf +++ /dev/null @@ -1,36 +0,0 @@ -# Public subnet -resource "aws_internet_gateway" "public" { - vpc_id = "${aws_vpc.default.id}" -} - -resource "aws_subnet" "public" { - vpc_id = "${aws_vpc.default.id}" - availability_zone = "${var.public_subnet_availability_zone}" - cidr_block = "${var.public_subnet_cidr_block}" - map_public_ip_on_launch = true - depends_on = ["aws_internet_gateway.public"] - tags { - Name = "public" - } -} - -resource "aws_route_table" "public" { - vpc_id = "${aws_vpc.default.id}" - route { - cidr_block = "0.0.0.0/0" - gateway_id = "${aws_internet_gateway.public.id}" - } - tags { - Name = "main" - } -} - -resource "aws_main_route_table_association" "public" { - vpc_id = "${aws_vpc.default.id}" - route_table_id = "${aws_route_table.public.id}" -} - -resource "aws_route_table_association" "public" { - subnet_id = "${aws_subnet.public.id}" - route_table_id = "${aws_route_table.public.id}" -} diff --git a/terraform/aws-public/sg-all-traffic/main.tf b/terraform/aws/sg-all-traffic/main.tf similarity index 90% rename from terraform/aws-public/sg-all-traffic/main.tf rename to terraform/aws/sg-all-traffic/main.tf index 5f98ee2e..03f6c17a 100644 --- a/terraform/aws-public/sg-all-traffic/main.tf +++ b/terraform/aws/sg-all-traffic/main.tf @@ -2,7 +2,7 @@ variable "security_group_name" { default = "default-apollo-mesos" } variable "vpc_id" {} variable "source_cidr_block" { default = "0.0.0.0/0" } -# Security group that allows all traffic everywhere +# Security group that allows all traffic resource "aws_security_group" "default" { name = "${var.security_group_name}" description = "Default security group that allows all traffic" @@ -16,7 +16,7 @@ resource "aws_security_group" "default" { self = true } - # Allows all inbound traffic from the internet. + # Allows all inbound traffic ingress { from_port = "0" to_port = "0" diff --git a/terraform/aws/variables.tf b/terraform/aws/variables.tf deleted file mode 100644 index 36d7c056..00000000 --- a/terraform/aws/variables.tf +++ /dev/null @@ -1,18 +0,0 @@ -variable "access_key" {} -variable "secret_key" {} -variable "key_name" { default = "Apollo" } -variable "ssh_public_key" {} -variable "ssh_private_key" {} -variable "region" { default = "eu-west-1" } -variable "availability_zones" { default = "eu-west-1a,eu-west-1b,eu-west-1c" } # availability zones list separated by , -variable "vpc_cidr_block" { default = "10.0.0.0/16" } -variable "public_subnet_cidr_block" { default = "10.0.0.0/24" } -variable "public_subnet_availability_zone" { default = "eu-west-1a" } -variable "coreos_channel" { default = "stable" } -variable "etcd_discovery_url_file" { default = "etcd_discovery_url.txt" } -variable "slaves" { default = "1" } -variable "masters" { default = "3" } -variable "master_instance_type" { default = "m3.medium" } -variable "slave_instance_type" { default = "m3.medium" } -variable "bastion_instance_type" { default = "t2.micro" } -variable "docker_version" { default = "1.9.1-0~trusty" } From 50dbf45e47e4c3e0c0146c8affa2ad2bdf1ebd01 Mon Sep 17 00:00:00 2001 From: Graham Taylor Date: Fri, 8 Jan 2016 09:37:54 +0000 Subject: [PATCH 4/4] Get the private VPC working --- bootstrap/aws/private-cloud/config-default.sh | 12 --- bootstrap/aws/private-cloud/util.sh | 2 +- bootstrap/aws/public-cloud/config-default.sh | 4 - terraform/aws/private-cloud/bastion-server.tf | 4 +- .../aws/private-cloud/cloud-config.yml.tpl | 13 +-- terraform/aws/private-cloud/main.tf | 19 ++-- terraform/aws/private-cloud/mesos-masters.tf | 2 +- terraform/aws/private-cloud/mesos-slaves.tf | 6 +- terraform/aws/private-cloud/private-subnet.tf | 29 ------ .../aws/private-cloud/security_groups.tf | 39 ++++---- terraform/aws/private-cloud/vpc/main.tf | 98 +++++++++++++++++++ .../aws/public-cloud/cloud-config.yml.tpl | 2 + terraform/aws/sg-all-traffic/main.tf | 2 +- user-data | 2 + 14 files changed, 151 insertions(+), 83 deletions(-) delete mode 100644 terraform/aws/private-cloud/private-subnet.tf create mode 100644 terraform/aws/private-cloud/vpc/main.tf diff --git a/bootstrap/aws/private-cloud/config-default.sh b/bootstrap/aws/private-cloud/config-default.sh index 9e2e411d..b352cf09 100644 --- a/bootstrap/aws/private-cloud/config-default.sh +++ b/bootstrap/aws/private-cloud/config-default.sh @@ -1,14 +1,7 @@ #!/bin/bash -# Keeping atlas variable without prefix as it's been shared by consul and tf at the moment. -export ATLAS_TOKEN=${ATLAS_TOKEN:?"Need to set ATLAS_TOKEN non-empty"} -export ATLAS_INFRASTRUCTURE=${ATLAS_INFRASTRUCTURE:-capgemini/apollo} - -export TF_VAR_user=${TF_VAR_user:?"Need to set User non-empty"} export TF_VAR_access_key=${TF_VAR_access_key:?"Need to set TF_VAR_access_key non-empty"} export TF_VAR_secret_key=${TF_VAR_secret_key:?"Need to set TF_VAR_secret_key non-empty"} -export TF_VAR_key_file=${TF_VAR_key_file:-$HOME/.ssh/apollo_aws_rsa} -export TF_VAR_key_name=${TF_VAR_key_name:-apollo} # Overrides default folder in Terraform.py inventory. export TF_VAR_STATE_ROOT="${APOLLO_ROOT}/terraform/${APOLLO_PROVIDER}" @@ -16,10 +9,5 @@ export TF_VAR_STATE_ROOT="${APOLLO_ROOT}/terraform/${APOLLO_PROVIDER}" export ANSIBLE_SSH_ARGS="-F ${APOLLO_ROOT}/terraform/${APOLLO_PROVIDER}/ssh.config -q" export TF_VAR_region=${TF_VAR_region:-eu-west-1} -export TF_VAR_master_instance_type=${TF_VAR_master_instance_type:-m3.medium} -export TF_VAR_slave_instance_type=${TF_VAR_slave_instance_type:-m3.medium} -export TF_VAR_slaves=${TF_VAR_slaves:-1} -export TF_VAR_availability_zones=${TF_VAR_availability_zones:-'eu-west-1a,eu-west-1b,eu-west-1c'} -export TF_VAR_public_subnet_availability_zone=${TF_VAR_public_subnet_availability_zone:-'eu-west-1a'} export APOLLO_consul_dc=${APOLLO_consul_dc:-$TF_VAR_region} export APOLLO_mesos_cluster_name=${APOLLO_mesos_cluster_name:-$TF_VAR_region} diff --git a/bootstrap/aws/private-cloud/util.sh b/bootstrap/aws/private-cloud/util.sh index 68ff6bb9..342471bb 100644 --- a/bootstrap/aws/private-cloud/util.sh +++ b/bootstrap/aws/private-cloud/util.sh @@ -18,7 +18,7 @@ ansible_ssh_config() { export APOLLO_bastion_ip=$( terraform output bastion.ip ) # Virtual private cloud CIDR IP. - ip=$( terraform output vpc_cidr_block.ip ) + ip=$( terraform output -module=vpc vpc_cidr_block ) export APOLLO_network_identifier=$( get_network_identifier "${ip}" ) cat < ssh.config diff --git a/bootstrap/aws/public-cloud/config-default.sh b/bootstrap/aws/public-cloud/config-default.sh index e902c2d1..b352cf09 100644 --- a/bootstrap/aws/public-cloud/config-default.sh +++ b/bootstrap/aws/public-cloud/config-default.sh @@ -1,9 +1,5 @@ #!/bin/bash -# Keeping atlas variable without prefix as it's been shared by consul and tf at the moment. -export ATLAS_TOKEN=${ATLAS_TOKEN:?"Need to set ATLAS_TOKEN non-empty"} -export ATLAS_INFRASTRUCTURE=${ATLAS_INFRASTRUCTURE:-capgemini/apollo} - export TF_VAR_access_key=${TF_VAR_access_key:?"Need to set TF_VAR_access_key non-empty"} export TF_VAR_secret_key=${TF_VAR_secret_key:?"Need to set TF_VAR_secret_key non-empty"} diff --git a/terraform/aws/private-cloud/bastion-server.tf b/terraform/aws/private-cloud/bastion-server.tf index d4ae6886..44ce043b 100644 --- a/terraform/aws/private-cloud/bastion-server.tf +++ b/terraform/aws/private-cloud/bastion-server.tf @@ -9,7 +9,9 @@ module "ami_bastion" { resource "aws_instance" "bastion" { ami = "${module.ami_bastion.ami_id}" instance_type = "${var.bastion_instance_type}" - subnet_id = "${module.vpc.public_subnets}" + # Just put the bastion in the first public subnet + subnet_id = "${element(split(",", module.vpc.public_subnets), 0)}" + # @todo - this allows bastion connection on any port which is not ideal but was like this previously. security_groups = ["${module.sg-default.security_group_id}", "${aws_security_group.bastion.id}"] key_name = "${module.aws-keypair.keypair_name}" source_dest_check = false diff --git a/terraform/aws/private-cloud/cloud-config.yml.tpl b/terraform/aws/private-cloud/cloud-config.yml.tpl index 4cc6a1c2..73a6d485 100644 --- a/terraform/aws/private-cloud/cloud-config.yml.tpl +++ b/terraform/aws/private-cloud/cloud-config.yml.tpl @@ -2,18 +2,19 @@ coreos: etcd2: - # $public_ipv4 and $private_ipv4 are populated by the cloud provider - advertise-client-urls: http://$public_ipv4:2379 + # $private_ipv4 is populated by the cloud provider + # we don't have a $public_ipv4 in the private VPC + advertise-client-urls: http://$private_ipv4:2379,http://$private_ipv4:4001 initial-advertise-peer-urls: http://$private_ipv4:2380 + # listen on both the official ports and the legacy ports + # legacy ports can be omitted if your application doesn't depend on them listen-client-urls: http://0.0.0.0:2379,http://0.0.0.0:4001 listen-peer-urls: http://$private_ipv4:2380,http://$private_ipv4:7001 # Discovery is populated by Terraform discovery: ${etcd_discovery_url} - fleet: - public-ip: "$public_ipv4" units: - name: etcd2.service command: start - - name: fleet.service - command: start + update: + reboot-strategy: "reboot" manage_etc_hosts: localhost diff --git a/terraform/aws/private-cloud/main.tf b/terraform/aws/private-cloud/main.tf index 1599ec7e..62305d65 100644 --- a/terraform/aws/private-cloud/main.tf +++ b/terraform/aws/private-cloud/main.tf @@ -21,15 +21,16 @@ provider "aws" { } module "vpc" { - source = "github.com/terraform-community-modules/tf_aws_vpc" + source = "./vpc" - name = "default" + name = "default" - cidr = "${var.vpc_cidr_block}" - private_subnets = "10.0.1.0/24,10.0.2.0/24,10.0.3.0/24" - public_subnets = "10.0.101.0/24,10.0.102.0/24,10.0.103.0/24" + cidr = "${var.vpc_cidr_block}" + private_subnets = "10.0.1.0/24,10.0.2.0/24,10.0.3.0/24" + public_subnets = "10.0.101.0/24,10.0.102.0/24,10.0.103.0/24" + bastion_instance_id = "${aws_instance.bastion.id}" - azs = "${var.availability_zones}" + azs = "${var.availability_zones}" } # ssh keypair for instances @@ -79,7 +80,9 @@ output "master_ips" { output "slave_ips" { value = "${join(",", aws_instance.mesos-slave.*.private_ip)}" } -/* +output "vpc_cidr_block_ip" { + value = "${module.vpc.vpc_cidr_block}" +} output "elb.hostname" { value = "${module.elb.elb_dns_name}" -}*/ +} diff --git a/terraform/aws/private-cloud/mesos-masters.tf b/terraform/aws/private-cloud/mesos-masters.tf index dea45d85..c61d6823 100644 --- a/terraform/aws/private-cloud/mesos-masters.tf +++ b/terraform/aws/private-cloud/mesos-masters.tf @@ -25,7 +25,7 @@ resource "aws_instance" "mesos-master" { count = "${var.masters}" key_name = "${module.aws-keypair.keypair_name}" source_dest_check = false - subnet_id = "${element(aws_subnet.private.*.id, count.index)}" + subnet_id = "${element(split(",", module.vpc.private_subnets), count.index)}" security_groups = ["${module.sg-default.security_group_id}"] depends_on = ["aws_instance.bastion"] user_data = "${template_file.master_cloud_init.rendered}" diff --git a/terraform/aws/private-cloud/mesos-slaves.tf b/terraform/aws/private-cloud/mesos-slaves.tf index 8b2de1fb..69b846ca 100644 --- a/terraform/aws/private-cloud/mesos-slaves.tf +++ b/terraform/aws/private-cloud/mesos-slaves.tf @@ -19,13 +19,17 @@ resource "template_file" "slave_cloud_init" { } } +/* + @todo This should be changed to be an autoscaling slave with launch config + */ resource "aws_instance" "mesos-slave" { instance_type = "${var.slave_instance_type}" ami = "${module.slave_ami.ami_id}" count = "${var.slaves}" key_name = "${module.aws-keypair.keypair_name}" source_dest_check = false - subnet_id = "${element(aws_subnet.private.*.id, count.index)}" + # @todo - fix this as this only allows 3 slaves maximum (due to splittingo on the count variable) + subnet_id = "${element(split(",", module.vpc.private_subnets), count.index)}" security_groups = ["${module.sg-default.security_group_id}"] depends_on = ["aws_instance.bastion", "aws_instance.mesos-master"] user_data = "${template_file.master_cloud_init.rendered}" diff --git a/terraform/aws/private-cloud/private-subnet.tf b/terraform/aws/private-cloud/private-subnet.tf deleted file mode 100644 index 671e277d..00000000 --- a/terraform/aws/private-cloud/private-subnet.tf +++ /dev/null @@ -1,29 +0,0 @@ -# Private subnet -resource "aws_subnet" "private" { - vpc_id = "${module.vpc.vpc_id}" - count = "${length(split(",", var.availability_zones))}" - availability_zone = "${element(split(",", var.availability_zones), count.index)}" - cidr_block = "10.0.${count.index+1}.0/24" - map_public_ip_on_launch = false - depends_on = ["aws_instance.bastion"] - tags { - Name = "private" - } -} - -resource "aws_route_table" "private" { - vpc_id = "${module.vpc.vpc_id}" - route { - cidr_block = "0.0.0.0/0" - instance_id = "${aws_instance.bastion.id}" - } - tags { - Name = "private" - } -} - -resource "aws_route_table_association" "private" { - count = "${length(split(",", var.availability_zones))}" - subnet_id = "${element(aws_subnet.private.*.id, count.index)}" - route_table_id = "${aws_route_table.private.id}" -} diff --git a/terraform/aws/private-cloud/security_groups.tf b/terraform/aws/private-cloud/security_groups.tf index eb02a46f..d30d0488 100644 --- a/terraform/aws/private-cloud/security_groups.tf +++ b/terraform/aws/private-cloud/security_groups.tf @@ -1,8 +1,24 @@ resource "aws_security_group" "bastion" { - name = "bastion-apollo-mesos" + name = "bastion-apollo" description = "Security group for bastion instances that allows SSH and VPN traffic from internet" vpc_id = "${module.vpc.vpc_id}" + # inbound http/https traffic from the private subnets to allow them to talk with the internet + ingress { + from_port = 80 + to_port = 80 + protocol = "tcp" + cidr_blocks = ["10.0.1.0/24", "10.0.2.0/24", "10.0.3.0/24"] + } + + ingress { + from_port = 443 + to_port = 443 + protocol = "tcp" + cidr_blocks = ["10.0.1.0/24", "10.0.2.0/24", "10.0.3.0/24"] + } + + # ssh ingress { from_port = 22 to_port = 22 @@ -10,6 +26,7 @@ resource "aws_security_group" "bastion" { cidr_blocks = ["0.0.0.0/0"] } + # openvpn ingress { from_port = 1194 to_port = 1194 @@ -17,6 +34,7 @@ resource "aws_security_group" "bastion" { cidr_blocks = ["0.0.0.0/0"] } + # outbound access to the inernet egress { from_port = 80 to_port = 80 @@ -32,23 +50,6 @@ resource "aws_security_group" "bastion" { } tags { - Name = "bastion-apollo-mesos" - } -} - -resource "aws_security_group" "web" { - name = "web-apollo-mesos" - description = "Security group that allows web traffic from the internet" - vpc_id = "${module.vpc.vpc_id}" - - ingress { - from_port = 80 - to_port = 80 - protocol = "tcp" - cidr_blocks = ["0.0.0.0/0"] - } - - tags { - Name = "web-apollo-mesos" + Name = "bastion-apollo-sg" } } diff --git a/terraform/aws/private-cloud/vpc/main.tf b/terraform/aws/private-cloud/vpc/main.tf new file mode 100644 index 00000000..47bf1f64 --- /dev/null +++ b/terraform/aws/private-cloud/vpc/main.tf @@ -0,0 +1,98 @@ +variable "name" { } +variable "cidr" { } +variable "public_subnets" { default = "" } +variable "private_subnets" { default = "" } +variable "bastion_instance_id" { } +variable "azs" { } +variable "enable_dns_hostnames" { + description = "should be true if you want to use private DNS within the VPC" + default = false +} +variable "enable_dns_support" { + description = "should be true if you want to use private DNS within the VPC" + default = false +} + +# resources +resource "aws_vpc" "mod" { + cidr_block = "${var.cidr}" + enable_dns_hostnames = "${var.enable_dns_hostnames}" + enable_dns_support = "${var.enable_dns_support}" + tags { + Name = "${var.name}" + } +} + +resource "aws_internet_gateway" "mod" { + vpc_id = "${aws_vpc.mod.id}" +} + +resource "aws_route_table" "public" { + vpc_id = "${aws_vpc.mod.id}" + route { + cidr_block = "0.0.0.0/0" + gateway_id = "${aws_internet_gateway.mod.id}" + } + tags { + Name = "${var.name}-public" + } +} + +resource "aws_route_table" "private" { + vpc_id = "${aws_vpc.mod.id}" + route { + cidr_block = "0.0.0.0/0" + instance_id = "${var.bastion_instance_id}" + } + tags { + Name = "${var.name}-private" + } +} + +resource "aws_subnet" "private" { + vpc_id = "${aws_vpc.mod.id}" + cidr_block = "${element(split(",", var.private_subnets), count.index)}" + availability_zone = "${element(split(",", var.azs), count.index)}" + count = "${length(compact(split(",", var.private_subnets)))}" + tags { + Name = "${var.name}-private" + } +} + +resource "aws_subnet" "public" { + vpc_id = "${aws_vpc.mod.id}" + cidr_block = "${element(split(",", var.public_subnets), count.index)}" + availability_zone = "${element(split(",", var.azs), count.index)}" + count = "${length(compact(split(",", var.public_subnets)))}" + tags { + Name = "${var.name}-public" + } + + map_public_ip_on_launch = true +} + +resource "aws_route_table_association" "private" { + count = "${length(compact(split(",", var.private_subnets)))}" + subnet_id = "${element(aws_subnet.private.*.id, count.index)}" + route_table_id = "${aws_route_table.private.id}" +} + +resource "aws_route_table_association" "public" { + count = "${length(compact(split(",", var.public_subnets)))}" + subnet_id = "${element(aws_subnet.public.*.id, count.index)}" + route_table_id = "${aws_route_table.public.id}" +} + +# outputs +output "private_subnets" { + value = "${join(",", aws_subnet.private.*.id)}" +} +output "public_subnets" { + value = "${join(",", aws_subnet.public.*.id)}" +} +output "vpc_id" { + value = "${aws_vpc.mod.id}" +} +output "vpc_cidr_block" { + value = "${aws_vpc.mod.cidr_block}" +} diff --git a/terraform/aws/public-cloud/cloud-config.yml.tpl b/terraform/aws/public-cloud/cloud-config.yml.tpl index 4cc6a1c2..a9a1aa35 100644 --- a/terraform/aws/public-cloud/cloud-config.yml.tpl +++ b/terraform/aws/public-cloud/cloud-config.yml.tpl @@ -16,4 +16,6 @@ coreos: command: start - name: fleet.service command: start + update: + reboot-strategy: "reboot" manage_etc_hosts: localhost diff --git a/terraform/aws/sg-all-traffic/main.tf b/terraform/aws/sg-all-traffic/main.tf index 03f6c17a..d31e6762 100644 --- a/terraform/aws/sg-all-traffic/main.tf +++ b/terraform/aws/sg-all-traffic/main.tf @@ -32,7 +32,7 @@ resource "aws_security_group" "default" { cidr_blocks = ["${var.source_cidr_block}"] } tags { - Name = "apollo-mesos-default-security-group" + Name = "apollo-default-sg" } } diff --git a/user-data b/user-data index 71e93ac1..951eacf0 100755 --- a/user-data +++ b/user-data @@ -15,4 +15,6 @@ coreos: command: start - name: fleet.service command: start + update: + reboot-strategy: "reboot" manage_etc_hosts: localhost