Carlos Aguni

Highly motivated self-taught IT analyst. Always learning and ready to explore new skills. An eternal apprentice.


ECS Fargate Terraform Study

01 Sep 2022 »

https://section411.com/2019/07/hello-world/

Autoscaling

https://dev.to/kieranjen/ecs-fargate-service-auto-scaling-with-terraform-2ld

Autoscaling

https://github.com/techservicesillinois/terraform-aws-ecs-service/blob/main/autoscale.tf


provider "aws" {
  region  = "us-east-1"
  profile = "ecscourse"
}

data "aws_caller_identity" "current" {}


data "aws_ecs_cluster" "app" {
  cluster_name = "app"
}

data "aws_iam_role" "sun_api_task_execution_role" {
  name               = "sun-api-task-execution-role"
}

output "ecs_cluster" {
  value = data.aws_ecs_cluster.app
}

locals {
    scale_down_name = "CWAlarmClusterAppScaleDown"
    scale_up_name = "CWAlarmClusterAppScaleUp"
}

variable cluster {
    default = "app"
}

variable name {
    default = "sun-api"
}

variable service_name {
    default = "sun-api"
}

variable autoscale {
    type = map
    default = {
      autoscale_max_capacity        = 5
      metric_name                   = "CPUUtilization"
      datapoints_to_alarm           = 1
      evaluation_periods            = 1
      period                        = 60
      cooldown                      = 60
      adjustment_type               = "ChangeInCapacity"

      scale_down_name = "ecsScaleDownAlarm"
      scale_up_name = "ecsScaleUpAlarm"

      ### Cloudwatch Alaram Scale up and Scale down ###
      scale_up_threshold            = 10
      scale_down_threshold          = 5

      ### AutoScale Policy Scale up ###
      scale_up_comparison_operator   = "GreaterThanOrEqualToThreshold"
      scale_up_interval_lower_bound  = 0
      scale_up_adjustment            = 1

      ### AutoScale Policy Scale down ###
      scale_down_comparison_operator  = "LessThanThreshold"
      scale_down_interval_lower_bound  = 0
      scale_down_adjustment            = -1
    }
}

output "a" {
    value = data.aws_ecs_cluster.app
}

resource "aws_cloudwatch_metric_alarm" "alarm_scale_down" {
  #count             = length(var.autoscale) > 0 ? 1 : 0
  alarm_description = "Scale down alarm for cluster"
  namespace         = "AWS/ECS"
  alarm_name        = var.autoscale.scale_down_name
  alarm_actions     = [aws_appautoscaling_policy.policy_scale_down.arn]

  comparison_operator = var.autoscale["scale_down_comparison_operator"]
  threshold           = var.autoscale["scale_down_threshold"]
  evaluation_periods  = var.autoscale["evaluation_periods"]
  metric_name         = var.autoscale["metric_name"]
  period              = lookup(var.autoscale, "period", 180)
  statistic           = lookup(var.autoscale, "statistic", "Average")
  datapoints_to_alarm = lookup(var.autoscale, "datapoints_to_alarm", 3)

  dimensions = {
    ClusterName = data.aws_ecs_cluster.app.cluster_name
    ServiceName = var.service_name
  }
}

# CLOUDWATCH ALARM  to monitor memory utilization of a service
resource "aws_cloudwatch_metric_alarm" "alarm_scale_up" {
  #count             = length(var.autoscale) > 0 ? 1 : 0
  alarm_description = "Scale up alarm for ${var.service_name}"
  namespace         = "AWS/ECS"
  alarm_name        = var.autoscale.scale_up_name
  alarm_actions     = [aws_appautoscaling_policy.policy_scale_up.arn]

  comparison_operator = var.autoscale["scale_up_comparison_operator"]
  threshold           = var.autoscale["scale_up_threshold"]
  evaluation_periods  = var.autoscale["evaluation_periods"]
  metric_name         = var.autoscale["metric_name"]
  period              = lookup(var.autoscale, "period", 180)
  statistic           = lookup(var.autoscale, "statistic", "Average")
  datapoints_to_alarm = lookup(var.autoscale, "datapoints_to_alarm", 3)

  dimensions = {
    ClusterName = data.aws_ecs_cluster.app.cluster_name
    ServiceName = var.service_name
  }
}

resource "aws_appautoscaling_target" "ecs_target" {
  #count        = length(var.autoscale) > 0 ? 1 : 0
  max_capacity = lookup(var.autoscale, "autoscale_max_capacity", 5)
  min_capacity = lookup(var.autoscale, "service_desired_count", 0)
  resource_id  = "service/${var.cluster}/${var.name}"
  role_arn = format(
    "arn:aws:iam::%s:role/aws-service-role/ecs.application-autoscaling.amazonaws.com/AWSServiceRoleForApplicationAutoScaling_ECSService",
    data.aws_caller_identity.current.account_id,
  )

  scalable_dimension = "ecs:service:DesiredCount"
  service_namespace  = "ecs"
}


#Set up the memory utilization policy for scale down when the cloudwatch alarm gets triggered.
resource "aws_appautoscaling_policy" "policy_scale_down" {
  #count              = length(var.autoscale) > 0 ? 1 : 0
  name               = local.scale_down_name
  resource_id        = aws_appautoscaling_target.ecs_target.resource_id
  scalable_dimension = aws_appautoscaling_target.ecs_target.scalable_dimension
  service_namespace  = aws_appautoscaling_target.ecs_target.service_namespace

  step_scaling_policy_configuration {
    adjustment_type         = var.autoscale["adjustment_type"]
    cooldown                = var.autoscale["cooldown"]
    metric_aggregation_type = lookup(var.autoscale, "aggregation_type", "Average")

    step_adjustment {
      metric_interval_upper_bound = lookup(var.autoscale, "scale_down_interval_lower_bound", 0)
      scaling_adjustment          = var.autoscale["scale_down_adjustment"]
    }
  }
}

#Set up the memory utilization policy for scale up when the cloudwatch alarm gets triggered.
resource "aws_appautoscaling_policy" "policy_scale_up" {
  #count              = length(var.autoscale) > 0 ? 1 : 0
  name               = local.scale_up_name
  resource_id        = aws_appautoscaling_target.ecs_target.resource_id
  scalable_dimension = aws_appautoscaling_target.ecs_target.scalable_dimension
  service_namespace  = aws_appautoscaling_target.ecs_target.service_namespace

  step_scaling_policy_configuration {
    adjustment_type         = var.autoscale["adjustment_type"]
    cooldown                = var.autoscale["cooldown"]
    metric_aggregation_type = lookup(var.autoscale, "aggregation_type", "Average")

    step_adjustment {
      metric_interval_lower_bound = lookup(var.autoscale, "scale_up_interval_lower_bound", 1)
      scaling_adjustment          = var.autoscale["scale_up_adjustment"]
    }
  }
}