Skip to content

l4gdev/terraform-aws-ecs-service

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

57 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

L4G ECS module

Supported features

  • Web server apps with ALB
  • ALB listener rules registrations.
  • TCP/UDP servers with NLB
  • Workers.
  • Cron jobs.
  • EC2 or FARGATE launch type.
  • Autoscaling
  • Volume mounts
  • Webserver as a sidecar container
  • Secrets from AWS Secrets Manager

Java app example

module "app" {
  source  = "registry.terraform.io/l4gdev/ecs-service/aws"
  version = "xxxxx"

  application_config = {
    name        = var.application_name
    environment = var.environment
    cpu         = 0,
    memory      = 0,
    port        = 5000
    image       = var.image,
    environments_variables = merge(
      local.app_envs,
    )
  }
   web_server             = {
    enabled = true
    name    = "nginx"
    image   = var.nginx_image
    port    = 80
  }
   
     placement_constraints = [
    {
      type       = "memberOf"
      expression = "attribute:ecs.instance-type =~ c5.*"
    }
  ]
  list_of_secrets_in_secrets_manager_to_load = []

  aws_alb_listener_rule_conditions = [
    {
      type   = "host_header",
      values = var.domains
    }
  ]

  health_checks = [
    {
      enabled             = true
      healthy_threshold   = 5
      interval            = 10
      matcher             = 200
      path                = "/api/v1/health"
      timeout             = 5
      unhealthy_threshold = 5
    }
  ]

  ecs_settings = {
    ecs_launch_type  = "EC2",
    ecs_cluster_name = local.ecs_cluster_name,
    run_type         = "WEB",
  }

  alb_listener_arn         = data.terraform_remote_state.backend.outputs.alb_arn
  alb_deregistration_delay = 30

  tags = {
    Environment = var.environment
    Service     = var.application_name
  }

  service_policy = data.aws_iam_policy_document.app_policy.json
  vpc_id         = local.vpc.vpc_id

  deployment = {
    first_deployment_desired_count = 1
    minimum_healthy_percent        = 50
    maximum_healthy_percent        = 200
    enable_asg                     = false
  }
}

Worker Example

locals {
  worker_configuration = [
    {
      args          = "my:awesome:consumer",
      desired_count = 1,
    },
  ]
}

module "asset-workers" {
  source   = "registry.terraform.io/l4gdev/ecs-service/aws"
  version  = "xxxx"
  for_each = { for worker in local.worker_configuration : replace(worker.args, ":", "-") => worker }

  application_config = {
    name                   = "worker-${each.key}",
    cpu                    = 0,
    memory                 = 150,
    port                   = 0
    image                  = var.image,
    environment            = var.environment
    environments_variables = local.app_envs
  }
  deployment = {
    first_deployment_desired_count = 1
    minimum_healthy_percent        = 50
    maximum_healthy_percent        = 200
    enable_asg                     = true
    auto_scaling = {
      minimum = 1
      maximum = 10
      rules = [
        {
          name               = "cpu_scale_up"
          metric             = "CPUUtilization"
          statistic          = "Average"
          comparison_operator = "GreaterThanOrEqualToThreshold"
          metric_period      = 120
          cooldown           = 60
          threshold          = 40
          period             = 60
          evaluation_periods = 2 #datapoins
          scaling_adjustment = 2
          }, {
          name               = "cpu_scale_down"
          metric             = "CPUUtilization"
          statistic          = "Average"
          comparison_operator = "LessThanThreshold"
          metric_period      = 120
          cooldown           = 300
          threshold          = 20
          period             = 60
          evaluation_periods = 5
          scaling_adjustment = -1
        }
      ]
    }
  }

  list_of_secrets_in_secrets_manager_to_load = local.list_of_secrets_in_secrets_manager_to_load
  worker_configuration = {
    execution_script = local.execution_script
    args             = each.value["args"]
  }
  desired_count = each.value["desired_count"]

  ecs_settings = {
    ecs_launch_type  = "EC2",
    ecs_cluster_name = local.terraform_env.ecs_cluster.name,
    run_type         = "WORKER",
  }

  tags = {
    Environment = var.environment
    Service     = var.application_name
  }
  security_groups = [local.terraform_env.ecs_cluster.security_group_id]
  subnets         = local.terraform_env.vpc.private_subnets
  vpc_id          = local.terraform_env.vpc.vpc_id
  service_policy  = data.aws_iam_policy_document.app_policy.json
}

