Skip to content

Repo for managing the ECS Fargate Terraform Module.

License

Notifications You must be signed in to change notification settings

sourcefuse/terraform-aws-arc-ecs

Repository files navigation

Module Structure

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, load balancing, and service discovery, 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.

Module Structure

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.
  • Application Load Balancer - default port 80 to 443 redirect.
  • 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.
  • Utilizes ACM to generate a certificate specific to the ALB.
  • Tags/SSM params - the module tags resources and outputs SSM params that can be used in data source lookups downstream for ECS services to reference to deploy into the cluster.

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.
  • Route 53 hosted zone
  • 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:

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" {
  source = "sourcefuse/arc-ecs/aws"
  version     = "1.5.2"

  environment = var.environment
  namespace   = var.namespace

  vpc_id                  = data.aws_vpc.vpc.id
  alb_subnet_ids          = data.aws_subnets.public.ids
  health_check_subnet_ids = data.aws_subnets.private.ids

  // --- Devs: DO NOT override, otherwise tests will fail --- //
  access_logs_enabled                             = false
  alb_access_logs_s3_bucket_force_destroy         = true
  alb_access_logs_s3_bucket_force_destroy_enabled = true
  // -------------------------- END ------------------------- //

  ## create acm certificate and dns record for health check
  route_53_zone_name            = var.route_53_zone
  route_53_zone_id              = data.aws_route53_zone.this.id
  acm_domain_name               = "healthcheck-ecs-${var.namespace}-${var.environment}.${local.route_53_zone}"
  acm_subject_alternative_names = []
  health_check_route_53_records = [
    "healthcheck-ecs-${var.namespace}-${var.environment}.${local.route_53_zone}"
  ]

  service_discovery_private_dns_namespace = [
    "${var.namespace}.${var.environment}.${local.route_53_zone}"
  ]

  tags = module.tags.tags
}
  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:

output "cluster_name" {
  description = "Name of the ECS Cluster"
  value       = module.ecs.cluster_name
}

output "health_check_fqdn" {
  description = "Health check FQDN record created in Route 53."
  value       = module.ecs.health_check_fqdn
}
  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.4, < 2.0.0
aws >= 4.0, < 6.0

Providers

Name Version
aws 4.67.0

Modules

Name Source Version
acm git::https://github.com/cloudposse/terraform-aws-acm-request-certificate 0.17.0
alb ./modules/alb n/a
alb_sg git::https://github.com/cloudposse/terraform-aws-security-group 2.0.0
ecs git::https://github.com/terraform-aws-modules/terraform-aws-ecs v5.11.1
health_check ./modules/health-check n/a

Resources

Name Type
aws_cloudwatch_log_group.this resource
aws_iam_role.execution resource
aws_iam_role_policy_attachment.execution resource
aws_lb_listener.http resource
aws_lb_listener.https resource
aws_service_discovery_private_dns_namespace.this resource
aws_ssm_parameter.this resource
aws_iam_policy_document.assume data source

Inputs

