diff --git a/infrastructure/modules/container_instances/asg.tf b/infrastructure/modules/container_instances/asg.tf new file mode 100644 index 000000000..6612ee987 --- /dev/null +++ b/infrastructure/modules/container_instances/asg.tf @@ -0,0 +1,32 @@ +resource "aws_autoscaling_group" "this" { + name = var.app_identifier + + launch_template { + id = aws_launch_template.this.id + version = aws_launch_template.this.latest_version + } + + vpc_zone_identifier = var.instance_subnets + max_size = var.max_capacity + min_size = 0 + desired_capacity = 0 + wait_for_capacity_timeout = 0 + protect_from_scale_in = true + + tag { + key = "Name" + value = var.app_identifier + propagate_at_launch = true + } + + tag { + key = "AmazonECSManaged" + value = "" + propagate_at_launch = true + } + + lifecycle { + ignore_changes = [desired_capacity] + create_before_destroy = true + } +} diff --git a/infrastructure/modules/container_instances/ec2.tf b/infrastructure/modules/container_instances/ec2.tf new file mode 100644 index 000000000..e69de29bb diff --git a/infrastructure/modules/container_instances/iam.tf b/infrastructure/modules/container_instances/iam.tf new file mode 100644 index 000000000..b12969284 --- /dev/null +++ b/infrastructure/modules/container_instances/iam.tf @@ -0,0 +1,52 @@ +locals { + create_iam_role = var.iam_instance_profile == null + iam_instance_profile = local.create_iam_role ? aws_iam_instance_profile.this[0] : var.iam_instance_profile +} + +data "aws_iam_role" "this" { + name = local.iam_instance_profile.role +} + +data "aws_iam_policy_document" "assume_role" { + statement { + effect = "Allow" + + principals { + type = "Service" + identifiers = ["ec2.amazonaws.com"] + } + + actions = ["sts:AssumeRole"] + } +} + +resource "aws_iam_role" "this" { + count = local.create_iam_role ? 1 : 0 + name = "${var.app_identifier}_ecs_container_instance_role" + + assume_role_policy = data.aws_iam_policy_document.assume_role.json +} + +resource "aws_iam_instance_profile" "this" { + count = local.create_iam_role ? 1 : 0 + name = "${var.app_identifier}_ecs_container_instance_profile" + role = aws_iam_role.this[0].name +} + +resource "aws_iam_role_policy_attachment" "ecs" { + count = local.create_iam_role ? 1 : 0 + role = aws_iam_role.this[0].id + policy_arn = "arn:aws:iam::aws:policy/service-role/AmazonECSTaskExecutionRolePolicy" +} + +resource "aws_iam_role_policy_attachment" "ecs_ec2_role" { + count = local.create_iam_role ? 1 : 0 + role = aws_iam_role.this[0].id + policy_arn = "arn:aws:iam::aws:policy/service-role/AmazonEC2ContainerServiceforEC2Role" +} + +resource "aws_iam_role_policy_attachment" "ssm" { + count = local.create_iam_role ? 1 : 0 + role = aws_iam_role.this[0].name + policy_arn = "arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore" +} diff --git a/infrastructure/modules/container_instances/launch_template.tf b/infrastructure/modules/container_instances/launch_template.tf new file mode 100644 index 000000000..7418514b2 --- /dev/null +++ b/infrastructure/modules/container_instances/launch_template.tf @@ -0,0 +1,56 @@ +locals { + user_data = concat(var.user_data, [ + { + path = "/opt/setup.sh" + content = templatefile( + "${path.module}/templates/setup.sh", + { + cluster_name = var.cluster_name + } + ) + permissions = "755" + } + ]) +} + +# https://docs.aws.amazon.com/AmazonECS/latest/developerguide/ecs-optimized_AMI.html +# https://docs.aws.amazon.com/AmazonECS/latest/developerguide/retrieve-ecs-optimized_AMI.html +data "aws_ssm_parameter" "amd64_ami" { + name = "/aws/service/ecs/optimized-ami/amazon-linux-2023/recommended" +} + +data "aws_ssm_parameter" "arm64_ami" { + name = "/aws/service/ecs/optimized-ami/amazon-linux-2023/arm64/recommended" +} + +data "aws_ec2_instance_type" "this" { + instance_type = var.instance_type +} + +resource "aws_launch_template" "this" { + name_prefix = var.app_identifier + image_id = jsondecode((var.architecture == "arm64" ? data.aws_ssm_parameter.arm64_ami : data.aws_ssm_parameter.amd64_ami).value).image_id + instance_type = data.aws_ec2_instance_type.this.instance_type + + iam_instance_profile { + name = local.iam_instance_profile.name + } + + network_interfaces { + associate_public_ip_address = var.associate_public_ip_address + security_groups = concat([aws_security_group.this.id], var.security_groups) + } + + user_data = base64encode(join("\n", [ + "#cloud-config", + yamlencode({ + # https://cloudinit.readthedocs.io/en/latest/topics/modules.html + write_files : local.user_data, + runcmd : [for i, v in local.user_data : v.path] + }) + ])) + + lifecycle { + create_before_destroy = true + } +} diff --git a/infrastructure/modules/container_instances/main.tf b/infrastructure/modules/container_instances/main.tf deleted file mode 100644 index 813b32d3c..000000000 --- a/infrastructure/modules/container_instances/main.tf +++ /dev/null @@ -1,164 +0,0 @@ -# https://docs.aws.amazon.com/AmazonECS/latest/developerguide/ecs-optimized_AMI.html -# https://docs.aws.amazon.com/AmazonECS/latest/developerguide/retrieve-ecs-optimized_AMI.html -data "aws_ssm_parameter" "amd64_ami" { - name = "/aws/service/ecs/optimized-ami/amazon-linux-2023/recommended" -} - -data "aws_ssm_parameter" "arm64_ami" { - name = "/aws/service/ecs/optimized-ami/amazon-linux-2023/arm64/recommended" -} - -data "aws_ec2_instance_type" "this" { - instance_type = var.instance_type -} - -locals { - user_data = concat(var.user_data, [ - { - path = "/opt/setup.sh" - content = templatefile( - "${path.module}/templates/setup.sh", - { - cluster_name = var.cluster_name - } - ) - permissions = "755" - } - ]) -} - -# IAM - -resource "aws_iam_role" "this" { - name = "${var.app_identifier}_ecs_container_instance_role" - - assume_role_policy = <