Skip to content
This repository was archived by the owner on May 4, 2023. It is now read-only.

Big service update #21

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions data.tf
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
data aws_region current {}
data aws_caller_identity current {}

data aws_lb passed_on {
arn = var.aws_lb_arn
Expand Down
244 changes: 86 additions & 158 deletions main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -2,25 +2,30 @@
# CloudWatch Log Groups
# ---------------------------------------------------
resource aws_cloudwatch_log_group ecs_group {
name = "${var.name_prefix}/fargate/${var.cluster_name}/${var.app_name}/"
tags = var.standard_tags
name = "${var.name_prefix}/fargate/${var.cluster_name}/${var.service_name}/"
tags = var.standard_tags
retention_in_days = var.retention_in_days
}


# ---------------------------------------------------
# ECS Service
# ---------------------------------------------------
resource aws_ecs_service aws_ecs_fargate_service {
name = "${var.name_prefix}-${var.app_name}"
resource time_sleep wait {
depends_on = [aws_ecs_service.main]
create_duration = "30s"
}

resource aws_ecs_service main {
name = "${var.name_prefix}-${var.service_name}"
cluster = var.cluster_arn
platform_version = var.platform_version
propagate_tags = "SERVICE"
deployment_maximum_percent = 200
deployment_minimum_healthy_percent = 100
desired_count = var.container_desired_count
task_definition = aws_ecs_task_definition.fargate_service_task_definition.arn
task_definition = aws_ecs_task_definition.main.arn
health_check_grace_period_seconds = var.health_check_grace_period_seconds
tags = merge(var.standard_tags, { Name = var.app_name })
tags = merge(var.standard_tags, { Name = var.service_name })

capacity_provider_strategy {
capacity_provider = "FARGATE"
Expand All @@ -37,49 +42,58 @@ resource aws_ecs_service aws_ecs_fargate_service {
network_configuration {
security_groups = var.security_groups
subnets = var.subnets
assign_public_ip = var.public
}

load_balancer {
target_group_arn = aws_lb_target_group.aws_ecs_fargate_service_target_group.arn
container_name = var.app_name
container_port = var.app_port
target_group_arn = aws_lb_target_group.main.arn
container_name = var.service_name
container_port = var.service_port
}

depends_on = [data.aws_lb.passed_on]
}


# ---------------------------------------------------
# ECS Task Definition
# ---------------------------------------------------
module fargate_service_ecs_container_definition {
source = "cloudposse/ecs-container-definition/aws"
version = "0.58.1"
module main_container_definition {
source = "cloudposse/ecs-container-definition/aws"
version = "0.58.1"

command = var.command
container_name = var.app_name
container_image = var.container_image
container_name = var.service_name
container_image = var.service_image
container_memory = var.container_memory
container_memory_reservation = var.container_memory
container_cpu = var.container_cpu
mount_points = var.mount_points
entrypoint = var.entrypoint
environment = setunion(var.environment,
secrets = var.secrets

port_mappings = [
{
containerPort = var.service_port
hostPort = var.service_port
protocol = "tcp"
}
]

environment = setunion(var.environment,
[
{
name = "PORT"
value = var.app_port
value = var.service_port
},
{
name = "APP_PORT"
value = var.app_port
}
])

port_mappings = [
value = var.service_port
},
{
containerPort = var.app_port
hostPort = var.app_port
protocol = "tcp"
}]
name = "SERVICE_PORT"
value = var.service_port
}
])

log_configuration = {
logDriver = "awslogs"
Expand All @@ -92,23 +106,26 @@ module fargate_service_ecs_container_definition {
}
}

resource aws_ecs_task_definition fargate_service_task_definition {
family = "${var.name_prefix}-${var.app_name}"

# ---------------------------------------------------
# Task Definition
# ---------------------------------------------------
resource aws_ecs_task_definition main {
family = "${var.name_prefix}-${var.zenv_name}-${var.service_name}"
requires_compatibilities = [var.launch_type]
network_mode = "awsvpc"
execution_role_arn = var.execution_role_arn
cpu = coalesce(var.task_cpu, var.container_cpu)
memory = coalesce(var.task_memory, var.container_memory)
task_role_arn = var.task_role_arn

container_definitions = jsonencode(concat([module.fargate_service_ecs_container_definition.json_map_object], var.additional_containers))
tags = var.standard_tags
tags = merge(var.standard_tags, tomap({ Name = var.service_name }))

dynamic "volume" {
dynamic volume {
for_each = var.volumes
content {
name = volume.value.name
dynamic "efs_volume_configuration" {
dynamic efs_volume_configuration {
for_each = lookup(volume.value, "efs_volume_configuration", [])
content {
file_system_id = lookup(efs_volume_configuration.value, "file_system_id", null)
Expand All @@ -122,114 +139,11 @@ resource aws_ecs_task_definition fargate_service_task_definition {


# ---------------------------------------------------
# CloudWatch Alarms for ASG
# Internal Load Balancer - If NOT Public
# ---------------------------------------------------
resource aws_cloudwatch_metric_alarm fargate_service_cpu_high {
alarm_name = "${var.name_prefix}-fargate-high-cpu-${var.app_name}"
comparison_operator = "GreaterThanOrEqualToThreshold"
evaluation_periods = "2"
threshold = var.container_cpu_high_threshold
datapoints_to_alarm = 1
statistic = "Average"
period = "60"

metric_name = "CPUUtilization"
namespace = "AWS/ECS"
dimensions = {
ClusterName = var.cluster_name
ServiceName = aws_ecs_service.aws_ecs_fargate_service.name
}

alarm_actions = [
aws_appautoscaling_policy.fargate_service_scale_up.arn
]
}

resource aws_cloudwatch_metric_alarm fargate_service_cpu_low {
alarm_name = "${var.name_prefix}-fargate-low-cpu-${var.app_name}"
comparison_operator = "LessThanThreshold"
evaluation_periods = "2"
threshold = var.container_cpu_low_threshold
datapoints_to_alarm = 1
statistic = "Average"
period = "60"

metric_name = "CPUUtilization"
namespace = "AWS/ECS"
dimensions = {
ClusterName = var.cluster_name
ServiceName = aws_ecs_service.aws_ecs_fargate_service.name
}

alarm_actions = [
aws_appautoscaling_policy.fargate_service_scale_down.arn
]
}


# ---------------------------------------------------
# Autoscaling
# ---------------------------------------------------
resource time_sleep wait {
depends_on = [aws_ecs_service.aws_ecs_fargate_service]
create_duration = "30s"
}

resource aws_appautoscaling_target fargate_service_autoscaling_target {
min_capacity = var.container_min_capacity
max_capacity = var.container_max_capacity
resource_id = "service/${var.cluster_name}/${var.name_prefix}-${var.app_name}"
role_arn = "arn:aws:iam::${var.account}:role/aws-service-role/ecs.application-autoscaling.amazonaws.com/AWSServiceRoleForApplicationAutoScaling_ECSService"
scalable_dimension = "ecs:service:DesiredCount"
service_namespace = "ecs"
depends_on = [time_sleep.wait]
}

resource aws_appautoscaling_policy fargate_service_scale_up {
name = "scale-up-${var.app_name}"
policy_type = "StepScaling"
resource_id = aws_appautoscaling_target.fargate_service_autoscaling_target.resource_id
scalable_dimension = aws_appautoscaling_target.fargate_service_autoscaling_target.scalable_dimension
service_namespace = aws_appautoscaling_target.fargate_service_autoscaling_target.service_namespace

step_scaling_policy_configuration {
adjustment_type = "ChangeInCapacity"
cooldown = 60
metric_aggregation_type = "Maximum"

step_adjustment {
metric_interval_upper_bound = 0
scaling_adjustment = 1
}
}
}

resource aws_appautoscaling_policy fargate_service_scale_down {
name = "scale-down-${var.app_name}"
policy_type = "StepScaling"
resource_id = aws_appautoscaling_target.fargate_service_autoscaling_target.resource_id
scalable_dimension = aws_appautoscaling_target.fargate_service_autoscaling_target.scalable_dimension
service_namespace = aws_appautoscaling_target.fargate_service_autoscaling_target.service_namespace

step_scaling_policy_configuration {
adjustment_type = "ChangeInCapacity"
cooldown = 60
metric_aggregation_type = "Maximum"

step_adjustment {
metric_interval_lower_bound = 0
scaling_adjustment = -1
}
}
}


# ---------------------------------------------------
# Internal Load Balancer - If Private Subnet
# ---------------------------------------------------
resource aws_lb_target_group aws_ecs_fargate_service_target_group {
name = "${var.name_prefix}-${var.app_name}-tg"
port = var.app_port
resource aws_lb_target_group main {
name = "${var.name_prefix}-${var.zenv_name}-${var.service_name}-tg"
port = var.service_port
protocol = "HTTP"
vpc_id = var.vpc_id
load_balancing_algorithm_type = "round_robin"
Expand All @@ -242,32 +156,33 @@ resource aws_lb_target_group aws_ecs_fargate_service_target_group {
timeout = 5
interval = 10
path = var.healthcheck_path
port = var.app_port
port = var.service_port
}
}

resource aws_lb_listener aws_ecs_fargate_service_aws_lb_listener {
load_balancer_arn = var.aws_lb_arn
port = var.aws_lb_out_port
resource aws_lb_listener main {
load_balancer_arn = data.aws_lb.passed_on.arn
port = var.public == true ? var.external_port : var.service_port
protocol = "HTTPS"
ssl_policy = "ELBSecurityPolicy-TLS-1-2-Ext-2018-06"
certificate_arn = var.aws_lb_certificate_arn

default_action {
type = "forward"
target_group_arn = aws_lb_target_group.aws_ecs_fargate_service_target_group.arn
target_group_arn = aws_lb_target_group.main.arn
}
}

resource "aws_lb_listener_rule" "block_header_rule" {
listener_arn = aws_lb_listener.aws_ecs_fargate_service_aws_lb_listener.arn
priority = 100
resource aws_lb_listener_rule block_header_rule {
count = var.public == true ? 0 : 1
listener_arn = aws_lb_listener.main.arn
priority = 100

condition {
http_header {
http_header_name = "X-Forwarded-Host"
values = ["*"]
}
http_header {
http_header_name = "X-Forwarded-Host"
values = ["*"]
}
}

action {
Expand All @@ -282,24 +197,24 @@ resource "aws_lb_listener_rule" "block_header_rule" {


# ---------------------------------------------------
# Public Load Balancer - If Public Subnet
# Public Load Balancer - If Public
# ---------------------------------------------------
resource aws_lb public {
count = var.public == true ? 1 : 0
name = "${var.name_prefix}-Pub-${var.app_name}-LB"
name = "${var.name_prefix}-${var.zenv_name}-${var.service_name}-Pub-LB"
load_balancer_type = "application"
security_groups = var.security_groups
subnets = var.subnets

access_logs {
bucket = var.s3_log_bucket
prefix = "${var.app_name}_lb"
prefix = "${var.service_name}_lb"
enabled = true
}

tags = merge(
var.standard_tags,
tomap({ Name = "Public-${var.app_name}" })
tomap({ Name = "Public-${var.service_name}" })
)
}

Expand Down Expand Up @@ -348,10 +263,23 @@ resource aws_lb_listener_rule block_header {
# DNS Record (CNAME)
# ---------------------------------------------------
resource aws_route53_record main {
count = var.public == true ? 1 : 0
count = var.public == true && var.domain_record != null ? 1 : 0
zone_id = data.aws_route53_zone.main.zone_id
name = "${var.name_prefix}-${var.app_name}"
name = "${var.name_prefix}-${var.zenv_name}-${var.service_name}"
type = "CNAME"
ttl = 300
records = [aws_lb.public[0].dns_name]
}


# ---------------------------------------------------
# LogDNA subsciprion
# ---------------------------------------------------
resource aws_cloudwatch_log_subscription_filter lambda_logfilter {
count = var.logdna_lambda_logs_arn != null ? 1 : 0
name = "${var.name_prefix}-${var.zenv_name}-${var.service_name}-filter"
log_group_name = "${var.name_prefix}/fargate/${var.cluster_name}/${var.service_name}/"
filter_pattern = ""
destination_arn = var.logdna_lambda_logs_arn
distribution = "ByLogStream"
}
10 changes: 5 additions & 5 deletions outputs.tf
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,18 @@ output load_balancer_fqdn {
value = var.public == true ? aws_lb.public[0].dns_name : null
}

output name {
output dns_name {
value = var.public == true ? aws_route53_record.main[0].name : null
}

output fqdn {
value = var.public == true ? aws_route53_record.main[0].fqdn : null
}

output app_port {
value = var.app_port
}

output cloudwatch_log_group_name {
value = aws_cloudwatch_log_group.ecs_group.name
}

output service_port {
value = var.service_port
}
Loading