Name Description Type Default Required
access_logs_enabled A boolean flag to enable/disable access_logs bool true no
acm_domain_name Domain name the ACM Certificate belongs to string n/a yes
acm_process_domain_validation_options Flag to enable/disable processing of the record to add to the DNS zone to complete certificate validation bool true no
acm_process_domain_validation_record_ttl The TTL of the record to add to the DNS zone to complete certificate validation string "300" no
acm_subject_alternative_names Subject alternative names for the ACM Certificate list(string) [] no
additional_ssm_params Additional SSM Parameters you would like to add for your ECS configuration.
The optional value defaults are:
description = "Managed by Terraform"
type = "SecureString"
overwrite = true
list(object({
name = string
value = string
description = string
type = string
overwrite = bool
}))
[] no
alb_access_logs_s3_bucket_force_destroy A boolean that indicates all objects should be deleted from the ALB access logs S3 bucket so that the bucket can be destroyed without error bool false no
alb_access_logs_s3_bucket_force_destroy_enabled When true, permits force_destroy to be set to true.
This is an extra safety precaution to reduce the chance that Terraform will destroy and recreate
your S3 bucket, causing COMPLETE LOSS OF ALL DATA even if it was stored in Glacier.
WARNING: Upgrading this module from a version prior to 0.27.0 to this version
will cause Terraform to delete your existing S3 bucket CAUSING COMPLETE DATA LOSS
unless you follow the upgrade instructions on the Wiki here.
See additional instructions for upgrading from v0.27.0 to v0.28.0 here.
bool false no
alb_certificate_arn ALB Certificate ARN. If var.create_acm_certificate is true, this will be ignored. string null no
alb_idle_timeout The time that the connection is allowed to be idle. number 300 no
alb_internal Determines if this load balancer is internally or externally facing. bool false no
alb_ssl_policy Load Balancer SSL policy. string "ELBSecurityPolicy-FS-1-2-Res-2020-10" no
alb_subnet_ids Subnet Ids assigned to the LB list(string) n/a yes
cluster_name_override Name to assign the cluster. If null, the default will be namespace-environment-cluster string null no
create_acm_certificate Create an ACM Certificate to use with the ALB bool true no
environment ID element. Usually used for region e.g. 'uw2', 'us-west-2', OR role 'prod', 'staging', 'dev', 'UAT' string n/a yes
execution_policy_attachment_arns The ARNs of the policies you want to apply list(string)
[
"arn:aws:iam::aws:policy/AmazonSSMReadOnlyAccess",
"arn:aws:iam::aws:policy/service-role/AmazonECSTaskExecutionRolePolicy"
]
no
externally_managed_route_53_record If there is a Route 53 Zone externally managed from the account you are running in. If true, you will have to manage your DNS yourself. bool false no
health_check_route_53_records List of Route 53 records for the health check service. list(string) n/a yes
health_check_subnet_ids Subnet IDs for the health check tasks to run in. If not defined, this will use var.alb_subnet_ids. list(string) [] no
log_group_retention_days 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, 1096,
1827, 2192, 2557, 2922, 3288, 3653, and 0.
If you select 0, the events in the log group are always retained and never expire
number 30 no
log_group_skip_destroy Set to true if you do not wish the log group (and any logs it may contain) to be deleted at destroy time, and instead just remove the log group from the Terraform state. bool false no
namespace Namespace your resource belongs to.
Usually an abbreviation of your organization name, e.g. 'example' or 'arc', to help ensure generated IDs are globally unique"
string n/a yes
route_53_zone_id Route 53 zone ID string null no
route_53_zone_name Route 53 domain to generate an ACM request for and to create A records against, i.e. sfrefarch.com. A wildcard subject alternative name is generated with the certificate. string null no
service_discovery_private_dns_namespace The name of the namespace list(string)
[
"default.example.local"
]
no
tags Tags to assign the resources. map(string) {} no
vpc_id Id of the VPC where the resources will live string n/a yes

Outputs

Name Description
alb_arn ARN to the ALB
alb_certificate_arn ACM Certificate ARN
alb_dns_name External DNS name to the ALB
alb_dns_zone_id External DNS name to the ALB
alb_http_listener_arn HTTP listener ARN for downstream services to use
alb_https_listener_arn HTTPS listener ARN for downstream services to use
alb_security_group_id ALB Security Group
cluster_arn ECS Cluster ARN
cluster_id ECS Cluster ID
cluster_name ECS Cluster name
health_check_fqdn Health check FQDN record created in Route 53.

SSM Parameters

There are some commonly referenced outputs generated by this module. These outputs are also published to SSM for ease of access for downstream resources.
The default SSM Parameter format used by this module is the following:

[
  ## alb
  {
    name        = "/${var.namespace}/${var.environment}/alb/${module.alb.alb_name}/endpoint"
    value       = module.alb.alb_dns_name
    description = "ALB DNS Endpoint"
    type        = "String"
  },
  {
    name        = "/${var.namespace}/${var.environment}/alb/${module.alb.alb_name}/arn"
    value       = module.alb.alb_arn
    description = "ALB ARN"
    type        = "String"
  },

  ## ecs
  {
    name        = "/${var.namespace}/${var.environment}/ecs/${module.ecs.cluster_name}/id"
    value       = module.ecs.cluster_id
    description = "ECS Cluster ID"
    type        = "String"
  },
  {
    name        = "/${var.namespace}/${var.environment}/ecs/${module.ecs.cluster_name}/arn"
    value       = module.ecs.cluster_arn
    description = "ECS Cluster ARN"
    type        = "String"
  }
]

You can append to this array by adding values to var.additional_ssm_params.

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
    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