Skip to content

pagarme/terraform-ecs-application

Repository files navigation

Terraform ECS Application

This module generate all core resources of ECS Application. you can use with Application load balancer and deploy securely with CodeDeploy.

Inspiration

We used these public modules to generate this module in a single one resource module:

This modules are excelents, but we need to customize some itens.

  • Guarantee all resources to receive our tags (we use Billing Tags)
  • Simplify complexibility from module consumers the responsibility to create target groups for CodeDeploy
  • Integrate CodeDeploy with uniformity in all applications (we plan to use this module in varios applications)
  • Remove responsability of customize Autoscaling policy from ECS Application module (We need to use some custom rules for scaling policies)
  • Change loop interaction from count to for_each (for_each is better)
  • Convert some variables from list(some_type) to set(some_type) (sets are immutable when change order of the elements)
  • Converge all decision in a single locals block (better to manage changes and code review)

Features inner this module

  • Create BLUE/GREEN target groups to connect in multiples Listeners in a Application Load Balancers (ALB).
  • Run deploy under Canary or Linear or Blue/Green Deployments under CodeDeploy.

simple-diagram

Terraform Versions

Terraform 1.0. Submit pull-requests to master branch.

Usage

Snippet example of using this code.

module "ecs_service" {
  source = "git@github.com:pagarme/terraform-ecs-application.git"

  code_deploy_deployment_config_name                    = "CodeDeployDefault.ECSLinear10PercentEvery3Minutes"
  code_deploy_deployment_ready_option_action_on_timeout = "CONTINUE_DEPLOYMENT"

  code_deploy_load_balancer_production_listener_arn = var.lb_listener_arn
  code_deploy_load_balancer_target_group_names      = [module.target_groups.target_group_blue.name, module.target_groups.target_group_green.name]

  desired_count = var.ecs_service_desired_count

  ecs_cluster_arn  = var.ecs_cluster_arn
  ecs_cluster_name = var.ecs_cluster_name

  # In this example, additional permissions are given for CloudWatch Log Group, ECR (so Fargate can pull images) and Parameter Store. Feel free to remove or add other permissions according to your case.
  iam_policy_statements_task_execution = [{
    actions = [
      "logs:CreateLogStream",
      "logs:PutLogEvents",
    ]
    resources = ["${var.cloudwatch_log_group_arn}:*"]
    }, {
    actions = [
      "ecr:GetDownloadUrlForLayer",
      "ecr:BatchCheckLayerAvailability",
      "ecr:DescribeRepositories",
      "ecr:BatchGetImage",
      "ecr:InitiateLayerUpload",
      "ecr:UploadLayerPart",
      "ecr:CompleteLayerUpload",
      "ecr:PutImage",
      "ecr:ListImages",
    ]
    resources = var.ecr_arns
    }, {
    actions = [
      "ssm:GetParameter",
      "ssm:GetParameters",
    ]
    resources = var.ssm_parameter_arns
  }]

  load_balancer_container_name   = var.ecs_cluster_name
  load_balancer_target_group_arn = module.target_groups.target_group_blue.arn

  name = local.ecs_service_name

  network_assign_public_ip = true
  network_subnets          = var.subnet_ids
  network_vpc_id           = var.vpc_id

  # Here, you probably want to use the Load Balancer Security Group
  source_security_group_id = var.security_group_id

  task_definition_container_definitions = var.task_definition_container_definitions # JSON encoded string
  task_definition_cpu                   = 2048
  task_definition_memory                = 4096
}

module "target_groups" {
  source = "git@github.com:pagarme/terraform-ecs-application.git//modules/load-balancer/target-groups"

  health_check_path = "/_health_check"
  name              = var.target_groups_name_prefix
  port              = 80
  vpc_id            = var.vpc_id
}

Limitations (Some limitations we be solved later)

  • Only with load balancer, we have CodeDeploy
  • If you will use Service Discovery from AWS, we can't help you with CodeDeploy (AWS Limitation?)

