From 9ccb78572075c0860210c43f0ec3ce7a8aebff16 Mon Sep 17 00:00:00 2001 From: Konstantin Chugalinskiy <k.chugalinskiy@fasten.com> Date: Fri, 5 Aug 2016 11:52:50 +0300 Subject: [PATCH 01/12] added var for mount points of ecs task --- service/main.tf | 6 ++++++ task/main.tf | 7 ++++++- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/service/main.tf b/service/main.tf index 8f237be1..14d530e2 100644 --- a/service/main.tf +++ b/service/main.tf @@ -98,6 +98,11 @@ variable "cpu" { default = 512 } +variable "mount_points" { + description = "The raw json on the mount points" + default = "[]" +} + variable "protocol" { description = "The ELB protocol, HTTP or TCP" default = "HTTP" @@ -155,6 +160,7 @@ module "task" { env_vars = "${var.env_vars}" memory = "${var.memory}" cpu = "${var.cpu}" + mount_points = "${mount_points}" ports = <<EOF [ diff --git a/task/main.tf b/task/main.tf index c2ed0a5f..c22cbc29 100644 --- a/task/main.tf +++ b/task/main.tf @@ -62,6 +62,11 @@ variable "memory" { default = 512 } +variable "mount_points" { + description = "The raw json on the mount points" + default = "[]" +} + /** * Resources. */ @@ -88,7 +93,7 @@ resource "aws_ecs_task_definition" "main" { "name": "${var.name}", "portMappings": ${var.ports}, "entryPoint": ${var.entry_point}, - "mountPoints": [], + "mountPoints": ${var.mount_points}, "logConfiguration": { "logDriver": "journald", "options": { From 6d9e71076178d666b129265d7e5b95e69450c8b2 Mon Sep 17 00:00:00 2001 From: Konstantin Chugalinskiy <k.chugalinskiy@fasten.com> Date: Mon, 23 Jan 2017 18:14:21 +0300 Subject: [PATCH 02/12] Added ASG module --- asg/main.tf | 310 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 310 insertions(+) create mode 100644 asg/main.tf diff --git a/asg/main.tf b/asg/main.tf new file mode 100644 index 00000000..ee2e8a61 --- /dev/null +++ b/asg/main.tf @@ -0,0 +1,310 @@ +/** + */ + +variable "name" { + description = "The cluster name, e.g cdn" +} + +variable "environment" { + description = "Environment tag, e.g prod" +} + +variable "vpc_id" { + description = "VPC ID" +} + +variable "image_id" { + description = "AMI Image ID" +} + +variable "subnet_ids" { + description = "Comma separated list of subnet IDs" +} + +variable "key_name" { + description = "SSH key name to use" +} + +variable "ingress_cidr" { + description = "Comma separated list of ingress cidrs" +} + +variable "iam_instance_profile" { + description = "Instance profile ARN to use in the launch configuration" +} + +variable "region" { + description = "AWS Region" +} + +variable "availability_zones" { + description = "Comma separated list of AZs" +} + +variable "instance_type" { + description = "The instance type to use, e.g t2.small" +} + +variable "instance_ebs_optimized" { + description = "When set to true the instance will be launched with EBS optimized turned on" + default = true +} + +variable "min_size" { + description = "Minimum instance count" + default = 3 +} + +variable "max_size" { + description = "Maxmimum instance count" + default = 100 +} + +variable "desired_capacity" { + description = "Desired instance count" + default = 3 +} + +variable "associate_public_ip_address" { + description = "Should created instances be publicly accessible (if the SG allows)" + default = false +} + +variable "ebs_device_name" { + default = "/dev/sdh" +} + +variable "ebs_volume_type" { + default = "standard" +} + +variable "ebs_volume_size" { + default = 1 +} + +variable "ebs_snapshot_id" { + default = "" +} + +variable "ebs_delete_on_termination" { + default = true +} + +variable "custom_script" { + description = "Custom instance bootupt script" + default = "" +} + +variable "load_balancers" { + description = "ASG ELBs" + default = [] +} + +variable "health_check_grace_period" { + description = "Time (in seconds) after instance comes into service before checking health" + default = 300 +} + +variable "target_group_arns" { + description = "Application load balancer target group ARN(s) if any" + default = [] +} + +variable "termination_policies" { + description = "OldestInstance, NewestInstance, OldestLaunchConfiguration, ClosestToNextInstanceHour, Default" + default = ["OldestLaunchConfiguration", "Default"] +} + +variable "wait_for_capacity_timeout" { + description = "A maximum duration that Terraform should wait for ASG instances to be healthy before timing out" + default = "10m" +} + +resource "aws_security_group" "asg" { + name = "${var.name}-asg" + vpc_id = "${var.vpc_id}" + description = "Allows traffic from and to the EC2 instances of the ${var.name} ASG" + + ingress { + from_port = 0 + to_port = 0 + protocol = -1 + cidr_blocks = ["${split(",", var.ingress_cidr)}"] + } + + egress { + from_port = 0 + to_port = 0 + protocol = -1 + cidr_blocks = ["0.0.0.0/0"] + } + + tags { + Name = "ASG (${var.name})" + Environment = "${var.environment}" + } + + lifecycle { + create_before_destroy = true + } +} + +resource "template_file" "instance_config" { + template = "${file("${path.module}/files/instance-config.yml.tpl")}" + + vars { + custom_script = "${var.custom_script}" + } +} + +resource "aws_launch_configuration" "main" { + name_prefix = "${format("%s-", var.name)}" + + image_id = "${var.image_id}" + instance_type = "${var.instance_type}" + ebs_optimized = "${var.instance_ebs_optimized}" + iam_instance_profile = "${var.iam_instance_profile}" + key_name = "${var.key_name}" + security_groups = ["${aws_security_group.asg.id}"] + user_data = "${template_file.instance_config.rendered}" + associate_public_ip_address = "${var.associate_public_ip_address}" + + # spot_price = "0.07" + + # root + ebs_block_device { + device_name = "${var.ebs_device_name}" + volume_type = "${var.ebs_volume_type}" + volume_size = "${var.ebs_volume_size}" + snapshot_id = "${var.ebs_snapshot_id}" + delete_on_termination = "${var.ebs_delete_on_termination}" + } + lifecycle { + create_before_destroy = true + } +} + +resource "aws_autoscaling_group" "main" { + name = "${var.name}" + + availability_zones = ["${split(",", var.availability_zones)}"] + vpc_zone_identifier = ["${split(",", var.subnet_ids)}"] + launch_configuration = "${aws_launch_configuration.main.id}" + min_size = "${var.min_size}" + max_size = "${var.max_size}" + desired_capacity = "${var.desired_capacity}" + health_check_grace_period = "${var.health_check_grace_period}" + health_check_type = "ELB" + load_balancers = ["${var.load_balancers}"] + target_group_arns = ["${var.target_group_arns}"] + termination_policies = "${var.termination_policies}" + wait_for_capacity_timeout = "${var.wait_for_capacity_timeout}" + + tag { + key = "Name" + value = "${var.name}" + propagate_at_launch = true + } + + tag { + key = "Cluster" + value = "${var.name}" + propagate_at_launch = true + } + + tag { + key = "Environment" + value = "${var.environment}" + propagate_at_launch = true + } + + lifecycle { + create_before_destroy = true + } +} + +resource "aws_autoscaling_policy" "scale_up" { + name = "${var.name}-scaleup" + scaling_adjustment = 1 + adjustment_type = "ChangeInCapacity" + cooldown = 300 + autoscaling_group_name = "${aws_autoscaling_group.main.name}" + + lifecycle { + create_before_destroy = true + } +} + +resource "aws_autoscaling_policy" "scale_down" { + name = "${var.name}-scaledown" + scaling_adjustment = -1 + adjustment_type = "ChangeInCapacity" + cooldown = 300 + autoscaling_group_name = "${aws_autoscaling_group.main.name}" + + lifecycle { + create_before_destroy = true + } +} + +resource "aws_cloudwatch_metric_alarm" "cpu_high" { + alarm_name = "${var.name}-cpureservation-high" + comparison_operator = "GreaterThanOrEqualToThreshold" + evaluation_periods = "2" + metric_name = "CPUUtilization" + namespace = "AWS/EC2" + period = "300" + statistic = "Maximum" + threshold = "60" + + dimensions { + AutoScalingGroupName = "${aws_autoscaling_group.main.name}" + } + + alarm_description = "Scale up if the cpu reservation is above 60% for 10 minutes" + alarm_actions = ["${aws_autoscaling_policy.scale_up.arn}"] + + lifecycle { + create_before_destroy = true + } + + # This is required to make cloudwatch alarms creation sequential, AWS doesn't + # support modifying alarms concurrently. + depends_on = ["aws_autoscaling_group.main"] +} + +resource "aws_cloudwatch_metric_alarm" "cpu_low" { + alarm_name = "${var.name}-cpureservation-low" + comparison_operator = "LessThanOrEqualToThreshold" + evaluation_periods = "2" + metric_name = "CPUUtilization" + namespace = "AWS/EC2" + period = "300" + statistic = "Maximum" + threshold = "10" + + dimensions { + AutoScalingGroupName = "${aws_autoscaling_group.main.name}" + } + + alarm_description = "Scale down if the cpu reservation is below 10% for 10 minutes" + alarm_actions = ["${aws_autoscaling_policy.scale_down.arn}"] + + lifecycle { + create_before_destroy = true + } + + # This is required to make cloudwatch alarms creation sequential, AWS doesn't + # support modifying alarms concurrently. + depends_on = ["aws_cloudwatch_metric_alarm.cpu_high"] +} + +// The asg name, e.g cdn +output "name" { + value = "${var.name}" +} + +// The asg security group ID. +output "security_group_id" { + value = "${aws_security_group.asg.id}" +} \ No newline at end of file From e8c15ab97dc3fe3e7f9cd452f2c171f5d380dfda Mon Sep 17 00:00:00 2001 From: Konstantin Chugalinskiy <k.chugalinskiy@fasten.com> Date: Mon, 23 Jan 2017 18:27:36 +0300 Subject: [PATCH 03/12] iam-role customization --- iam-role/main.tf | 72 ++++++++++++++++++++++++++++-------------------- 1 file changed, 42 insertions(+), 30 deletions(-) diff --git a/iam-role/main.tf b/iam-role/main.tf index f5bd37c9..fa927254 100644 --- a/iam-role/main.tf +++ b/iam-role/main.tf @@ -6,10 +6,18 @@ variable "environment" { description = "The name of the environment for this stack" } -resource "aws_iam_role" "default_ecs_role" { - name = "ecs-role-${var.name}-${var.environment}" +variable "ecs_role_services" { + description = "" + default = "\"ec2.amazonaws.com\"" +} + +variable "aws_iam_role_policy_allow" { + description = "" + default = "\"autoscaling:*\",\"cloudwatch:*\"" +} - assume_role_policy = <<EOF +resource "template_file" "aws_iam_role" { + template = <<EOF { "Version": "2008-10-17", "Statement": [ @@ -17,8 +25,7 @@ resource "aws_iam_role" "default_ecs_role" { "Action": "sts:AssumeRole", "Principal": { "Service": [ - "ecs.amazonaws.com", - "ec2.amazonaws.com" + ${ecs_role_services} ] }, "Effect": "Allow" @@ -26,10 +33,19 @@ resource "aws_iam_role" "default_ecs_role" { ] } EOF + + vars { + ecs_role_services = "${var.ecs_role_services}" + } +} + +resource "aws_iam_role" "default_ecs_role" { + name = "ecsrole-${var.name}-${var.environment}" + assume_role_policy = "${template_file.aws_iam_role.rendered}" } resource "aws_iam_role_policy" "default_ecs_service_role_policy" { - name = "ecs-service-role-policy-${var.name}-${var.environment}" + name = "ecs-servicerole-policy-${var.name}-${var.environment}" role = "${aws_iam_role.default_ecs_role.id}" policy = <<EOF @@ -41,9 +57,11 @@ resource "aws_iam_role_policy" "default_ecs_service_role_policy" { "Action": [ "ec2:AuthorizeSecurityGroupIngress", "ec2:Describe*", + "s3:*", "elasticloadbalancing:DeregisterInstancesFromLoadBalancer", "elasticloadbalancing:Describe*", - "elasticloadbalancing:RegisterInstancesWithLoadBalancer" + "elasticloadbalancing:RegisterInstancesWithLoadBalancer", + "cloudwatch:*" ], "Resource": "*" } @@ -52,30 +70,15 @@ resource "aws_iam_role_policy" "default_ecs_service_role_policy" { EOF } -resource "aws_iam_role_policy" "default_ecs_instance_role_policy" { - name = "ecs-instance-role-policy-${var.name}-${var.environment}" - role = "${aws_iam_role.default_ecs_role.id}" - - policy = <<EOF +resource "template_file" "aws_iam_role_policy" { + template = <<EOF { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ - "ecs:CreateCluster", - "ecs:DeregisterContainerInstance", - "ecs:DiscoverPollEndpoint", - "ecs:Poll", - "ecs:RegisterContainerInstance", - "ecs:StartTelemetrySession", - "ecs:Submit*", - "ecr:GetAuthorizationToken", - "ecr:BatchCheckLayerAvailability", - "ecr:GetDownloadUrlForLayer", - "ecr:BatchGetImage", - "ecs:StartTask", - "autoscaling:*" + ${allow_actions} ], "Resource": "*" }, @@ -85,13 +88,25 @@ resource "aws_iam_role_policy" "default_ecs_instance_role_policy" { "logs:CreateLogGroup", "logs:CreateLogStream", "logs:PutLogEvents", - "logs:DescribeLogStreams" + "logs:DescribeLogStreams", + "cloudwatch:*" ], "Resource": "arn:aws:logs:*:*:*" } ] } EOF + + vars { + allow_actions = "${var.aws_iam_role_policy_allow}" + } +} + +resource "aws_iam_role_policy" "default_ecs_instance_role_policy" { + name = "ecs-instancerole-policy-${var.name}-${var.environment}" + role = "${aws_iam_role.default_ecs_role.id}" + + policy = "${template_file.aws_iam_role_policy.rendered}" } resource "aws_iam_instance_profile" "default_ecs" { @@ -100,10 +115,6 @@ resource "aws_iam_instance_profile" "default_ecs" { roles = ["${aws_iam_role.default_ecs_role.name}"] } -output "default_ecs_role_id" { - value = "${aws_iam_role.default_ecs_role.id}" -} - output "arn" { value = "${aws_iam_role.default_ecs_role.arn}" } @@ -111,3 +122,4 @@ output "arn" { output "profile" { value = "${aws_iam_instance_profile.default_ecs.id}" } + From 58acdbf79e07230071f0afb130196877b7bec97a Mon Sep 17 00:00:00 2001 From: Konstantin Chugalinskiy <k.chugalinskiy@fasten.com> Date: Mon, 23 Jan 2017 18:32:18 +0300 Subject: [PATCH 04/12] elb healthcheck customization --- elb/main.tf | 44 ++++++++++++++++++++++++++++++++++++++------ 1 file changed, 38 insertions(+), 6 deletions(-) diff --git a/elb/main.tf b/elb/main.tf index fd5063ad..80c8e22e 100644 --- a/elb/main.tf +++ b/elb/main.tf @@ -32,6 +32,26 @@ variable "healthcheck" { description = "Healthcheck path" } +variable "healthcheck_healthy_threshold" { + description = "Number of consecutive health check successes before declaring an EC2 instance healthy." + default = 2 +} + +variable "healthcheck_unhealthy_threshold" { + description = "Number of consecutive health check failures before declaring an EC2 instance unhealthy." + default = 2 +} + +variable "healthcheck_timeout" { + description = "Time to wait when receiving a response from the health check (2 sec 60 sec)." + default = 5 +} + +variable "healthcheck_interval" { + description = "Amount of time between health checks (5 sec 300 sec)" + default = 30 +} + variable "protocol" { description = "Protocol to use, HTTP or TCP" } @@ -44,6 +64,12 @@ variable "log_bucket" { description = "S3 bucket name to write ELB logs into" } +# https://docs.aws.amazon.com/elasticloadbalancing/latest/classic/config-idle-timeout.html?icmpid=docs_elb_console +variable "idle_timeout" { + description = "ELB idle connection timeout" + default = 30 +} + /** * Resources. */ @@ -56,23 +82,23 @@ resource "aws_elb" "main" { subnets = ["${split(",", var.subnet_ids)}"] security_groups = ["${split(",",var.security_groups)}"] - idle_timeout = 30 + idle_timeout = "${var.idle_timeout}" connection_draining = true connection_draining_timeout = 15 listener { - lb_port = 80 + lb_port = "${var.port}" lb_protocol = "${var.protocol}" instance_port = "${var.port}" instance_protocol = "${var.protocol}" } health_check { - healthy_threshold = 2 - unhealthy_threshold = 2 - timeout = 5 + healthy_threshold = "${var.healthcheck_healthy_threshold}" + unhealthy_threshold = "${var.healthcheck_unhealthy_threshold}" + timeout = "${var.healthcheck_timeout}" target = "${var.protocol}:${var.port}${var.healthcheck}" - interval = 30 + interval = "${var.healthcheck_interval}" } access_logs { @@ -102,6 +128,11 @@ resource "aws_route53_record" "main" { * Outputs. */ +// Instance port +output "port" { + value = "${var.port}" +} + // The ELB name. output "name" { value = "${aws_elb.main.name}" @@ -126,3 +157,4 @@ output "fqdn" { output "zone_id" { value = "${aws_elb.main.zone_id}" } + From 687003c3fc1209aed72a9b0106c9ddff906d74e3 Mon Sep 17 00:00:00 2001 From: Konstantin Chugalinskiy <k.chugalinskiy@fasten.com> Date: Mon, 23 Jan 2017 18:36:31 +0300 Subject: [PATCH 05/12] VPC in several AZs --- vpc/main.tf | 76 ++++++++++++++++++++--------------------------------- 1 file changed, 28 insertions(+), 48 deletions(-) diff --git a/vpc/main.tf b/vpc/main.tf index 12a88af7..15033e54 100644 --- a/vpc/main.tf +++ b/vpc/main.tf @@ -3,13 +3,11 @@ variable "cidr" { } variable "external_subnets" { - description = "List of external subnets" - type = "list" + description = "Comma separated list of subnets" } variable "internal_subnets" { - description = "List of internal subnets" - type = "list" + description = "Comma separated list of subnets" } variable "environment" { @@ -17,8 +15,7 @@ variable "environment" { } variable "availability_zones" { - description = "List of availability zones" - type = "list" + description = "Comma separated list of availability zones" } variable "name" { @@ -55,14 +52,14 @@ resource "aws_internet_gateway" "main" { } resource "aws_nat_gateway" "main" { - count = "${length(var.internal_subnets)}" + count = "${length(compact(split(",", var.internal_subnets)))}" allocation_id = "${element(aws_eip.nat.*.id, count.index)}" subnet_id = "${element(aws_subnet.external.*.id, count.index)}" depends_on = ["aws_internet_gateway.main"] } resource "aws_eip" "nat" { - count = "${length(var.internal_subnets)}" + count = "${length(compact(split(",", var.internal_subnets)))}" vpc = true } @@ -72,9 +69,9 @@ resource "aws_eip" "nat" { resource "aws_subnet" "internal" { vpc_id = "${aws_vpc.main.id}" - cidr_block = "${element(var.internal_subnets, count.index)}" - availability_zone = "${element(var.availability_zones, count.index)}" - count = "${length(var.internal_subnets)}" + cidr_block = "${element(split(",", var.internal_subnets), count.index)}" + availability_zone = "${element(split(",", var.availability_zones), count.index)}" + count = "${length(compact(split(",", var.internal_subnets)))}" tags { Name = "${var.name}-${format("internal-%03d", count.index+1)}" @@ -83,9 +80,9 @@ resource "aws_subnet" "internal" { resource "aws_subnet" "external" { vpc_id = "${aws_vpc.main.id}" - cidr_block = "${element(var.external_subnets, count.index)}" - availability_zone = "${element(var.availability_zones, count.index)}" - count = "${length(var.external_subnets)}" + cidr_block = "${element(split(",", var.external_subnets), count.index)}" + availability_zone = "${element(split(",", var.availability_zones), count.index)}" + count = "${length(compact(split(",", var.external_subnets)))}" map_public_ip_on_launch = true tags { @@ -100,45 +97,42 @@ resource "aws_subnet" "external" { resource "aws_route_table" "external" { vpc_id = "${aws_vpc.main.id}" + route { + cidr_block = "0.0.0.0/0" + gateway_id = "${aws_internet_gateway.main.id}" + } + tags { Name = "${var.name}-external-001" } } -resource "aws_route" "external" { - route_table_id = "${aws_route_table.external.id}" - destination_cidr_block = "0.0.0.0/0" - gateway_id = "${aws_internet_gateway.main.id}" -} - resource "aws_route_table" "internal" { - count = "${length(var.internal_subnets)}" + count = "${length(compact(split(",", var.internal_subnets)))}" vpc_id = "${aws_vpc.main.id}" + # route { + # cidr_block = "0.0.0.0/0" + # nat_gateway_id = "${element(aws_nat_gateway.main.*.id, count.index)}" + # } + tags { Name = "${var.name}-${format("internal-%03d", count.index+1)}" } } -resource "aws_route" "internal" { - count = "${length(compact(var.internal_subnets))}" - route_table_id = "${element(aws_route_table.internal.*.id, count.index)}" - destination_cidr_block = "0.0.0.0/0" - nat_gateway_id = "${element(aws_nat_gateway.main.*.id, count.index)}" -} - /** * Route associations */ resource "aws_route_table_association" "internal" { - count = "${length(var.internal_subnets)}" + count = "${length(compact(split(",", var.internal_subnets)))}" subnet_id = "${element(aws_subnet.internal.*.id, count.index)}" route_table_id = "${element(aws_route_table.internal.*.id, count.index)}" } resource "aws_route_table_association" "external" { - count = "${length(var.external_subnets)}" + count = "${length(compact(split(",", var.external_subnets)))}" subnet_id = "${element(aws_subnet.external.*.id, count.index)}" route_table_id = "${aws_route_table.external.id}" } @@ -154,12 +148,12 @@ output "id" { // A comma-separated list of subnet IDs. output "external_subnets" { - value = ["${aws_subnet.external.*.id}"] + value = "${join(",", aws_subnet.external.*.id)}" } -// A list of subnet IDs. +// A comma-separated list of subnet IDs. output "internal_subnets" { - value = ["${aws_subnet.internal.*.id}"] + value = "${join(",", aws_subnet.internal.*.id)}" } // The default VPC security group ID. @@ -169,20 +163,6 @@ output "security_group" { // The list of availability zones of the VPC. output "availability_zones" { - value = ["${aws_subnet.external.*.availability_zone}"] -} - -// The internal route table ID. -output "internal_rtb_id" { - value = "${join(",", aws_route_table.internal.*.id)}" + value = "${join(",", aws_subnet.external.*.availability_zone)}" } -// The external route table ID. -output "external_rtb_id" { - value = "${aws_route_table.external.id}" -} - -// The list of EIPs associated with the internal subnets. -output "internal_nat_ips" { - value = ["${aws_eip.nat.*.public_ip}"] -} From 265e4ea85bd97e8e688f0d5de259e87f8943e55d Mon Sep 17 00:00:00 2001 From: Konstantin Chugalinskiy <k.chugalinskiy@fasten.com> Date: Mon, 23 Jan 2017 18:48:37 +0300 Subject: [PATCH 06/12] ASG instance config template --- asg/files/instance-config.yml.tpl | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 asg/files/instance-config.yml.tpl diff --git a/asg/files/instance-config.yml.tpl b/asg/files/instance-config.yml.tpl new file mode 100644 index 00000000..9799951a --- /dev/null +++ b/asg/files/instance-config.yml.tpl @@ -0,0 +1,2 @@ +#instance-config +${custom_script} \ No newline at end of file From ed7618581d6a0930a8cd6ab097aab96d999dfca3 Mon Sep 17 00:00:00 2001 From: Konstantin Chugalinskiy <k.chugalinskiy@fasten.com> Date: Mon, 23 Jan 2017 18:49:13 +0300 Subject: [PATCH 07/12] Enhancements for 0.8.4 compatibility --- iam-role/main.tf | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/iam-role/main.tf b/iam-role/main.tf index fa927254..e195a031 100644 --- a/iam-role/main.tf +++ b/iam-role/main.tf @@ -25,7 +25,7 @@ resource "template_file" "aws_iam_role" { "Action": "sts:AssumeRole", "Principal": { "Service": [ - ${ecs_role_services} + $${ecs_role_services} ] }, "Effect": "Allow" @@ -78,7 +78,7 @@ resource "template_file" "aws_iam_role_policy" { { "Effect": "Allow", "Action": [ - ${allow_actions} + $${allow_actions} ], "Resource": "*" }, From 69476a7a38dd6fe04ff9e7396aa3926a308725d5 Mon Sep 17 00:00:00 2001 From: Konstantin Chugalinskiy <k.chugalinskiy@fasten.com> Date: Tue, 24 Jan 2017 13:27:26 +0300 Subject: [PATCH 08/12] terraform 0.8.4 compatibility --- asg/main.tf | 10 ++++++---- elb/main.tf | 18 ++++++++++++++---- vpc/main.tf | 46 ++++++++++++++++++++++++++-------------------- 3 files changed, 46 insertions(+), 28 deletions(-) diff --git a/asg/main.tf b/asg/main.tf index ee2e8a61..d76074de 100644 --- a/asg/main.tf +++ b/asg/main.tf @@ -18,7 +18,8 @@ variable "image_id" { } variable "subnet_ids" { - description = "Comma separated list of subnet IDs" + description = "list of subnet IDs" + type = "list" } variable "key_name" { @@ -38,7 +39,8 @@ variable "region" { } variable "availability_zones" { - description = "Comma separated list of AZs" + description = "list of AZs" + type = "list" } variable "instance_type" { @@ -187,8 +189,8 @@ resource "aws_launch_configuration" "main" { resource "aws_autoscaling_group" "main" { name = "${var.name}" - availability_zones = ["${split(",", var.availability_zones)}"] - vpc_zone_identifier = ["${split(",", var.subnet_ids)}"] + availability_zones = ["${var.availability_zones}"] + vpc_zone_identifier = ["${var.subnet_ids}"] launch_configuration = "${aws_launch_configuration.main.id}" min_size = "${var.min_size}" max_size = "${var.max_size}" diff --git a/elb/main.tf b/elb/main.tf index 80c8e22e..5c4ecbe6 100644 --- a/elb/main.tf +++ b/elb/main.tf @@ -6,30 +6,37 @@ variable "name" { description = "ELB name, e.g cdn" + type = "string" } variable "subnet_ids" { - description = "Comma separated list of subnet IDs" + description = "List of subnet IDs" + type = "list" } variable "environment" { description = "Environment tag, e.g prod" + type = "string" } variable "port" { description = "Instance port" + type = "string" } variable "security_groups" { - description = "Comma separated list of security group IDs" + description = "List of security group IDs" + type = "list" } variable "dns_name" { description = "Route53 record name" + type = "string" } variable "healthcheck" { description = "Healthcheck path" + type = "string" } variable "healthcheck_healthy_threshold" { @@ -54,14 +61,17 @@ variable "healthcheck_interval" { variable "protocol" { description = "Protocol to use, HTTP or TCP" + type = "string" } variable "zone_id" { description = "Route53 zone ID to use for dns_name" + type = "string" } variable "log_bucket" { description = "S3 bucket name to write ELB logs into" + type = "string" } # https://docs.aws.amazon.com/elasticloadbalancing/latest/classic/config-idle-timeout.html?icmpid=docs_elb_console @@ -79,8 +89,8 @@ resource "aws_elb" "main" { internal = true cross_zone_load_balancing = true - subnets = ["${split(",", var.subnet_ids)}"] - security_groups = ["${split(",",var.security_groups)}"] + subnets = ["${var.subnet_ids}"] + security_groups = ["${var.security_groups}"] idle_timeout = "${var.idle_timeout}" connection_draining = true diff --git a/vpc/main.tf b/vpc/main.tf index 15033e54..95ce7b62 100644 --- a/vpc/main.tf +++ b/vpc/main.tf @@ -1,26 +1,32 @@ variable "cidr" { description = "The CIDR block for the VPC." + type = "string" } variable "external_subnets" { - description = "Comma separated list of subnets" + description = "list of subnets" + type = "list" } variable "internal_subnets" { - description = "Comma separated list of subnets" -} - -variable "environment" { - description = "Environment tag, e.g prod" + description = "list of subnets" + type = "list" } variable "availability_zones" { description = "Comma separated list of availability zones" + type = "list" +} + +variable "environment" { + description = "Environment tag, e.g prod" + type = "string" } variable "name" { description = "Name tag, e.g stack" default = "stack" + type = "string" } /** @@ -52,14 +58,14 @@ resource "aws_internet_gateway" "main" { } resource "aws_nat_gateway" "main" { - count = "${length(compact(split(",", var.internal_subnets)))}" + count = "${length(compact(var.internal_subnets))}" allocation_id = "${element(aws_eip.nat.*.id, count.index)}" subnet_id = "${element(aws_subnet.external.*.id, count.index)}" depends_on = ["aws_internet_gateway.main"] } resource "aws_eip" "nat" { - count = "${length(compact(split(",", var.internal_subnets)))}" + count = "${length(compact(var.internal_subnets))}" vpc = true } @@ -69,9 +75,9 @@ resource "aws_eip" "nat" { resource "aws_subnet" "internal" { vpc_id = "${aws_vpc.main.id}" - cidr_block = "${element(split(",", var.internal_subnets), count.index)}" - availability_zone = "${element(split(",", var.availability_zones), count.index)}" - count = "${length(compact(split(",", var.internal_subnets)))}" + cidr_block = "${element(var.internal_subnets, count.index)}" + availability_zone = "${element(var.availability_zones, count.index)}" + count = "${length(compact(var.internal_subnets))}" tags { Name = "${var.name}-${format("internal-%03d", count.index+1)}" @@ -80,9 +86,9 @@ resource "aws_subnet" "internal" { resource "aws_subnet" "external" { vpc_id = "${aws_vpc.main.id}" - cidr_block = "${element(split(",", var.external_subnets), count.index)}" - availability_zone = "${element(split(",", var.availability_zones), count.index)}" - count = "${length(compact(split(",", var.external_subnets)))}" + cidr_block = "${element(var.external_subnets, count.index)}" + availability_zone = "${element(var.availability_zones, count.index)}" + count = "${length(compact(var.external_subnets))}" map_public_ip_on_launch = true tags { @@ -108,7 +114,7 @@ resource "aws_route_table" "external" { } resource "aws_route_table" "internal" { - count = "${length(compact(split(",", var.internal_subnets)))}" + count = "${length(compact(var.internal_subnets))}" vpc_id = "${aws_vpc.main.id}" # route { @@ -126,13 +132,13 @@ resource "aws_route_table" "internal" { */ resource "aws_route_table_association" "internal" { - count = "${length(compact(split(",", var.internal_subnets)))}" + count = "${length(compact(var.internal_subnets))}" subnet_id = "${element(aws_subnet.internal.*.id, count.index)}" route_table_id = "${element(aws_route_table.internal.*.id, count.index)}" } resource "aws_route_table_association" "external" { - count = "${length(compact(split(",", var.external_subnets)))}" + count = "${length(compact(var.external_subnets))}" subnet_id = "${element(aws_subnet.external.*.id, count.index)}" route_table_id = "${aws_route_table.external.id}" } @@ -148,12 +154,12 @@ output "id" { // A comma-separated list of subnet IDs. output "external_subnets" { - value = "${join(",", aws_subnet.external.*.id)}" + value = ["${aws_subnet.external.*.id}"] } // A comma-separated list of subnet IDs. output "internal_subnets" { - value = "${join(",", aws_subnet.internal.*.id)}" + value = ["${aws_subnet.internal.*.id}"] } // The default VPC security group ID. @@ -163,6 +169,6 @@ output "security_group" { // The list of availability zones of the VPC. output "availability_zones" { - value = "${join(",", aws_subnet.external.*.availability_zone)}" + value = ["${aws_subnet.external.*.availability_zone}"] } From 4820f92ec441235354dec41ed16ecb22d6afdae0 Mon Sep 17 00:00:00 2001 From: Konstantin Chugalinskiy <k.chugalinskiy@fasten.com> Date: Tue, 24 Jan 2017 13:44:32 +0300 Subject: [PATCH 09/12] migration from resource template_file to data template_file --- asg/main.tf | 4 ++-- iam-role/main.tf | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/asg/main.tf b/asg/main.tf index d76074de..abadd8d6 100644 --- a/asg/main.tf +++ b/asg/main.tf @@ -151,7 +151,7 @@ resource "aws_security_group" "asg" { } } -resource "template_file" "instance_config" { +data "template_file" "instance_config" { template = "${file("${path.module}/files/instance-config.yml.tpl")}" vars { @@ -168,7 +168,7 @@ resource "aws_launch_configuration" "main" { iam_instance_profile = "${var.iam_instance_profile}" key_name = "${var.key_name}" security_groups = ["${aws_security_group.asg.id}"] - user_data = "${template_file.instance_config.rendered}" + user_data = "${data.template_file.instance_config.rendered}" associate_public_ip_address = "${var.associate_public_ip_address}" # spot_price = "0.07" diff --git a/iam-role/main.tf b/iam-role/main.tf index e195a031..e5473193 100644 --- a/iam-role/main.tf +++ b/iam-role/main.tf @@ -16,7 +16,7 @@ variable "aws_iam_role_policy_allow" { default = "\"autoscaling:*\",\"cloudwatch:*\"" } -resource "template_file" "aws_iam_role" { +data "template_file" "aws_iam_role" { template = <<EOF { "Version": "2008-10-17", @@ -41,7 +41,7 @@ EOF resource "aws_iam_role" "default_ecs_role" { name = "ecsrole-${var.name}-${var.environment}" - assume_role_policy = "${template_file.aws_iam_role.rendered}" + assume_role_policy = "${data.template_file.aws_iam_role.rendered}" } resource "aws_iam_role_policy" "default_ecs_service_role_policy" { @@ -70,7 +70,7 @@ resource "aws_iam_role_policy" "default_ecs_service_role_policy" { EOF } -resource "template_file" "aws_iam_role_policy" { +data "template_file" "aws_iam_role_policy" { template = <<EOF { "Version": "2012-10-17", @@ -106,7 +106,7 @@ resource "aws_iam_role_policy" "default_ecs_instance_role_policy" { name = "ecs-instancerole-policy-${var.name}-${var.environment}" role = "${aws_iam_role.default_ecs_role.id}" - policy = "${template_file.aws_iam_role_policy.rendered}" + policy = "${data.template_file.aws_iam_role_policy.rendered}" } resource "aws_iam_instance_profile" "default_ecs" { From e07b55e377f8caf2d7ff58c9b94adbc88fb80ae8 Mon Sep 17 00:00:00 2001 From: Konstantin Chugalinskiy <k.chugalinskiy@fasten.com> Date: Tue, 24 Jan 2017 15:06:16 +0300 Subject: [PATCH 10/12] Changed comma-separated lists with explicitly-typed lists, explicitly typed strings --- asg/main.tf | 13 +++++++++++++ bastion/main.tf | 7 +++++-- dns/main.tf | 2 +- ecs-cluster/main.tf | 5 +++-- main.tf | 15 --------------- service/main.tf | 6 ++++-- vpc/main.tf | 6 +++--- web-service/main.tf | 6 ++++-- 8 files changed, 33 insertions(+), 27 deletions(-) diff --git a/asg/main.tf b/asg/main.tf index abadd8d6..fea78a29 100644 --- a/asg/main.tf +++ b/asg/main.tf @@ -3,18 +3,22 @@ variable "name" { description = "The cluster name, e.g cdn" + type = "string" } variable "environment" { description = "Environment tag, e.g prod" + type = "string" } variable "vpc_id" { description = "VPC ID" + type = "string" } variable "image_id" { description = "AMI Image ID" + type = "string" } variable "subnet_ids" { @@ -24,18 +28,22 @@ variable "subnet_ids" { variable "key_name" { description = "SSH key name to use" + type = "string" } variable "ingress_cidr" { description = "Comma separated list of ingress cidrs" + type = "string" } variable "iam_instance_profile" { description = "Instance profile ARN to use in the launch configuration" + type = "string" } variable "region" { description = "AWS Region" + type = "string" } variable "availability_zones" { @@ -45,6 +53,7 @@ variable "availability_zones" { variable "instance_type" { description = "The instance type to use, e.g t2.small" + type = "string" } variable "instance_ebs_optimized" { @@ -74,10 +83,12 @@ variable "associate_public_ip_address" { variable "ebs_device_name" { default = "/dev/sdh" + type = "string" } variable "ebs_volume_type" { default = "standard" + type = "string" } variable "ebs_volume_size" { @@ -86,6 +97,7 @@ variable "ebs_volume_size" { variable "ebs_snapshot_id" { default = "" + type = "string" } variable "ebs_delete_on_termination" { @@ -95,6 +107,7 @@ variable "ebs_delete_on_termination" { variable "custom_script" { description = "Custom instance bootupt script" default = "" + type = "string" } variable "load_balancers" { diff --git a/bastion/main.tf b/bastion/main.tf index d5fe9a68..f6a10e4b 100644 --- a/bastion/main.tf +++ b/bastion/main.tf @@ -24,14 +24,17 @@ variable "instance_type" { default = "t2.micro" description = "Instance type, see a list at: https://aws.amazon.com/ec2/instance-types/" + type = "string" } variable "region" { description = "AWS Region, e.g us-west-2" + type = "string" } variable "security_groups" { - description = "a comma separated lists of security group IDs" + description = "List of security group IDs" + type = "list" } variable "vpc_id" { @@ -63,7 +66,7 @@ resource "aws_instance" "bastion" { instance_type = "${var.instance_type}" subnet_id = "${var.subnet_id}" key_name = "${var.key_name}" - vpc_security_group_ids = ["${split(",",var.security_groups)}"] + vpc_security_group_ids = ["${var.security_groups}"] monitoring = true user_data = "${file(format("%s/user_data.sh", path.module))}" diff --git a/dns/main.tf b/dns/main.tf index 2e3a7331..7c21a384 100644 --- a/dns/main.tf +++ b/dns/main.tf @@ -40,5 +40,5 @@ output "zone_id" { // A comma separated list of the zone name servers. output "name_servers" { - value = "${join(",",aws_route53_zone.main.name_servers)}" + value = ["${aws_route53_zone.main.name_servers}"] } diff --git a/ecs-cluster/main.tf b/ecs-cluster/main.tf index 4fae8565..e166ecb4 100644 --- a/ecs-cluster/main.tf +++ b/ecs-cluster/main.tf @@ -51,7 +51,8 @@ variable "key_name" { } variable "security_groups" { - description = "Comma separated list of security groups" + description = "List of security groups" + type = "list" } variable "iam_instance_profile" { @@ -135,7 +136,7 @@ resource "aws_security_group" "cluster" { from_port = 0 to_port = 0 protocol = -1 - security_groups = ["${split(",", var.security_groups)}"] + security_groups = ["${var.security_groups}"] } egress { diff --git a/main.tf b/main.tf index ff81ff31..04c18bd8 100644 --- a/main.tf +++ b/main.tf @@ -265,11 +265,6 @@ output "iam_role" { value = "${module.iam_role.arn}" } -// Default ECS role ID. Useful if you want to add a new policy to that role. -output "iam_role_default_ecs_role_id" { - value = "${module.iam_role.default_ecs_role_id}" -} - // S3 bucket ID for ELB logs. output "log_bucket_id" { value = "${module.s3_logs.id}" @@ -309,13 +304,3 @@ output "vpc_id" { output "ecs_cluster_security_group_id" { value = "${module.ecs_cluster.security_group_id}" } - -// Comma separated list of internal route table IDs. -output "internal_route_tables" { - value = "${module.vpc.internal_rtb_id}" -} - -// The external route table ID. -output "external_route_tables" { - value = "${module.vpc.external_rtb_id}" -} diff --git a/service/main.tf b/service/main.tf index 14d530e2..85f3eba4 100644 --- a/service/main.tf +++ b/service/main.tf @@ -36,11 +36,13 @@ variable "version" { } variable "subnet_ids" { - description = "Comma separated list of subnet IDs that will be passed to the ELB module" + description = "List of subnet IDs that will be passed to the ELB module" + type = "list" } variable "security_groups" { - description = "Comma separated list of security group IDs that will be passed to the ELB module" + description = "List of security group IDs that will be passed to the ELB module" + type = "list" } variable "port" { diff --git a/vpc/main.tf b/vpc/main.tf index 95ce7b62..e6b2fc36 100644 --- a/vpc/main.tf +++ b/vpc/main.tf @@ -4,17 +4,17 @@ variable "cidr" { } variable "external_subnets" { - description = "list of subnets" + description = "List of subnets" type = "list" } variable "internal_subnets" { - description = "list of subnets" + description = "List of subnets" type = "list" } variable "availability_zones" { - description = "Comma separated list of availability zones" + description = "List of availability zones" type = "list" } diff --git a/web-service/main.tf b/web-service/main.tf index 95b43db5..2348adb4 100644 --- a/web-service/main.tf +++ b/web-service/main.tf @@ -36,11 +36,13 @@ variable "version" { } variable "subnet_ids" { - description = "Comma separated list of subnet IDs that will be passed to the ELB module" + description = "List of subnet IDs that will be passed to the ELB module" + type = "list" } variable "security_groups" { - description = "Comma separated list of security group IDs that will be passed to the ELB module" + description = "List of security group IDs that will be passed to the ELB module" + type = "list" } variable "port" { From 1f2768e372cdbc8eace78520b6be32f0a6e462d7 Mon Sep 17 00:00:00 2001 From: Konstantin Chugalinskiy <k.chugalinskiy@fasten.com> Date: Tue, 24 Jan 2017 15:11:32 +0300 Subject: [PATCH 11/12] Removed parasite changes --- vpc/main.tf | 5 ----- 1 file changed, 5 deletions(-) diff --git a/vpc/main.tf b/vpc/main.tf index e6b2fc36..17c12d79 100644 --- a/vpc/main.tf +++ b/vpc/main.tf @@ -117,11 +117,6 @@ resource "aws_route_table" "internal" { count = "${length(compact(var.internal_subnets))}" vpc_id = "${aws_vpc.main.id}" - # route { - # cidr_block = "0.0.0.0/0" - # nat_gateway_id = "${element(aws_nat_gateway.main.*.id, count.index)}" - # } - tags { Name = "${var.name}-${format("internal-%03d", count.index+1)}" } From 0cf53bf54bf3d71b9c12c625151b803cb9264ec0 Mon Sep 17 00:00:00 2001 From: Konstantin Chugalinskiy <k.chugalinskiy@fasten.com> Date: Wed, 25 Jan 2017 12:06:40 +0300 Subject: [PATCH 12/12] removed strange changes --- asg/main.tf | 33 --------------------------------- 1 file changed, 33 deletions(-) diff --git a/asg/main.tf b/asg/main.tf index fea78a29..c5ef2472 100644 --- a/asg/main.tf +++ b/asg/main.tf @@ -81,29 +81,6 @@ variable "associate_public_ip_address" { default = false } -variable "ebs_device_name" { - default = "/dev/sdh" - type = "string" -} - -variable "ebs_volume_type" { - default = "standard" - type = "string" -} - -variable "ebs_volume_size" { - default = 1 -} - -variable "ebs_snapshot_id" { - default = "" - type = "string" -} - -variable "ebs_delete_on_termination" { - default = true -} - variable "custom_script" { description = "Custom instance bootupt script" default = "" @@ -184,16 +161,6 @@ resource "aws_launch_configuration" "main" { user_data = "${data.template_file.instance_config.rendered}" associate_public_ip_address = "${var.associate_public_ip_address}" - # spot_price = "0.07" - - # root - ebs_block_device { - device_name = "${var.ebs_device_name}" - volume_type = "${var.ebs_volume_type}" - volume_size = "${var.ebs_volume_size}" - snapshot_id = "${var.ebs_snapshot_id}" - delete_on_termination = "${var.ebs_delete_on_termination}" - } lifecycle { create_before_destroy = true }