This guide explains how to install the ECS EC2 Collection Agent on an Amazon ECS cluster with Foundry and Terraform.
Prerequisites
- An Amazon ECS cluster with EC2 container instances or ECS Anywhere external instances, running Docker Engine 25 or newer.
- Terraform 1.4 or newer and the AWS CLI on the same machine, with AWS credentials that can create ECS services, task definitions, IAM roles, and AWS AppConfig applications.
- A SigNoz to send data to: SigNoz Cloud or a self-hosted SigNoz.
Install the Collection Agent
Step 1: Install foundryctl
Run this on the machine where you run Terraform:
curl -fsSL https://signoz.io/foundry.sh | bashFor manual install (Windows PowerShell, air-gapped, etc.) or PATH setup, see the foundry getting-started guide.
Step 2: Create casting.yaml
Create a file named casting.yaml with one document for the collector described in How it works. collector.kind: agent selects that collector. Pick the tab for the instances your cluster runs on:
apiVersion: v1alpha1
kind: CollectionAgent
metadata:
name: signoz
annotations:
foundry.signoz.io/ecs-region: <aws-region>
foundry.signoz.io/ecs-cluster-arn: <ecs-cluster-arn>
spec:
deployment:
platform: aws
mode: ecs
flavor: terraform
collector:
kind: agent
spec:
env:
SIGNOZ_INGESTION_ENDPOINT: https://ingest.<region>.signoz.cloud:443
SIGNOZ_INGESTION_KEY: <your-ingestion-key>
OTEL_RESOURCE_ATTRIBUTES: deployment.environment=<DEPLOYMENT_ENVIRONMENT>
config:
data:
collector/agent/agent.yaml: |
exporters:
otlphttp/signoz:
headers:
signoz-ingestion-key: ${env:SIGNOZ_INGESTION_KEY}Verify these values:
<aws-region>: The AWS region of your ECS cluster, for exampleus-east-1.<ecs-cluster-arn>: The ARN of your ECS cluster, from the Amazon ECS console oraws ecs list-clusters.<region>: Your SigNoz Cloud region.<your-ingestion-key>: Your SigNoz Cloud ingestion key.<DEPLOYMENT_ENVIRONMENT>: Your deployment environment, for examplestagingorproduction. It becomesdeployment.environmenton the collected telemetry.
For every option of this casting, see the ECS EC2 Terraform example.
This casting runs the collector with the EXTERNAL launch type, detects the host with the system detector, and also collects /var/log/syslog and /var/log/auth.log:
apiVersion: v1alpha1
kind: CollectionAgent
metadata:
name: signoz
annotations:
foundry.signoz.io/ecs-region: <aws-region>
foundry.signoz.io/ecs-cluster-arn: <ecs-cluster-arn>
spec:
deployment:
platform: aws
mode: ecs
flavor: terraform
collector:
kind: agent
spec:
env:
SIGNOZ_INGESTION_ENDPOINT: https://ingest.<region>.signoz.cloud:443
SIGNOZ_INGESTION_KEY: <your-ingestion-key>
OTEL_RESOURCE_ATTRIBUTES: deployment.environment=<DEPLOYMENT_ENVIRONMENT>
config:
data:
collector/agent/agent.yaml: |
exporters:
otlphttp/signoz:
headers:
signoz-ingestion-key: ${env:SIGNOZ_INGESTION_KEY}
processors:
resourcedetection:
detectors: [env, system]
receivers:
filelog/host:
include:
- /hostfs/var/log/messages
- /hostfs/var/log/secure
- /hostfs/var/log/syslog
- /hostfs/var/log/auth.log
- /hostfs/var/log/ecs/*.log
patches:
- target: collectionagent/collector/agent/collector.tf.json
operations:
- op: replace
path: /resource/aws_ecs_task_definition/collector_agent/requires_compatibilities/0
value: EXTERNAL
- op: replace
path: /resource/aws_ecs_service/collector_agent/launch_type
value: EXTERNALVerify these values:
<aws-region>: The AWS region of your ECS cluster, for exampleus-east-1.<ecs-cluster-arn>: The ARN of the ECS cluster your external instances are registered to, from the Amazon ECS console oraws ecs list-clusters.<region>: Your SigNoz Cloud region.<your-ingestion-key>: Your SigNoz Cloud ingestion key.<DEPLOYMENT_ENVIRONMENT>: Your deployment environment, for examplestagingorproduction. It becomesdeployment.environmenton the collected telemetry.
For every option of this casting, see the ECS EC2 Terraform example.
Step 3: Deploy
Run this from the directory that contains casting.yaml:
foundryctl cast -f casting.yamlThis command:
- writes the Terraform root
pours/collectionagent/collector/agent; - applies it with Terraform, using the AWS credentials on this machine;
- creates the collector's config in AWS AppConfig, the
signoz-collector-agenttask definition and daemon service, and the default IAM roles ( if not specified).
Step 4: Verify the Collection Agent
Run this on the machine where you use the AWS CLI to check that the daemon service runs one collector task on every instance:
aws ecs describe-services --region <aws-region> --cluster <ecs-cluster-arn> \
--services signoz-collector-agent \
--query 'services[0].{status:status,desiredCount:desiredCount,runningCount:runningCount}'Verify these values:
<aws-region>: Thefoundry.signoz.io/ecs-regionvalue incasting.yaml.<ecs-cluster-arn>: Thefoundry.signoz.io/ecs-cluster-arnvalue incasting.yaml.
The output should look similar to the following, with runningCount equal to desiredCount, the number of instances in the cluster. The counts vary:
{
"status": "ACTIVE",
"desiredCount": 3,
"runningCount": 3
}In SigNoz, open the Hosts view under Infrastructure Monitoring, which lists each instance under its host.name. Check Logs Explorer to confirm container and host logs are flowing; host logs show under service.name ecs-host.
Customize the Collection Agent
Every change follows the same loop: edit casting.yaml, then run foundryctl cast -f casting.yaml again.
-
Collector settings (image, environment): set them in the collector's
spec(see spec fields). For example, to pin the collector image:spec: collector: spec: image: otel/opentelemetry-collector-contrib:0.139.0 -
Collector config (receivers, processors, pipelines): add it under
spec.collector.spec.config.data, keyedcollector/agent/agent.yaml. It merges into the generated config (see custom config files). For example, to collect host metrics every 30s:spec: collector: spec: config: data: collector/agent/agent.yaml: | receivers: hostmetrics: collection_interval: 30s -
Terraform (task definition, service): add patches under
spec.patchesagainst the files undercollectionagent/collector/agent/, such ascollector.tf.jsonfor the task definition and daemon service. To find the path to patch, runfoundryctl forge -f casting.yamland look in the generated files underpours/collectionagent/collector/agent/. For example, to reserve more memory for the collector:spec: patches: - target: collectionagent/collector/agent/collector.tf.json operations: - op: replace path: /locals/containers_collector_agent/1/memoryReservation value: 1024Each run regenerates the files under
pours/, so keep every change incasting.yaml.
Troubleshooting
The collector task is not placed on an instance
In Step 4, runningCount stays below desiredCount. Run this on the machine where you use the AWS CLI to read the service's latest events:
aws ecs describe-services --region <aws-region> --cluster <ecs-cluster-arn> \
--services signoz-collector-agent --query 'services[0].events[:5].message'Verify these values:
<aws-region>: Thefoundry.signoz.io/ecs-regionvalue incasting.yaml.<ecs-cluster-arn>: Thefoundry.signoz.io/ecs-cluster-arnvalue incasting.yaml.
The events include service signoz-collector-agent was unable to place a task because no container instance met all of its requirements. The closest matching container-instance <container-instance-id> is already using a port required by your task.
Cause: another task on that instance holds host port 4317 or 4318, for example another OpenTelemetry Collector running as a daemon service. The task also uses port 13133 (the collector's health check) and port 2772 (the AppConfig agent) on the instance without reserving them. A process that holds one of those makes the container fail at start instead of blocking placement.
Fix: list the cluster's services with aws ecs list-services --region <aws-region> --cluster <ecs-cluster-arn>, then delete the service that holds the ports or move its ports. The daemon service places its task on that instance again on its own.
After the fix, the Step 4 command shows runningCount equal to desiredCount.
The AppConfig agent container never turns healthy
In the Step 4 command, runningCount stays below desiredCount. Run this on a container instance to see the AppConfig agent container's status:
docker ps -a --filter label=com.amazonaws.ecs.container-name=signoz-collector-appconfig-agent --format '{{.Status}}'The status shows (unhealthy). To see the error it gets from AWS AppConfig, read its logs:
docker logs --since 10m $(docker ps -aq --filter label=com.amazonaws.ecs.container-name=signoz-collector-appconfig-agent | head -n 1)Cause: the task has no AWS credentials that can read the config. Either the task role you stated with foundry.signoz.io/ecs-task-role-arn lacks appconfig:StartConfigurationSession and appconfig:GetLatestConfiguration, or task IAM roles are not enabled for the host network mode on the instance.
Fix: add both actions to the task role, or enable task IAM roles as External instance additional configuration describes. The daemon service replaces the unhealthy task on its own.
After the fix, the Step 4 command shows runningCount equal to desiredCount.
foundryctl cast rejects a patch
In Step 3, or after you add a patch from Customize the Collection Agent, foundryctl cast -f casting.yaml stops before it applies anything, with the message failed to apply patch for target "<target>". Its cause ends with doc is missing key: <path>: missing value or doc is missing path: <path>: missing value, or, when no generated file matches the target, patch target "<target>" did not match any generated material.
Cause: the patch's target or path does not exist in what Foundry generates.
Fix: remove the patch and run foundryctl forge -f casting.yaml. Then take the target and the path from the generated files under pours/collectionagent/collector/agent/, add the patch back, and run Step 3 again.
After the fix, the cast creates the resources, and the Step 4 command shows the service.
terraform plan rejects the region or the cluster ARN
In Step 3, foundryctl cast -f casting.yaml stops at terraform plan with Error: Invalid value for variable and one of these messages:
aws_region must be a region identifier such as us-east-1.
cluster_arn must be the ARN of an ECS cluster.Cause: the foundry.signoz.io/ecs-region or foundry.signoz.io/ecs-cluster-arn annotation is missing or malformed. The region must look like us-east-1, and the cluster ARN must start with arn:aws:ecs:. A role annotation that is not an IAM role ARN fails the same way.
Fix: set the annotation under metadata.annotations in casting.yaml, as in Step 2, then run Step 3 again.
After the fix, the cast creates the resources, and the Step 4 command shows the service.
terraform plan stops on an interpolation in env
In Step 3, foundryctl cast -f casting.yaml stops at terraform plan on collector.tf.json, in locals.containers_collector_agent[1].environment, with Error: Invalid reference for a value such as ${MY_KEY}, or Error: Extra characters after interpolation expression for a value such as ${env:MY_KEY}.
Cause: a value under spec.collector.spec.env contains ${, which Terraform reads as one of its own expressions.
Fix: replace the expression with the literal value in casting.yaml, then run Step 3 again.
After the fix, the cast creates the resources, and the Step 4 command shows the service.
terraform plan finds no AWS credentials
In Step 3, foundryctl cast -f casting.yaml stops at terraform plan with Error: No valid credential sources found.
Cause: Terraform's AWS provider found no credentials on the machine where you run foundryctl.
Fix: sign in with the AWS CLI or select a profile in the shell you run foundryctl from, for example:
export AWS_PROFILE=<profile-name>Verify these values:
<profile-name>: A profile fromaws configure list-profiles.
For every way to pass credentials, see the AWS provider authentication docs.
After the fix, aws sts get-caller-identity prints your account and role, and Step 3 gets past terraform plan.
Send data from your applications
Host metrics, container metrics, and container and host logs flow as soon as the collector is running. To send traces, metrics, and logs from your applications, see Send Data from Applications to the Collector.