Part of the Terraform for this site This Website
data "aws_ami" "awsecslinux" {
most_recent = true
owners = [ "amazon" ]
filter {
name = "name"
values = ["al2023-ami-ecs-hvm-2023*-x86_64"]
}
filter {
name = "virtualization-type"
values = ["hvm"]
}
filter {
name = "root-device-type"
values = [ "ebs" ]
}
filter {
name = "architecture"
values = [ "x86_64" ]
}
}
resource "aws_iam_instance_profile" "ecs_server_profile" {
name = "ecs_server_profile"
role = aws_iam_role.ecs_role.name
}
data "aws_iam_policy_document" "ecs_assume_role" {
statement {
effect = "Allow"
principals {
type = "Service"
identifiers = ["ec2.amazonaws.com"]
}
actions = ["sts:AssumeRole"]
}
}
resource "aws_iam_role" "ecs_role" {
name = "ecs_server_role"
path = "/"
assume_role_policy = data.aws_iam_policy_document.ecs_assume_role.json
}
resource "aws_iam_role_policy_attachment" "ecs_policy_attachment" {
policy_arn = "arn:aws:iam::aws:policy/service-role/AmazonEC2ContainerServiceforEC2Role"
role = aws_iam_role.ecs_role.name
}
resource "aws_launch_template" "ecs_server_template" {
name_prefix = "server_template-ecs"
image_id = data.aws_ami.awsecslinux.id
instance_type = "t3.small"
key_name = "anaconda"
user_data = base64encode(<<-EOF
#!/bin/bash
echo ECS_CLUSTER=${aws_ecs_cluster.server_cluster.name} >> /etc/ecs/ecs.config
EOF
)
iam_instance_profile {
name = aws_iam_instance_profile.ecs_server_profile.name
}
network_interfaces {
associate_public_ip_address = true
security_groups = [ aws_security_group.ecs_instance_sg.id ]
}
monitoring {
enabled = true
}
metadata_options {
http_endpoint = "enabled"
http_tokens = "required"
http_put_response_hop_limit = 1
}
block_device_mappings {
device_name = "/dev/xvda"
ebs {
volume_size = 30
}
}
tag_specifications {
resource_type = "instance"
tags = {
Name = "AWS Linux Server"
Server = "Main"
}
}
credit_specification {
cpu_credits = "standard"
}
lifecycle {
create_before_destroy = true
}
depends_on = [aws_ecs_cluster.server_cluster]
}
resource "aws_autoscaling_group" "ecs_asg" {
name = "ecs_asg"
vpc_zone_identifier = [for ps in aws_subnet.private_subnets : ps.id]
min_size = 1
max_size = 20
health_check_type = "EC2"
health_check_grace_period = 300
default_cooldown = 3600
capacity_rebalance = true
max_instance_lifetime = 518400 # 6 days
lifecycle {
create_before_destroy = true
ignore_changes = [ target_group_arns, desired_capacity, desired_capacity_type ]
}
mixed_instances_policy {
launch_template {
launch_template_specification {
launch_template_id = aws_launch_template.ecs_server_template.id
version = "$Latest"
}
override {
instance_requirements {
memory_mib {
min = 1500
# max = 8500
}
vcpu_count {
min = 2
max = 4
}
burstable_performance = "included"
cpu_manufacturers = ["intel"]
instance_generations = ["current"]
local_storage = "excluded"
accelerator_count {
max = 0
}
}
}
}
instances_distribution {
on_demand_allocation_strategy = "lowest-price"
on_demand_base_capacity = 0
on_demand_percentage_above_base_capacity = 0
spot_allocation_strategy = "price-capacity-optimized"
}
}
tag {
key = "AmazonECSManaged"
value = true
propagate_at_launch = true
}
}
resource "aws_ecs_cluster_capacity_providers" "asg_instances_capacity" {
cluster_name = aws_ecs_cluster.server_cluster.name
capacity_providers = [aws_ecs_capacity_provider.asg_capacity.name]
default_capacity_provider_strategy {
capacity_provider = aws_ecs_capacity_provider.asg_capacity.name
weight = 100
base = 1
}
}
resource "aws_ecs_capacity_provider" "asg_capacity" {
name = "asg_capacity"
auto_scaling_group_provider {
auto_scaling_group_arn = aws_autoscaling_group.ecs_asg.arn
managed_termination_protection = "DISABLED"
managed_scaling {
status = "ENABLED"
instance_warmup_period = 3600
maximum_scaling_step_size = 2
minimum_scaling_step_size = 1
target_capacity = 100
}
}
}
resource "aws_appautoscaling_target" "ecs_service" {
for_each = var.backend_tasks
max_capacity = 100
min_capacity = 1
resource_id = "service/${aws_ecs_cluster.server_cluster.name}/${aws_ecs_service.server_services[each.key].name}"
scalable_dimension = "ecs:service:DesiredCount"
service_namespace = "ecs"
}
resource "aws_appautoscaling_policy" "ecs_service_cpu" {
for_each = var.backend_tasks
name = "${each.key}_cpu_scaling_policy"
resource_id = aws_appautoscaling_target.ecs_service[each.key].resource_id
scalable_dimension = aws_appautoscaling_target.ecs_service[each.key].scalable_dimension
service_namespace = aws_appautoscaling_target.ecs_service[each.key].service_namespace
policy_type = "TargetTrackingScaling"
target_tracking_scaling_policy_configuration {
predefined_metric_specification {
predefined_metric_type = "ECSServiceAverageCPUUtilization"
}
target_value = 75.0
scale_in_cooldown = 300
scale_out_cooldown = 60
}
}
resource "aws_appautoscaling_policy" "ecs_service_memory" {
for_each = var.backend_tasks
name = "${each.key}_memory_scaling_policy"
resource_id = aws_appautoscaling_target.ecs_service[each.key].resource_id
scalable_dimension = aws_appautoscaling_target.ecs_service[each.key].scalable_dimension
service_namespace = aws_appautoscaling_target.ecs_service[each.key].service_namespace
policy_type = "TargetTrackingScaling"
target_tracking_scaling_policy_configuration {
predefined_metric_specification {
predefined_metric_type = "ECSServiceAverageMemoryUtilization"
}
target_value = 75.0
scale_in_cooldown = 300
scale_out_cooldown = 60
}
}