terraformamazon-ecsaws-fargateautoscaling

ECS nightly scale in of fargate services


To save on fargate costs I wanted to scale down our dev environment consisting of around 100 ECS services overnight and on weekends. I've setup auto scaling via Terraform to achieve this as so:

resource "aws_appautoscaling_target" "service_to_target" {
  for_each           = local.services_for_offpeak_scaling
  max_capacity       = 1
  min_capacity       = 1
  resource_id        = "service/applications/${each.value}"
  scalable_dimension = "ecs:service:DesiredCount"
  service_namespace  = "ecs"
}

// create a scheuled action to scale down all targets in local.services_for_offpeak_scaling at 10pm
resource "aws_appautoscaling_scheduled_action" "scale_service_down" {
  for_each           = aws_appautoscaling_target.service_to_target
  name               = "${each.key}-scale-down"
  service_namespace  = "ecs"
  resource_id        = each.value.resource_id
  scalable_dimension = each.value.scalable_dimension
  schedule           = "cron(0 22 ? * MON-FRI *)"
  timezone           = "Europe/London"

  scalable_target_action {
    min_capacity = 0
    max_capacity = 0
  }
}

// create a scheuled action to scale up all targets in local.services_for_offpeak_scaling weekdays only
resource "aws_appautoscaling_scheduled_action" "scale_service_up" {
  for_each           = aws_appautoscaling_target.service_to_target
  name               = "${each.key}-scale-up"
  service_namespace  = "ecs"
  resource_id        = each.value.resource_id
  scalable_dimension = each.value.scalable_dimension
  schedule           = "cron(0 6 ? * MON-FRI *)"
  timezone           = "Europe/London"

  scalable_target_action {
    min_capacity = 1
    max_capacity = 1
  }
  depends_on = [aws_appautoscaling_scheduled_action.scale_service_down]
}

My question is what would the purpose of max_capacity and min_capacity be on the aws_appautoscaling_target? Also the desired count already defined on the ecs service definitions? Are they not both redundant as once the scaling action is applied it will stay that way until some other scaling action kicks in?

My initial thought before setting this up is it would be like "scale down at 10pm then go back to how it was before at 6am" but I'm not sure how to get it to just go back to the way it was without explicitly setting a new scaling action?


Solution

  • The desired count defined in the ECS service definitions tells ECS how many instances of the service to deploy. You have to have something defined here, because the value will be used for the initial deployment of the service.

    The aws_appautoscaling_target resource allows Application Autoscaling to change the ECS service's desired count attribute in response to Autoscaling events. The min/max capacity you define in this resource tells it what initial values Application Autoscaling should start with when the resource is created.

    The aws_appautoscaling_scheduled_action resources define what your autoscaling events are. These define the conditions which should trigger a change in the min/max autoscaling values. When one of these things triggers, it updates the min/max values of the aws_appautoscaling_target resource, which in turn will update the desired count value on the ECS service, which in turn causes ECS to either terminate some services instances, or deploy more service instances.

    It feels a bit convoluted/redundant because Application Autoscaling works with a lot of other AWS services besides ECS, so they had to make it fairly generic.