Skip to content

oozou/terraform-aws-ecs-fargate-service

Repository files navigation

Terraform AWS ECS Fargate Service Module

TargetTrackingScaling

  # Predefined Metrics
  target_tracking_configuration = {
    policy_type = "TargetTrackingScaling"
    name        = "cpu-average"
    capacity = {
      min_capacity = 1
      max_capacity = 10
    }
    scaling_behaviors = {
      predefined_metric_type = "ECSServiceAverageCPUUtilization"
      target_value           = 60
      scale_in_cooldown      = 180
      scale_out_cooldown     = 60
    }
  }

  # Customization Metrics
  target_tracking_configuration = {
    policy_type = "TargetTrackingScaling"
    name        = "concurrency-per-task"
    capacity = {
      min_capacity = 1
      max_capacity = 10
    }
    scaling_behaviors = {
      target_value       = 1500
      scale_in_cooldown  = 180
      scale_out_cooldown = 60
      custom_metrics = {
        active_connection_count = {
          id          = "acc"
          label       = "Get value of ActiveConnectionCount metric"
          return_data = false
          metric_stat = {
            stat        = "Sum"
            metric_name = "ActiveConnectionCount"
            namespace   = "AWS/ApplicationELB"
            dimensions = [
              {
                name  = "LoadBalancer"
                value = "app/oozou-devops-demo-alb/f0f65a9c9ea681e0"
              }
            ]
          }
        }
        running_task_count = {
          id          = "rtc"
          label       = "Get value of RunningTaskCount metric"
          return_data = false
          metric_stat = {
            stat        = "Average"
            metric_name = "RunningTaskCount"
            namespace   = "ECS/ContainerInsights"
            dimensions = [
              {
                name  = "ServiceName"
                value = "oozou-devops-demo-service-api"
              },
              {
                name  = "ClusterName"
                value = "oozou-devops-demo-cluster"
              },
            ]
          }
        }
        scaling_expression = {
          id          = "e1"
          label       = "ActiveConnectionCount/RunningTaskCount"
          expression  = "(acc)/rtc"
          return_data = true
        }
      }
    }
  }

