Skip to content

Module Structure

terraform-aws-arc-ecs

Latest Release Last Updated Terraform GitHub Actions

Quality gate

Known Vulnerabilities

Overview

SourceFuse's AWS Reference Architecture Terraform module leverages the terraform-aws-modules/terraform-aws-ecs GitHub repository to facilitate the deployment and management of an AWS ECS (Elastic Container Service) cluster. It streamlines the configuration of ECS tasks, services, and related components, providing a scalable and efficient solution for orchestrating containerized applications. With customizable settings for logging and load balancing the module promotes seamless deployment and management of containerized workloads on AWS.

The module assumes that upstream dependencies, namely networking dependencies, are created upstream and the values are passed into this module via mechanisms such as Terraform data source queries.

The module provisions

  • ECS Cluster - we are focusing on the Fargate launch type, so we do not provision any underlying EC2 instances for the ECS launch type for the time being.
  • Application Load Balancer - default port 80.
  • Health Check Service - vanilla HTTP echo service that is used as the default target group for the load balancer. The purpose of the health check service is to ensure that the core infrastructure, networking, security groups, etc. are configured correctly.
  • Task execution IAM role - used by downstream services for task execution.
  • Tags - the module tags resources for easy reference in the AWS console.

Module Structure

Our approach to ECS Fargate clusters is to provision a cluster and allow downstream services to attach to it via convention based data source queries.

Prerequisites

Before using this module, ensure you have the following:

  • AWS credentials configured.
  • Terraform installed.
  • A working knowledge of Terraform.
  • Network

Getting Started

  1. Define the Module

Initially, it's essential to define a Terraform module, which is organized as a distinct directory encompassing Terraform configuration files. Within this module directory, input variables and output values must be defined in the variables.tf and outputs.tf files, respectively. The following illustrates an example directory structure:

1
2
3
4
ecs/
|-- main.tf
|-- variables.tf
|-- outputs.tf
  1. Define Input Variables

Inside the variables.tf or in *.tfvars file, you should define values for the variables that the module requires.

  1. Use the Module in Your Main Configuration In your main Terraform configuration file (e.g., main.tf), you can use the module. Specify the source of the module, and version, For Example
module "ecs_cluster" {
  source = "./modules/ecs_cluster"

  ecs_cluster = {
    name                        = var.ecs_cluster.name
    configuration               = var.ecs_cluster.configuration
    create_cloudwatch_log_group = var.ecs_cluster.create_cloudwatch_log_group
    service_connect_defaults    = var.ecs_cluster.service_connect_defaults
    settings                    = var.ecs_cluster.settings
  }

  capacity_provider = {
    autoscaling_capacity_providers        = var.capacity_provider.autoscaling_capacity_providers
    default_capacity_provider_use_fargate = var.capacity_provider.default_capacity_provider_use_fargate
    fargate_capacity_providers            = var.capacity_provider.fargate_capacity_providers
  }
}
  1. Output Values

Inside the outputs.tf file of the module, you can define output values that can be referenced in the main configuration. For example:

1
2
3
4
output "cluster_name" {
  description = "Name of the ECS Cluster"
  value       = module.ecs.cluster_name
}
  1. Execute Terraform Commands

After defining your main configuration, navigate to the directory containing your Terraform files and run the following commands:

terraform init
terraform apply
  1. Review and Confirm

Terraform will display a plan showing the changes it intends to make. Review the plan and confirm by typing 'yes' when prompted.

Requirements

Name Version
terraform ~> 1.5
aws ~> 5.0

Providers

No providers.

Modules

Name Source Version
alb ./modules/alb n/a
ecs_cluster ./modules/ecs_cluster n/a
ecs_service ./modules/ecs_service n/a

Resources

No resources.

Inputs

Name Description Type Default Required
alb Configuration settings for the Application Load Balancer (ALB). This includes attributes related to the ALB itself, such as its name, port, protocol, and other optional settings like access logs and tags.
object({
name = optional(string, null)
port = optional(number)
protocol = optional(string, "HTTP")
internal = optional(bool, false)
load_balancer_type = optional(string, "application")
idle_timeout = optional(number, 60)
enable_deletion_protection = optional(bool, false)
enable_http2 = optional(bool, true)
certificate_arn = optional(string, null)
create_alb = optional(bool, false)

access_logs = optional(object({
bucket = string
enabled = optional(bool, false)
prefix = optional(string, "")
}))

tags = optional(map(string), {})
})
n/a yes
alb_target_group List of target groups to create
list(object({
name = optional(string, "target-group")
port = number
protocol = optional(string, null)
protocol_version = optional(string, "HTTP1")
vpc_id = optional(string, "")
target_type = optional(string, "ip")
ip_address_type = optional(string, "ipv4")
load_balancing_algorithm_type = optional(string, "round_robin")
load_balancing_cross_zone_enabled = optional(string, "use_load_balancer_configuration")
deregistration_delay = optional(number, 300)
slow_start = optional(number, 0)
tags = optional(map(string), {})

health_check = optional(object({
enabled = optional(bool, true)
protocol = optional(string, "HTTP")
path = optional(string, "/")
port = optional(string, "traffic-port")
timeout = optional(number, 6)
healthy_threshold = optional(number, 3)
unhealthy_threshold = optional(number, 3)
interval = optional(number, 30)
matcher = optional(string, "200")
}))

stickiness = optional(object({
enabled = optional(bool, true)
type = string
cookie_duration = optional(number, 86400)
})
)

}))
n/a yes
capacity_provider Configuration settings for the ECS capacity providers, including the capacity providers used for autoscaling and Fargate. This variable defines the properties of each capacity provider and how they are managed, such as scaling policies and termination protection.
object({
autoscaling_capacity_providers = map(object({
name = optional(string)
auto_scaling_group_arn = string
managed_termination_protection = optional(string, "DISABLED")
managed_draining = optional(string, "ENABLED")
managed_scaling = optional(object({
instance_warmup_period = optional(number)
maximum_scaling_step_size = optional(number)
minimum_scaling_step_size = optional(number)
status = optional(string)
target_capacity = optional(number)
}))
tags = optional(map(string), {})
}))
use_fargate = bool
fargate_capacity_providers = any
})
n/a yes
cidr_blocks CIDR blocks for security group ingress rules list(string)
[
"0.0.0.0/0"
]
no
ecs_cluster The ECS-specific values to use such as cluster, service, and repository names.

Keys:
- cluster_name: The name of the ECS cluster.
- cluster_configuration: The execute command configuration for the cluster.
- cluster_settings: A list of cluster settings (e.g., container insights). Default is an empty list.
- cluster_service_connect_defaults: Configures a default Service Connect namespace.
- create_cloudwatch_log_group: Boolean flag to specify whether to create a CloudWatch log group for the ECS cluster.
object({
name = string
configuration = optional(object({
execute_command_configuration = optional(object({
kms_key_id = optional(string, "")
logging = optional(string, "DEFAULT")
log_configuration = optional(object({
cloudwatch_encryption_enabled = optional(bool, null)
log_group_name = optional(string, null)
log_group_retention_in_days = optional(number, null)
log_group_kms_key_id = optional(string, null)
log_group_tags = optional(map(string), null)
s3_bucket_name = optional(string, null)
s3_bucket_encryption_enabled = optional(bool, null)
s3_key_prefix = optional(string, null)
}), {})
}), {})
}), {})
create_cloudwatch_log_group = bool
service_connect_defaults = optional(map(string), null)
settings = optional(any, null)
tags = optional(map(string), null)
})
n/a yes
ecs_service The ECS-specific values to use such as cluster, service, and repository names.
object({
cluster_name = string
service_name = string
repository_name = string
enable_load_balancer = bool
aws_lb_target_group_name = optional(string)
create_service = optional(bool, false)
})
n/a yes
environment The environment associated with the ECS service string n/a yes
lb ALB-related information (listening port, deletion protection, security group)
object({
name = string
listener_port = number
deregistration_delay = optional(number)
security_group_id = string
})
n/a yes
listener_rules List of listener rules to create
list(object({
priority = number

conditions = list(object({
field = string
values = list(string)
}))

actions = list(object({
type = string
target_group_arn = optional(string)
order = optional(number)
redirect = optional(object({
protocol = string
port = string
host = optional(string)
path = optional(string)
query = optional(string)
status_code = string
}), null)

fixed_response = optional(object({
content_type = string
message_body = optional(string)
status_code = optional(string)
}), null)
}))
}))
n/a yes
task Task-related information (vCPU, memory, # of tasks, port, and health check info.)
object({
tasks_desired = optional(number)
container_vcpu = optional(number)
container_memory = optional(number)
container_port = number
container_health_check_path = optional(string)
container_definition = optional(string)
environment_variables = optional(map(string))
task_execution_role = optional(string)
})
n/a yes
vpc_id ID of VPC in which all resources need to be created string n/a yes

Outputs

Name Description
alb_name The names of the ALBs.
ecs_cluster_name The name of the ECS cluster.
ecs_service_name The service names of the ECS services.
ecs_task_definition_arn The ARNs of the ECS task definitions.

Development

Versioning

while Contributing or doing git commit please specify the breaking change in your commit message whether its major,minor or patch

For Example

git commit -m "your commit message #major"
By specifying this , it will bump the version and if you don't specify this in your commit message then by default it will consider patch and will bump that accordingly

Prerequisites

Configurations

  • Configure pre-commit hooks
    pre-commit install
    

Tests

  • Tests are available in test directory
  • Configure the dependencies
    1
    2
    3
    cd test/
    go mod init github.com/sourcefuse/terraform-aws-refarch-ecs
    go get github.com/gruntwork-io/terratest/modules/terraform
    
  • Now execute the test
    go test -timeout  30m
    

Authors

This project is authored by: - SourceFuse ARC Team