Skip to content

Commit

Permalink
Merge pull request #14 from DNXLabs/dnx-feature-add-autoscalling
Browse files Browse the repository at this point in the history
adding auto scalling feature
  • Loading branch information
olialvesrobson authored Mar 28, 2024
2 parents 0886ff7 + 5d184c4 commit 176dc74
Show file tree
Hide file tree
Showing 3 changed files with 193 additions and 1 deletion.
12 changes: 12 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,13 +51,23 @@ In addition you have the option to create or not :
|------|-------------|------|---------|:--------:|
| alarm\_prefix | String prefix for cloudwatch alarms. (Optional, leave blank to use iam\_account\_alias) | `string` | `""` | no |
| alarm\_sns\_topics | Alarm topics to create and alert on ECS service metrics | `list` | `[]` | no |
| autoscaling\_cpu | Enables autoscaling based on average CPU tracking | `bool` | `false` | no |
| autoscaling\_custom | Set one or more app autoscaling by customized metric | <pre>list(object({<br> name = string<br> scale_in_cooldown = number<br> scale_out_cooldown = number<br> target_value = number<br> metric_name = string<br> namespace = string<br> statistic = string<br> }))</pre> | `[]` | no |
| autoscaling\_max | Max number of containers to scale with autoscaling | `number` | `4` | no |
| autoscaling\_memory | Enables autoscaling based on average Memory tracking | `bool` | `false` | no |
| autoscaling\_min | Min number of containers to scale with autoscaling | `number` | `1` | no |
| autoscaling\_scale\_in\_cooldown | Cooldown in seconds to wait between scale in events | `number` | `300` | no |
| autoscaling\_scale\_out\_cooldown | Cooldown in seconds to wait between scale out events | `number` | `300` | no |
| autoscaling\_target\_cpu | Target average CPU percentage to track for autoscaling | `number` | `50` | no |
| autoscaling\_target\_memory | Target average Memory percentage to track for autoscaling | `number` | `90` | no |
| cloudwatch\_logs\_export | Whether to mark the log group to export to an S3 bucket (needs terraform-aws-log-exporter to be deployed in the account/region) | `bool` | `false` | no |
| cloudwatch\_logs\_retention | Specifies the number of days you want to retain log events in the specified log group. Possible values are: 1, 3, 5, 7, 14, 30, 60, 90, 120, 150, 180, 365, 400, 545, 731, 1827, and 3653. | `number` | `120` | no |
| cluster\_name | n/a | `string` | `"Name of existing ECS Cluster to deploy this app to"` | no |
| cpu | Hard limit for CPU for the container | `string` | `"0"` | no |
| deployment\_maximum\_percent | Deployment maximum percentage | `string` | `"100"` | no |
| deployment\_minimum\_healthy\_percent | Deployment minumum health percentage | `string` | `"0"` | no |
| desired\_count | Number of containers (tasks) to run | `number` | `1` | no |
| enable\_schedule | Enables schedule to shut down and start up instances outside business hours. | `bool` | `false` | no |
| fargate\_spot | Set true to use FARGATE\_SPOT capacity provider by default (only when launch\_type=FARGATE) | `bool` | `false` | no |
| image | Docker image to deploy (can be a placeholder) | `string` | `"dnxsolutions/nginx-hello:latest"` | no |
| launch\_type | The launch type on which to run your service. The valid values are EC2 and FARGATE. Defaults to EC2. | `string` | `"EC2"` | no |
Expand All @@ -70,6 +80,8 @@ In addition you have the option to create or not :
| network\_mode | The Docker networking mode to use for the containers in the task. The valid values are none, bridge, awsvpc, and host. (REQUIRED IF 'LAUCH\_TYPE' IS FARGATE) | `any` | `null` | no |
| ordered\_placement\_strategy | Service level strategy rules that are taken into consideration during task placement. List from top to bottom in order of precedence. The maximum number of ordered\_placement\_strategy blocks is 5. | <pre>list(object({<br> field = string<br> expression = string<br> }))</pre> | `[]` | no |
| placement\_constraints | Rules that are taken into consideration during task placement. Maximum number of placement\_constraints is 10. | <pre>list(object({<br> type = string<br> expression = string<br> }))</pre> | `[]` | no |
| schedule\_cron\_start | Cron expression to define when to trigger a start of the auto-scaling group. E.g. 'cron(00 21 ? \* SUN-THU \*)' to start at 8am UTC time. | `string` | `""` | no |
| schedule\_cron\_stop | Cron expression to define when to trigger a stop of the auto-scaling group. E.g. 'cron(00 09 ? \* MON-FRI \*)' to start at 8am UTC time | `string` | `""` | no |
| security\_groups | The security groups associated with the task or service | `any` | `null` | no |
| subnets | The subnets associated with the task or service. (REQUIRED IF 'LAUCH\_TYPE' IS FARGATE) | `any` | `null` | no |
| task\_role\_policies | Custom policies to be added on the task role. | `list` | `[]` | no |
Expand Down
74 changes: 73 additions & 1 deletion _variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -143,4 +143,76 @@ variable "task_role_policies_managed" {
variable "task_role_policies" {
default = []
description = "Custom policies to be added on the task role."
}
}

variable "autoscaling_cpu" {
default = false
description = "Enables autoscaling based on average CPU tracking"
}

variable "autoscaling_memory" {
default = false
description = "Enables autoscaling based on average Memory tracking"
}

variable "autoscaling_max" {
default = 4
description = "Max number of containers to scale with autoscaling"
}

