/terraform-aws-ecs

Module that runs service in ECS

Primary LanguageHCL

terraform-aws-ecs

The module creates an Elastic Container Service and runs one docker image in it.

ECS.drawio.png

A user is expected to create a VPC, subnets (See the service network module if you need to do it), and a Route53 zone.

The module uses the infrahouse/website-pod/aws module to create a load balancer, autoscaling group, and update DNS.

Usage

Basically, you need to pass the docker image and subnets where to place a load balancer and autoscaling group.

The module will create an SSL certificate and a DNS record. If the dns_names is ["www"] and the zone is "domain.com", the module will create a record "www.domain.com". You can specify more than one DNS name, then the module will create DNS records for all of them and the certificate will list them as aliases. You can also specify an empty name - dns_names = ["", "www"] - if you want a popular setup https://domain.com + https://www.domain.com/.

For usage see how the module is used in the using tests in test_data/test_module.

module "httpd" {
  source  = "infrahouse/ecs/aws"
  version = "3.2.0"
  providers = {
    aws     = aws
    aws.dns = aws
  }
  load_balancer_subnets         = module.service-network.subnet_public_ids
  asg_subnets                   = module.service-network.subnet_private_ids
  dns_names                     = ["foo-ecs"]
  docker_image                  = "httpd"
  container_port                = 80
  service_name                  = var.service_name
  ssh_key_name                  = aws_key_pair.test.key_name
  zone_id                       = data.aws_route53_zone.cicd.zone_id
  internet_gateway_id           = module.service-network.internet_gateway_id
}

Mount EFS volume

The module can attach one or more EFS volumes to a container.

To do that, create the EFS volume with a mount point:

resource "aws_efs_file_system" "my-volume" {
  creation_token = "my-volume"
  tags = {
    Name = "my-volume"
  }
}

resource "aws_efs_mount_target" "my-volume" {
  for_each       = toset(var.subnet_private_ids)
  file_system_id = aws_efs_file_system.my-volume.id
  subnet_id      = each.key
}

Pass the volumes to the ECS module:

module "httpd" {
  source  = "infrahouse/ecs/aws"
  version = "3.2.0"
  providers = {
    aws     = aws
    aws.dns = aws
  }
...
  task_volumes = {
    "my-volume" : {
      file_system_id : aws_efs_file_system.my-volume.id
      container_path : "/mnt/"
    }
}

Requirements

Name Version
terraform ~> 1.5
aws ~> 5.56
cloudinit ~> 2.3

Providers

Name Version
aws ~> 5.56
cloudinit ~> 2.3

Modules

Name Source Version
pod registry.infrahouse.com/infrahouse/website-pod/aws 3.3.7

Resources

Name Type
aws_appautoscaling_policy.ecs_policy resource
aws_appautoscaling_target.ecs_target resource
aws_ecs_capacity_provider.ecs resource
aws_ecs_cluster.ecs resource
aws_ecs_cluster_capacity_providers.ecs resource
aws_ecs_service.ecs resource
aws_ecs_task_definition.ecs resource
aws_iam_role.ecs_task_execution_role resource
aws_iam_role_policy_attachment.ecs_task_execution_role_policy resource
aws_security_group.backend_extra resource
aws_vpc_security_group_ingress_rule.backend_extra_reserved resource
aws_vpc_security_group_ingress_rule.backend_extra_user resource
aws_ami.ecs data source
aws_caller_identity.current data source
aws_ec2_instance_type.ecs data source
aws_iam_policy.ecs-task-execution-role-policy data source
aws_iam_policy_document.assume_role_policy data source
aws_iam_policy_document.instance_policy data source
aws_key_pair.ssh_key_pair data source
aws_region.current data source
aws_subnet.selected data source
cloudinit_config.ecs data source

Inputs

Name Description Type Default Required
alb_access_log_force_destroy Destroy S3 bucket with access logs even if non-empty bool false no
alb_healthcheck_interval Number of seconds between checks number 5 no
alb_healthcheck_path Path on the webserver that the elb will check to determine whether the instance is healthy or not. string "/index.html" no
alb_healthcheck_response_code_matcher Range of http return codes that can match string "200-299" no
alb_idle_timeout The time in seconds that the connection is allowed to be idle. number 60 no
alb_internal If true, the LB will be internal. bool false no
ami_id Image for host EC2 instances. If not specified, the latest Amazon image will be used. string null no
asg_health_check_grace_period ASG will wait up to this number of seconds for instance to become healthy number 300 no
asg_instance_type EC2 instances type string "t3.micro" no
asg_max_size Maximum number of instances in ASG. number 10 no
asg_min_size Minimum number of instances in ASG. number 2 no
asg_subnets Auto Scaling Group Subnets. list(string) n/a yes
autoscaling_target_cpu_usage How much CPU an ECS service aims to use. number 80 no
container_command If specified, use this list of strings as a docker command. list(string) null no
container_cpu Number of CPU units that a container is going to use. number 200 no
container_healthcheck_command A shell command that a container runs to check if it's healthy. Exit code 0 means healthy, non-zero - unhealthy. string `"curl -f http://localhost/
container_memory Amount of RAM in megabytes the container is going to use. number 128 no
container_port TCP port that a container serves client requests on. number 8080 no
dns_names List of hostnames the module will create in var.zone_id. list(string) n/a yes
docker_image A container image that will run the service. string n/a yes
environment Name of environment. string "development" no
extra_files Additional files to create on a host EC2 instance.
list(object({
content = string
path = string
permissions = string
}))
[] no
internet_gateway_id Internet gateway id. Usually created by 'infrahouse/service-network/aws' string n/a yes
load_balancer_subnets Load Balancer Subnets. list(string) n/a yes
managed_draining Enables or disables a graceful shutdown of instances without disturbing workloads. bool true no
managed_termination_protection Enables or disables container-aware termination of instances in the auto scaling group when scale-in happens. bool true no
root_volume_size Root volume size in EC2 instance in Gigabytes number 30 no
service_health_check_grace_period_seconds Seconds to ignore failing load balancer health checks on newly instantiated tasks to prevent premature shutdown, up to 2147483647. number null no
service_name Service name. string n/a yes
ssh_key_name ssh key name installed in ECS host instances. string n/a yes
task_desired_count Number of containers the ECS service will maintain. number 1 no
task_efs_volumes Map name->{file_system_id, container_path} of EFS volumes defined in task and available for containers to mount.
map(
object(
{
file_system_id : string
container_path : string
}
)
)
{} no
task_environment_variables Environment variables passed down to a task.
list(
object(
{
name : string
value : string
}
)
)
[] no
task_ipc_mode The IPC resource namespace to use for the containers in the task. See https://docs.aws.amazon.com/AmazonECS/latest/APIReference/API_TaskDefinition.html string null no
task_local_volumes Map name->{host_path, container_path} of local volumes defined in task and available for containers to mount.
map(
object(
{
host_path : string
container_path : string
}
)
)
{} no
task_max_count Highest number of tasks to run number 10 no
task_min_count Lowest number of tasks to run number 1 no
task_role_arn Task Role ARN. The role will be assumed by a container. string null no
users A list of maps with user definitions according to the cloud-init format any null no
zone_id Zone where DNS records will be created for the service and certificate validation. string n/a yes

Outputs

Name Description
asg_arn Autoscaling group ARN created for the ECS service.
asg_name Autoscaling group name created for the ECS service.
service_arn ECS service ARN.