Fluent Bit doesn’t actually send logs to CloudWatch Logs; it just tails log files and forwards them to a designated endpoint.

Here’s how you get Fluent Bit happily tailing and forwarding logs from your application container within an ECS task definition.

# Example ECS Task Definition Snippet
Resources:
  MyService:
    Type: AWS::ECS::Service
    Properties:
      Cluster: !Ref MyCluster
      TaskDefinition: !Ref MyTaskDefinition
      # ... other service properties

MyTaskDefinition:
  Type: AWS::ECS::TaskDefinition
  Properties:
    Family: fluent-bit-sidecar-example
    NetworkMode: awsvpc
    ExecutionRoleArn: arn:aws:iam::123456789012:role/ecsTaskExecutionRole
    TaskRoleArn: arn:aws:iam::123456789012:role/ecsTaskRole # For CloudWatch Logs access
    Cpu: '256'
    Memory: '512'
    RequiresCompatibilities:
      - FARGATE
    ContainerDefinitions:
      - Name: app-container
        Image: 'public.ecr.aws/amazonlinux/amazonlinux:2023' # Replace with your app image
        Command: ["sh", "-c", "echo 'Hello from app!' > /proc/1/fd/1 && sleep infinity"]
        LogConfiguration: # This is where Fluent Bit will *read* from
          LogDriver: awslogs
          Options:
            awslogs-group: /ecs/app-container # App container logs directed here for Fluent Bit to tail
            awslogs-region: us-east-1
            awslogs-stream-prefix: app
        PortMappings:
          - ContainerPort: 80
            Protocol: tcp
        # Mount a shared volume for Fluent Bit to access app logs
        VolumesFrom:
          - SourceContainer: fluent-bit-container

      - Name: fluent-bit-container
        Image: 'fluent/fluent-bit:latest'
        Command:
          - "/fluent-bit/bin/fluent-bit"
          - "-c"
          - "/fluent-bit/etc/fluent-bit.conf"
        Essential: true # Fluent Bit is essential for logging
        LogConfiguration: # Fluent Bit's own logs go here
          LogDriver: awslogs
          Options:
            awslogs-group: /ecs/fluent-bit
            awslogs-region: us-east-1
            awslogs-stream-prefix: fluent-bit
        # Mount the configuration file and the shared volume
        Volumes:
          - Host:
              SourcePath: /path/to/your/fluent-bit.conf # Local path on your ECS host/Fargate ephemeral storage
            ContainerPath: /fluent-bit/etc/fluent-bit.conf
        MountPoints:
          - SourceVolume: app-logs # This volume name matches the Volume definition below
            ContainerPath: /fluent-bit/logs # Where Fluent Bit will look for logs
            ReadOnly: true

    Volumes:
      - Name: app-logs # Define the shared volume
        # For Fargate, this volume is managed by ECS and shared between containers.
        # For EC2, you'd typically use host volumes.

The core idea is to have your application container write its logs to a location that the Fluent Bit container can read. In ECS, a common and effective pattern is to use a shared volume. Your application writes to a file within that shared volume, and Fluent Bit tails that file.

Here’s a simplified fluent-bit.conf that tails a file within the shared volume and forwards to CloudWatch Logs:

[SERVICE]
    Flush        1
    Daemon       off
    Log_Level    info
    Parsers_File parsers.conf # Optional: if you have custom parsers

[INPUT]
    Name         tail
    Path         /fluent-bit/logs/app.log # Tailing the log file in the shared volume
    Tag          app.log # A tag to identify these logs
    Refresh_Interval 5 # Check for new log entries every 5 seconds

[OUTPUT]
    Name         cloudwatch_logs
    Match        app.log # Only process logs tagged with 'app.log'
    Region       us-east-1 # Your AWS region
    LogGroupName /ecs/app-container # The CloudWatch Log Group name
    LogStreamName_Template app-${ecs_container_name}-${ecs_task_id} # Dynamic stream naming
    AutoCreateCollection true # Automatically create the log group if it doesn't exist

How it works:

  1. Application Container: Writes logs to a file (e.g., /proc/1/fd/1 which is stdout/stderr, or a specific file path if configured) that is accessible via a shared volume. In the example above, we’re directing the app’s stdout/stderr to be captured by ECS’s awslogs driver and we’re using VolumesFrom to make the app container’s log directory (where ECS writes stdout/stderr) available to Fluent Bit. If your app writes to a file, ensure that file is within the volume mounted by Fluent Bit.
  2. Fluent Bit Container:
    • Is configured to read from a specific path (/fluent-bit/logs/app.log in the example) within its own mounted volume.
    • Uses the tail input plugin to monitor this file for new entries.
    • The cloudwatch_logs output plugin takes these entries and sends them to the specified CloudWatch Log Group and Stream.
  3. Shared Volume: The Volumes definition in the task places a volume named app-logs into the Fluent Bit container at /fluent-bit/logs. The VolumesFrom on the app-container makes the log directory of the app-container (which is where ECS writes its stdout/stderr to be picked up by the awslogs driver) accessible to the Fluent Bit container. This is the critical link. Fluent Bit tails the log file that the app container is writing to.

Crucial Configuration Points:

  • VolumesFrom on App Container: This is key. It makes the log directory of the app-container (where ECS writes stdout/stderr for log collection) accessible to the fluent-bit-container. Fluent Bit then tails the files within this directory.
  • MountPoints on Fluent Bit Container: This maps the shared volume defined at the task level (app-logs) to a specific path (/fluent-bit/logs) inside the Fluent Bit container.
  • fluent-bit.conf Path: Must point to the log file inside the Fluent Bit container, which corresponds to the shared volume mount.
  • fluent-bit.conf LogGroupName and LogStreamName_Template: These need to match your desired CloudWatch Log Group and how you want to name your log streams. The template can use ECS metadata variables.
  • IAM Permissions: The TaskRoleArn of your task definition must have permissions to write to CloudWatch Logs (logs:CreateLogGroup, logs:CreateLogStream, logs:PutLogEvents, logs:DescribeLogStreams).

This setup ensures that your application logs are first captured by Fluent Bit and then forwarded to CloudWatch Logs, giving you a robust centralized logging solution within ECS.

Want structured learning?

Take the full Fluentbit course →