diff --git a/.terraform.lock.hcl b/.terraform.lock.hcl deleted file mode 100644 index 6108f54..0000000 --- a/.terraform.lock.hcl +++ /dev/null @@ -1,44 +0,0 @@ -# This file is maintained automatically by "terraform init". -# Manual edits may be lost in future updates. - -provider "registry.terraform.io/hashicorp/aws" { - version = "5.19.0" - constraints = ">= 4.0.0" - hashes = [ - "h1:B14fi+fHRJorCabBF2NAx7JpO58qZdve9eZi3zMdp8c=", - "zh:03aa0f857c6dfce5f46c9bf3aad45534b9421e68983994b6f9dd9812beaece9c", - "zh:0639818c5bf9f9943667f39ec38bb945c9786983025dff407390133fa1ca5041", - "zh:0b82ad42ced8fb4a138eaf2fd37cf6059ca0bb482114b35fb84f22fc1500324a", - "zh:173e8c19a9f1d8f6457c80f4a73a92f420a81d650fc4ad0f97a5dc4b9485bba8", - "zh:42913a40ddfe9b4f3c78ad2e3cdc1dcfd48151bc132dc6b49fc32cd6da79db21", - "zh:452db5caca2e53d5f7090979d518e77aa5fd98385514b11ee2ce76a46e89cb53", - "zh:9b12af85486a96aedd8d7984b0ff811a4b42e3d88dad1a3fb4c0b580d04fa425", - "zh:a12377ade89ee18d9be116436e411e8396898bd70b21ab027c161c785e86238d", - "zh:aa9e4746ba49044ad5b4dda57fcdba7bc16fe65f696766fb2c55c30a27abf844", - "zh:adfaee76d283f1c321fad2e4154be88d57da8c2ecfdca9516c8920bd2ece36ed", - "zh:bf6fbc6d60661c03ed2214173c1deced908dc62480dd41e67ac399fa4abd7467", - "zh:cb685da03ad00d1a27891f3d366d75e8795ac81f1b427888b434e6832ca40633", - "zh:e0432c78dfaf2baebe2bf5c0ad8087f547c69c2c5a00e4c1dcd5a6344ce726df", - "zh:e0ec9ccb8d34d6d0d8bf7f8628c223951832b4d50ea8887fc711fa854b3a28b4", - "zh:f274397ada4ef3c1dce2f70e719c8ccf19fc4e7a2e3f45d018764c6267fd7157", - ] -} - -provider "registry.terraform.io/hashicorp/local" { - version = "2.4.0" - hashes = [ - "h1:7RnIbO3CFakblTJs7o0mUiY44dc9xGYsLhSNFSNS1Ds=", - "zh:53604cd29cb92538668fe09565c739358dc53ca56f9f11312b9d7de81e48fab9", - "zh:66a46e9c508716a1c98efbf793092f03d50049fa4a83cd6b2251e9a06aca2acf", - "zh:70a6f6a852dd83768d0778ce9817d81d4b3f073fab8fa570bff92dcb0824f732", - "zh:78d5eefdd9e494defcb3c68d282b8f96630502cac21d1ea161f53cfe9bb483b3", - "zh:82a803f2f484c8b766e2e9c32343e9c89b91997b9f8d2697f9f3837f62926b35", - "zh:9708a4e40d6cc4b8afd1352e5186e6e1502f6ae599867c120967aebe9d90ed04", - "zh:973f65ce0d67c585f4ec250c1e634c9b22d9c4288b484ee2a871d7fa1e317406", - "zh:c8fa0f98f9316e4cfef082aa9b785ba16e36ff754d6aba8b456dab9500e671c6", - "zh:cfa5342a5f5188b20db246c73ac823918c189468e1382cb3c48a9c0c08fc5bf7", - "zh:e0e2b477c7e899c63b06b38cd8684a893d834d6d0b5e9b033cedc06dd7ffe9e2", - "zh:f62d7d05ea1ee566f732505200ab38d94315a4add27947a60afa29860822d3fc", - "zh:fa7ce69dde358e172bd719014ad637634bbdabc49363104f4fca759b4b73f2ce", - ] -} diff --git a/README.md b/README.md index 923cdc4..410cfb5 100644 --- a/README.md +++ b/README.md @@ -13,7 +13,7 @@ customized solution you may need to use this code more as a pattern or guideline ```hcl module "my_app" { - source = "github.com/byu-oit/terraform-aws-fargate-api?ref=v6.0.1" + source = "github.com/byu-oit/terraform-aws-fargate-api?ref=v7.0.0" app_name = "example-api" container_port = 8000 primary_container_definition = { @@ -68,8 +68,8 @@ module "my_app" { * CodeDeploy Group * DNS A-Record * AutoScaling Target -* AutoScaling Policies (one for stepping up and one for stepping down) -* CloudWatch Metric Alarms (one for stepping up and one for stepping down) +* AutoScaling Policy +* CloudWatch Metric Alarms - Managed by AWS as a part of the Scaling Policy, and not by Terraform directly ## Requirements @@ -92,8 +92,8 @@ module "my_app" { | health_check_unhealthy_threshold | number | Number of consecutive failed health checks required before considering target as unhealthy | 3 | | health_check_grace_period | number | Health check grace period in seconds | 0 | | task_policies | list(string) | List of IAM Policy ARNs to attach to the task execution IAM Policy | [] | -| task_cpu | number | CPU for the task definition | 256 | -| task_memory | number | Memory for the task definition | 512 | +| task_cpu | number | CPU for the task definition | | +| task_memory | number | Memory for the task definition | | | cpu_architecture | string | CPU architecture for the task definition. [See docs for options](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/task_definition_parameters.html#runtime-platform) | "X86_64" | | security_groups | list(string) | List of extra security group IDs to attach to the fargate task | [] | | vpc_id | string | VPC ID to deploy the ECS fargate service and ALB | | @@ -114,11 +114,7 @@ module "my_app" { | overwrite_records | bool | Allow creation of Route53 records in Terraform to overwrite an existing record, if any. | false | | hosted_zone | [object](#hosted_zone) | Hosted Zone object to redirect to ALB. (Can pass in the aws_hosted_zone object). A and AAAA records created in this hosted zone | | | https_certificate_arn | string | ARN of the HTTPS certificate of the hosted zone/domain | | -| autoscaling_config | [object](#autoscaling_config) | Configuration for default autoscaling policies and alarms. Additional advanced scaling options, which are optional, can be made with the "scaling_up_policy_config", "scaling_up_metric_alarm_config", "scaling_down_policy_config", and "scaling_down_metric_alarm_config" variables. Omit or set to `null` if you want to set up your own autoscaling policies and alarms. | `null` | -| scaling_up_policy_config | [object](#scaling_up_policy_config) | Optional advanced configuration for the scaling up policy if 'autoscaling_config' is in use. | See object definition [object](#scaling_up_policy_config) | -| scaling_up_metric_alarm_config | [object](#scaling_up_metric_alarm_config) | Optional advanced configuration for the scaling up metric alarm if 'autoscaling_config' is in use. | See object definition [object](#scaling_up_metric_alarm_config) | -| scaling_down_policy_config | [object](#scaling_down_policy_config) | Optional advanced configuration for the scaling down policy if 'autoscaling_config' is in use. | See object definition [object](#scaling_down_policy_config) | -| scaling_down_metric_alarm_config | [object](#scaling_down_metric_alarm_config) | Optional advanced configuration for scaling the down metric alarm if 'autoscaling_config' is in use." | See object definition [object](#scaling_down_metric_alarm_config) | +| autoscaling_config | [object](#autoscaling_config) | Configuration for default autoscaling policies and alarms. Omit or set to `null` if you want to set up your own autoscaling policies and alarms. | `null` | | log_group_name | string | CloudWatch log group name. | | | log_retention_in_days | number | CloudWatch log group retention in days | 120 | | tags | map(string) | A map of AWS Tags to attach to each resource created | `null` | @@ -215,11 +211,15 @@ following attributes: #### autoscaling_config This module will create basic default autoscaling policies and alarms and you can define some variables of these default -autoscaling policies. +autoscaling policies. The underlying mechanism for scaling is a [Target tracking scaling policy](https://docs.aws.amazon.com/AmazonECS/latest/userguide/service-autoscaling-targettracking.html). * **`min_capacity`** - (Required) Minimum task count for autoscaling (this will also be used to define the initial desired count of the ECS Fargate Service) * **`max_capacity`** - (Required) Maximum task count for autoscaling +* **`target_metric`** - The Metric Type for scaling. Either `ECSServiceAverageCPUUtilization` or `ECSServiceAverageMemoryUtilization` +* **`target_value`** (Required) Target value for the metric. That value represents the ideal average utilization or throughput level for your application for the chosen metric +* **`scale_in_cooldown`** (Optional) Amount of time, in seconds, after a scale in activity completes before another scale in activity can start. Setting to null will omit the cooldown. Defaults to `300` +* **`scale_out_cooldown`** (Optional) Amount of time, in seconds, after a scale out activity completes before another scale out activity can start. Setting to null will omit the cooldown. Defaults to `60` **Note:** If you want to define your own autoscaling policies/alarms then you need to set this field to `null` at which point this module will not create any policies/alarms. @@ -227,99 +227,7 @@ point this module will not create any policies/alarms. **Note:** the desired count of the ECS Fargate Service will be set the first time terraform runs but changes to desired count will be ignored after the first time. -#### scaling_up_policy_config - -This will allow the scaling up policy to be configured if necessary. - -* **`adjustment_type`** - (Required) Specifies whether the adjustment is an absolute number or a percentage of the - current capacity. -* **`metric_aggregation_type`** - (Required) The aggregation type for the policy's metrics. -* **`cooldown`** - (Required) The amount of time, in seconds, after a scaling activity completes and before the next - scaling activity can start. -* **`scaling_adjustment`** - (Required) The number of members by which to scale, when the adjustment bounds are - breached. A positive value scales up. A negative value scales down. -* **`metric_interval_lower_bound`** - (Required) The lower bound for the difference between the alarm threshold and the - CloudWatch metric. -* Default: - ``` - { - adjustment_type = "ChangeInCapacity" - metric_aggregation_type = "Average" - cooldown = 300 - scaling_adjustment = 1 - metric_interval_lower_bound = 0 - } - ``` - -#### scaling_down_policy_config - -This will allow the scaling down policy to be configured if necessary. - -* **`adjustment_type`** - (Required) Specifies whether the adjustment is an absolute number or a percentage of the - current capacity. -* **`metric_aggregation_type`** - (Required) The aggregation type for the policy's metrics. -* **`cooldown`** - (Required) The amount of time, in seconds, after a scaling activity completes and before the next - scaling activity can start. -* **`scaling_adjustment`** - (Required) The number of members by which to scale, when the adjustment bounds are - breached. A positive value scales up. A negative value scales down. -* **`metric_interval_upper_bound`** - The upper bound for the difference between the alarm threshold and the CloudWatch - metric. -* Default: - ``` - { - adjustment_type = "ChangeInCapacity" - metric_aggregation_type = "Average" - cooldown = 300 - scaling_adjustment = -1 - metric_interval_upper_bound = 0 - } - ``` -#### scaling_up_metric_alarm_config - -This will allow the scaling up alarm to be configured if necessary. - -* **`statistic`** - (Required) The statistic to apply to the alarm's associated metric. -* **`metric_name`** - (Required) The name for the alarm's associated metric. -* **`comparison_operator`** - (Required) The arithmetic operation to use when comparing the specified Statistic and - Threshold. -* **`threshold`** - (Required) The value against which the specified statistic is compared. -* **`period`** - (Required) The period in seconds over which the specified statistic is applied. -* **`evaluation_periods`** - (Required) The number of periods over which data is compared to the specified threshold. -* Default: - ``` - { - statistic = "Average" - metric_name = "CPUUtilization" - comparison_operator = "GreaterThanThreshold" - threshold = 75 - period = 300 - evaluation_periods = 5 - } - ``` - -#### scaling_down_metric_alarm_config - -This will allow the scaling down alarm to be configured if necessary. - -* **`statistic`** - (Required) The statistic to apply to the alarm's associated metric. -* **`metric_name`** - (Required) The name for the alarm's associated metric. -* **`comparison_operator`** - (Required) The arithmetic operation to use when comparing the specified Statistic and - Threshold. -* **`threshold`** - (Required) The value against which the specified statistic is compared. -* **`period`** - (Required) The period in seconds over which the specified statistic is applied. -* **`evaluation_periods`** - (Required) The number of periods over which data is compared to the specified threshold. -* Default: - ``` - { - statistic = "Average" - metric_name = "CPUUtilization" - comparison_operator = "LessThanThreshold" - threshold = 25 - period = 300 - evaluation_periods = 5 - } - ``` #### CloudWatch logs @@ -344,8 +252,7 @@ with the container logs in `example-api/example/12d344fd34b556ae4326...` | alb_target_group_green | [object](https://www.terraform.io/docs/providers/aws/r/lb_target_group.html#attributes-reference) | The Application Load Balancer Target Group (ALB Target Group) object for the green deployment | | alb_security_group | [object](https://www.terraform.io/docs/providers/aws/r/security_group.html#attributes-reference) | The ALB's security group object | | dns_record | [object](https://www.terraform.io/docs/providers/aws/r/route53_record.html#attributes-reference) | The DNS A-record mapped to the ALB | -| autoscaling_step_up_policy | [object](https://www.terraform.io/docs/providers/aws/r/autoscaling_policy.html#attributes-reference) | Autoscaling policy to step up | -| autoscaling_step_down_policy | [object](https://www.terraform.io/docs/providers/aws/r/autoscaling_policy.html#attributes-reference) | Autoscaling policy to step down | +| autoscaling_policy | [object](https://www.terraform.io/docs/providers/aws/r/autoscaling_policy.html#attributes-reference) | Autoscaling policy to step up | | task_role | [object](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role#attributes-reference) | IAM role created for the tasks. | | task_execution_role | [object](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role#attributes-reference) | IAM role created for the execution of tasks. | diff --git a/examples/ci/ci.tf b/examples/ci/ci.tf index 850a6f9..3503ca6 100644 --- a/examples/ci/ci.tf +++ b/examples/ci/ci.tf @@ -55,6 +55,8 @@ module "fargate_api" { } autoscaling_config = null + task_memory = 256 + task_cpu = 512 codedeploy_test_listener_port = 8443 codedeploy_lifecycle_hooks = { BeforeInstall = null @@ -131,12 +133,8 @@ output "cloudwatch_log_group" { value = module.fargate_api.cloudwatch_log_group.arn } -output "autoscaling_step_up_policy" { - value = module.fargate_api.autoscaling_step_up_policy -} - -output "autoscaling_step_down_policy" { - value = module.fargate_api.autoscaling_step_down_policy +output "autoscaling_policy" { + value = module.fargate_api.autoscaling_policy } output "task_role" { diff --git a/examples/logging/logging.tf b/examples/logging/logging.tf index 15f5372..4f97236 100644 --- a/examples/logging/logging.tf +++ b/examples/logging/logging.tf @@ -24,7 +24,7 @@ data "aws_elb_service_account" "main" {} // name = "fake-example-cluster" //} module "fargate_api" { - source = "github.com/byu-oit/terraform-aws-fargate-api?ref=v6.0.1" + source = "github.com/byu-oit/terraform-aws-fargate-api?ref=v7.0.0" // source = "../../" // for local testing app_name = "example-api" //ecs_cluster_name = aws_ecs_cluster.existing.name diff --git a/main.tf b/main.tf index f65d887..c96077d 100644 --- a/main.tf +++ b/main.tf @@ -578,76 +578,25 @@ resource "aws_appautoscaling_target" "default" { scalable_dimension = "ecs:service:DesiredCount" service_namespace = "ecs" } -resource "aws_appautoscaling_policy" "up" { - count = var.autoscaling_config != null ? 1 : 0 - name = "${var.app_name}-autoscale-up" - resource_id = aws_appautoscaling_target.default[0].resource_id - scalable_dimension = aws_appautoscaling_target.default[0].scalable_dimension - service_namespace = aws_appautoscaling_target.default[0].service_namespace - - step_scaling_policy_configuration { - adjustment_type = var.scaling_up_policy_config.adjustment_type - metric_aggregation_type = var.scaling_up_policy_config.metric_aggregation_type - cooldown = var.scaling_up_policy_config.cooldown - step_adjustment { - scaling_adjustment = var.scaling_up_policy_config.scaling_adjustment - metric_interval_lower_bound = var.scaling_up_policy_config.metric_interval_lower_bound - } - } -} -resource "aws_cloudwatch_metric_alarm" "up" { - count = var.autoscaling_config != null ? 1 : 0 - alarm_name = "${var.app_name}-alarm-up" - namespace = "AWS/ECS" - dimensions = { - ClusterName = local.cluster_name - ServiceName = aws_ecs_service.service.name - } - statistic = var.scaling_up_metric_alarm_config.statistic - metric_name = var.scaling_up_metric_alarm_config.metric_name - comparison_operator = var.scaling_up_metric_alarm_config.comparison_operator - threshold = var.scaling_up_metric_alarm_config.threshold - period = var.scaling_up_metric_alarm_config.period - evaluation_periods = var.scaling_up_metric_alarm_config.evaluation_periods - alarm_actions = [aws_appautoscaling_policy.up[0].arn] - tags = var.tags -} -resource "aws_appautoscaling_policy" "down" { +resource "aws_appautoscaling_policy" "default" { count = var.autoscaling_config != null ? 1 : 0 - name = "${var.app_name}-autoscale-down" + name = "${var.app_name}-tracking-autoscale" + policy_type = "TargetTrackingScaling" resource_id = aws_appautoscaling_target.default[0].resource_id scalable_dimension = aws_appautoscaling_target.default[0].scalable_dimension service_namespace = aws_appautoscaling_target.default[0].service_namespace - step_scaling_policy_configuration { - adjustment_type = var.scaling_down_policy_config.adjustment_type - metric_aggregation_type = var.scaling_down_policy_config.metric_aggregation_type - cooldown = var.scaling_down_policy_config.cooldown - - step_adjustment { - scaling_adjustment = var.scaling_down_policy_config.scaling_adjustment - metric_interval_upper_bound = var.scaling_down_policy_config.metric_interval_upper_bound + target_tracking_scaling_policy_configuration { + predefined_metric_specification { + predefined_metric_type = var.autoscaling_config.target_metric } + target_value = var.autoscaling_config.target_value + scale_in_cooldown = var.autoscaling_config.scale_in_cooldown + scale_out_cooldown = var.autoscaling_config.scale_out_cooldown } } -resource "aws_cloudwatch_metric_alarm" "down" { - count = var.autoscaling_config != null ? 1 : 0 - alarm_name = "${var.app_name}-alarm-down" - namespace = "AWS/ECS" - dimensions = { - ClusterName = local.cluster_name - ServiceName = aws_ecs_service.service.name - } - statistic = var.scaling_down_metric_alarm_config.statistic - metric_name = var.scaling_down_metric_alarm_config.metric_name - comparison_operator = var.scaling_down_metric_alarm_config.comparison_operator - threshold = var.scaling_down_metric_alarm_config.threshold - period = var.scaling_down_metric_alarm_config.period - evaluation_periods = var.scaling_down_metric_alarm_config.evaluation_periods - alarm_actions = [aws_appautoscaling_policy.down[0].arn] - tags = var.tags -} + # ==================== AppSpec file ==================== resource "local_file" "appspec_json" { diff --git a/outputs.tf b/outputs.tf index 6c19e66..0bef6f8 100644 --- a/outputs.tf +++ b/outputs.tf @@ -46,12 +46,8 @@ output "cloudwatch_log_group" { value = aws_cloudwatch_log_group.container_log_group } -output "autoscaling_step_up_policy" { - value = var.autoscaling_config != null ? aws_appautoscaling_policy.up : null -} - -output "autoscaling_step_down_policy" { - value = var.autoscaling_config != null ? aws_appautoscaling_policy.down : null +output "autoscaling_policy" { + value = var.autoscaling_config != null ? aws_appautoscaling_policy.default[0] : null } output "task_role" { diff --git a/variables.tf b/variables.tf index b5fa392..8958142 100644 --- a/variables.tf +++ b/variables.tf @@ -99,13 +99,11 @@ variable "task_policies" { } variable "task_cpu" { type = number - description = "CPU for the task definition. Defaults to 256." - default = 256 + description = "CPU for the task definition." } variable "task_memory" { type = number - description = "Memory for the task definition. Defaults to 512." - default = 512 + description = "Memory for the task definition." } variable "cpu_architecture" { type = string @@ -215,84 +213,17 @@ variable "https_certificate_arn" { } variable "autoscaling_config" { type = object({ - min_capacity = number - max_capacity = number + min_capacity = number + max_capacity = number + target_metric = string + target_value = number + scale_in_cooldown = optional(number, 300) # 5 minutes between scale down actions + scale_out_cooldown = optional(number, 60) # 1 minute between scale up actions }) description = "Configuration for default autoscaling policies and alarms. Set to null if you want to set up your own autoscaling policies and alarms." default = null } -variable "scaling_up_policy_config" { - type = object({ - adjustment_type = string - metric_aggregation_type = string - cooldown = number - scaling_adjustment = number - metric_interval_lower_bound = number - }) - description = "Advanced configuration for the scaling up policy if 'autoscaling_config' is in use." - default = { - adjustment_type = "ChangeInCapacity" - metric_aggregation_type = "Average" - cooldown = 300 - scaling_adjustment = 1 - metric_interval_lower_bound = 0 - } -} -variable "scaling_up_metric_alarm_config" { - type = object({ - statistic = string - metric_name = string - comparison_operator = string - threshold = number - period = number - evaluation_periods = number - }) - description = "Advanced configuration for the scaling up metric alarm if 'autoscaling_config' is in use." - default = { - statistic = "Average" - metric_name = "CPUUtilization" - comparison_operator = "GreaterThanThreshold" - threshold = 75 - period = 300 - evaluation_periods = 5 - } -} -variable "scaling_down_policy_config" { - type = object({ - adjustment_type = string - metric_aggregation_type = string - cooldown = number - scaling_adjustment = number - metric_interval_upper_bound = number - }) - description = "Advanced configuration for the scaling down policy if 'autoscaling_config' is in use." - default = { - adjustment_type = "ChangeInCapacity" - metric_aggregation_type = "Average" - cooldown = 300 - scaling_adjustment = -1 - metric_interval_upper_bound = 0 - } -} -variable "scaling_down_metric_alarm_config" { - type = object({ - statistic = string - metric_name = string - comparison_operator = string - threshold = number - period = number - evaluation_periods = number - }) - description = "Advanced configuration for scaling the down metric alarm if 'autoscaling_config' is in use." - default = { - statistic = "Average" - metric_name = "CPUUtilization" - comparison_operator = "LessThanThreshold" - threshold = 25 - period = 300 - evaluation_periods = 5 - } -} + variable "log_group_name" { type = string description = "CloudWatch log group name."