Requirements

Name Version
terraform >= 1.3.0

Providers

Name Version
aws 4.59.0
local 2.4.0

Modules

Name Source Version
asg ./asg n/a
cron ./cron/ n/a

Resources

Name Type
aws_cloudwatch_log_group.task_log_group resource
aws_cloudwatch_log_group.task_log_group_webserver resource
aws_ecs_service.service_net resource
aws_ecs_service.service_web resource
aws_ecs_service.service_worker resource
aws_ecs_task_definition.service resource
aws_iam_role.ecs_events resource
aws_iam_role.ecs_task_execution_role resource
aws_iam_role.service_role resource
aws_iam_role_policy.ecs_events_run_task_with_any_role resource
aws_iam_role_policy.get_s3_envs resource
aws_iam_role_policy.service resource
aws_iam_role_policy.ssm_access resource
aws_iam_role_policy_attachment.ecs-execution resource
aws_lb_listener.network_lb_listener resource
aws_lb_listener_rule.web-app-advance resource
aws_lb_listener_rule.web-app-simple resource
aws_lb_target_group.app resource
aws_lb_target_group.app_test resource
aws_lb_target_group.network_lb_target resource
aws_s3_object.secrets resource
local_file.secrets resource
aws_iam_policy_document.placeholder data source
aws_region.current data source
aws_secretsmanager_secret.secrets data source
aws_secretsmanager_secret_version.secrets data source

Inputs

