Skip to main content
ECS containers produce logs through the log driver configured in the container definition. This module’s container-definition sub-module supports two logging backends: CloudWatch Logs and FireLens (FluentBit/Fluentd).

How log groups are managed

When CloudWatch logging is enabled, ECS will create a log group automatically if one does not exist. The problem with this approach is that the log group is created outside of Terraform: it cannot be tagged, its retention period cannot be set, it will not be deleted when you destroy the stack, and it cannot be encrypted with a customer-managed KMS key. To address this, the container-definition module creates the CloudWatch log group on your behalf by default. This means you get full Terraform control over the log group lifecycle.
The default retention period for log groups created by the container-definition module is 14 days. The cluster-level log group defaults to 90 days. Override both with cloudwatch_log_group_retention_in_days.

The four logging scenarios

Set enable_cloudwatch_logging = false to disable all logging for the container. No log group is created and no log driver is configured.
module "ecs_service" {
  source = "terraform-aws-modules/ecs/aws//modules/service"

  # ... omitted for brevity

  container_definitions = {
    default = {
      enable_cloudwatch_logging = false
      # ...
    }
  }
}
Use this when:
  • The container writes logs to a file or stdout that another sidecar collects.
  • You want zero logging overhead for non-critical containers.

Log group configuration options

When the module manages the CloudWatch log group (create_cloudwatch_log_group = true), you can control its configuration through container definition inputs:
InputDefaultDescription
cloudwatch_log_group_nameAuto-generatedCustom name for the log group.
cloudwatch_log_group_retention_in_days14Days to retain log events. Set to 0 for indefinite retention.
cloudwatch_log_group_kms_key_idnullARN of a KMS key for encrypting log data at rest.
cloudwatch_log_group_classnullLog class: STANDARD or INFREQUENT_ACCESS.

KMS encryption example

container_definitions = {
  default = {
    cloudwatch_log_group_kms_key_id        = aws_kms_key.logs.arn
    cloudwatch_log_group_retention_in_days = 30
  }
}
If you provide a KMS key, ensure the key policy grants CloudWatch Logs the kms:GenerateDataKey* and kms:Decrypt permissions. Without the correct key policy, log group creation will fail.

FireLens with Kinesis Firehose

The service module README shows a complete FireLens example forwarding to Kinesis Firehose:
module "ecs_service" {
  source = "terraform-aws-modules/ecs/aws//modules/service"

  name        = "example"
  cluster_arn = "arn:aws:ecs:us-west-2:123456789012:cluster/default"

  cpu    = 1024
  memory = 4096

  container_definitions = {

    fluent-bit = {
      cpu       = 512
      memory    = 1024
      essential = true
      image     = "906394416424.dkr.ecr.us-west-2.amazonaws.com/aws-for-fluent-bit:stable"
      firelensConfiguration = {
        type = "fluentbit"
      }
      memoryReservation = 50
    }

    ecs-sample = {
      cpu       = 512
      memory    = 1024
      essential = true
      image     = "public.ecr.aws/aws-containers/ecsdemo-frontend:776fd50"
      portMappings = [
        {
          name          = "ecs-sample"
          containerPort = 80
          protocol      = "tcp"
        }
      ]

      readonlyRootFilesystem = false

      dependsOn = [{
        containerName = "fluent-bit"
        condition     = "START"
      }]

      enable_cloudwatch_logging = false
      logConfiguration = {
        logDriver = "awsfirelens"
        options = {
          Name                    = "firehose"
          region                  = "eu-west-1"
          delivery_stream         = "my-stream"
          log-driver-buffer-limit = "2097152"
        }
      }
      memoryReservation = 100
    }
  }

  subnet_ids = ["subnet-abcde012", "subnet-bcde012a", "subnet-fghi345a"]
}
Retrieve the latest stable FluentBit image from SSM Parameter Store rather than hardcoding the image tag:
data "aws_ssm_parameter" "fluentbit" {
  name = "/aws/service/aws-for-fluent-bit/stable"
}
Then reference it as nonsensitive(data.aws_ssm_parameter.fluentbit.value) in the container definition.
For more FireLens configuration examples, see the FireLens examples repository.

Build docs developers (and LLMs) love