Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add autoscaling.tf #195

Merged
merged 4 commits into from
Oct 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion terraform/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,11 @@ The alb.tf file configures an Application Load Balancer (ALB) to route traffic t
api_gateway.tf:
The api_gateway.tf file configures an API Gateway to expose the WFPREV API for external access. It sets up a secure connection between the API Gateway and the internal VPC resources using a VPC link, and routes incoming HTTP requests to a load balancer within the VPC. The file also defines deployment stages and automates redeployment when changes are made, ensuring a consistent and reliable API interface across different environments.

autoscaling.tf:
The autoscaling.tf file sets up auto scaling for multiple ECS services within the WFPrev application, including the main service, nginx, and client. It utilizes AWS Application Auto Scaling to dynamically adjust the number of tasks running in each service based on CPU utilization. The file defines scaling targets, step scaling policies for both scaling up and down, and associated CloudWatch alarms. These alarms monitor CPU utilization, triggering scale-up actions when utilization exceeds 50% and scale-down actions when it falls below 10%. The configuration allows each service to scale between 1 and 10 tasks, with a 60-second cooldown period between scaling actions. This setup ensures that the application can efficiently handle varying loads while optimizing resource usage and costs.

ecs.tf:
This file sets up an ECS cluster for deploying the WFPREV server and client applications using FARGATE and FARGATE_SPOT capacity providers. It defines task definitions for both server and client containers, including resource allocations, environment variables, and logging configurations. The file also creates ECS services to manage these tasks, linking them to the appropriate load balancers for traffic routing and health checks.
This file sets up an ECS cluster for deploying the WFPREV server and client applications using FARGATE and FARGATE_SPOT capacity providers. It defines task definitions for both server and client containers, including resource allocations, environment variables, and logging configurations. The wfprev_client and wfprev_server task definitons here are setting iam roles for execution, network mode, provisionsing CPU and memory allocation, and setting volumes on the cluster for deployment of the client and server. The wfprev-liquibase task definition does the same allocation and runs database migrations. The file also creates ECS services to manage these tasks, linking them to the appropriate load balancers for traffic routing and health checks. The network condiguration sets a custom wfprev_tomcat_access security group, subnets and assigns the container a public IP address. This file also includes logConfiguration sections within the container definitions for both the WFPrev server and client task definitions. These configurations use the "awslogs" log driver, which is designed to send container logs directly to Amazon CloudWatch Logs. The options specified in each logConfiguration block determine how the logs are organized in CloudWatch. The "awslogs-create-group" option set to "true" allows ECS to automatically create the log group if it doesn't exist. The "awslogs-group" option specifies the name of the log group in CloudWatch where the logs will be sent, typically following the pattern "/ecs/{container-name}". The "awslogs-region" option ensures logs are sent to the correct AWS region, while "awslogs-stream-prefix" adds a prefix to the log stream names for easier identification. With these configurations in place, when the ECS tasks run, the Amazon ECS container agent automatically collects the stdout and stderr outputs from the containers and sends them to CloudWatch Logs without any additional setup required. This seamless integration allows for centralized logging and monitoring of ECS tasks. The CloudWatch logs can be accessed in the Log groups section of the CloudWatch service in the AWS console.

iam.tf:
This file defines IAM roles and policies to grant necessary permissions for ECS tasks and Lambda functions. It configures roles for ECS and Lambda execution, attaches relevant AWS policies for accessing resources like SQS, VPC, and RDS, and includes custom policies for specific tasks like CloudFront invalidation.
Expand Down
287 changes: 287 additions & 0 deletions terraform/autoscaling.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,287 @@
# auto_scaling.tf

resource "aws_appautoscaling_target" "wfprev_target" {
service_namespace = "ecs"
resource_id = "service/${aws_ecs_cluster.wfprev_main.name}/${aws_ecs_service.wfprev_main.name}"
scalable_dimension = "ecs:service:DesiredCount"
min_capacity = 1
max_capacity = 10
}

resource "aws_appautoscaling_target" "wfprev_nginx_target" {
service_namespace = "ecs"
resource_id = "service/${aws_ecs_cluster.wfprev_main.name}/${aws_ecs_service.nginx.name}"
scalable_dimension = "ecs:service:DesiredCount"
min_capacity = 1
max_capacity = 10
}

# Automatically scale capacity up by one
resource "aws_appautoscaling_policy" "wfprev_up" {
name = "wfprev_scale_up"
service_namespace = "ecs"
resource_id = "service/${aws_ecs_cluster.wfprev_main.name}/${aws_ecs_service.wfprev_main.name}"
scalable_dimension = "ecs:service:DesiredCount"

step_scaling_policy_configuration {
adjustment_type = "ChangeInCapacity"
cooldown = 60
metric_aggregation_type = "Maximum"

step_adjustment {
metric_interval_lower_bound = 0
scaling_adjustment = 1
}
}

depends_on = [aws_appautoscaling_target.wfprev_target]
}

resource "aws_appautoscaling_policy" "wfprev_nginx_up" {
name = "wfprev_nginx_scale_up"
service_namespace = "ecs"
resource_id = "service/${aws_ecs_cluster.wfprev_main.name}/${aws_ecs_service.nginx.name}"
scalable_dimension = "ecs:service:DesiredCount"

step_scaling_policy_configuration {
adjustment_type = "ChangeInCapacity"
cooldown = 60
metric_aggregation_type = "Maximum"

step_adjustment {
metric_interval_lower_bound = 0
scaling_adjustment = 1
}
}

depends_on = [aws_appautoscaling_target.wfprev_nginx_target]
}

# Automatically scale capacity down by one
resource "aws_appautoscaling_policy" "wfprev_down" {
name = "wfprev_scale_down"
service_namespace = "ecs"
resource_id = "service/${aws_ecs_cluster.wfprev_main.name}/${aws_ecs_service.wfprev_main.name}"
scalable_dimension = "ecs:service:DesiredCount"

step_scaling_policy_configuration {
adjustment_type = "ChangeInCapacity"
cooldown = 60
metric_aggregation_type = "Maximum"

step_adjustment {
metric_interval_upper_bound = 0
scaling_adjustment = -1
}
}

depends_on = [aws_appautoscaling_target.wfprev_target]
}

resource "aws_appautoscaling_policy" "wfprev_nginx_down" {
name = "wfprev_nginx_scale_down"
service_namespace = "ecs"
resource_id = "service/${aws_ecs_cluster.wfprev_main.name}/${aws_ecs_service.nginx.name}"
scalable_dimension = "ecs:service:DesiredCount"

step_scaling_policy_configuration {
adjustment_type = "ChangeInCapacity"
cooldown = 60
metric_aggregation_type = "Maximum"

step_adjustment {
metric_interval_upper_bound = 0
scaling_adjustment = -1
}
}

depends_on = [aws_appautoscaling_target.wfprev_nginx_target]
}

# CloudWatch alarm that triggers the autoscaling up policy
resource "aws_cloudwatch_metric_alarm" "wfprev_service_cpu_high" {
alarm_name = "wfprev_cpu_utilization_high"
comparison_operator = "GreaterThanOrEqualToThreshold"
evaluation_periods = "1"
metric_name = "CPUUtilization"
namespace = "AWS/ECS"
period = "60"
statistic = "Average"
threshold = "50"

dimensions = {
ClusterName = aws_ecs_cluster.wfprev_main.name
ServiceName = aws_ecs_service.wfprev_main.name
}

alarm_actions = [aws_appautoscaling_policy.wfprev_up.arn]


tags = {
Environment = "${var.TARGET_ENV}"
}
}

resource "aws_cloudwatch_metric_alarm" "wfprev_nginx_service_cpu_high" {
alarm_name = "wfprev_nginx_cpu_utilization_high"
comparison_operator = "GreaterThanOrEqualToThreshold"
evaluation_periods = "1"
metric_name = "CPUUtilization"
namespace = "AWS/ECS"
period = "60"
statistic = "Average"
threshold = "50"

dimensions = {
ClusterName = aws_ecs_cluster.wfprev_main.name
ServiceName = aws_ecs_service.nginx.name
}

alarm_actions = [aws_appautoscaling_policy.wfprev_nginx_up.arn]

tags = {
Environment = "${var.TARGET_ENV}"
}
}

# CloudWatch alarm that triggers the autoscaling down policy
resource "aws_cloudwatch_metric_alarm" "wfprev_service_cpu_low" {
alarm_name = "wfprev_cpu_utilization_low"
comparison_operator = "LessThanOrEqualToThreshold"
evaluation_periods = "2"
metric_name = "CPUUtilization"
namespace = "AWS/ECS"
period = "60"
statistic = "Average"
threshold = "10"

dimensions = {
ClusterName = aws_ecs_cluster.wfprev_main.name
ServiceName = aws_ecs_service.wfprev_main.name
}

alarm_actions = [aws_appautoscaling_policy.wfprev_down.arn]

tags = {
Environment = "${var.TARGET_ENV}"
}
}

resource "aws_cloudwatch_metric_alarm" "wfprev_nginx_service_cpu_low" {
alarm_name = "wfprev_nginx_cpu_utilization_low"
comparison_operator = "LessThanOrEqualToThreshold"
evaluation_periods = "2"
metric_name = "CPUUtilization"
namespace = "AWS/ECS"
period = "60"
statistic = "Average"
threshold = "10"

dimensions = {
ClusterName = aws_ecs_cluster.wfprev_main.name
ServiceName = aws_ecs_service.nginx.name
}

alarm_actions = [aws_appautoscaling_policy.wfprev_nginx_down.arn]


tags = {
Environment = "${var.TARGET_ENV}"
}
}

resource "aws_appautoscaling_target" "wfprev_client_target" {
service_namespace = "ecs"
resource_id = "service/${aws_ecs_cluster.wfprev_main.name}/${aws_ecs_service.client.name}"
scalable_dimension = "ecs:service:DesiredCount"
min_capacity = 1
max_capacity = 10
}

# Automatically scale capacity up by one
resource "aws_appautoscaling_policy" "wfprev_client_up" {
name = "wfprev_client_scale_up"
service_namespace = "ecs"
resource_id = "service/${aws_ecs_cluster.wfprev_main.name}/${aws_ecs_service.client.name}"
scalable_dimension = "ecs:service:DesiredCount"

step_scaling_policy_configuration {
adjustment_type = "ChangeInCapacity"
cooldown = 60
metric_aggregation_type = "Maximum"

step_adjustment {
metric_interval_lower_bound = 0
scaling_adjustment = 1
}
}

depends_on = [aws_appautoscaling_target.wfprev_client_target]
}

# Automatically scale capacity down by one
resource "aws_appautoscaling_policy" "wfprev_client_down" {
name = "wfprev_client_scale_down"
service_namespace = "ecs"
resource_id = "service/${aws_ecs_cluster.wfprev_main.name}/${aws_ecs_service.client.name}"
scalable_dimension = "ecs:service:DesiredCount"

step_scaling_policy_configuration {
adjustment_type = "ChangeInCapacity"
cooldown = 60
metric_aggregation_type = "Maximum"

step_adjustment {
metric_interval_upper_bound = 0
scaling_adjustment = -1
}
}

depends_on = [aws_appautoscaling_target.wfprev_client_target]
}

# CloudWatch alarm that triggers the autoscaling down policy
resource "aws_cloudwatch_metric_alarm" "wfprev_client_service_cpu_low" {
alarm_name = "wfprev_client_cpu_utilization_low"
comparison_operator = "LessThanOrEqualToThreshold"
evaluation_periods = "2"
metric_name = "CPUUtilization"
namespace = "AWS/ECS"
period = "60"
statistic = "Average"
threshold = "10"

dimensions = {
ClusterName = aws_ecs_cluster.wfprev_main.name
ServiceName = aws_ecs_service.client.name
}

alarm_actions = [aws_appautoscaling_policy.wfprev_client_down.arn]

tags = {
Environment = "${var.TARGET_ENV}"
}
}

# CloudWatch alarm that triggers the autoscaling up policy
resource "aws_cloudwatch_metric_alarm" "wfprev_client_service_cpu_high" {
alarm_name = "wfprev_client_cpu_utilization_high"
comparison_operator = "GreaterThanOrEqualToThreshold"
evaluation_periods = "1"
metric_name = "CPUUtilization"
namespace = "AWS/ECS"
period = "60"
statistic = "Average"
threshold = "50"

dimensions = {
ClusterName = aws_ecs_cluster.wfprev_main.name
ServiceName = aws_ecs_service.client.name
}

alarm_actions = [aws_appautoscaling_policy.wfprev_client_up.arn]

tags = {
Environment = "${var.TARGET_ENV}"
}
}
Loading