StepScaling

  # Predefined Metrics
  step_scaling_configuration = {
    policy_type = "StepScaling"
    capacity = {
      min_capacity = 1
      max_capacity = 10
    }
    scaling_behaviors = {
      cpu_up = {
        metric_name         = "CPUUtilization"
        namespace           = "AWS/ECS"
        statistic           = "Average"
        comparison_operator = ">="
        threshold           = "60"
        period              = "60"
        evaluation_periods  = "1"
        cooldown            = 60
        # If value in (threshold+lower_bound, threshold+upper_bound), in crease scaling_adjustment
        step_adjustment = [
          {
            # (60, 80) increase 1
            metric_interval_lower_bound = 0
            metric_interval_upper_bound = 20
            scaling_adjustment          = 1
          },
          {
            # (80, n) increase 2
            metric_interval_lower_bound = 20
            scaling_adjustment          = 2
          }
        ]
      }
      cpu_down = {
        metric_name         = "CPUUtilization"
        namespace           = "AWS/ECS"
        statistic           = "Average"
        comparison_operator = "<="
        threshold           = "40"
        period              = "60"
        evaluation_periods  = "2"
        cooldown            = 120
        step_adjustment = [
          # If value in (threshold+lower_bound, threshold+upper_bound), in crease scaling_adjustment
          {
            metric_interval_upper_bound = 0.0
            scaling_adjustment          = -1
          }
        ]
      }
    }
  }

  # Customization Metrics
  step_scaling_configuration = {
    policy_type = "StepScaling"
    capacity = {
      min_capacity = 1
      max_capacity = 2
    }
    scaling_behaviors = {
      scaling_up = {
        metric_query = [
          {
            id = "acc"
            metric = [
              {
                metric_name = "ActiveConnectionCount"
                namespace   = "AWS/ApplicationELB"
                period      = "60"
                stat        = "Sum"
                dimensions = {
                  LoadBalancer = "app/oozou-dev-cms-alb/8c877c9bfb7aede3"
                }
              }
            ]
          },
          {
            id = "rtc"
            metric = [
              {
                metric_name = "RunningTaskCount"
                namespace   = "ECS/ContainerInsights"
                period      = "60"
                stat        = "Average"
                dimensions = {
                  ClusterName = "oozou-devops-demo-cluster"
                  ServiceName = "oozou-devops-demo-service-api"
                }
              }
            ]
          },
          {
            id          = "e1"
            expression  = "(acc*10)/rtc"
            label       = "ActiveConnectionCount/RunningTaskCount"
            return_data = true
          }
        ]
        statistic           = "Average"
        comparison_operator = ">="
        evaluation_periods  = "1"
        threshold           = 1500
        cooldown            = 60
        # If value in (threshold+lower_bound, threshold+upper_bound), in crease scaling_adjustment
        step_adjustment = [
          {
            # (1500, 2500) increase 1
            metric_interval_lower_bound = 0
            metric_interval_upper_bound = 1000
            scaling_adjustment          = 1
          },
          {
            # (2500, 4500) increase 2
            metric_interval_lower_bound = 1000
            metric_interval_upper_bound = 3000
            scaling_adjustment          = 2
          },
          {
            # (4500, n) increase 4
            metric_interval_lower_bound = 3000
            scaling_adjustment          = 4
          }
        ]
      }
      scaling_down = {
        metric_query = [
          {
            id = "acc"
            metric = [
              {
                metric_name = "ActiveConnectionCount"
                namespace   = "AWS/ApplicationELB"
                period      = "60"
                stat        = "Sum"
                dimensions = {
                  LoadBalancer = "app/oozou-dev-cms-alb/8c877c9bfb7aede3"
                }
              }
            ]
          },
          {
            id = "rtc"
            metric = [
              {
                metric_name = "RunningTaskCount"
                namespace   = "ECS/ContainerInsights"
                period      = "60"
                stat        = "Average"
                dimensions = {
                  ClusterName = "oozou-devops-demo-cluster"
                  ServiceName = "oozou-devops-demo-service-api"
                }
              }
            ]
          },
          {
            id          = "e1"
            expression  = "(acc*10)/rtc"
            label       = "ActiveConnectionCount/RunningTaskCount"
            return_data = true
          }
        ]
        statistic           = "Average"
        comparison_operator = "<="
        evaluation_periods  = "1"
        threshold           = 1300
        cooldown            = 300
        # If value in (threshold+lower_bound, threshold+upper_bound), in crease scaling_adjustment
        step_adjustment = [
          {
            # (0, 1300) increase 1
            metric_interval_upper_bound = 0
            scaling_adjustment          = -1
          }
        ]
      }
    }
  }

Requirements

Name Version
terraform >= 1.0.0
aws >= 4.0.0
random >= 2.3.0

Providers

Name Version
aws 5.22.0
random 3.5.1

Modules

Name Source Version
cloudwatch_log_group_kms oozou/kms-key/aws 1.0.0
secret_kms_key oozou/kms-key/aws 1.0.0
step_alarm oozou/cloudwatch-alarm/aws 1.0.0

Resources

Name Type
aws_appautoscaling_policy.step_scaling_policies resource
aws_appautoscaling_policy.target_tracking_scaling_policies resource
aws_appautoscaling_target.this resource
aws_cloudwatch_log_group.this resource
aws_ecs_service.this resource
aws_ecs_task_definition.this resource
aws_iam_role.task_execution_role resource
aws_iam_role.task_role resource
aws_iam_role_policy.task_execution_role_access_secret resource
aws_iam_role_policy_attachment.task_execution_role resource
aws_iam_role_policy_attachment.task_role resource
aws_lb_listener_rule.this resource
aws_lb_target_group.this resource
aws_secretsmanager_secret.this resource
aws_secretsmanager_secret_version.this resource
aws_service_discovery_service.service resource
random_string.service_secret_random_suffix resource
aws_caller_identity.this data source
aws_iam_policy_document.cloudwatch_log_group_kms_policy data source
aws_iam_policy_document.task_assume_role_policy data source
aws_iam_policy_document.task_execution_assume_role_policy data source
aws_region.this data source

Inputs

Name Description Type Default Required
additional_ecs_task_execution_role_policy_arns List of policies ARNs to attach to the ECS Task Role. eg: { rds_arn = module.postgres_db.rds_policy_arn } list(string) [] no
additional_ecs_task_role_policy_arns List of policies ARNs to attach to the ECS Task Role. eg: { rds_arn = module.postgres_db.rds_policy_arn } list(string) [] no
alb_host_header Mention host header for api endpoint string null no
alb_listener_arn The ALB listener to attach to string "" no
alb_paths Mention list Path For ALB routing eg: ["/"] or ["/route1"] list(string) [] no
alb_priority Priority of ALB rule https://docs.aws.amazon.com/elasticloadbalancing/latest/application/load-balancer-listeners.html#listener-rules string "100" no
application_subnet_ids Subnet IDs to deploy into list(string) n/a yes
capacity_provider_strategy Capacity provider strategies to use for the service EC2 Autoscaling group map(any) null no
cloudwatch_log_group_kms_key_arn The ARN for the KMS encryption key. string null no
cloudwatch_log_retention_in_days Retention day for cloudwatch log group number 90 no
container The container(s) that would be rendered in task definition; see example for completion any {} no
custom_header_token [Required] Specify secret value for custom header string "" no
deployment_circuit_breaker Configuration block for deployment circuit breaker
object({
enable = bool
rollback = bool
})
{
"enable": true,
"rollback": true
}
no
ecs_cluster_name ECS Cluster name to deploy in string n/a yes
efs_volumes Task EFS volume definitions as list of configuration objects. You cannot define both Docker volumes and EFS volumes on the same task definition. list(any) [] no
environment (Optional) Environment as a part of format("%s-%s-%s-cf", var.prefix, var.environment, var.name); ex. xxx-prod-xxx-cf string "" no
environment_variables Map of environment varaibles ex. { RDS_ENDPOINT = "admin@rds@123"} map(map(any)) {} no
exists_task_execution_role_arn The existing arn of task exec role string "" no
exists_task_role_arn The existing arn of task role string "" no
health_check Health Check Config for the service map(string) {} no
is_application_scratch_volume_enabled To enabled the temporary storage for the service bool false no
is_create_cloudwatch_log_group Whether to create cloudwatch log group or not bool true no
is_create_default_kms Whether to create cloudwatch log group kms or not bool true no
is_create_iam_role Create the built in IAM role for task role and task exec role bool true no
is_enable_execute_command Specifies whether to enable Amazon ECS Exec for the tasks within the service. bool false no
name (Optional) Name as a part of format("%s-%s-%s-cf", var.prefix, var.environment, var.name); ex. xxx-xxx-cms-cf string "" no
name_override (Optional) Full name to override usage from format("%s-%s-%s-cf", var.prefix, var.environment, var.name) string "" no
ordered_placement_strategy Service level strategy rules that are taken into consideration during task placement
set(object({
type = string
field = string
}))
[
{
"field": "attribute:ecs.availability-zone",
"type": "spread"
}
]
no
prefix (Optional) Prefix as a part of format("%s-%s-%s-cf", var.prefix, var.environment, var.name); ex. oozou-xxx-xxx-cf string "" no
propagate_tags (Optional) Specifies whether to propagate the tags from the task definition or the service to the tasks. The valid values are SERVICE and TASK_DEFINITION. string "TASK_DEFINITION" no
secret_variables Map of secret name(as reflected in Secrets Manager) and secret JSON string associated map(map(any)) {} no
security_groups Security groups to apply to service list(string) n/a yes
service_count Number of containers to deploy number 1 no
service_discovery_namespace DNS Namespace to deploy to string n/a yes
step_scaling_configuration (optional) Define step scaling behaviour, example in README any {} no
tags Custom tags which can be passed on to the AWS resources. They should be key value pairs having distinct keys map(any) {} no
target_group_deregistration_delay (Optional) Amount time for Elastic Load Balancing to wait before changing the state of a deregistering target from draining to unused. The range is 0-3600 seconds. The default value is 300 seconds. number 300 no
target_tracking_configuration (optional) Define traget tracking behaviour, example in README any {} no
task_cpu (Require): cpu for task level number n/a yes
task_memory (Require): memory for task level number n/a yes
vpc_id VPC id where security group is created string "" no

Outputs

Name Description
cloudwatch_log_group_arn The name of the log group
cloudwatch_log_group_name The name of the log group
secret_arns List of ARNs of the SecretsManager secrets
target_group_arn id - ARN of the Target Group (matches arn).
target_group_id id - ARN of the Target Group (matches arn).
task_execution_role_arn ECS Task execution role ARN
task_execution_role_id ECS Task execution role ID
task_role_arn ECS Task role ARN