AWS CloudWatch Logs is very useful service but it does have its limitations. Retaining logs for a long period of time can get expensive. Logs cannot be easily searched across multiple streams. Logs are hard to export and integration requires AWS specific code. Sometimes it makes more sense to store logs as text files in S3. That’s not always possible with some AWS services like Lambda that write logs directly to CloudWatch Logs.
One option to get around CloudWatch Logs limitations is exporting logs to S3 where data can be stored and processed longer-term for a cheaper price. Logs can be exported one-time or automatically as they come in. Setting up an automatic pipeline to export the logs is not a one-click process, but luckily Amazon detailed all the steps in a recent blog post titled Stream Amazon CloudWatch Logs to a Centralized Account for Audit and Analysis.
Amazon’s blog post has a lot of great information about the topic and the solution. In short, they create a Kinesis Stream writing to S3. CloudWatch Logs subscriptions to export logs to the new stream are created either manually with a script or in response to CloudTrail events about new log streams. This architecture is stable and scalable, but the implementation has a few drawbacks:
- Writes compressed CloudWatch JSON files to S3.
- Setup is still a little manual, requiring you to create a bucket, edit permissions, modify and upload source code, and run a script to initialize.
- Requires CloudTrail.
- Configuration requires editing source code.
- Has a minor bug limiting initial subscription to 50 log streams.
That is why I created CloudWatch2S3 – a single CloudFormation template that sets everything up in one go while still leaving room for tweaking with parameters.
The architecture is mostly the same as Amazon’s but adds a subscription timer to remove the hard requirement on CloudTrail, and post-processing to optionally write raw log files to S3 instead of compressed CloudWatch JSON files.
Setup is simple. There is just one CloudFormation template and the default parameters should be good for most.
- Download the CloudFormation template
- Open AWS Console
- Go to CloudFormation page
- Click “Create stack“
- Under “Specify template” choose “Upload a template file”, choose the file downloaded in step 1, and click “Next”
- Under “Stack name” choose a name like “CloudWatch2S3”
- If you have a high volume of logs, consider increasing Kinesis Shard Count
- Review other parameters and click “Next”
- Add tags if needed and click “Next”
- Check “I acknowledge that AWS CloudFormation might create IAM resources” and click “Create stack”
- Wait for the stack to finish
- Go to “Outputs” tab and note the bucket where logs will be written
- That’s it!
Another feature is the ability to export logs from multiple accounts to the same bucket. To set this up you need to set the
AllowedAccounts parameter to a comma-separated list of AWS account identifiers allowed to export logs. Once the stack is created, go to the “Outputs” tab and copy the value of
LogDestination. Then simply deploy the CloudWatch2S3-additional-account.template to the other accounts while setting
LogDestination to the value previously copied.
For troubleshooting and more technical details, see https://github.com/CloudSnorkel/CloudWatch2S3/blob/master/README.md.
If you are exporting logs to S3 to save money, don’t forget to also change the retention settings in CloudWatch so old logs are automatically purged and your bill actually goes down.