AWS Fargate – predefined tracking autoscaling policies for memory and CPU utilization

A

Hi, DevOps fans. Welcome to series of articles devotes to AWS Fargate, autoscaling and terraform. I assume that you have read 4 parts at how to deploy web application at AWS Fargate using terraform and, as a result, you are aware of all terrafrom code related with that.

At that tutorial I will show you how to deploy predefined autoscaling policies for memory and CPU utilization. For that purpose we will use terraform module. As always we will start from physical file structure:

I propose to skip ti the instantly to the main logical part:

# auto_scaling.tf

resource "aws_appautoscaling_target" "ecs_target" {
  service_namespace  = "ecs"
  resource_id        = "service/${var.ecs_cluster_name}/${var.ecs_service_name}"
  scalable_dimension = "ecs:service:DesiredCount"
  min_capacity       = var.auto_scale_min_capacity
  max_capacity       = var.auto_scale_max_capacity
}

resource "aws_appautoscaling_policy" "predefined_memory" {
  name               = "${var.env}-${var.app_name}-predefined-memory"
  policy_type        = "TargetTrackingScaling"
  service_namespace  = aws_appautoscaling_target.ecs_target.service_namespace
  resource_id        = aws_appautoscaling_target.ecs_target.resource_id
  scalable_dimension = aws_appautoscaling_target.ecs_target.scalable_dimension

  target_tracking_scaling_policy_configuration {
    predefined_metric_specification {
      predefined_metric_type = "ECSServiceAverageMemoryUtilization"
    }
    target_value = var.desired_memory_utilization
  }
}

resource "aws_appautoscaling_policy" "predefined_cpu" {
  name               = "${var.env}-${var.app_name}-predefined-cpu"
  policy_type        = "TargetTrackingScaling"
  service_namespace  = aws_appautoscaling_target.ecs_target.service_namespace
  resource_id        = aws_appautoscaling_target.ecs_target.resource_id
  scalable_dimension = aws_appautoscaling_target.ecs_target.scalable_dimension

  target_tracking_scaling_policy_configuration {
    predefined_metric_specification {
      predefined_metric_type = "ECSServiceAverageCPUUtilization"
    }

    target_value = var.desired_cpu_utilization
  }
}

So, at 1st step we define autoscaling target, we need to provide service name – and it should be “ecs”, then resource – you may treat it as path to our fargate ecs service. At 4th line there is a scalable dimension. You may ask – where to take it? Here is the according aws documentation, where you may look at ScalableDimension part. You will notice rather fast, that in case ECS, there is only one option – it is number of containers. Finally we need to provide the min and max number of containers as an autoscaling range – it is called min_capacity and max_capacity. As it is a terraform module, current values are set as vars.

After setting an auto scaling target, we can go further and define an autoscaling policy. We need to provide a unique name, policy type. You may read more at terraform documentation, according to which we are using TargetTrackingScaling.  Next 3 properties (service_namespace, resource_id, scalable_dimension) are set  using reference from the autoscaling target. After that there is target_tracking_scaling_policy_configuration, the main part of which is predefined_metric_type. Reasonable question appears: what can we autoscale as predefined AWS metrics? According to aws documentation, for Fargate we can use:

  • ECSServiceAverageCPUUtilization
  • ECSServiceAverageMemoryUtilization
  • ALBRequestCountPerTarget

So, in our exact case we are using the 2 predefined metrics related with memory and CPU utilization, and for every according metric we are setting (similar to home thermostat) desirable target value. And again, as it is terraform module – current value are passed, of course, as variables.

Now, let me show you realization example, which you can use to extend tutorial code (at screen with files structure it is fargate-app/auto_scaling.tf) mentioned at the beginning of the article:

module "auto_scaling_fargate_predefined_cpu_ram" {
  source = "../../modules/autoscaling-fargate-predefined-cpu-ram"

  account_id = var.account_id
  env        = var.env
  project    = var.project
  region     = var.region

  auto_scale_min_capacity = 1
  auto_scale_max_capacity = 3

  desired_memory_utilization = 80
  desired_cpu_utilization    = 80

  ecs_cluster_name = module.fargate.ecs_cluster_name
  ecs_service_name = module.fargate.ecs_service_name
  app_name         = module.fargate.app_name
}

Let me provide rest of the files from autoscaling terraform module (small notice – outputs.tf in that case is empty):

# main.tf

terraform {
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = ">=5.32.1"
    }
  }

  required_version = ">=0.14.5"
}
# variables.tf

variable "ecs_cluster_name" {
  type = string
}

variable "ecs_service_name" {
  type = string
}

variable "app_name" {
  type = string
}

variable "auto_scale_min_capacity" {
  type = number
}

variable "auto_scale_max_capacity" {
  type = number
}

variable "desired_memory_utilization" {
  type = number
}

variable "desired_cpu_utilization" {
  type = number
}
# variables_env.tf

variable "account_id" {
  type        = string
  description = "AWS Account ID"
}

variable "env" {
  type        = string
  description = "Environment name"
}

variable "project" {
  type        = string
  description = "Project name"
}

variable "region" {
  type        = string
  description = "AWS Region"
}

OK, now let’s verify how all works by creating overloading at our test API application. Let me show you how can we do it using free video from my course: “AWS Fargate DevOps: Autoscaling with Terraform at practice“, which I also uploaded to my YouTube channel in order you could view it from website:

Thank you for the attention.

P.S. If you want to pass all material at once in fast and convenient way, with detailed explanations, then welcome to my course: “AWS Fargate DevOps: Autoscaling with Terraform at practice”, here you may find coupon with discount.


architecture AWS cluster cyber-security devops devops-basics docker elasticsearch flask geo high availability java machine learning opensearch php programming languages python recommendation systems search systems spring boot symfony