Skip to content

Instantly share code, notes, and snippets.

@alexjeen
Last active July 18, 2023 21:03
Show Gist options
  • Save alexjeen/984dd2b092ffa49e1c3bf4f6505d0ebe to your computer and use it in GitHub Desktop.
Save alexjeen/984dd2b092ffa49e1c3bf4f6505d0ebe to your computer and use it in GitHub Desktop.
Autoscaling ECS cluster (Terraform)
variable "prefix" {
type = string
}
variable "vpc_id" {
type = string
}
variable "private_subnets" {
type = list(string)
default = []
}
locals {
sizes = ["xxl", "xxxl"]
sizeMap = {
xxl = "m6a.4xlarge"
xxxl = "m6a.8xlarge"
}
}
// execution role for the ec2 instances
resource "aws_iam_role" "execution_role" {
name = "${var.prefix}-ecs-ec2-role"
assume_role_policy = jsonencode({
Version = "2012-10-17"
Statement = [
{
Action = "sts:AssumeRole"
Effect = "Allow"
Sid = ""
Principal = {
Service = "ec2.amazonaws.com"
}
}
]
})
}
// attach the general permissions to for instance
resource "aws_iam_role_policy_attachment" "ecs_task_permissions" {
role = aws_iam_role.execution_role.name
policy_arn = "arn:aws:iam::aws:policy/service-role/AmazonEC2ContainerServiceforEC2Role"
}
// ecs optimized ami
data "aws_ssm_parameter" "ami" {
name = "/aws/service/ecs/optimized-ami/amazon-linux-2/recommended/image_id"
}
// create the security group
module "security_group" {
source = "terraform-aws-modules/security-group/aws"
name = "${var.prefix}-ec2-ecs-security-group"
vpc_id = var.vpc_id
ingress_with_source_security_group_id = []
egress_rules = ["all-all"]
}
resource "aws_iam_instance_profile" "instance_profile" {
name = "${var.prefix}-instanceprofile"
role = aws_iam_role.execution_role.name
}
resource "aws_launch_template" "launchtemplate" {
for_each = toset(local.sizes)
name = "${var.prefix}-template-${each.value}"
block_device_mappings {
device_name = "/dev/sda1"
ebs {
volume_size = 60
encrypted = true
delete_on_termination = true
}
}
update_default_version = true
iam_instance_profile {
arn = aws_iam_instance_profile.instance_profile.arn
}
image_id = data.aws_ssm_parameter.ami.value
instance_type = local.sizeMap[each.value]
monitoring {
enabled = true
}
vpc_security_group_ids = [
module.security_group.security_group_id
]
user_data = base64encode(
<<EOF
#!/bin/bash
echo "ECS_CLUSTER=${var.prefix}-cluster" >> /etc/ecs/ecs.config
EOF
)
}
resource "aws_autoscaling_group" "asg" {
lifecycle {
ignore_changes = [
tags
]
}
for_each = toset(local.sizes)
name = "${var.prefix}-asg-${each.value}"
desired_capacity = 0
max_size = 1
min_size = 0
protect_from_scale_in = true
vpc_zone_identifier = var.private_subnets
launch_template {
id = aws_launch_template.launchtemplate[each.value].id
version = "$Latest"
}
}
resource "aws_ecs_capacity_provider" "cp" {
for_each = toset(local.sizes)
name = upper(each.value)
auto_scaling_group_provider {
auto_scaling_group_arn = aws_autoscaling_group.asg[each.value].arn
managed_termination_protection = "ENABLED"
managed_scaling {
status = "ENABLED"
target_capacity = 100
}
}
}
// the cluster to run stuff in
resource "aws_ecs_cluster" "ecs" {
depends_on = [
aws_ecs_capacity_provider.cp
]
name = "${var.prefix}-cluster"
capacity_providers = ["FARGATE", "FARGATE_SPOT", "XXL", "XXXL"]
default_capacity_provider_strategy {
capacity_provider = "FARGATE"
}
setting {
name = "containerInsights"
value = "enabled"
}
}
ecs.runTask({
// further parameters for runtask
launchType: null,
capacityProviderStrategy = [
{
// to run the task on the XXL cluster
"capacityProvider": "XXL"
}
]
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment