Giter Site home page Giter Site logo

archi-village-kobayashi / terraform-aws-ecs-fargate-3 Goto Github PK

View Code? Open in Web Editor NEW

This project forked from stroeer/terraform-aws-ecs-fargate

0.0 0.0 0.0 1.75 MB

Terraform module for ECS Fargate Services

Home Page: https://registry.terraform.io/modules/stroeer/ecs-fargate/aws

License: Apache License 2.0

Makefile 4.48% HCL 95.52%

terraform-aws-ecs-fargate-3's Introduction

AWS Fargate ECS Terraform Module

CI Terraform Registry Terraform Version License: Apache 2.0

A somewhat opinionated Terraform module to create Fargate ECS resources on AWS.

This module does the heavy lifting for:

Requirements

The following resources are referenced from this module and therefore prerequisites:

  • Subnets — within this VPC, there must be at least one subnet tagged with either Tier = (public|private). The fargate Elastic Network Interface will be placed here.
  • SG (1) — within this VPC there must be a security group Name = default
  • SG (2) — within this VPC there must be a security group to allow traffic from ALB Name = fargate-allow-alb-traffic
  • IAM role — There should be a role named ssm_ecs_task_execution_role that will be used as a task execution role

Load Balancing

` A service can be attached to a ALB. Neither the ALB nor the Listeners are created by the module (see example app).

Sample for an service running a HTTP service on port 80:

module "service" {
  source = "..."

  target_groups = [
    {
      name             = "${local.service_name}-public"
      backend_port     = 80
      backend_protocol = "HTTP"
      target_type      = "ip"
      health_check     = {
        enabled = true
        path    = "/"
      }
    }
  ]

  https_listener_rules = [{
    listener_arn = aws_lb_listener.http.arn

    priority   = 42
    actions    = [{
      type               = "forward"
      target_group_index = 0
    }]
    conditions = [{
      path_patterns = ["/"]
      host_headers  = ["www.example.com"]
    }]
  }]
}

DNS / Route53

DNS is also not part of this module and needs to be provided by the caller:

resource "aws_route53_record" "this" {
  name    = "..."
  type    = "..."
  zone_id = "..."
}

this should point to your ALB. If TLS/HTTPS will be used an ACM certificate is also required.

In order to disable ALB target group attachments (e.g. for services in an App Mesh) set target_groups = [].

AppAutoscaling

module "service" {
  source = "..."

  appautoscaling_settings = {
    predefined_metric_type = "ECSServiceAverageCPUUtilization"
    target_value           = 30
    max_capacity           = 8
    min_capacity           = 2
    disable_scale_in       = true
    scale_in_cooldown      = 120
    scale_out_cooldown     = 15
  }
}

Use this configuration map to enable and alter the autoscaling settings for this app.

key description
target_value (mandatory) the target value, refers to predefined_metric_type
predefined_metric_type see docs for possible values
max_capacity upper threshold for scale out
min_capacity lower threshold for scale in
disable_scale_in prevent scale in if set to true
scale_in_cooldown delay (in seconds) between scale in events
scale_out_cooldown delay (in seconds) between scale out events

When using the automated deployment pipeline (optional):

  • A shared S3 bucket for storing artifacts from CodePipeline can be used. You can specify it through the variable code_pipeline_artifact_bucket. Otherwise a new bucket is created for every service.
  • A shared IAM::Role for CodePipeline and CodeBuild can be used. You can specify those through the variables code_pipeline_role_name and code_build_role_name. Otherwise new roles are created for every service. For the permissions required see the module code

Usage

Simple Fargate ECS service:

locals {
  service_name = "example"
}

data "aws_caller_identity" "current" {}
data "aws_region" "current" {}

module "service" {
  source  = "stroeer/ecs-fargate/aws"
  version = "0.29.1"

  assign_public_ip           = true
  cluster_id                 = aws_ecs_cluster.main.id
  container_port             = 80
  create_deployment_pipeline = false
  desired_count              = 1
  service_name               = local.service_name
  vpc_id                     = module.vpc.vpc_id

  target_groups = [
    {
      name             = "${local.service_name}-public"
      backend_port     = 80
      backend_protocol = "HTTP"
      target_type      = "ip"
      health_check     = {
        enabled = true
        path    = "/"
      }
    }
  ]

  https_listener_rules = [{
    listener_arn = aws_lb_listener.http.arn

    priority   = 42
    actions    = [{
      type               = "forward"
      target_group_index = 0
    }]
    conditions = [{
      path_patterns = ["/"]
    }]
  }]

  container_definitions = jsonencode([
    {
      command: [
        "/bin/sh -c \"echo '<html> <head> <title>Hello from httpd service</title> <style>body {margin-top: 40px; background-color: #333;} </style> </head><body> <div style=color:white;text-align:center> <h1>Amazon ECS Sample App</h1> <h2>Congratulations!</h2> <p>Your application is now running on a container in Amazon ECS.</p> </div></body></html>' >  /usr/local/apache2/htdocs/index.html && httpd-foreground\""
      ],
      cpu: 256,
      entryPoint: ["sh", "-c"],
      essential: true,
      image: "httpd:2.4",
      memory: 512,
      name: local.service_name,
      portMappings: [{
        containerPort: 80
        hostPort: 80
        protocol: "tcp"
      }]
    }
  ])

  ecr = {
    image_tag_mutability         = "IMMUTABLE"
    image_scanning_configuration = {
      scan_on_push = true
    }
  }
}

Naming Conventions

  • Service Names var.service_name = [a-z-]+

Examples

Documentation

Documentation is generated with brew install terraform-docs ( see Makefile).

Terraform versions

Only Terraform 0.12+ is supported.

Release

Release a new module version to the Terraform registry (BUMP defaults to patch):

make BUMP=(major|minor|patch) release

Automated Service Deployment

Once create_deployment_pipeline is set to true, we will create an automated Deployment Pipeline:

deployment pipeline

How it works

  • You'll need AWS credentials that allow pushing images into the ECR container registry.
  • Once you push an image with [tag=production] - a Cloudwatch Event will trigger the start of a CodePipeline
  • ⚠ This tag will only trigger the pipeline. You will need a minimum of 3 tags
  1. production will trigger the pipeline
  2. container.$CONTAINER_NAME is required to locate the correct container from the service's task-definition.json
  3. One more tag that will be unique and used for the actual deployment and the task-definition.json. A good choice would be git.sha. To be specific, we chose a tag that does not start with container. and is none of ["local", "production", "staging", "infrastructure"]

That CodePipeline will do the heavy lifting (see deployment flow above)

  1. Pull the full imagedefinitions.json from the ECR registry
  2. Trigger a CodeBuild to transform the imagedefinitions.json into a imagedefinitions.json for deployment
  3. Update the ECS service's task-definition by replacing the specified imageUri for the given name.

Notifications

We will create a notification rule for the pipeline. You can provide your ARN of a notification rule target (e.g. a SNS topic ARN) using codestar_notifications_target_arn. Otherwise a new SNS topic with required permissions is created for every service. See aws_codestarnotifications_notification_rule for details.

You can then configure an integration between those notifications and AWS Chatbot for example.

Todos

  • Cognito auth for ALB listeners
  • CodeDeploy with ECR trigger
  • ECR policies
  • Notification for the deployment pipeline [success/failure]

Requirements

Name Version
terraform >= 1.3
aws >= 3.0

Providers

Name Version
aws >= 3.0
terraform n/a

Modules

Name Source Version
code_deploy ./modules/deployment n/a
container_definition cloudposse/config/yaml//modules/deepmerge 0.2.0
ecr ./modules/ecr n/a
envoy_container_definition cloudposse/config/yaml//modules/deepmerge 0.2.0
fluentbit_container_definition cloudposse/config/yaml//modules/deepmerge 0.2.0
otel_container_definition cloudposse/config/yaml//modules/deepmerge 0.2.0
sg registry.terraform.io/terraform-aws-modules/security-group/aws ~> 3.0

Resources

Name Type
aws_alb_listener_rule.public resource
aws_alb_target_group.main resource
aws_appautoscaling_policy.ecs resource
aws_appautoscaling_target.ecs resource
aws_cloudwatch_log_group.containers resource
aws_ecs_service.this resource
aws_ecs_task_definition.this resource
aws_iam_policy.acm resource
aws_iam_policy.cloudwatch_logs_policy resource
aws_iam_policy.otel resource
aws_iam_role.ecs_task_role resource
aws_iam_role_policy.ecs_task_role_policy resource
aws_iam_role_policy_attachment.acm resource
aws_iam_role_policy_attachment.appmesh resource
aws_iam_role_policy_attachment.cloudwatch_logs_policy resource
aws_iam_role_policy_attachment.otel resource
aws_security_group_rule.trusted_egress_attachment resource
aws_service_discovery_service.this resource
aws_caller_identity.current data source
aws_ecs_task_definition.this data source
aws_iam_policy.appmesh data source
aws_iam_policy_document.acm data source
aws_iam_policy_document.cloudwatch_logs_policy data source
aws_iam_policy_document.ecs_task_assume_role_policy data source
aws_iam_policy_document.nothing_is_allowed data source
aws_iam_policy_document.otel data source
aws_iam_role.task_execution_role data source
aws_lb.public data source
aws_region.current data source
aws_subnets.selected data source
terraform_remote_state.ecs data source

Inputs

Name Description Type Default Required
additional_container_definitions Additional container definitions added to the task definition of this service, see https://docs.aws.amazon.com/AmazonECS/latest/developerguide/task_definition_parameters.html for allowed parameters. list(any) [] no
app_mesh Configuration of optional AWS App Mesh integration using an Envoy sidecar.
object({
container_definition = optional(any, {})
container_name = optional(string, "envoy")
enabled = optional(bool, false)
mesh_name = optional(string, "apps")

tls = optional(object({
acm_certificate_arn = optional(string)
root_ca_arn = optional(string)
}), {})
})
{} no
appautoscaling_settings Autoscaling configuration for this service. map(any) null no
assign_public_ip This services will be placed in a public subnet and be assigned a public routable IP. bool false no
capacity_provider_strategy Capacity provider strategies to use for the service. Can be one or more.
list(object({
capacity_provider = string
weight = string
base = optional(string, null)
}))
null no
cloudwatch_logs CloudWatch logs configuration for the containers of this service. CloudWatch logs will be used as the default log configuration if Firelens is disabled and for the fluentbit and otel containers.
object({
enabled = optional(bool, true)
name = optional(string, "")
retention_in_days = optional(number, 7)
})
{} no
cluster_id The ECS cluster id that should run this service string n/a yes
code_build_role_name Use an existing role for codebuild permissions that can be reused for multiple services. Otherwise a separate role for this service will be created. string "" no
code_pipeline_artifact_bucket Use an existing bucket for codepipeline artifacts that can be reused for multiple services. Otherwise a separate bucket for each service will be created. string "" no
code_pipeline_artifact_bucket_sse AWS KMS master key id for server-side encryption. any {} no
code_pipeline_role_name Use an existing role for codepipeline permissions that can be reused for multiple services. Otherwise a separate role for this service will be created. string "" no
codestar_notifications_detail_type The level of detail to include in the notifications for this resource. Possible values are BASIC and FULL. string "BASIC" no
codestar_notifications_event_type_ids A list of event types associated with this notification rule. For list of allowed events see https://docs.aws.amazon.com/dtconsole/latest/userguide/concepts.html#concepts-api. list(string)
[
"codepipeline-pipeline-pipeline-execution-succeeded",
"codepipeline-pipeline-pipeline-execution-failed"
]
no
codestar_notifications_kms_master_key_id AWS KMS master key id for server-side encryption. string null no
codestar_notifications_target_arn Use an existing ARN for a notification rule target (for example, a SNS Topic ARN). Otherwise a separate sns topic for this service will be created. string "" no
container_definition_overwrites Additional container definition parameters or overwrites of defaults for your service, see https://docs.aws.amazon.com/AmazonECS/latest/developerguide/task_definition_parameters.html for allowed parameters. any {} no
container_name Defaults to var.service_name, can be overridden if it differs. Used as a target for LB. string "" no
container_port The port used by the app within the container. number n/a yes
cpu Amount of CPU required by this service. 1024 == 1 vCPU number 256 no
create_deployment_pipeline Creates a deploy pipeline from ECR trigger if create_ecr_repo == true. bool true no
create_ecr_repository Create an ECR repository for this service. bool true no
create_ingress_security_group Create a security group allowing ingress from target groups to the application ports. Disable this for target groups attached to a Network Loadbalancer. bool true no
deployment_circuit_breaker Deployment circuit breaker configuration.
object({
enable = bool
rollback = bool
})
{
"enable": false,
"rollback": false
}
no
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. Not valid when using the DAEMON scheduling strategy. 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. number 100 no
desired_count Desired count of services to be started/running. number 0 no
ecr_custom_lifecycle_policy JSON formatted ECR lifecycle policy used for this repository (disabled the default lifecycle policy), see https://docs.aws.amazon.com/AmazonECR/latest/userguide/LifecyclePolicies.html#lifecycle_policy_parameters for details. string null no
ecr_enable_default_lifecycle_policy Enables an ECR lifecycle policy for this repository which expires all images except for the last 30. bool true no
ecr_force_delete If true, will delete this repository even if it contains images. bool false no
ecr_image_scanning_configuration n/a map(any)
{
"scan_on_push": true
}
no
ecr_image_tag_mutability n/a string "MUTABLE" no
ecr_repository_name Existing repo to register to use with this service module, e.g. creating deployment pipelines. string "" no
efs_volumes Configuration block for EFS volumes. any [] no
enable_execute_command Specifies whether to enable Amazon ECS Exec for the tasks within the service. bool false no
firelens Configuration for optional custom log routing using FireLens over fluentbit sidecar.
object({
container_definition = optional(any, {})
enabled = optional(bool, false)
opensearch_host = optional(string, "")
})
{} no
force_new_deployment Enable to force a new task deployment of the service. This can be used to update tasks to use a newer Docker image with same image/tag combination (e.g. myimage:latest), roll Fargate tasks onto a newer platform version, or immediately deploy ordered_placement_strategy and placement_constraints updates. bool false no
https_listener_rules A list of maps describing the Listener Rules for this ALB. Required key/values: actions, conditions. Optional key/values: priority, https_listener_index (default to https_listeners[count.index]) any [] no
memory Amount of memory [MB] is required by this service. number 512 no
otel Configuration for (optional) AWS Distro für OpenTelemetry sidecar.
object({
container_definition = optional(any, {})
enabled = optional(bool, false)
})
{} no
platform_version The platform version on which to run your service. Defaults to LATEST. string "LATEST" no
policy_document AWS Policy JSON describing the permissions required for this service. string "" no
requires_compatibilities The launch type the task is using. This enables a check to ensure that all of the parameters used in the task definition meet the requirements of the launch type. set(string)
[
"EC2",
"FARGATE"
]
no
requires_internet_access As Fargate does not support IPv6 yet, this is the only way to enable internet access for the service by placing it in a public subnet (but not assigning a public IP). bool false no
security_groups A list of security group ids that will be attached additionally to the ecs deployment. list(string) [] no
service_name The service name. Will also be used as Route53 DNS entry. string n/a yes
subnet_tags The subnet tags where the ecs service will be deployed. If not specified all subnets will be used. map(string) null no
tags Additional tags (_e.g._ { map-migrated : d-example-443255fsf }) map(string) {} no
target_groups A list of maps containing key/value pairs that define the target groups to be created. Order of these maps is important and the index of these are to be referenced in listener definitions. Required key/values: name, backend_protocol, backend_port any [] no
task_role_arn ARN of the IAM role that allows your Amazon ECS container task to make calls to other AWS services. If not specified, the default ECS task role created in this module will be used. string "" no
vpc_id VPC id where the load balancer and other resources will be deployed. string n/a yes

Outputs

Name Description
autoscaling_target ECS auto scaling targets if auto scaling enabled.
aws_alb_target_group_arns ARNs of the created target groups.
cloudwatch_log_group Name of the CloudWatch log group for container logs.
container_definitions Container definitions used by this service including all sidecars.
ecr_repository_arn Full ARN of the ECR repository.
ecr_repository_url URL of the ECR repository.
ecs_task_exec_role_arn The ARN of the ECS task role created for this service.
ecs_task_exec_role_name The name of the ECS task role created for this service.
ecs_task_exec_role_unique_id The unique id of the ECS task role created for this service.
target_group_arns ARNs of the created target groups.

terraform-aws-ecs-fargate-3's People

Contributors

moritzzimmer avatar thisismana avatar saefty avatar vmk1vmk avatar dependabot[bot] avatar jadiedrich avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.