Skip to content

Instantly share code, notes, and snippets.

@asheliahut
Last active May 2, 2020 06:48
Show Gist options
  • Save asheliahut/fb6baefdb3f650a284e99679570933a9 to your computer and use it in GitHub Desktop.
Save asheliahut/fb6baefdb3f650a284e99679570933a9 to your computer and use it in GitHub Desktop.
ECS Cluster does not swap Capacity Providers on ASG swap.
resource "aws_autoscaling_group" "cluster_asg" {
# Apply the name based on an existing pattern
name = "${local.cluster_name}-asg-lt${aws_launch_template.cluster_lt.latest_version}"
# Does forceful delete on termination
force_delete = var.delete_on_termination
# https://www.terraform.io/docs/providers/aws/r/autoscaling_group.html#waiting-for-capacity
wait_for_capacity_timeout = var.asg_wait_timeout
# Required for Capacity Providers
# https://www.terraform.io/docs/providers/aws/r/autoscaling_group.html#protect_from_scale_in
protect_from_scale_in = true
# Standard configuration
vpc_zone_identifier = var.subnets
desired_capacity = var.cluster_desired_size
min_size = var.cluster_min_size
max_size = var.cluster_max_size
# https://www.terraform.io/docs/providers/aws/r/autoscaling_group.html#termination_policies
termination_policies = [
"OldestLaunchTemplate",
"ClosestToNextInstanceHour",
"Default"
]
# https://www.terraform.io/docs/configuration/resources.html#lifecycle-lifecycle-customizations
lifecycle {
create_before_destroy = true
ignore_changes = [
tags,
desired_capacity
]
}
# Apply the ASG flavor of the tagging output
# https://www.terraform.io/docs/configuration/expressions.html#dynamic-blocks
# https://github.com/hashicorp/terraform-guides/tree/master/infrastructure-as-code/terraform-0.12-examples/advanced-dynamic-blocks
dynamic "tag" {
for_each = var.tags
content {
key = tag.key
value = tag.value
propagate_at_launch = true
}
}
# https://www.terraform.io/docs/providers/aws/r/autoscaling_group.html#launch_template-1
launch_template {
id = aws_launch_template.cluster_lt.id
version = "$Latest"
}
# https://www.terraform.io/docs/configuration/resources.html#operation-timeouts
timeouts {
delete = "1h"
}
}
resource "aws_ecs_capacity_provider" "cluster" {
name = "${local.cluster_name}-cp-${substr(sha256(aws_autoscaling_group.cluster_asg.arn), 0, 20)}"
# https://www.terraform.io/docs/providers/aws/r/ecs_capacity_provider.html#auto_scaling_group_provider-1
auto_scaling_group_provider {
auto_scaling_group_arn = aws_autoscaling_group.cluster_asg.arn
# Container-aware termination of instances in the autoscaling group when scale-in happens.
managed_termination_protection = "ENABLED"
# https://www.terraform.io/docs/providers/aws/r/ecs_capacity_provider.html#managed_scaling-1
managed_scaling {
maximum_scaling_step_size = var.max_step_size
minimum_scaling_step_size = var.min_step_size
target_capacity = var.target_capacity
status = "ENABLED"
}
}
}
resource "aws_ecs_cluster" "ecs_cluster" {
# Explicit dependency so that a `terraform destroy` deletes things in the correct order.
depends_on = [
aws_autoscaling_group.cluster_asg
]
# Name should follow a specific pattern.
# Defined in variables.tf
name = local.cluster_name
# Apply tags to the cluster
tags = var.tags
# https://www.terraform.io/docs/providers/aws/r/ecs_cluster.html#capacity_providers
capacity_providers = [
aws_ecs_capacity_provider.cluster.name
]
# https://www.terraform.io/docs/providers/aws/r/ecs_cluster.html#default_capacity_provider_strategy-1
default_capacity_provider_strategy {
capacity_provider = aws_ecs_capacity_provider.cluster.name
weight = 1
base = 0
}
# Whether or not ECS container insights should be enabled.
# https://www.terraform.io/docs/providers/aws/r/ecs_cluster.html#setting-1
setting {
name = "containerInsights"
value = var.container_insights ? "enabled" : "disabled"
}
}
resource "aws_launch_template" "cluster_lt" {
# This naming pattern + an IAM policy enables the EC2 to rename itself at
# launch according to Rackspace guidelines.
name_prefix = "${local.cluster_name}-"
description = "From aws-ecs-asg-cluster module. The launch template for spinning up new instances in the ASG."
# This is expected to be the value of an MHE Base AMI.
image_id = var.ami_id
# Standard configuration.
instance_type = var.instance_type
key_name = var.keypair
# EC2 Instance tags
# https://www.terraform.io/docs/providers/aws/r/launch_template.html#tag-specifications
# https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_LaunchTemplateTagSpecificationRequest.html
tag_specifications {
resource_type = "instance"
# Merge a "Name" tag into the list of tags passed-in.
tags = merge(
var.tags,
{
"Name" = "${local.cluster_name}-XX-XX-"
},
)
}
# EBS Volume tags
# https://www.terraform.io/docs/providers/aws/r/launch_template.html#tag-specifications
# https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_LaunchTemplateTagSpecificationRequest.html
tag_specifications {
resource_type = "volume"
tags = var.tags
}
# Set this as you need it.
user_data = base64encode(data.template_file.internal_userdata.rendered)
# For performance reasons, it is preferable to enable ECS-optimization (for the instance types which support it).
ebs_optimized = true
# Root volume
# https://www.terraform.io/docs/providers/aws/r/launch_template.html#block-devices
block_device_mappings {
device_name = "/dev/xvda"
ebs {
volume_size = var.root_volume_size
# Encrypt EBS volumes by default.
encrypted = var.ebs_encrypted
# EBS volumes should clean-up by default.
delete_on_termination = var.delete_on_termination
}
}
# Docker devicemapper volume
# https://www.terraform.io/docs/providers/aws/r/launch_template.html#block-devices
block_device_mappings {
device_name = "/dev/xvdcz"
ebs {
volume_size = var.device_mapper_volume_size
# Encrypt EBS volumes by default.
encrypted = var.ebs_encrypted
# EBS volumes should clean-up by default.
delete_on_termination = var.delete_on_termination
}
}
# Make sure the instance profile includes the policy described here:
iam_instance_profile {
name = aws_iam_instance_profile.instance_profile.name
}
# https://www.terraform.io/docs/providers/aws/r/launch_template.html#network-interfaces
network_interfaces {
associate_public_ip_address = false
delete_on_termination = var.delete_on_termination
security_groups = var.security_groups
}
# Enhanced monitoring (definitely yes for Prod)
# https://www.terraform.io/docs/providers/aws/r/launch_template.html#monitoring-1
monitoring {
enabled = var.enhanced_monitoring
}
# https://www.terraform.io/docs/configuration/resources.html#lifecycle-lifecycle-customizations
lifecycle {
create_before_destroy = true
ignore_changes = [
tags,
tag_specifications,
]
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment