Terraform module to create Fargate ECS resources on AWS.
- integration with AWS Cloud Map service discovery
- integration with App Mesh including Envoy sidecar and IAM permission configuration
- configuration of listener rules and target groups for Application Load Balancers
- Elastic Container Registry configuration like image scanning and lifecycle policies
- blue/green deployments using CodePipeline and CodeDeploy
- configuration of custom log routing using FireLens and Fluent Bit
- CloudWatch log group and IAM permissions for storing container logs
- AWS Distro for OpenTelemetry sidecar and IAM permission configuration
see example for details
module "service" {
source = "registry.terraform.io/stroeer/ecs-fargate/aws"
cpu = 256
cluster_id = "my-ecs-cluster-id"
container_port = 8000
create_ingress_security_group = false
create_deployment_pipeline = false
desired_count = 1
ecr_force_delete = true
memory = 512
service_name = "my-service"
vpc_id = module.vpc.vpc_id
// add listener rules that determine how the load balancer routes requests to its registered targets.
https_listener_rules = [{
listener_arn = aws_lb_listener.http.arn
actions = [{
type = "forward"
target_group_index = 0
}]
conditions = [{
path_patterns = ["/"]
}]
}]
// add a target group to route ALB traffic to this service
target_groups = [
{
name = "my-service"
backend_protocol = "HTTP"
backend_port = 8000
load_balancer_arn = "my-lb-arn"
target_type = "ip"
health_check = {
enabled = true
path = "/"
protocol = "HTTP"
}
}
]
}
module "service" {
// see above
appautoscaling_settings = {
predefined_metric_type = "ECSServiceAverageCPUUtilization"
target_value = 30
max_capacity = 8
min_capacity = 2
disable_scale_in = true
scale_in_cooldown = 120
scale_out_cooldown = 15
}
}
Use this configuration map to enable and alter the autoscaling settings for this app.
key | description |
---|---|
target_value |
(mandatory) the target value, refers to predefined_metric_type |
predefined_metric_type |
see docs for possible values |
max_capacity |
upper threshold for scale out |
min_capacity |
lower threshold for scale in |
disable_scale_in |
prevent scale in if set to true |
scale_in_cooldown |
delay (in seconds) between scale in events |
scale_out_cooldown |
delay (in seconds) between scale out events |
This module will can create an automated deployment pipeline for your service (set create_deployment_pipeline
is set to true
).
- you'll need AWS credentials that allows pushing images into the ECR container registry.
- Once you push an image with
[tag=production]
- a Cloudwatch Event will trigger the start of a CodePipeline. This tag will only trigger the pipeline. In addition, you'll need the following tags:container.$CONTAINER_NAME
is required to locate the correct container from the service's task-definition.json- another tag that will be unique and used for the actual deployment and the task-definition.json. A good choice would
be
git.sha
. To be specific, we chose a tag that does notstart with container.
and is none of["local", "production", "staging", "infrastructure"]
That CodePipeline will do the heavy lifting (see deployment flow above)
- Pull the full
imagedefinitions.json
from the ECR registry - Trigger a CodeBuild to transform the
imagedefinitions.json
into aimagedefinitions.json
for deployment - Update the ECS service's task-definition by replacing the specified
imageUri
for the givenname
.
Notifications
We will create a notification rule for the pipeline. You can provide your ARN of a notification rule target (e.g. a SNS
topic ARN) using
codestar_notifications_target_arn
. Otherwise a new SNS topic with required permissions is created for every service.
See
aws_codestarnotifications_notification_rule
for details.
You can then configure an integration between those notifications and AWS Chatbot for example.
Optional shared pipeline resources
- A shared S3 bucket for storing artifacts from CodePipeline can be used. You can specify it through the
variable
code_pipeline_artifact_bucket
. Otherwise, a new bucket is created for every service. - A shared
IAM::Role
for CodePipeline and CodeBuild can be used. You can specify those through the variablescode_pipeline_role_name
andcode_build_role_name
. Otherwise, new roles are created for every service. For the permissions required see the module code
- complete: complete example showcasing ALB integration, autoscaling and task definition configuration
Name | Version |
---|---|
terraform | >= 1.3 |
aws | >= 5.32 |
Name | Version |
---|---|
aws | >= 5.32 |
Name | Source | Version |
---|---|---|
code_deploy | ./modules/deployment | n/a |
container_definition | registry.terraform.io/cloudposse/config/yaml//modules/deepmerge | 1.0.2 |
ecr | ./modules/ecr | n/a |
envoy_container_definition | registry.terraform.io/cloudposse/config/yaml//modules/deepmerge | 1.0.2 |
fluentbit_container_definition | registry.terraform.io/cloudposse/config/yaml//modules/deepmerge | 1.0.2 |
otel_container_definition | registry.terraform.io/cloudposse/config/yaml//modules/deepmerge | 1.0.2 |
sg | registry.terraform.io/terraform-aws-modules/security-group/aws | ~> 3.0 |
Name | Description | Type | Default | Required |
---|---|---|---|---|
additional_container_definitions | Additional container definitions added to the task definition of this service, see https://docs.aws.amazon.com/AmazonECS/latest/developerguide/task_definition_parameters.html for allowed parameters. | list(any) |
[] |
no |
app_mesh | Configuration of optional AWS App Mesh integration using an Envoy sidecar. | object({ |
{} |
no |
appautoscaling_settings | Autoscaling configuration for this service. | map(any) |
null |
no |
assign_public_ip | Assign a public IP address to the ENI of this service. | bool |
false |
no |
capacity_provider_strategy | Capacity provider strategies to use for the service. Can be one or more. | list(object({ |
null |
no |
cloudwatch_logs | CloudWatch logs configuration for the containers of this service. CloudWatch logs will be used as the default log configuration if Firelens is disabled and for the fluentbit and otel containers. | object({ |
{} |
no |
cluster_id | The ECS cluster id that should run this service | string |
n/a | yes |
code_build_environment_compute_type | Information about the compute resources the CodeBuild stage of the deployment pipeline will use. | string |
"BUILD_LAMBDA_1GB" |
no |
code_build_environment_image | Docker image to use for the CodeBuild stage of the deployment pipeline. The image needs to include python. | string |
"aws/codebuild/amazonlinux-aarch64-lambda-standard:python3.12" |
no |
code_build_environment_type | Type of build environment for the CodeBuild stage of the deployment pipeline. | string |
"ARM_LAMBDA_CONTAINER" |
no |
code_build_log_retention_in_days | Log retention in days of the CodeBuild CloudWatch log group. | number |
7 |
no |
code_build_role_name | Use an existing role for codebuild permissions that can be reused for multiple services. Otherwise a separate role for this service will be created. | string |
"" |
no |
code_pipeline_artifact_bucket | Use an existing bucket for codepipeline artifacts that can be reused for multiple services. Otherwise a separate bucket for each service will be created. | string |
"" |
no |
code_pipeline_artifact_bucket_sse | AWS KMS master key id for server-side encryption. | any |
{} |
no |
code_pipeline_role_name | Use an existing role for codepipeline permissions that can be reused for multiple services. Otherwise a separate role for this service will be created. | string |
"" |
no |
code_pipeline_type | Type of the CodePipeline. Possible values are: V1 and V2 . |
string |
"V1" |
no |
code_pipeline_variables | CodePipeline variables. Valid only when codepipeline_type is V2 . |
list(object({ |
[] |
no |
codestar_notifications_detail_type | The level of detail to include in the notifications for this resource. Possible values are BASIC and FULL. | string |
"BASIC" |
no |
codestar_notifications_event_type_ids | A list of event types associated with this notification rule. For list of allowed events see https://docs.aws.amazon.com/dtconsole/latest/userguide/concepts.html#concepts-api. | list(string) |
[ |
no |
codestar_notifications_kms_master_key_id | AWS KMS master key id for server-side encryption. | string |
null |
no |
codestar_notifications_target_arn | Use an existing ARN for a notification rule target (for example, a SNS Topic ARN). Otherwise a separate sns topic for this service will be created. | string |
"" |
no |
container_definition_overwrites | Additional container definition parameters or overwrites of defaults for your service, see https://docs.aws.amazon.com/AmazonECS/latest/developerguide/task_definition_parameters.html for allowed parameters. | any |
{} |
no |
container_name | Defaults to var.service_name, can be overridden if it differs. Used as a target for LB. | string |
"" |
no |
container_port | The port used by the app within the container. | number |
n/a | yes |
cpu | Amount of CPU required by this service. 1024 == 1 vCPU | number |
256 |
no |
cpu_architecture | Must be set to either X86_64 or ARM64 , see https://docs.aws.amazon.com/AmazonECS/latest/developerguide/task_definition_parameters.html#runtime-platform. |
string |
"X86_64" |
no |
create_deployment_pipeline | Creates a deploy pipeline from ECR trigger if create_ecr_repo == true . |
bool |
true |
no |
create_ecr_repository | Create an ECR repository for this service. | bool |
true |
no |
create_ingress_security_group | Create a security group allowing ingress from target groups to the application ports. Disable this for target groups attached to a Network Loadbalancer. | bool |
true |
no |
deployment_circuit_breaker | Deployment circuit breaker configuration. | object({ |
{ |
no |
deployment_failure_detection_alarms | CloudWatch alarms used to detect deployment failures. | object({ |
{ |
no |
deployment_maximum_percent | Upper limit (as a percentage of the service's desiredCount) of the number of running tasks that can be running in a service during a deployment. Not valid when using the DAEMON scheduling strategy. |
number |
200 |
no |
deployment_minimum_healthy_percent | Lower limit (as a percentage of the service's desiredCount) of the number of running tasks that must remain running and healthy in a service during a deployment. | number |
100 |
no |
desired_count | Desired count of services to be started/running. | number |
0 |
no |
ecr_custom_lifecycle_policy | JSON formatted ECR lifecycle policy used for this repository (disabled the default lifecycle policy), see https://docs.aws.amazon.com/AmazonECR/latest/userguide/LifecyclePolicies.html#lifecycle_policy_parameters for details. | string |
null |
no |
ecr_enable_default_lifecycle_policy | Enables an ECR lifecycle policy for this repository which expires all images except for the last 30. | bool |
true |
no |
ecr_force_delete | If true , will delete this repository even if it contains images. |
bool |
false |
no |
ecr_image_scanning_configuration | n/a | map(any) |
{ |
no |
ecr_image_tag | Tag of the new image pushed to the Amazon ECR repository to trigger the deployment pipeline. | string |
"production" |
no |
ecr_image_tag_mutability | n/a | string |
"MUTABLE" |
no |
ecr_repository_name | Existing repo to register to use with this service module, e.g. creating deployment pipelines. | string |
"" |
no |
efs_volumes | Configuration block for EFS volumes. | any |
[] |
no |
enable_execute_command | Specifies whether to enable Amazon ECS Exec for the tasks within the service. | bool |
false |
no |
firelens | Configuration for optional custom log routing using FireLens over fluentbit sidecar. Enable attach_init_config_s3_policy to attach an IAM policy granting access to the init config files on S3. |
object({ |
{} |
no |
force_new_deployment | Enable to force a new task deployment of the service. This can be used to update tasks to use a newer Docker image with same image/tag combination (e.g. myimage:latest), roll Fargate tasks onto a newer platform version, or immediately deploy ordered_placement_strategy and placement_constraints updates. | bool |
false |
no |
health_check_grace_period_seconds | Seconds to ignore failing load balancer health checks on newly instantiated tasks to prevent premature shutdown, up to 2147483647. Only valid for services configured to use load balancers. | number |
0 |
no |
https_listener_rules | A list of maps describing the Listener Rules for this ALB. Required key/values: actions, conditions. Optional key/values: priority, https_listener_index (default to https_listeners[count.index]) | any |
[] |
no |
memory | Amount of memory [MB] is required by this service. | number |
512 |
no |
operating_system_family | If the requires_compatibilities is FARGATE this field is required. Must be set to a valid option from https://docs.aws.amazon.com/AmazonECS/latest/developerguide/task_definition_parameters.html#runtime-platform. |
string |
"LINUX" |
no |
otel | Configuration for (optional) AWS Distro für OpenTelemetry sidecar. | object({ |
{} |
no |
platform_version | The platform version on which to run your service. Defaults to LATEST. | string |
"LATEST" |
no |
policy_document | AWS Policy JSON describing the permissions required for this service. | string |
"" |
no |
requires_compatibilities | The launch type the task is using. This enables a check to ensure that all of the parameters used in the task definition meet the requirements of the launch type. | set(string) |
[ |
no |
security_groups | A list of security group ids that will be attached additionally to the ecs deployment. | list(string) |
[] |
no |
service_discovery_dns_namespace | The ID of a Service Discovery private DNS namespace. If provided, the module will create a Route 53 Auto Naming Service to enable service discovery using Cloud Map. | string |
"" |
no |
service_name | The service name. Will also be used as Route53 DNS entry. | string |
n/a | yes |
subnet_tags | Map of tags to identify the subnets associated with this service. Each pair must exactly match a pair on the desired subnet. Defaults to { Tier = public } for services with assign_public_ip == true and { Tier = private } otherwise. |
map(string) |
null |
no |
tags | Additional tags (_e.g._ { map-migrated : d-example-443255fsf }) | map(string) |
{} |
no |
target_groups | A list of maps containing key/value pairs that define the target groups to be created. Order of these maps is important and the index of these are to be referenced in listener definitions. Required key/values: name, backend_protocol, backend_port | any |
[] |
no |
task_execution_role_arn | ARN of the task execution role that the Amazon ECS container agent and the Docker daemon can assume. If not provided, a default role will be created and used. | string |
"" |
no |
task_role_arn | ARN of the IAM role that allows your Amazon ECS container task to make calls to other AWS services. If not specified, the default ECS task role created in this module will be used. | string |
"" |
no |
vpc_id | VPC id where the load balancer and other resources will be deployed. | string |
n/a | yes |
Name | Description |
---|---|
alb_target_group_arn_suffixes | ARN suffixes of the created target groups. |
alb_target_group_arns | ARNs of the created target groups. |
autoscaling_target | ECS auto scaling targets if auto scaling enabled. |
cloudwatch_log_group | Name of the CloudWatch log group for container logs. |
container_definitions | Container definitions used by this service including all sidecars. |
ecr_repository_arn | Full ARN of the ECR repository. |
ecr_repository_id | The registry ID where the repository was created. |
ecr_repository_url | The URL of the repository (in the form aws_account_id.dkr.ecr.region.amazonaws.com/repositoryName ) |
task_execution_role_arn | ARN of the task execution role that the Amazon ECS container agent and the Docker daemon can assume. |
task_execution_role_name | Friendly name of the task execution role that the Amazon ECS container agent and the Docker daemon can assume. |
task_execution_role_unique_id | Stable and unique string identifying the IAM role that the Amazon ECS container agent and the Docker daemon can assume. |
task_role_arn | ARN of IAM role that allows your Amazon ECS container task to make calls to other AWS services. |
task_role_name | Friendly name of IAM role that allows your Amazon ECS container task to make calls to other AWS services. |
task_role_unique_id | Stable and unique string identifying the IAM role that allows your Amazon ECS container task to make calls to other AWS services. |