Shipping Logs from AWS CloudWatch to ElasticSearch with Fargate and Filebeat
Centralizing logs and efficiently analyzing them is vital for maintaining the health of your system. In this guide, we’ll walk through how to ship logs from AWS CloudWatch to ElasticSearch using Filebeat running on a Fargate cluster.
Requirements
- A Fargate Cluster.
- IAM roles for task execution and access control.
- Filebeat configuration.
Setting Up a Fargate Cluster
Before we proceed, you’ll need to have an operational Fargate cluster ready to run the task.
IAM Roles Configuration
IAM roles define what ECS and the running process can do. AWS documents this split between task and execution roles.
Task role: Supplies credentials to Filebeat through ECS task metadata. It—not the execution role—needs permission to read the selected CloudWatch log groups.
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "logs:DescribeLogGroups", "logs:GetQueryResults" ], "Resource": "*" }, { "Effect": "Allow", "Action": [ "logs:FilterLogEvents", "logs:GetLogEvents", "logs:StartQuery" ], "Resource": "arn:aws:logs:YOUR_REGION:YOUR_ACCOUNT_ID:log-group:YOUR_LOG_GROUP_TO_SHIP:*" } ] }Execution role: Used by the ECS agent to pull the image and send this container’s own logs. It is not the identity Filebeat uses for AWS API calls.
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "ecr:GetAuthorizationToken", "ecr:BatchCheckLayerAvailability", "ecr:GetDownloadUrlForLayer", "ecr:BatchGetImage", "logs:CreateLogGroup", "logs:CreateLogStream", "logs:PutLogEvents" ], "Resource": "*" } ] }
Filebeat Configuration
Filebeat is the tool that will be used to read logs from CloudWatch and forward them to ElasticSearch. Here’s a sample configuration for Filebeat:
Includes settings, input for AWS Cloudwatch, and output to Logstash
name: 'filebeat-cloudwatch'
tags: []
fields_under_root: true
fields:
domain: 'domain.com'
cluster: 'my-pony-cluster'
logging.level: debug
# This can be used to debug the input by going to
# :5066/inputs/?pretty <-- this will show the status of the cloudwatch input
http:
enabled: true
host: 127.0.0.1
port: 5066
http.pprof.enabled: false
# Persist the Filebeat registry across task replacements.
path.data: /mnt/share/filebeat-data
filebeat.inputs:
- type: aws-cloudwatch
log_group_arn: arn:aws:logs:YOUR_REGION:YOUR_ACCOUND_ID:log-group:YOUR_LOG_GROUP_TO_SHIP:*
scan_frequency: 1m
start_position: end
region_name: YOUR_REGION
fields_under_root: true
fields:
logzio_codec: json
type: fargate
processors:
- rename:
ignore_missing: true
fields:
- from: 'agent'
to: 'beat_agent'
- from: 'log.file.path'
to: 'source'
output:
logstash:
hosts:
- 'logstash:5015'
ssl:
certificate_authorities:
- |
-----BEGIN CERTIFICATE-----
...
...
-----END CERTIFICATE-----
Fargate Service Configuration
Define a Fargate service and task in JSON format. These will include the details about the cluster, desired count of running tasks, network configurations, and container definitions.
JSON for Fargate Service
{
"cluster": "MyTestCluster",
"serviceName": "filebeat",
"taskDefinition": "arn:aws:ecs:YOUR_REGION:YOUR_ACCOUND_ID:task-definition/filebeat:1",
"desiredCount": 1,
"launchType": "FARGATE",
"deploymentConfiguration": {
"maximumPercent": 200,
"minimumHealthyPercent": 0
},
"networkConfiguration": {
"awsvpcConfiguration": {
"subnets": ["subnet-***********"],
"securityGroups": ["sg-************"],
"assignPublicIp": "DISABLED"
}
}
}
JSON for Fargate Task
{
"networkMode": "awsvpc",
"taskRoleArn": "arn:aws:iam::YOUR_ACCOUND_ID:role/ecsTaskRole",
"executionRoleArn": "arn:aws:iam::YOUR_ACCOUND_ID:role/ecsTaskExecutionRole",
"cpu": "256",
"memory": "512",
"containerDefinitions": [
{
"name": "filebeat",
"essential": true,
"image": "docker.elastic.co/beats/filebeat:FILEBEAT_VERSION",
"command": ["-c", "/mnt/share/filebeat/filebeat.yml"],
"mountPoints": [
{
"sourceVolume": "efs-volume",
"containerPath": "/mnt/share/"
}
],
"logConfiguration": {
"logDriver": "awslogs",
"options": {
"awslogs-group": "YOUR_LOG_GROUP_TO_MONITOR_FILEBEAT",
"awslogs-region": "YOUR_REGION",
"awslogs-create-group": "true",
"awslogs-stream-prefix": "filebeat"
}
}
}
],
"volumes": [
{
"name": "efs-volume",
"efsVolumeConfiguration": {
"fileSystemId": "fs-****************",
"transitEncryption": "ENABLED"
}
}
],
"requiresCompatibilities": ["FARGATE"],
"family": "filebeat"
}
The logConfiguration block is optional; it sends Filebeat’s own container logs to CloudWatch and is separate from the log groups Filebeat collects.
Deployment
With the configurations ready, you can deploy the Filebeat on the Fargate cluster:
- Deploy the task definition.
- Deploy the service definition.
- Monitor your logs in ElasticSearch.
I replace FILEBEAT_VERSION during task-definition generation with the Filebeat release compatible with Elasticsearch/Logstash instead of leaving the old 8.8.2 image hard-coded. Elastic publishes the compatibility matrix.
The EFS-backed path.data holds Filebeat’s registry. Keeping it prevents a replacement task replaying the whole available CloudWatch window; losing or sharing that state can cause replay or duplicates, so one collector task owns the directory. Filebeat gets short-lived AWS credentials from its task role—there are no static access keys in this definition. Diagnostics stay on loopback and can be inspected through ECS Exec.
Buy Me a Coffee