Name Description Type Default Required
alb_deregistration_delay The amount time for Elastic Load Balancing to wait before changing the state of a deregistering target from draining to unused. The range is 0-3600 seconds. The default value is 300 seconds number 30 no
alb_listener_arn The ARN of the listener to which to attach the routing rule. string "" no
alb_slow_start The amount time for targets to warm up before the load balancer sends them a full share of requests. The range is 30-900 seconds or 0 to disable. The default value is 0 seconds.The amount time for targets to warm up before the load balancer sends them a full share of requests. The range is 30-900 seconds or 0 to disable. The default value is 0 seconds. number 0 no
application_config n/a
object({
name = string,
environment = string,
cpu = optional(number, 0),
memory = optional(number, 0),
image = string,
entrypoint = optional(list(string), null)
cmd = optional(list(string), null)
port = optional(number)
environments_variables = any
})
n/a yes
aws_alb_listener_rule_conditions Example [{ type = "host_header", values = ["google.com"] }, { type = "path_pattern", values = ["/"] }]
list(object({
type = string
values = list(string)
}))
[] no
aws_alb_listener_rule_conditions_advanced A list of maps describing the conditions of the rule. The order in which conditions are specified is not significant. Any condition block with a type of path-pattern or host-header must include a values block. For any other condition type, only one values block can be specified. For more information, see the AWS documentation on Listener Rules. Example:
list(object({
name = string
rules = list(object({
type = string
values = list(string)
http_header_name = optional(string, null)
}))
auth = optional(object({
type = string
authorization_endpoint = optional(string, null) # oidc
client_id = optional(string, null) # oidc
client_secret = optional(string, null) # oidc
issuer = optional(string, null) # oidc
token_endpoint = optional(string, null) # oidc
user_info_endpoint = optional(string, null) # oidc
authentication_request_extra_params = optional(list(string), null) # cognito
on_unauthenticated_request = optional(string, null) # cognito
scope = optional(string, null) # cognito
session_cookie_name = optional(string, null) # cognito
session_timeout = optional(number, null) # cognito
user_pool_arn = optional(string, null) # cognito
user_pool_client_id = optional(string, null) # cognito
user_pool_domain = optional(string, null) # cognito
}), null)
}))
null no
capacity_provider_strategy n/a
list(object({
capacity_provider = string
weight = optional(number, 1)
base = optional(number, 0)
}))
[] no
cloudwatch_logs Cloudwatch logs configuration
object({
enabled = optional(bool, true)
retention_in_days = optional(number, 30)
})
{
"enabled": true,
"retention_in_days": 30
}
no
cron Allows to set cron jobs using aws event bridge please check examples
object({
settings = list(object({
name = string
args = list(string)
schedule_expression = string
desired_count = optional(number, 1)
})),
execution_script = list(string)
})
null no
deployment Desired count will be ignored after first deployment
object({
first_deployment_desired_count = optional(number, 1) # I have no idea
minimum_healthy_percent = optional(number, 50)
maximum_healthy_percent = optional(number, 200)
enable_asg = optional(bool, false)
auto_scaling = optional(object({
minimum = number
maximum = number
rules = list(object({
name = string
metric = string
metric_period = number
cooldown = number
threshold = number
period = number
comparison_operator = string
statistic = string
evaluation_periods = number
scaling_adjustment = number
}))
}))
})
n/a yes
docker_labels Docker labels to be added to the container. The labels map is a set of key/value pairs. Application container is named var.application_config.name .To add labels to webserver you have to set container_name to webserver name for example nginx.
list(object({
container_name = string
labels = optional(map(string), {})
}))
[] no
ecs_settings n/a
object({
ecs_launch_type = string,
ecs_cluster_name = string,
run_type = string,
})
n/a yes
enable_code_build Enable code build bool false no
fargate_datadog_sidecar_parameters n/a
object({
image = optional(string, "public.ecr.aws/datadog/agent:latest")
dd_site = optional(string, "datadoghq.eu")
key = string
})
{
"dd_site": "datadoghq.eu",
"image": "public.ecr.aws/datadog/agent:latest",
"key": null
}
no
health_checks Health check configuration for the service.
list(object({
enabled = optional(bool, true)
healthy_threshold = number
interval = number
matcher = string
path = string
timeout = number
unhealthy_threshold = number
}))
[
{
"enabled": true,
"healthy_threshold": 5,
"interval": 10,
"matcher": 200,
"path": "/",
"timeout": 10,
"unhealthy_threshold": 5
}
]
no
list_of_secrets_in_secrets_manager_to_load List of names of secret manager secrets to load by theirs name. Module will load all secrets from secret manager and put them to envs. set(string) [] no
network_lb Network load balancer configuration
object({
nlb_arn = string,
port_configuration = set(object({
protocol = string,
port = number
}))
})
{
"nlb_arn": "",
"port_configuration": []
}
no
network_mode The network mode to use for the tasks. The valid values are awsvpc, bridge, host, and none. If no network mode is specified, the default is bridge. string null no
ordered_placement_strategy https://docs.aws.amazon.com/AmazonECS/latest/APIReference/API_PlacementStrategy.html
list(object({
type = string
field = optional(string, null)
}))
[
{
"field": "attribute:ecs.availability-zone",
"type": "spread"
}
]
no
placement_constraints Placement constraints for the task
list(object({
type = string
expression = string
}))
[] no
scheduling_strategy Scheduling strategy to use for the service. The valid values are REPLICA and DAEMON. Defaults to REPLICA. Note that Tasks using the Fargate launch type or the CODE_DEPLOY or EXTERNAL deployment controller types don't support the DAEMON scheduling strategy. string "REPLICA" no
security_groups Setting requires network_mode to be set to awsvpc. list(string) [] no
service_policy please use aws_iam_policy_document to define your policy string "" no
store_secrets_at_s3 Store secrets at s3 bucket, i dont recommend this option
object({
enable = bool
bucket_name = string
prefix_name = optional(string, "")
})
{
"bucket_name": "",
"enable": false,
"prefix_name": ""
}
no
subnets Setting requires network_mode to be set to awsvpc. list(string) [] no
tags A mapping of tags to assign to the resource. map(string) {} no
use_static_port_on_ec2 If set to true, the service will use the random port on the EC2 instances. bool false no
volumes Volumes to attach to the container. This parameter maps to Volumes in the Create a container section of the Docker Remote API and the --volume option to docker run. List of maps with keys: name, host_path, container_path, read_only list(any) [] no
volumes_mount_point Volumes mount point at host
list(object({
sourceVolume = string
containerPath = string
readOnly = bool
}))
[] no
vpc_id The ID of the VPC. string n/a yes
web_server n/a
object({
enabled = bool
name = optional(string, "nginx")
container_port = optional(number, 80)
host_port = optional(number, 0)
image = optional(string, "nginx:latest")
command = optional(list(string), null)
entrypoint = optional(list(string), null)
})
{
"enabled": false
}
no
worker_configuration Allows to set worker configuration
object({
binary = optional(string, "node")
execution_script = optional(string, "")
args = optional(string, "")
})
null no

Outputs

Name Description
s3_secrets n/a
task_iam_role_arn n/a
task_iam_role_name n/a

About

No description, website, or topics provided.

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages