summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--asg.tf67
-rw-r--r--cloudwatch.tf45
-rw-r--r--eip.tf15
-rw-r--r--elb.tf36
-rw-r--r--files/app_data.tpl11
-rw-r--r--iam.tf53
-rw-r--r--keypair.tf4
-rw-r--r--main.tf27
-rw-r--r--nat.tf18
-rw-r--r--route_tables.tf22
-rw-r--r--s3.tf5
-rw-r--r--sg.tf59
-rw-r--r--subnets.tf18
-rw-r--r--variables.tf35
14 files changed, 415 insertions, 0 deletions
diff --git a/asg.tf b/asg.tf
new file mode 100644
index 0000000..46c3616
--- /dev/null
+++ b/asg.tf
@@ -0,0 +1,67 @@
+resource "aws_launch_configuration" "fundapp_demo" {
+ name_prefix = "${var.vpc_name}_app"
+ image_id = "${var.image_id}"
+ instance_type = "t2.nano"
+ iam_instance_profile = "${aws_iam_instance_profile.app_profile.id}"
+ key_name = "${aws_key_pair.server_keypair.key_name}"
+
+ security_groups = [
+ "${aws_security_group.app_sg.id}",
+ "${aws_security_group.external_ssh_accept_sg.id}",
+ ]
+
+ user_date = "${data.template_file.app_user_data.rendered}"
+
+ root_block_device {
+ volume_type = "gp2"
+ volume_size = "30"
+ }
+
+ lifecycle {
+ create_before_destroy = true
+ }
+}
+
+resource "aws_autoscaling_group" "app_asg" {
+ name = "${var.vpc_name}_app_asg"
+ launch_configuration = "${aws_launch_configuration.fundapp_demo.name}"
+
+ availability_zones = [
+ "${var.aws_az_1}",
+ "${var.aws_az_2}",
+ "${var.aws_az_3}",
+ ]
+
+ vpc_zone_identifier = [
+ "${aws_subnet.public_1.id}",
+ "${aws_subnet.public_2.id}",
+ "${aws_subnet.public_3.id}",
+ ]
+
+ min_size = 1
+ max_size = 3
+ desired_capacity = 2
+ health_check_grace_period = 300
+
+ enabled_metrics = [
+ "GroupMinSize",
+ "GroupMazSize",
+ "GroupDesiredCapacity",
+ "GroupInServiceInstances",
+ "GroupPendingInstances",
+ "GroupStandbyInstances",
+ "GroupTerminatingInstances",
+ "GroupTotalInstances",
+ ]
+
+ load_balancers = ["${aws_elb.app_elb.name}"]
+ health_check_type = "EC2"
+
+ lifecycle {
+ create_before_destroy = true
+ }
+}
+
+data "template_file" "app_user_data" {
+ template = "${file("${path.module}/files/app_data.tpl")}"
+}
diff --git a/cloudwatch.tf b/cloudwatch.tf
new file mode 100644
index 0000000..9a73918
--- /dev/null
+++ b/cloudwatch.tf
@@ -0,0 +1,45 @@
+resource "aws_cloudwatch_metric_alarm" "target_healthy_count" {
+ alarm_name = "ELB-target-healthy-count"
+ comparison_operator = "LessThanOrEqualToThreshold"
+ evaluation_periods = "1"
+ metric_name = "HealthyHostCount"
+ period = "60"
+ statistic = "Average"
+ threshold = "0"
+
+ dimensions {
+ LoadBalancer = "${aws_elb.app_elb.id}"
+ }
+
+ alarm_description = "Trigger an alert when elb has 1 or more unhealthy hosts"
+
+ #alarm_actions = "Would point at sns here"
+ #ok_actions = "Would also point at sns"
+ treat_missing_data = "breaching"
+}
+
+resource "aws_autoscaling_policy" "app_as_policy" {
+ name = "app_autoscaling_policy"
+ scaling_adjustment = 1
+ adjustment_type = "ChangeInCapacity"
+ cooldown = 300
+ autoscaling_group_name = "${aws_autoscaling_group.app_asg.name}"
+}
+
+resource "aws_cloudwatch_metric_alarm" "app_asg_alarm" {
+ alarm_name = "app_asg_alarm"
+ comparison_operator = "GreaterThanOrEqualToThreshold"
+ evaluation_periods = "2"
+ metric_name = "CPUUtilization"
+ namespace = "AWS/EC2"
+ period = "120"
+ statistic = "Average"
+ threshold = "80"
+
+ dimensions = {
+ AutoScalingGroupName = "${aws_autoscaling_group.app_asg.name}"
+ }
+
+ alarm_description = "This metric monitors ec2 cpu utilization"
+ alarm_actions = ["${aws_autoscaling_policy.app_as_policy.arn}"]
+}
diff --git a/eip.tf b/eip.tf
new file mode 100644
index 0000000..3c6110b
--- /dev/null
+++ b/eip.tf
@@ -0,0 +1,15 @@
+# Elastic IPs
+resource "aws_eip" "fundapp_demo_eip_az1" {
+ vpc = true
+ depends_on = ["aws_internet_gateway.fundapp_demo_aws_igw"]
+}
+
+resource "aws_eip" "fundapp_demo_eip_az2" {
+ vpc = true
+ depends_on = ["aws_internet_gateway.fundapp_demo_aws_igw"]
+}
+
+resource "aws_eip" "fundapp_demo_eip_az3" {
+ vpc = true
+ depends_on = ["aws_internet_gateway.fundapp_demo_aws_igw"]
+}
diff --git a/elb.tf b/elb.tf
new file mode 100644
index 0000000..69a090a
--- /dev/null
+++ b/elb.tf
@@ -0,0 +1,36 @@
+resource "aws_elb" "app_elb" {
+ name = "${var.vpc_name}_app_elb"
+
+ access_logs {
+ bucket = "${aws_s3_bucket.elb_logs.name}"
+ bucket_prefix = "app_logs"
+ interval = 60
+ }
+
+ listener {
+ instance_port = 80
+ instance_protocol = "http"
+ lb_port = 80
+ lb_protocol = "http"
+ }
+
+ health_check {
+ healthy_threshold = 2
+ unhealthy_threshold = 2
+ timeout = 3
+ target = "HTTP:80"
+ interval = 5
+ }
+
+ cross_zone_load_balancing = true
+ idle_timeout = 400
+ connection_draining = true
+ connetion_draining_timeout = 400
+ security_groups = ["${aws_security_group.app_sg.id}"]
+
+ subnets = [
+ "${aws_subnet.public_1.id}",
+ "${aws_subnet.public_2.id}",
+ "${aws_subnet.public_3.id}",
+ ]
+}
diff --git a/files/app_data.tpl b/files/app_data.tpl
new file mode 100644
index 0000000..419eff6
--- /dev/null
+++ b/files/app_data.tpl
@@ -0,0 +1,11 @@
+#!/bin/bash
+
+# Update OS
+apt-get update
+DEBIAN_FRONTEND=noninteractive apt-get -y upgrade
+
+# Install nginx
+apt-get -y install nginx
+
+# Start nginx. This will act the part of our healthcheck
+service nginx start
diff --git a/iam.tf b/iam.tf
new file mode 100644
index 0000000..9578c64
--- /dev/null
+++ b/iam.tf
@@ -0,0 +1,53 @@
+resource "aws_iam_role" "app_role" {
+ name = "app_role"
+ path = "/"
+
+ assume_role_policy = <<EOF
+{
+ "Version": "2012-10-17",
+ "Statement": [
+ {
+ "Action": "sts:AssumeRole",
+ "Principal": {
+ "Service": "ec2.amazonaws.com"
+ },
+ "Effect": "Allow",
+ "Sid": ""
+ }
+ ]
+}
+EOF
+}
+
+data "aws_iam_policy" "app_policy_document" {
+ statement {
+ actions = ["sts:AssumeRole"]
+ resources = ["*"]
+ }
+
+ statement {
+ actions = ["ec2:DescribeInstances"]
+ resources = ["*"]
+ }
+
+ statement {
+ actions = ["s3:*"]
+ resources = ["*"]
+ }
+}
+
+resource "aws_iam_policy" "app_policy" {
+ name = "app_policy"
+ path = "/"
+ policy = "${data.aws_iam_policy_document.app_policy_document.json}"
+}
+
+resource "aws_iam_role_policy_attachment" "app_policy_attachment" {
+ role = "${aws_iam_role.app_role.name}"
+ policy_arn = "${aws_iam_policy.app_policy.arn}"
+}
+
+resource "aws_iam_instance_profile" "app_profile" {
+ name = "app_profile"
+ role = "${aws_iam_role.app_role.name}"
+}
diff --git a/keypair.tf b/keypair.tf
new file mode 100644
index 0000000..16c2ae5
--- /dev/null
+++ b/keypair.tf
@@ -0,0 +1,4 @@
+resource "aws_key_pair" "server_keypair" {
+ key_name = "${var.vpc_name}_server_key"
+ public_key = "${var.keypair_pubkey}"
+}
diff --git a/main.tf b/main.tf
new file mode 100644
index 0000000..0355e22
--- /dev/null
+++ b/main.tf
@@ -0,0 +1,27 @@
+terraform {
+ backend "s3" {
+ bucket = "fundapp_demo_remote_state"
+ region = "eu-west-2"
+ key = "terraform.tfstate"
+ dynamodb_table = "terraform-state-lock-dynamo"
+ encrypt = true
+ }
+}
+
+provider "aws" {
+ region = "${var.aws_region}"
+}
+
+resource "aws_vpc" "fundapp_demo_vpc" {
+ cidr_block = "${var.vpn_cidr}"
+ enable_dns_support = true
+ enable_dns_hostnames = true
+}
+
+resource "aws_internet_gateway" "fundapp_demo_aws_igw" {
+ vpc_id = "${aws_vpc.fundapp_demo_vpc.id}"
+
+ tags {
+ Name = "${var.vpc_name}_igw"
+ }
+}
diff --git a/nat.tf b/nat.tf
new file mode 100644
index 0000000..c8bb0e5
--- /dev/null
+++ b/nat.tf
@@ -0,0 +1,18 @@
+# Nat gateways
+resource "aws_nat_gateway" "fundapp_demo_nat_gateway_az1" {
+ allocation_id = "${aws_eip.fundapp_demo_eip_az1.id}"
+ subnet_id = "${aws_subnet.public_1.id}"
+ depends_on = ["aws_internet_gateway.fundapp_demo_aws_igw"]
+}
+
+resource "aws_nat_gateway" "fundapp_demo_nat_gateway_az2" {
+ allocation_id = "${aws_eip.fundapp_demo_eip_az2.id}"
+ subnet_id = "${aws_subnet.public_2.id}"
+ depends_on = ["aws_internet_gateway.fundapp_demo_aws_igw"]
+}
+
+resource "aws_nat_gateway" "fundapp_demo_nat_gateway_az3" {
+ allocation_id = "${aws_eip.fundapp_demo_eip_az3.id}"
+ subnet_id = "${aws_subnet.public_3.id}"
+ depends_on = ["aws_internet_gateway.fundapp_demo_aws_igw"]
+}
diff --git a/route_tables.tf b/route_tables.tf
new file mode 100644
index 0000000..c4ead17
--- /dev/null
+++ b/route_tables.tf
@@ -0,0 +1,22 @@
+# Public route table
+resource "aws_route" "fundapp_demo_public_route_table" {
+ route_table_id = "${aws_vpc.fundapp_demo_vpc.main_route_table_id}"
+ destination_cidr_block = "0.0.0.0/0"
+ gateway_id = "${aws_internet_gateway.fundapp_demo_aws_igw.id}"
+}
+
+# Public route table associations
+resource "aws_route_table_association" "vpc_pub_net_association_az1" {
+ subnet_id = "${aws_subnet.public_1.id}"
+ route_table_id = "${aws_vpc.fundapp_demo_vpc.main_route_table_id}"
+}
+
+resource "aws_route_table_association" "vpc_pub_net_association_az2" {
+ subnet_id = "${aws_subnet.public_2.id}"
+ route_table_id = "${aws_vpc.fundapp_demo_vpc.main_route_table_id}"
+}
+
+resource "aws_route_table_association" "vpc_pub_net_association_az2" {
+ subnet_id = "${aws_subnet.public_2.id}"
+ route_table_id = "${aws_vpc.fundapp_demo_vpc.main_route_table_id}"
+}
diff --git a/s3.tf b/s3.tf
new file mode 100644
index 0000000..2e58a4b
--- /dev/null
+++ b/s3.tf
@@ -0,0 +1,5 @@
+resource "aws_s3_bucket" "elb_logs" {
+ bucket = "${var.vpc_name}_elb_logs"
+ acl = "private"
+ region = "${var.vpc_region}"
+}
diff --git a/sg.tf b/sg.tf
new file mode 100644
index 0000000..c8776d6
--- /dev/null
+++ b/sg.tf
@@ -0,0 +1,59 @@
+resource "aws_security_group" "external_ssh_accept_sg" {
+ name = "${var.vpc-name}_external_ssh_accept_sg"
+ description = "${var.vpc-name}_external_ssh_accept_sg"
+ vpc_id = "${aws_vpc.fundapp_demo_aws_vpc.id}"
+
+ ingress {
+ from_port = 22
+ to_port = 22
+ protocol = "tcp"
+ cidr_blocks = ["0.0.0.0/0"]
+ }
+
+ egress {
+ from_port = 0
+ to_port = 0
+ protocol = "-1"
+ cidr_blocks = ["0.0.0.0/0"]
+ }
+}
+
+resource "aws_security_group" "app_sg" {
+ name = "${var.vpc_name}_app_sg"
+ description = "${var.vpc_name}_app_sg"
+ vpc_id = "${aws_vpc.fundapp_demo_vpc.id}"
+
+ ingress {
+ from_port = 80
+ to_port = 80
+ protocol = "tcp"
+ security_groups = ["${aws_security_group.app_elb_sg.id}"]
+ }
+
+ egress {
+ from_port = 0
+ to_port = 0
+ protocol = "-1"
+ cidr_blocks = ["0.0.0.0/0"]
+ }
+}
+
+resource "aws_security_group" "app_elb_sg" {
+ name = "${var.vpc_name}_app_elb_sg"
+ description = "${var.vpc_name}_app_elb_sg"
+ vpc_id = "${aws_vpc.fundapp_demo_vpc.id}"
+
+ ingress {
+ from_port = 443
+ to_port = 443
+ protocol = "tcp"
+ cidr_blocks = ["0.0.0.0/0"]
+ }
+
+ egress {
+ from_port = 0
+ to_port = 0
+ protocol = "-1"
+ cidr_blocks = ["0.0.0.0/0"]
+ }
+}
diff --git a/subnets.tf b/subnets.tf
new file mode 100644
index 0000000..7ed881f
--- /dev/null
+++ b/subnets.tf
@@ -0,0 +1,18 @@
+# Public Subnets
+resource "aws_subnet" "public_1" {
+ vpc_id = "${aws_vpc.fundapp_demo_vpc.id}"
+ cidr_block = "${var.vpc_net_prefix}.10.0/24"
+ availability_zone = "${var.aws_az_1}"
+}
+
+resource "aws_subnet" "public_2" {
+ vpc_id = "${aws_vpc.fundapp_demo_vpc.id}"
+ cidr_block = "${var.vpc_net_prefix}.20.0/24"
+ availability_zone = "${var.aws_az_2}"
+}
+
+resource "aws_subnet" "public_3" {
+ vpc_id = "${aws_vpc.fundapp_demo_vpc.id}"
+ cidr_block = "${var.vpc_net_prefix}.30.0/24"
+ availability_zone = "${var.aws_az_3}"
+}
diff --git a/variables.tf b/variables.tf
new file mode 100644
index 0000000..9bdc1bb
--- /dev/null
+++ b/variables.tf
@@ -0,0 +1,35 @@
+variable "aws_region" {
+ default = "eu-west-2"
+}
+
+variable "aws_az_1" {
+ default = "eu-west-2a"
+}
+
+variable "aws_az_2" {
+ default = "eu-west-2b"
+}
+
+variable "aws_az_3" {
+ default = "eu-west-2c"
+}
+
+variable "vpc_net_prefix" {
+ default = "10.0"
+}
+
+variable "vpc_cidr" {
+ default = "10.0.0.0/16"
+}
+
+variable "vpc_name" {
+ default = "fundapp_demo"
+}
+
+variable "keypair_pubkey" {
+ default = "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDf1MEiSSwe2ew6ahu7SZRkucrDEDvbYVoMMEvMk091/YQFOvzE+sSl6kh+9qTceayxEEMzSw3Rmlyon+OZiDf6vp8ovxdINUfJjAUiSeo/O4pg4BMHrv1rJ+kft70lyBAHs9zGzu8JB0jVHrJMlAt4e9VCbAUvFUB+DPhCTIBeZjOpoMU7cLf0LqVoRtwGrp4YbXaBVFQWm9SZIJk2Fq5mcF+3+wxkOzacKq8ZYP3AvGoZbvSBOrhMvw9vpoBSprXzKXSd+HkBnqN2O4JRAxsxgwhQU3/HNROvha/L+aPt/muOksZtOA9wlrSbeWmFsdto/eOxFUlBgwaDMv1PSSjd hen3ry@Hen3ry-Desktop"
+}
+
+variable "image_id" {
+ default = "ami-068f09e337d7da0c4"
+}