Requirements

Name Version
terraform >= 1.0
aws >= 3.0

Providers

No providers.

Modules

Name Source Version
code_deploy ./modules/code-deploy n/a
ecs_service ./modules/ecs/service n/a

Resources

No resources.

Inputs

Name Description Type Default Required
code_deploy_auto_rollback_enabled Indicates whether a defined automatic rollback configuration is currently enabled for this Deployment Group. If you enable automatic rollback, you must specify at least one event type. Default: true bool true no
code_deploy_auto_rollback_events The event type or types that trigger a rollback. Supported types are DEPLOYMENT_FAILURE and DEPLOYMENT_STOP_ON_ALARM. Default: [DEPLOYMENT_FAILURE] set(string)
[
"DEPLOYMENT_FAILURE"
]
no
code_deploy_deployment_config_name The name of the group's deployment config. string n/a yes
code_deploy_deployment_ready_option_action_on_timeout When to reroute traffic from an original environment to a replacement environment in a blue/green deployment. Supported types are CONTINUE_DEPLOYMENT and STOP_DEPLOYMENT. string n/a yes
code_deploy_deployment_ready_option_wait_time_in_minutes The number of minutes to wait before the status of a blue/green deployment changed to Stopped if rerouting is not started manually. Applies only to the STOP_DEPLOYMENT option for action_on_timeout. Default: 20 number 20 no
code_deploy_deployment_termination_wait_time_in_minutes The number of minutes to wait after a successful blue/green deployment before terminating instances from the original environment. Default: 20 number 20 no
code_deploy_load_balancer_production_listener_arn ARN of the load balancer production listener. string n/a yes
code_deploy_load_balancer_target_group_names Names of the blue and green target groups. set(string) n/a yes
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. Default: 200 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. Default: 100 number 100 no
desired_count Number of instances of the task definition to place and keep running. Default: 1 number 1 no
ecs_cluster_arn ARN of an ECS cluster string n/a yes
ecs_cluster_name The name of the ECS cluster string n/a yes
health_check_grace_period_seconds Seconds to ignore failing load balancer health checks on newly instantiated tasks to prevent premature shutdown, up to 2147483647. Default: 60 number 60 no
iam_policy_statements_task_execution Additional policy statements for the task execution role policy.
set(object({
actions = set(string)
resources = set(string)
}))
[] no
launch_type Use FARGATE or EC2. Default: FARGATE string "FARGATE" no
load_balancer_container_name Name of the container to associate with the load balancer (as it appears in a container definition). string n/a yes
load_balancer_target_group_arn ARN of the Load Balancer target group to associate with the service. string n/a yes
name Name of the service string n/a yes
network_assign_public_ip Assign a public IP address to the ENI (Fargate launch type only). Valid values are true or false. Default false. bool false no
network_subnets Subnets associated with the task or service. set(string) n/a yes
network_vpc_id The VPC id. string n/a yes
platform_version Platform version on which to run your service. Only applicable for launch_type set to FARGATE. Default: 1.4.0 string "1.4.0" no
source_security_group_id Security group id to allow access from string n/a yes
task_definition_container_definitions A list of valid container definitions provided as a single valid JSON document. string n/a yes
task_definition_cpu Number of cpu units used by the task. If the launch_type is FARGATE this field is required. number n/a yes
task_definition_memory Amount (in MiB) of memory used by the task. If the launch_type is FARGATE this field is required. number n/a yes

Outputs

Name Description
code_deploy The code deploy outputs.
ecs_service The ESC service outputs.

Developer Setup

Install dependencies (macOS)

brew install pre-commit go terraform terraform-docs

Testing

Terratest is being used for automated testing with this module. Tests in the test folder can be run locally by running the following command:

make test

Or with aws-vault:

AWS_VAULT_KEYCHAIN_NAME=<NAME> aws-vault exec <PROFILE> -- make test