Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow Spot Instances + Terraform 0.12 Upgrade #52

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
*.iml
.idea/
.terraform
43 changes: 22 additions & 21 deletions consul_agent.tf
Original file line number Diff line number Diff line change
@@ -1,26 +1,26 @@
data "template_file" "consul" {
template = "${file("${path.module}/templates/consul.json")}"

vars {
env = "${aws_ecs_cluster.cluster.name}"
image = "${var.consul_image}"
registrator_image = "${var.registrator_image}"
consul_memory_reservation = "${var.consul_memory_reservation}"
registrator_memory_reservation = "${var.registrator_memory_reservation}"
template = file("${path.module}/templates/consul.json")

vars = {
env = aws_ecs_cluster.cluster.name
image = var.consul_image
registrator_image = var.registrator_image
consul_memory_reservation = var.consul_memory_reservation
registrator_memory_reservation = var.registrator_memory_reservation
awslogs_group = "consul-agent-${aws_ecs_cluster.cluster.name}"
awslogs_stream_prefix = "consul-agent-${aws_ecs_cluster.cluster.name}"
awslogs_region = "${var.region}"
awslogs_region = var.region
}
}

# End Data block

resource "aws_ecs_task_definition" "consul" {
count = "${var.enable_agents ? 1 : 0}"
count = var.enable_agents ? 1 : 0
family = "consul-agent-${aws_ecs_cluster.cluster.name}"
container_definitions = "${data.template_file.consul.rendered}"
container_definitions = data.template_file.consul.rendered
network_mode = "host"
task_role_arn = "${aws_iam_role.consul_task.arn}"
task_role_arn = aws_iam_role.consul_task[0].arn

volume {
name = "consul-config-dir"
Expand All @@ -34,24 +34,25 @@ resource "aws_ecs_task_definition" "consul" {
}

resource "aws_cloudwatch_log_group" "consul" {
count = "${var.enable_agents ? 1 : 0}"
name = "${aws_ecs_task_definition.consul.family}"
count = var.enable_agents ? 1 : 0
name = aws_ecs_task_definition.consul[0].family

tags {
VPC = "${data.aws_vpc.vpc.tags["Name"]}"
Application = "${aws_ecs_task_definition.consul.family}"
tags = {
VPC = data.aws_vpc.vpc.tags["Name"]
Application = aws_ecs_task_definition.consul[0].family
}
}

resource "aws_ecs_service" "consul" {
count = "${var.enable_agents ? 1 : 0}"
count = var.enable_agents ? 1 : 0
name = "consul-agent-${aws_ecs_cluster.cluster.name}"
cluster = "${aws_ecs_cluster.cluster.id}"
task_definition = "${aws_ecs_task_definition.consul.arn}"
desired_count = "${var.servers}"
cluster = aws_ecs_cluster.cluster.id
task_definition = aws_ecs_task_definition.consul[0].arn
desired_count = var.servers
deployment_minimum_healthy_percent = "60"

placement_constraints {
type = "distinctInstance"
}
}

5 changes: 3 additions & 2 deletions graceful_shutdown.tf
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,9 @@

resource "aws_autoscaling_lifecycle_hook" "graceful_shutdown_asg_hook" {
name = "graceful_shutdown_asg"
autoscaling_group_name = "${aws_autoscaling_group.ecs.name}"
autoscaling_group_name = aws_autoscaling_group.ecs.name
default_result = "CONTINUE"
heartbeat_timeout = "${var.heartbeat_timeout}"
heartbeat_timeout = var.heartbeat_timeout
lifecycle_transition = "autoscaling:EC2_INSTANCE_TERMINATING"
}

113 changes: 73 additions & 40 deletions iam.tf
Original file line number Diff line number Diff line change
@@ -1,12 +1,20 @@
resource "aws_iam_instance_profile" "ecs_profile" {
name_prefix = "${replace(format("%.102s", replace("tf-ECSProfile-${var.name}-", "_", "-")), "/\\s/", "-")}"
role = "${aws_iam_role.ecs_role.name}"
path = "${var.iam_path}"
name_prefix = replace(
format("%.102s", replace("tf-ECSProfile-${var.name}-", "_", "-")),
"/\\s/",
"-",
)
role = aws_iam_role.ecs_role.name
path = var.iam_path
}

resource "aws_iam_role" "ecs_role" {
name_prefix = "${replace(format("%.32s", replace("tf-ECSInRole-${var.name}-", "_", "-")), "/\\s/", "-")}"
path = "${var.iam_path}"
name_prefix = replace(
format("%.32s", replace("tf-ECSInRole-${var.name}-", "_", "-")),
"/\\s/",
"-",
)
path = var.iam_path

assume_role_policy = <<EOF
{
Expand All @@ -24,6 +32,7 @@ resource "aws_iam_role" "ecs_role" {
]
}
EOF

}

# It may be useful to add the following for troubleshooting the InstanceStatus
Expand All @@ -32,10 +41,14 @@ EOF
# "autoscaling:Describe*",

resource "aws_iam_policy" "ecs_policy" {
name_prefix = "${replace(format("%.102s", replace("tf-ECSInPol-${var.name}-", "_", "-")), "/\\s/", "-")}"
name_prefix = replace(
format("%.102s", replace("tf-ECSInPol-${var.name}-", "_", "-")),
"/\\s/",
"-",
)
description = "A terraform created policy for ECS"
path = "${var.iam_path}"
count = "${length(var.custom_iam_policy) > 0 ? 0 : 1}"
path = var.iam_path
count = length(var.custom_iam_policy) > 0 ? 0 : 1

policy = <<EOF
{
Expand Down Expand Up @@ -63,57 +76,77 @@ resource "aws_iam_policy" "ecs_policy" {
]
}
EOF

}

resource "aws_iam_policy" "custom_ecs_policy" {
name_prefix = "${replace(format("%.102s", replace("tf-ECSInPol-${var.name}-", "_", "-")), "/\\s/", "-")}"
description = "A terraform created policy for ECS"
path = "${var.iam_path}"
count = "${length(var.custom_iam_policy) > 0 ? 1 : 0}"

policy = "${var.custom_iam_policy}"
name_prefix = replace(
format("%.102s", replace("tf-ECSInPol-${var.name}-", "_", "-")),
"/\\s/",
"-",
)
description = "A terraform created policy for ECS"
path = var.iam_path
count = length(var.custom_iam_policy) > 0 ? 1 : 0

policy = var.custom_iam_policy
}

resource "aws_iam_policy_attachment" "attach_ecs" {
name = "ecs-attachment"
roles = ["${aws_iam_role.ecs_role.name}"]
policy_arn = "${element(concat(aws_iam_policy.ecs_policy.*.arn, aws_iam_policy.custom_ecs_policy.*.arn), 0)}"
name = "ecs-attachment"
roles = [aws_iam_role.ecs_role.name]
policy_arn = element(
concat(
aws_iam_policy.ecs_policy.*.arn,
aws_iam_policy.custom_ecs_policy.*.arn,
),
0,
)
}

# IAM Resources for Consul and Registrator Agents

data "aws_iam_policy_document" "consul_task_policy" {
statement {
actions = [
"ec2:Describe*",
"autoscaling:Describe*",
]

resources = ["*"]
}
statement {
actions = [
"ec2:Describe*",
"autoscaling:Describe*",
]

resources = ["*"]
}
}

data "aws_iam_policy_document" "assume_role_consul_task" {
statement {
actions = ["sts:AssumeRole"]
statement {
actions = ["sts:AssumeRole"]

principals {
type = "Service"
identifiers = ["ecs-tasks.amazonaws.com"]
}
}
principals {
type = "Service"
identifiers = ["ecs-tasks.amazonaws.com"]
}
}
}

resource "aws_iam_role" "consul_task" {
count = "${var.enable_agents ? 1 : 0}"
name_prefix = "${replace(format("%.32s", replace("tf-agentTaskRole-${var.name}-", "_", "-")), "/\\s/", "-")}"
path = "${var.iam_path}"
assume_role_policy = "${data.aws_iam_policy_document.assume_role_consul_task.json}"
count = var.enable_agents ? 1 : 0
name_prefix = replace(
format("%.32s", replace("tf-agentTaskRole-${var.name}-", "_", "-")),
"/\\s/",
"-",
)
path = var.iam_path
assume_role_policy = data.aws_iam_policy_document.assume_role_consul_task.json
}

resource "aws_iam_role_policy" "consul_ecs_task" {
count = "${var.enable_agents ? 1 : 0}"
name_prefix = "${replace(format("%.102s", replace("tf-agentTaskPol-${var.name}-", "_", "-")), "/\\s/", "-")}"
role = "${aws_iam_role.consul_task.id}"
policy = "${data.aws_iam_policy_document.consul_task_policy.json}"
count = var.enable_agents ? 1 : 0
name_prefix = replace(
format("%.102s", replace("tf-agentTaskPol-${var.name}-", "_", "-")),
"/\\s/",
"-",
)
role = aws_iam_role.consul_task[0].id
policy = data.aws_iam_policy_document.consul_task_policy.json
}

87 changes: 48 additions & 39 deletions main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -9,39 +9,47 @@ data "aws_ami" "ecs_ami" {
}

data "template_file" "user_data" {
template = "${file("${path.module}/templates/user_data.tpl")}"

vars {
additional_user_data_script = "${var.additional_user_data_script}"
cluster_name = "${aws_ecs_cluster.cluster.name}"
docker_storage_size = "${var.docker_storage_size}"
dockerhub_token = "${var.dockerhub_token}"
dockerhub_email = "${var.dockerhub_email}"
template = file("${path.module}/templates/user_data.tpl")

vars = {
additional_user_data_script = var.additional_user_data_script
cluster_name = aws_ecs_cluster.cluster.name
docker_storage_size = var.docker_storage_size
dockerhub_token = var.dockerhub_token
dockerhub_email = var.dockerhub_email
}
}

data "aws_vpc" "vpc" {
id = "${var.vpc_id}"
id = var.vpc_id
}

resource "aws_launch_configuration" "ecs" {
name_prefix = "${coalesce(var.name_prefix, "ecs-${var.name}-")}"
image_id = "${var.ami == "" ? format("%s", data.aws_ami.ecs_ami.id) : var.ami}" # Workaround until 0.9.6
instance_type = "${var.instance_type}"
key_name = "${var.key_name}"
iam_instance_profile = "${aws_iam_instance_profile.ecs_profile.name}"
security_groups = ["${concat(list(aws_security_group.ecs.id), var.security_group_ids)}"]
associate_public_ip_address = "${var.associate_public_ip_address}"
spot_price = "${var.spot_bid_price}"
name_prefix = coalesce(var.name_prefix, "ecs-${var.name}-")
image_id = var.ami == "" ? format("%s", data.aws_ami.ecs_ami.id) : var.ami # Workaround until 0.9.6
instance_type = var.instance_type
key_name = var.key_name
iam_instance_profile = aws_iam_instance_profile.ecs_profile.name
# TF-UPGRADE-TODO: In Terraform v0.10 and earlier, it was sometimes necessary to
# force an interpolation expression to be interpreted as a list by wrapping it
# in an extra set of list brackets. That form was supported for compatibilty in
# v0.11, but is no longer supported in Terraform v0.12.
#
# If the expression in the following list itself returns a list, remove the
# brackets to avoid interpretation as a list of lists. If the expression
# returns a single list item then leave it as-is and remove this TODO comment.
security_groups = concat([aws_security_group.ecs.id], var.security_group_ids)
associate_public_ip_address = var.associate_public_ip_address
spot_price = var.spot_bid_price

ebs_block_device {
device_name = "${var.ebs_block_device}"
volume_size = "${var.docker_storage_size}"
device_name = var.ebs_block_device
volume_size = var.docker_storage_size
volume_type = "gp2"
delete_on_termination = true
}

user_data = "${coalesce(var.user_data, data.template_file.user_data.rendered)}"
user_data = coalesce(var.user_data, data.template_file.user_data.rendered)

lifecycle {
create_before_destroy = true
Expand All @@ -50,22 +58,22 @@ resource "aws_launch_configuration" "ecs" {

resource "aws_autoscaling_group" "ecs" {
name_prefix = "asg-${aws_launch_configuration.ecs.name}-"
vpc_zone_identifier = ["${var.subnet_id}"]
launch_configuration = "${aws_launch_configuration.ecs.name}"
min_size = "${var.min_servers}"
max_size = "${var.max_servers}"
desired_capacity = "${var.servers}"
vpc_zone_identifier = var.subnet_id
launch_configuration = aws_launch_configuration.ecs.name
min_size = var.min_servers
max_size = var.max_servers
desired_capacity = var.servers
termination_policies = ["OldestLaunchConfiguration", "ClosestToNextInstanceHour", "Default"]
load_balancers = ["${var.load_balancers}"]
enabled_metrics = ["${var.enabled_metrics}"]
load_balancers = var.load_balancers
enabled_metrics = var.enabled_metrics

tags = [{
key = "Name"
value = "${var.name} ${var.tagName}"
propagate_at_launch = true
}]

tags = ["${var.extra_tags}"]
tags = list(
{
key = "Name"
value = "${var.name} ${var.tagName}"
propagate_at_launch = true
}
, var.extra_tags)

lifecycle {
create_before_destroy = true
Expand All @@ -79,20 +87,20 @@ resource "aws_autoscaling_group" "ecs" {
resource "aws_security_group" "ecs" {
name = "ecs-sg-${var.name}"
description = "Container Instance Allowed Ports"
vpc_id = "${data.aws_vpc.vpc.id}"
vpc_id = data.aws_vpc.vpc.id

ingress {
from_port = 0
to_port = 65535
protocol = "tcp"
cidr_blocks = "${var.allowed_cidr_blocks}"
cidr_blocks = var.allowed_cidr_blocks
}

ingress {
from_port = 0
to_port = 65535
protocol = "udp"
cidr_blocks = "${var.allowed_cidr_blocks}"
cidr_blocks = var.allowed_cidr_blocks
}

egress {
Expand All @@ -102,12 +110,13 @@ resource "aws_security_group" "ecs" {
cidr_blocks = ["0.0.0.0/0"]
}

tags {
tags = {
Name = "ecs-sg-${var.name}"
}
}

# Make this a var that an get passed in?
resource "aws_ecs_cluster" "cluster" {
name = "${var.name}"
name = var.name
}

Loading