Part of the Terraform for this site This Website
resource "aws_ecs_cluster" "server_cluster" {
name = "website_server_cluster"
setting {
name = "containerInsights"
value = "disabled"
}
}
resource "aws_cloudwatch_log_group" "cluster_logs" {
for_each = var.backend_tasks
name = "/ecs/webserver/${each.key}"
retention_in_days = 30
}
resource "aws_iam_role" "ecs_task_execution_role" {
name = "website_server_task_execution_role"
assume_role_policy = jsonencode({
Version = "2012-10-17"
Statement = [
{
Action = "sts:AssumeRole"
Effect = "Allow"
Principal = {
Service = "ecs-tasks.amazonaws.com"
}
}
]
})
}
resource "aws_iam_role_policy_attachment" "ecs_task_execution_role_policy" {
policy_arn = "arn:aws:iam::aws:policy/service-role/AmazonECSTaskExecutionRolePolicy"
role = aws_iam_role.ecs_task_execution_role.name
}
resource "aws_iam_role" "ecs_task_role" {
name = "website_server_task_role"
assume_role_policy = jsonencode({
Version = "2012-10-17"
Statement = [
{
Action = "sts:AssumeRole"
Effect = "Allow"
Principal = {
Service = "ecs-tasks.amazonaws.com"
}
}
]
})
}
resource "aws_iam_role_policy" "assetaccess" {
name = "assetaccess"
role = aws_iam_role.ecs_task_role.name
policy = file("s3files.json")
}
resource "aws_ecs_task_definition" "site_definitions" {
for_each = var.backend_tasks
family = "${each.key}_task"
network_mode = "awsvpc"
requires_compatibilities = ["FARGATE"]
execution_role_arn = aws_iam_role.ecs_task_execution_role.arn
task_role_arn = aws_iam_role.ecs_task_role.arn
container_definitions = jsonencode([
{
name = "${each.key}_container_task"
image = "${aws_ecr_repository.site_containers[each.key].repository_url}:latest"
essential = true
cpu = each.value.cpu
memory = each.value.memory
readonlyRootFilesystem = false # I'll need to check this out later. The app couldn't write to cache when this was on.
healthCheck = {
command = ["CMD-SHELL", "curl -f http://localhost:${each.value.internal_port}/ || exit 1"]
interval = 30
timeout = 5
retries = 3
startPeriod = 60
}
portMappings = [
{
containerPort = each.value.internal_port
hostPort = 0
protocol = "tcp"
}
]
logConfiguration = {
logDriver = "awslogs"
options = {
"awslogs-group" = aws_cloudwatch_log_group.cluster_logs[each.key].name
"awslogs-stream-prefix" = "ecs"
"awslogs-region" = aws_vpc.ecs_vpc.region
}
}
environment = [
{
name = "PORT"
value = tostring(each.value.internal_port)
},
{
name = "NEXT_PUBLIC_SITE_URL"
value = "https://${aws_lb.ECSWebServerLB.dns_name}"
},
{
name = "INTERNAL_API_URL"
value = "http://localhost:${each.value.internal_port}"
},
{
name = "HOSTNAME"
value = "0.0.0.0"
},
]
}]
)
}
resource "aws_ecs_service" "server_services" {
for_each = var.backend_tasks
name = "${each.key}_service"
cluster = aws_ecs_cluster.server_cluster.id
task_definition = aws_ecs_task_definition.site_definitions[each.key].arn
desired_count = each.value.desired_count
force_new_deployment = true
capacity_provider_strategy {
capacity_provider = aws_ecs_capacity_provider.asg_capacity.name
weight = 100
base = 1
}
dynamic "load_balancer" {
for_each = {for k, v in var.frontend_apps : k => v if v.backend_key == each.key }
content {
target_group_arn = aws_lb_target_group.TG[load_balancer.key].arn
container_name = "${each.key}_container_task"
container_port = each.value.external_port
}
}
deployment_circuit_breaker {
enable = true
rollback = true
}
depends_on = [
aws_lb_listener.ECSWebServerListener,
aws_iam_role_policy_attachment.ecs_task_execution_role_policy,
]
lifecycle {
replace_triggered_by = [aws_subnet.private_subnets]
create_before_destroy = true
}
}