Fargate keeps container stdout and stderr on the Fargate node, outside every pod, so application logs reach the collector in one of two ways:
- Over OTLP from the application. The OpenTelemetry SDK sends logs to the same endpoint the application already uses for traces and metrics: the sidecar in its own pod or the deployment collector's Service, as Send Data from Applications to the Collector shows. They carry the trace context of the request that wrote them, and the Kubernetes resource attributes too. To turn on log export for your language, see SDK OTLP export.
- From CloudWatch Logs. Fargate's log router writes stdout and stderr to CloudWatch Logs, and the collector's
awscloudwatchreceiver reads them from there. Use this route for applications whose logging you can't change. CloudWatch Logs bills for ingestion and storage, logs arrive within the poll interval, and each record keeps the pod's details in its body rather than as Kubernetes resource attributes.
Pick one route per application: an application on both shows every line twice.
The steps below set up the CloudWatch route.
Prerequisites
- The EKS Fargate Collection Agent, installed with Foundry (see the install guide).
kubectlconfigured to reach the cluster, and access to create IAM policies and roles in your AWS account.
Step 1: Create the aws-observability namespace
Create a file named aws-observability-namespace.yaml for the aws-observability namespace, where the log router reads its config:
kind: Namespace
apiVersion: v1
metadata:
name: aws-observability
labels:
aws-observability: enabledRun this from the directory that contains the file:
kubectl apply -f aws-observability-namespace.yamlStep 2: Configure the log router
Create a file named aws-logging-configmap.yaml with the aws-logging ConfigMap, which sends container logs to CloudWatch Logs:
kind: ConfigMap
apiVersion: v1
metadata:
name: aws-logging
namespace: aws-observability
data:
flb_log_cw: "false"
filters.conf: |
[FILTER]
Name parser
Match *
Key_name log
Parser crio
[FILTER]
Name kubernetes
Match kube.*
Merge_Log On
Keep_Log Off
Buffer_Size 0
Kube_Meta_Cache_TTL 300s
K8S-Logging.Parser On
K8S-Logging.Exclude On
output.conf: |
[OUTPUT]
Name cloudwatch_logs
Match kube.*
region <aws-region>
log_group_name <LOG_GROUP>
log_stream_prefix <LOG_STREAM_PREFIX>
log_retention_days 1
auto_create_group false
parsers.conf: |
[PARSER]
Name crio
Format Regex
Regex ^(?<time>[^ ]+) (?<stream>stdout|stderr) (?<logtag>P|F) (?<log>.*)$
Time_Key time
Time_Format %Y-%m-%dT%H:%M:%S.%L%zVerify these values:
<aws-region>: The AWS region of your cluster, for exampleus-east-1.<LOG_GROUP>: The CloudWatch Logs log group for the container logs, which must exist unless you setauto_create_group trueso the log router creates it.<LOG_STREAM_PREFIX>: A prefix for the log streams, for examplefrom-fluent-bit-.
Run this from the directory that contains the file:
kubectl apply -f aws-logging-configmap.yamlThen attach the CloudWatch Logs permissions to the pod execution role of your Fargate profile, as the AWS Fargate logging guide shows.
Step 3: Create an IAM role for the collector
Create an IAM role for the service account of the collector that reads the logs, with the CloudWatchReadOnlyAccess policy, trusted by your cluster's OIDC provider for that collector's service account, system:serviceaccount:signoz:signoz-collector-deployment. That is the deployment collector's service account, where signoz is the namespace from metadata.name in casting.yaml.
Step 4: Read the logs into the collector
In the deployment collector's document of casting.yaml, add the awscloudwatch receiver, list it in the logs pipeline, and annotate the deployment collector's service account with the role from Step 3:
spec:
collector:
spec:
config:
data:
collector/deployment/deployment.yaml: |
receivers:
awscloudwatch:
region: <aws-region>
logs:
poll_interval: 1m
groups:
autodiscover:
limit: 100
prefix: <LOG_GROUP>
streams:
prefixes: [<LOG_STREAM_PREFIX>]
service:
pipelines:
logs:
receivers: [otlp/http, otlp/grpc, k8s_events, awscloudwatch]
patches:
- target: collectionagent/collector/deployment/serviceaccount.yaml
operations:
- op: add
path: /metadata/annotations
value:
eks.amazonaws.com/role-arn: arn:aws:iam::<account-id>:role/<collector-role>Verify these values:
<aws-region>,<LOG_GROUP>,<LOG_STREAM_PREFIX>: The values from Step 2.<account-id>: Your AWS account ID.<collector-role>: The name of the IAM role from Step 3.
Lists replace, so the logs pipeline is restated with Foundry's default receivers otlp/http, otlp/grpc, and k8s_events. Run foundryctl cast -f casting.yaml from the directory that contains casting.yaml.
Then restart your application Deployments so the log router starts for their pods. Run this on the machine where you use kubectl:
kubectl rollout restart -n <your-namespace> deployment/<your-workload>Verify these values:
<your-namespace>: Your application's namespace.<your-workload>: The name of your application's Deployment.
The events of the new pods show the log router starting:
Normal LoggingEnabled 3m5s fargate-scheduler Successfully enabled logging for podWithin the poll interval, the container logs show in Logs Explorer in SigNoz.
Troubleshooting
Container logs do not reach SigNoz
In Step 4, no container logs show in Logs Explorer. Read the logs of the deployment collector, which runs the awscloudwatch receiver, as View the Collector's Logs shows. The logs show errors from the awscloudwatch receiver.
Cause: the collector's service account has no eks.amazonaws.com/role-arn annotation, or the role's trust policy does not name that service account.
Fix: check that the role from Step 3 trusts the service account, and that the annotation is set. Run this on the machine where you use kubectl:
kubectl get serviceaccount -n signoz signoz-collector-deployment -o jsonpath='{.metadata.annotations}'Here signoz is the namespace from metadata.name. The collector picks up the role when its pod starts, so restart it after a fix with kubectl rollout restart -n signoz deployment/signoz-collector-deployment. Under the OpenTelemetry Operator, restart deployment/signoz-collector-deployment-collector.
After the fix, the container logs show in Logs Explorer within the poll interval.