EKS Fargate Container Logs Module
This module supports collecting logs from Fargate Pods and shipping them to CloudWatch Logs, Elasticsearch, Kinesis Streams, or Kinesis Firehose.
This Terraform Module sets up the required Kubernetes Namespace
and ConfigMap
for configuring the Fluent
Bit instance that runs on Fargate worker nodes. This allows you to instrument container log
aggregation on Fargate Pods in EKS without setting up a side car container.
This module is for setting up log aggregation for EKS Fargate Pods. For other pods, take a look at the eks-container-logs module.
How does this work?
This module solves the problem of unifying the log streams from EKS Fargate Pods in your Kubernetes cluster to be
shipped to an aggregation service on AWS (CloudWatch Logs, Kinesis, or Firehose) so that you have a single interface to
search and monitor your logs. Since Fargate doesn't support DaemonSets
, traditionally you had to rely on side car
containers to implement the log aggregation. This required writing logs to a location that was shared with the side
cars, requiring instrumentation to both the application and infrastructure.
This module leverages the built in fluent-bit
service on Fargate worker nodes that run the EKS Pods. EKS supports
configuring fluent-bit
on the Fargate workers to ship to arbitrary targets if it sees a special ConfigMap
that
contains the fluent-bit
configuration. The Fargate fluent-bit
service expects to see the fluent-bit
configuration
in a ConfigMap
named aws-logging
in the aws-observability
Namespace. This module can be used to manage the
Namespace
and the ConfigMap
.
You can read more about fluent-bit
in their official home page. You can also learn more about
Fargate Pod Logging in the official AWS
documentation.
What is the difference with fluentd?
fluent-bit is an optimized version of fluentd that focuses on
streaming and aggregating log files. fluentd
has a larger ecosystem of plugins that enable various processing
capabilities on top of the logs prior to aggregating in the data store.
For most EKS deployments, it is recommended to use this fluent-bit
module for container log aggregation. Unless you have a specific
need for a plugin only supported by fluentd
, the superior performance and memory footprint of fluent-bit
will
ensure resources are available on your EKS workers for your Pods.
Log format
This module leverages native plugins for Kubernetes built into fluent-bit
that extract additional
metadata for each Pod that is reporting. Each log is shipped to the respective outputs in the following structure:
{
"kubernetes": {
"namespace_name": "NAMESPACE_WHERE_POD_LOCATED",
"pod_name": "NAME_OF_POD_EMITTING_LOG",
"pod_id": "ID_IN_KUBERNETES_OF_POD",
"container_hash": "KUBERNETES_GENERATED_HASH_OF_CONTAINER_EMITTING_LOG",
"container_name": "NAME_OF_CONTAINER_IN_POD_EMITTING_LOG",
"docker_id": "ID_IN_DOCKER_OF_CONTAINER",
"host": "NODE_NAME_OF_HOST_EMITTING_LOG",
"labels": {
"KEY": "VALUE",
},
"annotations": {
"KEY": "VALUE"
}
},
"log": "CONTENTS_OF_LOG_MESSAGE",
"stream": "STDERR_OR_STDOUT",
"time": "TIMESTAMP_OF_LOG"
}
This allows you to filter and search the logs by the respective attributes. For example, the following CloudWatch
Insights Query can be used to search for all logs from Pods in the kube-system
Namespace:
fields @timestamp, @message
| filter kubernetes.namespace_name = "kube-system"
| sort @timestamp desc
| limit 20
Sample Usage
- Terraform
- Terragrunt
# ------------------------------------------------------------------------------------------------------
# DEPLOY GRUNTWORK'S EKS-FARGATE-CONTAINER-LOGS MODULE
# ------------------------------------------------------------------------------------------------------
module "eks_fargate_container_logs" {
source = "git::git@github.com:gruntwork-io/terraform-aws-eks.git//modules/eks-fargate-container-logs?ref=v0.72.0"
# ----------------------------------------------------------------------------------------------------
# REQUIRED VARIABLES
# ----------------------------------------------------------------------------------------------------
# List of ARNs of Fargate execution IAM roles that should have permission to
# talk to each output target. Policies that grant permissions to each output
# service will be attached to these IAM roles.
fargate_execution_iam_role_arns = <list(string)>
# ----------------------------------------------------------------------------------------------------
# OPTIONAL VARIABLES
# ----------------------------------------------------------------------------------------------------
# Configurations for forwarding logs to AWS managed Elasticsearch. Set to null
# if you do not wish to forward the logs to ES.
aws_elasticsearch_configuration = null
# The AWS partition used for default AWS Resources.
aws_partition = "aws"
# Configurations for forwarding logs to CloudWatch Logs. Set to null if you do
# not wish to forward the logs to CloudWatch Logs.
cloudwatch_configuration = null
# Annotations to associate with the aws-logging ConfigMap
configmap_annotations = {}
# Labels to associate with the aws-logging ConfigMap
configmap_labels = {}
# Can be used to provide custom filtering of the log output. This string
# should be formatted according to Fluent Bit docs, as it will be injected
# directly into the fluent-bit.conf file.
extra_filters = ""
# Can be used to provide custom parsers of the log output. This string should
# be formatted according to Fluent Bit docs, as it will be injected directly
# into the fluent-bit.conf file.
extra_parsers = ""
# Configurations for forwarding logs to Kinesis Firehose. Set to null if you
# do not wish to forward the logs to Firehose.
firehose_configuration = null
# Whether or not Kubernetes metadata is added to the log files
include_kubernetes_metadata = true
# Configurations for forwarding logs to Kinesis stream. Set to null if you do
# not wish to forward the logs to Kinesis.
kinesis_configuration = null
# The time Fluent Bit waits until it communicates with the API server for the
# latest metadata. The smaller the TTL, the more load is generated on the API
# server. This setting will only have effect, when
# 'include_kubernetes_metadata' is 'true'.
kubernetes_metadata_cache_ttl = "300s"
# When enabled, it checks if the log field content is a JSON string map, if
# so, it append the map fields as part of the log structure. This setting will
# only have effect, when 'include_kubernetes_metadata' is 'true'.
kubernetes_metadata_merge_log = false
# If Merge_Log_Key is set, all the new structured fields taken from the
# original log content are inserted under the new key. This setting will only
# have effect, when 'include_kubernetes_metadata' is 'true'.
kubernetes_metadata_merge_log_key = null
# Annotations to associate with the aws-observability Namespace
namespace_annotations = {}
# Labels to associate with the aws-observability Namespace
namespace_labels = {}
# When true, all IAM policies will be managed as dedicated policies rather
# than inline policies attached to the IAM roles. Dedicated managed policies
# are friendlier to automated policy checkers, which may scan a single
# resource for findings. As such, it is important to avoid inline policies
# when targeting compliance with various security standards.
use_managed_iam_policies = true
}
# ------------------------------------------------------------------------------------------------------
# DEPLOY GRUNTWORK'S EKS-FARGATE-CONTAINER-LOGS MODULE
# ------------------------------------------------------------------------------------------------------
terraform {
source = "git::git@github.com:gruntwork-io/terraform-aws-eks.git//modules/eks-fargate-container-logs?ref=v0.72.0"
}
inputs = {
# ----------------------------------------------------------------------------------------------------
# REQUIRED VARIABLES
# ----------------------------------------------------------------------------------------------------
# List of ARNs of Fargate execution IAM roles that should have permission to
# talk to each output target. Policies that grant permissions to each output
# service will be attached to these IAM roles.
fargate_execution_iam_role_arns = <list(string)>
# ----------------------------------------------------------------------------------------------------
# OPTIONAL VARIABLES
# ----------------------------------------------------------------------------------------------------
# Configurations for forwarding logs to AWS managed Elasticsearch. Set to null
# if you do not wish to forward the logs to ES.
aws_elasticsearch_configuration = null
# The AWS partition used for default AWS Resources.
aws_partition = "aws"
# Configurations for forwarding logs to CloudWatch Logs. Set to null if you do
# not wish to forward the logs to CloudWatch Logs.
cloudwatch_configuration = null
# Annotations to associate with the aws-logging ConfigMap
configmap_annotations = {}
# Labels to associate with the aws-logging ConfigMap
configmap_labels = {}
# Can be used to provide custom filtering of the log output. This string
# should be formatted according to Fluent Bit docs, as it will be injected
# directly into the fluent-bit.conf file.
extra_filters = ""
# Can be used to provide custom parsers of the log output. This string should
# be formatted according to Fluent Bit docs, as it will be injected directly
# into the fluent-bit.conf file.
extra_parsers = ""
# Configurations for forwarding logs to Kinesis Firehose. Set to null if you
# do not wish to forward the logs to Firehose.
firehose_configuration = null
# Whether or not Kubernetes metadata is added to the log files
include_kubernetes_metadata = true
# Configurations for forwarding logs to Kinesis stream. Set to null if you do
# not wish to forward the logs to Kinesis.
kinesis_configuration = null
# The time Fluent Bit waits until it communicates with the API server for the
# latest metadata. The smaller the TTL, the more load is generated on the API
# server. This setting will only have effect, when
# 'include_kubernetes_metadata' is 'true'.
kubernetes_metadata_cache_ttl = "300s"
# When enabled, it checks if the log field content is a JSON string map, if
# so, it append the map fields as part of the log structure. This setting will
# only have effect, when 'include_kubernetes_metadata' is 'true'.
kubernetes_metadata_merge_log = false
# If Merge_Log_Key is set, all the new structured fields taken from the
# original log content are inserted under the new key. This setting will only
# have effect, when 'include_kubernetes_metadata' is 'true'.
kubernetes_metadata_merge_log_key = null
# Annotations to associate with the aws-observability Namespace
namespace_annotations = {}
# Labels to associate with the aws-observability Namespace
namespace_labels = {}
# When true, all IAM policies will be managed as dedicated policies rather
# than inline policies attached to the IAM roles. Dedicated managed policies
# are friendlier to automated policy checkers, which may scan a single
# resource for findings. As such, it is important to avoid inline policies
# when targeting compliance with various security standards.
use_managed_iam_policies = true
}
Reference
- Inputs
- Outputs
Required
fargate_execution_iam_role_arns
list(string)List of ARNs of Fargate execution IAM roles that should have permission to talk to each output target. Policies that grant permissions to each output service will be attached to these IAM roles.
Optional
aws_elasticsearch_configuration
object(…)Configurations for forwarding logs to AWS managed Elasticsearch. Set to null if you do not wish to forward the logs to ES.
object({
# The AWS region where the Elasticsearch instance is deployed.
region = string
# Elasticsearch endpoint to ship logs to.
endpoint = object({
host = string
port = number
})
# Whether or not AWS based authentication and authorization is enabled on the Elasticsearch instance.
use_aws_auth = bool
# Whether or not TLS is enabled on the Elasticsearch endpoint.
use_tls = bool
# Match string for logs to send to Elasticsearch.
match = string
})
null
Details
Elasticsearch endpoint to ship logs to.
Details
Whether or not AWS based authentication and authorization is enabled on the Elasticsearch instance.
Details
Whether or not TLS is enabled on the Elasticsearch endpoint.
Details
Match string for logs to send to Elasticsearch.
aws_partition
stringThe AWS partition used for default AWS Resources.
"aws"
cloudwatch_configuration
object(…)Configurations for forwarding logs to CloudWatch Logs. Set to null if you do not wish to forward the logs to CloudWatch Logs.
object({
# The AWS region that holds the CloudWatch Log Group where the logs will be streamed to.
region = string
# The name of the AWS CloudWatch Log Group to use for all the logs shipped by the cluster.
log_group_name = string
# Prefix to append to all CloudWatch Log Streams in the group shipped by fluentbit.
log_stream_prefix = string
})
null
Details
The name of the AWS CloudWatch Log Group to use for all the logs shipped by the cluster.
Details
Prefix to append to all CloudWatch Log Streams in the group shipped by fluentbit.
configmap_annotations
map(string)Annotations to associate with the aws-logging ConfigMap
{}
configmap_labels
map(string)Labels to associate with the aws-logging ConfigMap
{}
extra_filters
stringCan be used to provide custom filtering of the log output. This string should be formatted according to Fluent Bit docs, as it will be injected directly into the fluent-bit.conf file.
""
extra_parsers
stringCan be used to provide custom parsers of the log output. This string should be formatted according to Fluent Bit docs, as it will be injected directly into the fluent-bit.conf file.
""
firehose_configuration
object(…)Configurations for forwarding logs to Kinesis Firehose. Set to null if you do not wish to forward the logs to Firehose.
object({
# The AWS region that holds the Firehose delivery stream.
region = string
# The name of the delivery stream you want log records sent to. This must already exist.
delivery_stream_name = string
})
null
Details
The name of the delivery stream you want log records sent to. This must already exist.
Whether or not Kubernetes metadata is added to the log files
true
kinesis_configuration
object(…)Configurations for forwarding logs to Kinesis stream. Set to null if you do not wish to forward the logs to Kinesis.
object({
# The AWS region that holds the Kinesis stream.
region = string
# The name of the stream you want log records sent to. This must already exist.
stream_name = string
})
null
Details
The name of the stream you want log records sent to. This must already exist.
The time Fluent Bit waits until it communicates with the API server for the latest metadata. The smaller the TTL, the more load is generated on the API server. This setting will only have effect, when 'include_kubernetes_metadata' is 'true'.
"300s"
When enabled, it checks if the log field content is a JSON string map, if so, it append the map fields as part of the log structure. This setting will only have effect, when 'include_kubernetes_metadata' is 'true'.
false
If Merge_Log_Key is set, all the new structured fields taken from the original log content are inserted under the new key. This setting will only have effect, when 'include_kubernetes_metadata' is 'true'.
null
namespace_annotations
map(string)Annotations to associate with the aws-observability Namespace
{}
namespace_labels
map(string)Labels to associate with the aws-observability Namespace
{}
When true, all IAM policies will be managed as dedicated policies rather than inline policies attached to the IAM roles. Dedicated managed policies are friendlier to automated policy checkers, which may scan a single resource for findings. As such, it is important to avoid inline policies when targeting compliance with various security standards.
true
The ID of the Kubernetes ConfigMap containing the logging configuration. This can be used to chain other downstream dependencies to the ConfigMap.