ecs (terraform)
Reference
Deploy a service into an ECS cluster behind a public load balancer
Includes scale in (decrease) and scale out (increase) in CloudFormation format.
https://github.com/nathanpeck/ecs-cloudformation/blob/master/service/service-ec2-public-lb.yml
ECS (Fargate) with ALB Deployment Using Terraform — Part 3
Includes security groups for load balancer, ecs, etc.
Sample: ECS cluster
modules/ecs/ecs.tf
resource "aws_ecs_cluster" "cluster" {
name = var.ecs_cluster_name
setting {
name = "containerInsights" #CloudWatch Container Insights
value = "disabled" #Additional charges, only if needed, eg: Dashboard container specific
}
}
Sample: ECS autoscaling by memory (target tracking) and cpu (step)
Tested w/ Terraform AWS provider v5.x.x
main.tf
###Scale mem false to disable or true to enable
is_mem_scale = true #scale task by memory usage
mem_target_value = 40 #target value of scale task by memory usage (%)
mem_scale_in_cooldown = 300 #cool down time of scale in (decrease) task by memory usage
mem_scale_out_cooldown = 300 #cool down time of scale out (increase) task by memory usage
###Scale cpu false to disable or true to enable
is_cpu_scale = true #scale task by cpu usage
cpu_target_value = 40 #target value of scale task by cpu usage (%)
cpu_scale_in_cooldown = 300 #cool down time of scale in (decrease) task by cpu usage
cpu_scale_out_cooldown = 300 #cool down time of scale out (increase) task by cpu usage
###Time inactivity to desire
inactivity = true
ecs.tf
# -------------------------------------
# Auto Scaling Target
# -------------------------------------
resource "aws_appautoscaling_target" "main" {
count = var.inactivity || var.is_cpu_scale || var.is_mem_scale ? 1 : 0
depends_on = [aws_ecs_service.service]
max_capacity = var.task_max_count
min_capacity = var.task_desired_count
resource_id = "service/${var.ecs_cluster_name}/${var.ecs_service_name}"
scalable_dimension = "ecs:service:DesiredCount"
service_namespace = "ecs"
}
# ----------------------------------------
# Auto Scaling Policy (ECS desired tasks)
# ----------------------------------------
resource "aws_appautoscaling_policy" "cpu_scale_down" {
count = var.is_cpu_scale ? 1 : 0
depends_on = [aws_appautoscaling_target.main]
name = "scale/${local.env}/${local.ci}/down"
policy_type = "StepScaling" #"TargetTrackingScaling"
resource_id = aws_appautoscaling_target.main[0].resource_id
scalable_dimension = aws_appautoscaling_target.main[0].scalable_dimension
service_namespace = aws_appautoscaling_target.main[0].service_namespace
step_scaling_policy_configuration {
adjustment_type = "ChangeInCapacity"
step_adjustment {
metric_interval_upper_bound = 0
scaling_adjustment = -1
}
metric_aggregation_type = "Maximum"
cooldown = var.cpu_scale_in_cooldown
}
}
resource "aws_appautoscaling_policy" "cpu_scale_up" {
count = var.is_cpu_scale ? 1 : 0
depends_on = [aws_appautoscaling_target.main]
name = "scale/${local.env}/${local.ci}/up"
policy_type = "StepScaling" #"TargetTrackingScaling"
resource_id = aws_appautoscaling_target.main[0].resource_id
scalable_dimension = aws_appautoscaling_target.main[0].scalable_dimension
service_namespace = aws_appautoscaling_target.main[0].service_namespace
step_scaling_policy_configuration {
adjustment_type = "ChangeInCapacity"
step_adjustment {
metric_interval_lower_bound = 0
metric_interval_upper_bound = 15
scaling_adjustment = 1
}
step_adjustment {
metric_interval_lower_bound = 15
metric_interval_upper_bound = 25
scaling_adjustment = 2
}
step_adjustment {
metric_interval_lower_bound = 25
scaling_adjustment = 3
}
metric_aggregation_type = "Maximum"
cooldown = var.cpu_scale_out_cooldown
}
}
resource "aws_cloudwatch_metric_alarm" "low_cpu_usage_alarm" {
count = var.is_cpu_scale ? 1 : 0
alarm_name = "${local.env}-${local.ci}-low-cpu-fargate"
comparison_operator = "LessThanOrEqualToThreshold"
evaluation_periods = "4"
metric_name = "CPUUtilization"
namespace = "AWS/ECS"
period = "10" # In seconds. Valid values are 10, 30, or any multiple of 60
statistic = "Average"
threshold = var.cpu_target_value
dimensions = {
"ClusterName" = aws_ecs_cluster.jboss.name
"ServiceName" = aws_ecs_service.service.name
}
alarm_description = "Low CPU utilization for service ${local.env}-${local.ci}"
alarm_actions = [aws_appautoscaling_policy.cpu_scale_down[0].arn]
insufficient_data_actions = [] #(Optional)
}
resource "aws_cloudwatch_metric_alarm" "high_cpu_usage_alarm" {
count = var.is_cpu_scale ? 1 : 0
alarm_name = "${local.env}-${local.ci}-high-cpu-fargate"
comparison_operator = "GreaterThanThreshold"
evaluation_periods = "4"
metric_name = "CPUUtilization"
namespace = "AWS/ECS"
period = "10" # In seconds. Valid values are 10, 30, or multiple of 60
statistic = "Maximum"
threshold = var.cpu_target_value
dimensions = {
"ClusterName" = aws_ecs_cluster.jboss.name
"ServiceName" = aws_ecs_service.service.name
}
alarm_description = "High CPU utilization for service ${local.env}-${local.ci}"
alarm_actions = [aws_appautoscaling_policy.cpu_scale_up[0].arn]
insufficient_data_actions = [] #(Optional)
}
# -------------------------------------
# Auto Scaling Policy (Memory)
# -------------------------------------
resource "aws_appautoscaling_policy" "mem" {
count = var.is_mem_scale ? 1 : 0
depends_on = [aws_appautoscaling_target.main]
name = "memory"
policy_type = "TargetTrackingScaling"
resource_id = aws_appautoscaling_target.main[0].resource_id
scalable_dimension = aws_appautoscaling_target.main[0].scalable_dimension
service_namespace = aws_appautoscaling_target.main[0].service_namespace
target_tracking_scaling_policy_configuration {
predefined_metric_specification {
predefined_metric_type = "ECSServiceAverageMemoryUtilization"
}
target_value = var.mem_target_value
scale_in_cooldown = var.mem_scale_in_cooldown
scale_out_cooldown = var.mem_scale_out_cooldown
}
}