provider "aws" { region = local.region } data "aws_availability_zones" "available" {} locals { region = "us-east-1" name = "ex-${basename(path.cwd)}" vpc_cidr = "10.0.0.0/16" azs = slice(data.aws_availability_zones.available.names, 0, 3) container_name = "ecs-sample" container_port = 80 tags = { Name = local.name Example = local.name Repository = "https://github.com/terraform-aws-modules/terraform-aws-ecs" } network_acls = { public_inbound = [ { rule_number = 100 rule_action = "allow" from_port = 80 to_port = 80 protocol = "tcp" cidr_block = "10.0.0.0/16" }, { rule_number = 110 rule_action = "allow" from_port = 443 to_port = 443 protocol = "tcp" cidr_block = "10.0.0.0/16" }, { rule_number = 120 rule_action = "allow" from_port = 22 to_port = 22 protocol = "tcp" cidr_block = "10.0.0.0/16" } ] public_outbound = [ { rule_number = 100 rule_action = "allow" from_port = 80 to_port = 80 protocol = "tcp" cidr_block = "10.0.0.0/16" }, { rule_number = 110 rule_action = "allow" from_port = 443 to_port = 443 protocol = "tcp" cidr_block = "10.0.0.0/16" } ] } } ################################################################################ # Cluster ################################################################################ module "ecs_cluster" { source = "terraform-aws-modules/ecs/aws" version = "5.2.2" cluster_name = local.name # Capacity provider - autoscaling groups default_capacity_provider_use_fargate = false create_task_exec_iam_role = true task_exec_iam_role_name = "ecs_monitor_task_exec_role" task_exec_iam_role_policies = { "module.ecs_cluster.module.cluster.aws_iam_policy.task_exec[0]" : "arn:aws:iam::aws:policy/AmazonPrometheusRemoteWriteAccess" } autoscaling_capacity_providers = { # On-demand instances ex-1 = { auto_scaling_group_arn = module.autoscaling["ex-1"].autoscaling_group_arn managed_termination_protection = "ENABLED" managed_scaling = { maximum_scaling_step_size = 5 minimum_scaling_step_size = 1 status = "ENABLED" target_capacity = 60 } default_capacity_provider_strategy = { weight = 60 base = 20 } } } tags = local.tags } module "autoscaling" { source = "terraform-aws-modules/autoscaling/aws" version = "~> 6.5" for_each = { # On-demand instances ex-1 = { instance_type = "t3.large" use_mixed_instances_policy = false mixed_instances_policy = {} user_data = <<-EOT #!/bin/bash cat <<'EOF' >> /etc/ecs/ecs.config ECS_CLUSTER=${local.name} ECS_LOGLEVEL=debug ECS_CONTAINER_INSTANCE_TAGS=${jsonencode(local.tags)} ECS_ENABLE_TASK_IAM_ROLE=true EOF EOT } } name = "${local.name}-${each.key}" image_id = jsondecode(data.aws_ssm_parameter.ecs_optimized_ami.value)["image_id"] instance_type = each.value.instance_type security_groups = [module.autoscaling_sg.security_group_id] user_data = base64encode(each.value.user_data) ignore_desired_capacity_changes = true create_iam_instance_profile = true iam_role_name = local.name iam_role_description = "ECS role for ${local.name}" iam_role_policies = { AmazonEC2ContainerServiceforEC2Role = "arn:aws:iam::aws:policy/service-role/AmazonEC2ContainerServiceforEC2Role" AmazonSSMManagedInstanceCore = "arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore" } vpc_zone_identifier = module.vpc.private_subnets health_check_type = "EC2" min_size = 1 max_size = 5 desired_capacity = 2 # https://github.com/hashicorp/terraform-provider-aws/issues/12582 autoscaling_group_tags = { AmazonECSManaged = true } # Required for managed_termination_protection = "ENABLED" protect_from_scale_in = true # Spot instances use_mixed_instances_policy = each.value.use_mixed_instances_policy mixed_instances_policy = each.value.mixed_instances_policy metadata_options = { http_tokens = "required" } tags = local.tags } module "autoscaling_sg" { source = "terraform-aws-modules/security-group/aws" version = "~> 5.0" name = local.name description = "Autoscaling group security group" vpc_id = module.vpc.vpc_id computed_ingress_with_source_security_group_id = [ { rule = "http-80-tcp" source_security_group_id = module.alb_sg.security_group_id } ] number_of_computed_ingress_with_source_security_group_id = 1 tags = local.tags } module "vpc" { source = "terraform-aws-modules/vpc/aws" version = "~> 5.0" name = local.name cidr = local.vpc_cidr azs = local.azs private_subnets = [for k, v in local.azs : cidrsubnet(local.vpc_cidr, 4, k)] public_subnets = [for k, v in local.azs : cidrsubnet(local.vpc_cidr, 8, k + 48)] public_dedicated_network_acl = true public_inbound_acl_rules = local.network_acls["public_inbound"] public_outbound_acl_rules = local.network_acls["public_outbound"] private_dedicated_network_acl = true private_inbound_acl_rules = local.network_acls["public_inbound"] private_outbound_acl_rules = local.network_acls["public_outbound"] manage_default_network_acl = true enable_nat_gateway = true single_nat_gateway = true tags = local.tags } data "aws_ssm_parameter" "ecs_optimized_ami" { name = "/aws/service/ecs/optimized-ami/amazon-linux-2/recommended" } module "alb_sg" { source = "terraform-aws-modules/security-group/aws" version = "~> 5.0" name = "${local.name}-service" description = "Service security group" vpc_id = module.vpc.vpc_id ingress_rules = ["http-80-tcp"] ingress_cidr_blocks = ["10.0.0.0/16"] egress_cidr_blocks = module.vpc.private_subnets_cidr_blocks tags = local.tags } module "ecs_monitoring" { source = "../../modules/ecs-monitoring" aws_ecs_cluster_name = module.ecs_cluster.cluster_name task_role_arn = module.ecs_cluster.task_exec_iam_role_arn execution_role_arn = module.ecs_cluster.task_exec_iam_role_arn depends_on = [ module.ecs_cluster ] }