variable "autoscaling_min" {
default = 1
description = "Min number of containers to scale with autoscaling"
}

variable "autoscaling_target_cpu" {
default = 50
description = "Target average CPU percentage to track for autoscaling"
}

variable "autoscaling_target_memory" {
default = 90
description = "Target average Memory percentage to track for autoscaling"
}

variable "autoscaling_scale_in_cooldown" {
default = 300
description = "Cooldown in seconds to wait between scale in events"
}

variable "autoscaling_scale_out_cooldown" {
default = 300
description = "Cooldown in seconds to wait between scale out events"
}

variable "enable_schedule" {
default = false
description = "Enables schedule to shut down and start up instances outside business hours."
}

variable "autoscaling_custom" {
type = list(object({
name = string
scale_in_cooldown = number
scale_out_cooldown = number
target_value = number
metric_name = string
namespace = string
statistic = string
}))
default = []
description = "Set one or more app autoscaling by customized metric"
}

variable "schedule_cron_start" {
type = string
default = ""
description = "Cron expression to define when to trigger a start of the auto-scaling group. E.g. 'cron(00 21 ? * SUN-THU *)' to start at 8am UTC time."
}

variable "schedule_cron_stop" {
type = string
default = ""
description = "Cron expression to define when to trigger a stop of the auto-scaling group. E.g. 'cron(00 09 ? * MON-FRI *)' to start at 8am UTC time"
}

108 changes: 108 additions & 0 deletions appautoscaling.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
resource "aws_appautoscaling_target" "ecs" {
count = var.autoscaling_cpu || var.autoscaling_memory || length(var.autoscaling_custom) > 0 ? 1 : 0
max_capacity = var.autoscaling_max
min_capacity = var.autoscaling_min
resource_id = "service/${var.cluster_name}/${aws_ecs_service.default.name}"
scalable_dimension = "ecs:service:DesiredCount"
service_namespace = "ecs"
}

resource "aws_appautoscaling_policy" "scale_cpu" {
count = var.autoscaling_cpu ? 1 : 0
name = "scale-cpu"
policy_type = "TargetTrackingScaling"
resource_id = aws_appautoscaling_target.ecs[0].resource_id
scalable_dimension = aws_appautoscaling_target.ecs[0].scalable_dimension
service_namespace = aws_appautoscaling_target.ecs[0].service_namespace

target_tracking_scaling_policy_configuration {
target_value = var.autoscaling_target_cpu
disable_scale_in = false
scale_in_cooldown = var.autoscaling_scale_in_cooldown
scale_out_cooldown = var.autoscaling_scale_out_cooldown

predefined_metric_specification {
predefined_metric_type = "ECSServiceAverageCPUUtilization"
}
}
}

resource "aws_appautoscaling_policy" "scale_memory" {
count = var.autoscaling_memory ? 1 : 0
name = "scale-memory"
policy_type = "TargetTrackingScaling"
resource_id = aws_appautoscaling_target.ecs[0].resource_id
scalable_dimension = aws_appautoscaling_target.ecs[0].scalable_dimension
service_namespace = aws_appautoscaling_target.ecs[0].service_namespace

target_tracking_scaling_policy_configuration {
target_value = var.autoscaling_target_memory
disable_scale_in = false
scale_in_cooldown = var.autoscaling_scale_in_cooldown
scale_out_cooldown = var.autoscaling_scale_out_cooldown

predefined_metric_specification {
predefined_metric_type = "ECSServiceAverageMemoryUtilization"
}
}
}

resource "aws_appautoscaling_policy" "scale_custom" {
for_each = { for custom in var.autoscaling_custom : custom.name => custom }

name = each.value.name
policy_type = "TargetTrackingScaling"
resource_id = aws_appautoscaling_target.ecs[0].resource_id
scalable_dimension = aws_appautoscaling_target.ecs[0].scalable_dimension
service_namespace = aws_appautoscaling_target.ecs[0].service_namespace

target_tracking_scaling_policy_configuration {
scale_in_cooldown = each.value.scale_in_cooldown
scale_out_cooldown = each.value.scale_out_cooldown
target_value = each.value.target_value

customized_metric_specification {
metric_name = each.value.metric_name
namespace = each.value.namespace
statistic = each.value.statistic
dimensions {
name = "ClusterName"
value = var.cluster_name
}
dimensions {
name = "ServiceName"
value = var.name
}
}
}
}

resource "aws_appautoscaling_scheduled_action" "scale_service_out" {
count = var.enable_schedule ? 1 : 0
name = "${var.name}-scale-out"
service_namespace = aws_appautoscaling_target.ecs[0].service_namespace
resource_id = aws_appautoscaling_target.ecs[0].resource_id
scalable_dimension = aws_appautoscaling_target.ecs[0].scalable_dimension
schedule = var.schedule_cron_stop
timezone = "UTC"

scalable_target_action {
min_capacity = 0
max_capacity = 0
}
}

resource "aws_appautoscaling_scheduled_action" "scale_service_in" {
count = var.enable_schedule ? 1 : 0
name = "${var.name}-scale-in"
service_namespace = aws_appautoscaling_target.ecs[0].service_namespace
resource_id = aws_appautoscaling_target.ecs[0].resource_id
scalable_dimension = aws_appautoscaling_target.ecs[0].scalable_dimension
schedule = var.schedule_cron_start
timezone = "UTC"

scalable_target_action {
min_capacity = var.autoscaling_min
max_capacity = var.autoscaling_max
}
}

0 comments on commit 176dc74

Please sign in to comment.