commit 77e1e104c0471e5eafdc119fcb0f816865071036 Author: Tommy Parnell Date: Tue Feb 7 07:15:34 2017 -0500 init diff --git a/ecs.tf b/ecs.tf new file mode 100644 index 0000000..3ef42bb --- /dev/null +++ b/ecs.tf @@ -0,0 +1,96 @@ + +resource "aws_ecr_repository" "registry" { + name = "${var.container_name}" +} + +resource "aws_ecs_cluster" "cluster" { + name = "${var.container_name}" +} + +resource "aws_launch_configuration" "ecs" { + name = "ecs-${aws_ecr_repository.registry.name}" + /*this is the ami for aws irl, we should probably take this as a var or have a map of all the images*/ + image_id = "ami-48f9a52e" + instance_type = "m3.medium" + iam_instance_profile = "${aws_iam_instance_profile.ecs.id}" + security_groups = ["${aws_security_group.allow_all.id}"] + iam_instance_profile = "${aws_iam_instance_profile.ecs.name}" + user_data = "#!/bin/bash\necho ECS_CLUSTER=${aws_ecr_repository.cluster.name} > /etc/ecs/ecs.config" +} + +/** + * Autoscaling group. + */ +resource "aws_autoscaling_group" "ecs" { + name = "ecs-asg" + /* @todo take subnets as either 1 list arg or maybe some other way?*/ + vpc_zone_identifier = ["${var.SubnetPrivate1a}", "${var.SubnetPrivate1b}", "${var.SubnetPrivate1c}"] + launch_configuration = "${aws_launch_configuration.ecs.name}" + /* @todo - variablize */ + min_size = 1 + max_size = 10 + desired_capacity = 3 +} + + +data "template_file" "task-definitions" { + template = "${file("task-definitions/tasks.json")}" + + vars { + registry = "${var.account_id}.dkr.ecr.eu-west-1.amazonaws.com/${aws_ecr_repository.registry.name}" + container_name = "${var.container_name}" + container_port = "${var.container_port}" + host_port = "${var.host_port}" + } +} + +output "rendered" { + value = "${data.template_file.task-definitions.rendered}" +} + +resource "aws_ecs_task_definition" "main_task_definition" { + family = "${var.container_name}" + container_definitions = "${data.template_file.task-definitions.rendered}" +} + +resource "aws_ecs_service" "main-service" { + name = "${var.container_name}-service" + cluster = "${aws_ecr_repository.cluster.id}" + iam_role = "${aws_iam_role.ecs_service_role.arn}" + depends_on = ["aws_iam_role_policy.ecs_service_role_policy"] + task_definition = "${aws_ecs_task_definition.main_task_definition.arn}" + desired_count = 1 + load_balancer { + elb_name = "${aws_elb.elb-http.id}" + container_name = "${var.container_name}" + container_port = "${var.host_port}" + } +} + + +resource "aws_elb" "elb-http" { + name = "${var.container_name}-elb" + security_groups = ["${aws_security_group.allow_all.id}"] + subnets = ["${var.SubnetPublic1a}","${var.SubnetPublic1b}","${var.SubnetPublic1c}"] + + listener { + lb_protocol = "http" + lb_port = "${var.lb_port}" + + instance_protocol = "http" + instance_port = "${var.host_port}" + } + /* uncomment for livecheck, todo variable-ize */ + /* + health_check { + healthy_threshold = 3 + unhealthy_threshold = 2 + timeout = 3 + target = "HTTP:${var.lb_port}/livecheck" + interval = 5 + } +*/ + cross_zone_load_balancing = true +} + + diff --git a/main.tf b/main.tf new file mode 100644 index 0000000..0977ba5 --- /dev/null +++ b/main.tf @@ -0,0 +1,3 @@ +provider "aws" { + region = "${var.region}" +} diff --git a/policies/ecs-instance-role-policy.json b/policies/ecs-instance-role-policy.json new file mode 100644 index 0000000..9044143 --- /dev/null +++ b/policies/ecs-instance-role-policy.json @@ -0,0 +1,23 @@ +{ + "Version": "2012-10-17", + "Statement": [ + { + "Effect": "Allow", + "Action": [ + "ecs:CreateCluster", + "ecs:DeregisterContainerInstance", + "ecs:DiscoverPollEndpoint", + "ecs:Poll", + "ecs:RegisterContainerInstance", + "ecs:StartTelemetrySession", + "ecs:Submit*", + "ecs:StartTask", + "ecr:BatchCheckLayerAvailability", + "ecr:BatchGetImage", + "ecr:GetDownloadUrlForLayer", + "ecr:GetAuthorizationToken" + ], + "Resource": "*" + } + ] +} \ No newline at end of file diff --git a/policies/ecs-role.json b/policies/ecs-role.json new file mode 100644 index 0000000..a662b99 --- /dev/null +++ b/policies/ecs-role.json @@ -0,0 +1,15 @@ +{ + "Version": "2008-10-17", + "Statement": [ + { + "Action": "sts:AssumeRole", + "Principal": { + "Service": [ + "ecs.amazonaws.com", + "ec2.amazonaws.com" + ] + }, + "Effect": "Allow" + } + ] +} \ No newline at end of file diff --git a/policies/ecs-service-role-policy.json b/policies/ecs-service-role-policy.json new file mode 100644 index 0000000..81bfbb8 --- /dev/null +++ b/policies/ecs-service-role-policy.json @@ -0,0 +1,18 @@ +{ + "Version": "2012-10-17", + "Statement": [ + { + "Effect": "Allow", + "Action": [ + "elasticloadbalancing:Describe*", + "elasticloadbalancing:DeregisterInstancesFromLoadBalancer", + "elasticloadbalancing:RegisterInstancesWithLoadBalancer", + "ec2:Describe*", + "ec2:AuthorizeSecurityGroupIngress" + ], + "Resource": [ + "*" + ] + } + ] +} \ No newline at end of file diff --git a/security-group.tf b/security-group.tf new file mode 100644 index 0000000..4fc3a0b --- /dev/null +++ b/security-group.tf @@ -0,0 +1,19 @@ +resource "aws_security_group" "allow_all" { + name = "allow_all" + description = "Allow all inbound traffic" + vpc_id = "${var.VpcId}" + + ingress { + from_port = 0 + to_port = 0 + protocol = "-1" + cidr_blocks = ["0.0.0.0/0"] + } + + egress { + from_port = 0 + to_port = 0 + protocol = "-1" + cidr_blocks = ["0.0.0.0/0"] + } +} \ No newline at end of file diff --git a/security.tf b/security.tf new file mode 100644 index 0000000..8e8c514 --- /dev/null +++ b/security.tf @@ -0,0 +1,30 @@ + +resource "aws_iam_role" "ecs_host_role" { + name = "ecs_host_role" + assume_role_policy = "${file("policies/ecs-role.json")}" +} + +resource "aws_iam_instance_profile" "ecs" { + name = "ecs-instance-profile" + path = "/" + roles = ["${aws_iam_role.ecs_host_role.name}"] +} + +resource "aws_iam_role_policy" "ecs_instance_role_policy" { + name = "ecs_instance_role_policy" + policy = "${file("policies/ecs-instance-role-policy.json")}" + role = "${aws_iam_role.ecs_host_role.id}" +} + +resource "aws_iam_role" "ecs_service_role" { + name = "ecs_service_role" + assume_role_policy = "${file("policies/ecs-role.json")}" +} + +resource "aws_iam_role_policy" "ecs_service_role_policy" { + name = "ecs_service_role_policy" + policy = "${file("policies/ecs-service-role-policy.json")}" + role = "${aws_iam_role.ecs_service_role.id}" +} + + diff --git a/task-definitions/tasks.json b/task-definitions/tasks.json new file mode 100644 index 0000000..cf658ac --- /dev/null +++ b/task-definitions/tasks.json @@ -0,0 +1,23 @@ +[ + + { + "name": "${container_name}", + "image": "${registry}:${container_name}-latest", + "cpu": 300, + "memory": 300, + "links": [], + "portMappings": [ + { + "containerPort": ${container_port}, + "hostPort": ${host_port}, + "protocol": "tcp" + } + ], + "essential": true, + "entryPoint": [], + "command": [], + "environment": [], + "mountPoints": [], + "volumesFrom": [] + } +] \ No newline at end of file diff --git a/variables.tf b/variables.tf new file mode 100644 index 0000000..4ff9c43 --- /dev/null +++ b/variables.tf @@ -0,0 +1,42 @@ +variable "SubnetPublic1a" { + type = "string" +} +variable "SubnetPublic1b" { + type = "string" +} +variable "SubnetPublic1c" { + type = "string" +} +variable "SubnetPrivate1a" { + type = "string" +} +variable "SubnetPrivate1b" { + type = "string" +} +variable "SubnetPrivate1c" { + type = "string" +} + +variable "VpcId"{ + type = "string" + default = "" +} + +variable "account_id"{ + type = "string" + default = "" +} +variable "region"{ + type = "string" + default = "eu-west-1" +} + +variable "container_name"{ + type = "string" +} +variable "container_port"{ + type = "string" +} +variable "lb_port"{ + type = "string" +} \ No newline at end of file