This guide explains how to install the OpenTelemetry Operator collection agent on a Kubernetes cluster with Foundry, through Helm or Kustomize.
Prerequisites
- A Kubernetes cluster.
kubectlconfigured to reach the cluster.- For the Helm path or the operator's Helm chart, Helm 3 installed on the same machine.
- cert-manager installed in the cluster. The operator uses it for the certificate of its admission webhook.
- A SigNoz to send data to: SigNoz Cloud or a self-hosted SigNoz.
Install the OpenTelemetry Operator
Foundry generates the collectors as OpenTelemetryCollector resources for the operator to reconcile. Install operator v0.139.0, which matches the OpenTelemetry Collector 0.139.0 these resources run:
Run this on the machine where you use kubectl to install the operator and its CRDs:
kubectl apply -f https://github.com/open-telemetry/opentelemetry-operator/releases/download/v0.139.0/opentelemetry-operator.yamlThen run this on the same machine to check the operator:
kubectl get deployment opentelemetry-operator-controller-manager -n opentelemetry-operator-systemThe operator is ready when READY shows 1/1.
Run this on the machine where you use kubectl to install the operator's Helm chart, version 0.100.0, which installs operator v0.139.0 and its CRDs:
helm repo add open-telemetry https://open-telemetry.github.io/opentelemetry-helm-charts
helm repo update
helm install opentelemetry-operator open-telemetry/opentelemetry-operator \
--version 0.100.0 \
--create-namespace \
--namespace opentelemetry-operator-systemThen run this on the same machine to check the operator:
kubectl get deployment opentelemetry-operator -n opentelemetry-operator-systemThe operator is ready when READY shows 1/1. For every chart setting, see the OpenTelemetry Operator Helm chart.
Install the Collection Agent
Step 1: Install foundryctl
Run this on the machine where you use kubectl:
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 for your Kubernetes platform, with one document for each collector described in How it works:
apiVersion: v1alpha1
kind: CollectionAgent
metadata:
name: signoz
annotations:
foundry.signoz.io/kubernetes-collector-controller: opentelemetry-operator
spec:
deployment:
mode: kubernetes
flavor: helm
collector:
spec:
env:
SIGNOZ_INGESTION_ENDPOINT: https://ingest.<region>.signoz.cloud:443
SIGNOZ_INGESTION_KEY: <your-ingestion-key>
K8S_CLUSTER_NAME: <CLUSTER_NAME>
OTEL_RESOURCE_ATTRIBUTES: deployment.environment=<DEPLOYMENT_ENVIRONMENT>
config:
data:
collector/agent/agent.yaml: |
exporters:
otlphttp/signoz:
headers:
signoz-ingestion-key: ${env:SIGNOZ_INGESTION_KEY}
---
apiVersion: v1alpha1
kind: CollectionAgent
metadata:
name: signoz
annotations:
foundry.signoz.io/kubernetes-collector-controller: opentelemetry-operator
spec:
deployment:
mode: kubernetes
flavor: helm
collector:
kind: deployment
spec:
env:
SIGNOZ_INGESTION_ENDPOINT: https://ingest.<region>.signoz.cloud:443
SIGNOZ_INGESTION_KEY: <your-ingestion-key>
K8S_CLUSTER_NAME: <CLUSTER_NAME>
OTEL_RESOURCE_ATTRIBUTES: deployment.environment=<DEPLOYMENT_ENVIRONMENT>
config:
data:
collector/deployment/deployment.yaml: |
exporters:
otlphttp/signoz:
headers:
signoz-ingestion-key: ${env:SIGNOZ_INGESTION_KEY}Verify these values:
<region>: Your SigNoz Cloud region.<your-ingestion-key>: Your SigNoz Cloud ingestion key. It is set as a plain environment variable on the collector pods.<CLUSTER_NAME>: A name for this cluster, unique across the clusters that send to the same SigNoz. Use the same value in both documents. It becomesk8s.cluster.nameon every signal and names the cluster in the SigNoz Kubernetes views.<DEPLOYMENT_ENVIRONMENT>: Your deployment environment, for examplestagingorproduction. It becomesdeployment.environmenton the collected telemetry.
For every option of this casting, see the Kubernetes Helm example for the OpenTelemetry Operator.
apiVersion: v1alpha1
kind: CollectionAgent
metadata:
name: signoz
annotations:
foundry.signoz.io/kubernetes-collector-controller: opentelemetry-operator
spec:
deployment:
platform: aws
mode: kubernetes
flavor: helm
collector:
spec:
env:
SIGNOZ_INGESTION_ENDPOINT: https://ingest.<region>.signoz.cloud:443
SIGNOZ_INGESTION_KEY: <your-ingestion-key>
K8S_CLUSTER_NAME: <CLUSTER_NAME>
OTEL_RESOURCE_ATTRIBUTES: deployment.environment=<DEPLOYMENT_ENVIRONMENT>
config:
data:
collector/agent/agent.yaml: |
exporters:
otlphttp/signoz:
headers:
signoz-ingestion-key: ${env:SIGNOZ_INGESTION_KEY}
---
apiVersion: v1alpha1
kind: CollectionAgent
metadata:
name: signoz
annotations:
foundry.signoz.io/kubernetes-collector-controller: opentelemetry-operator
spec:
deployment:
platform: aws
mode: kubernetes
flavor: helm
collector:
kind: deployment
spec:
env:
SIGNOZ_INGESTION_ENDPOINT: https://ingest.<region>.signoz.cloud:443
SIGNOZ_INGESTION_KEY: <your-ingestion-key>
K8S_CLUSTER_NAME: <CLUSTER_NAME>
OTEL_RESOURCE_ATTRIBUTES: deployment.environment=<DEPLOYMENT_ENVIRONMENT>
config:
data:
collector/deployment/deployment.yaml: |
exporters:
otlphttp/signoz:
headers:
signoz-ingestion-key: ${env:SIGNOZ_INGESTION_KEY}Verify these values:
<region>: Your SigNoz Cloud region.<your-ingestion-key>: Your SigNoz Cloud ingestion key. It is set as a plain environment variable on the collector pods.<CLUSTER_NAME>: A name for this cluster, unique across the clusters that send to the same SigNoz. Use the same value in both documents. It becomesk8s.cluster.nameon every signal and names the cluster in the SigNoz Kubernetes views.<DEPLOYMENT_ENVIRONMENT>: Your deployment environment, for examplestagingorproduction. It becomesdeployment.environmenton the collected telemetry.
For every option of this casting, see the Kubernetes Helm example for the OpenTelemetry Operator.
apiVersion: v1alpha1
kind: CollectionAgent
metadata:
name: signoz
annotations:
foundry.signoz.io/kubernetes-collector-controller: opentelemetry-operator
spec:
deployment:
platform: gcp
mode: kubernetes
flavor: helm
collector:
spec:
env:
SIGNOZ_INGESTION_ENDPOINT: https://ingest.<region>.signoz.cloud:443
SIGNOZ_INGESTION_KEY: <your-ingestion-key>
K8S_CLUSTER_NAME: <CLUSTER_NAME>
OTEL_RESOURCE_ATTRIBUTES: deployment.environment=<DEPLOYMENT_ENVIRONMENT>
config:
data:
collector/agent/agent.yaml: |
exporters:
otlphttp/signoz:
headers:
signoz-ingestion-key: ${env:SIGNOZ_INGESTION_KEY}
---
apiVersion: v1alpha1
kind: CollectionAgent
metadata:
name: signoz
annotations:
foundry.signoz.io/kubernetes-collector-controller: opentelemetry-operator
spec:
deployment:
platform: gcp
mode: kubernetes
flavor: helm
collector:
kind: deployment
spec:
env:
SIGNOZ_INGESTION_ENDPOINT: https://ingest.<region>.signoz.cloud:443
SIGNOZ_INGESTION_KEY: <your-ingestion-key>
K8S_CLUSTER_NAME: <CLUSTER_NAME>
OTEL_RESOURCE_ATTRIBUTES: deployment.environment=<DEPLOYMENT_ENVIRONMENT>
config:
data:
collector/deployment/deployment.yaml: |
exporters:
otlphttp/signoz:
headers:
signoz-ingestion-key: ${env:SIGNOZ_INGESTION_KEY}Verify these values:
<region>: Your SigNoz Cloud region.<your-ingestion-key>: Your SigNoz Cloud ingestion key. It is set as a plain environment variable on the collector pods.<CLUSTER_NAME>: A name for this cluster, unique across the clusters that send to the same SigNoz. Use the same value in both documents. It becomesk8s.cluster.nameon every signal and names the cluster in the SigNoz Kubernetes views.<DEPLOYMENT_ENVIRONMENT>: Your deployment environment, for examplestagingorproduction. It becomesdeployment.environmenton the collected telemetry.
For every option of this casting, see the Kubernetes Helm example for the OpenTelemetry Operator.
apiVersion: v1alpha1
kind: CollectionAgent
metadata:
name: signoz
annotations:
foundry.signoz.io/kubernetes-collector-controller: opentelemetry-operator
spec:
deployment:
platform: azure
mode: kubernetes
flavor: helm
collector:
spec:
env:
SIGNOZ_INGESTION_ENDPOINT: https://ingest.<region>.signoz.cloud:443
SIGNOZ_INGESTION_KEY: <your-ingestion-key>
K8S_CLUSTER_NAME: <CLUSTER_NAME>
OTEL_RESOURCE_ATTRIBUTES: deployment.environment=<DEPLOYMENT_ENVIRONMENT>
config:
data:
collector/agent/agent.yaml: |
exporters:
otlphttp/signoz:
headers:
signoz-ingestion-key: ${env:SIGNOZ_INGESTION_KEY}
---
apiVersion: v1alpha1
kind: CollectionAgent
metadata:
name: signoz
annotations:
foundry.signoz.io/kubernetes-collector-controller: opentelemetry-operator
spec:
deployment:
platform: azure
mode: kubernetes
flavor: helm
collector:
kind: deployment
spec:
env:
SIGNOZ_INGESTION_ENDPOINT: https://ingest.<region>.signoz.cloud:443
SIGNOZ_INGESTION_KEY: <your-ingestion-key>
K8S_CLUSTER_NAME: <CLUSTER_NAME>
OTEL_RESOURCE_ATTRIBUTES: deployment.environment=<DEPLOYMENT_ENVIRONMENT>
config:
data:
collector/deployment/deployment.yaml: |
exporters:
otlphttp/signoz:
headers:
signoz-ingestion-key: ${env:SIGNOZ_INGESTION_KEY}Verify these values:
<region>: Your SigNoz Cloud region.<your-ingestion-key>: Your SigNoz Cloud ingestion key. It is set as a plain environment variable on the collector pods.<CLUSTER_NAME>: A name for this cluster, unique across the clusters that send to the same SigNoz. Use the same value in both documents. It becomesk8s.cluster.nameon every signal and names the cluster in the SigNoz Kubernetes views.<DEPLOYMENT_ENVIRONMENT>: Your deployment environment, for examplestagingorproduction. It becomesdeployment.environmenton the collected telemetry.
For every option of this casting, see the Kubernetes Helm example for the OpenTelemetry Operator.
Step 3: Deploy
Run this from the directory that contains casting.yaml:
foundryctl cast -f casting.yamlThis installs the opentelemetry-kube-stack chart, version 0.13.0, into the signoz namespace as two releases, signoz-collector-agent and signoz-collector-deployment, and creates the namespace when it is missing. Each release creates one OpenTelemetryCollector resource with the release's name, and the operator creates the collector workloads from it. Run the same command again after editing casting.yaml to apply the change.
Step 4: Verify the Collection Agent
Run this on the machine where you use kubectl to check that the pods are running:
kubectl get pods -n signozThe output should look similar to the following, with one signoz-collector-agent-collector pod per node. The operator names each workload after its OpenTelemetryCollector resource with a -collector suffix. Pod suffixes vary, and if SigNoz runs in the same namespace its pods are listed too:
NAME READY STATUS RESTARTS AGE
signoz-collector-agent-collector-7xk2p 1/1 Running 0 2m
signoz-collector-agent-collector-q9m4d 1/1 Running 0 2m
signoz-collector-deployment-collector-6d9c7b8f5c-k2x9p 1/1 Running 0 2mIn SigNoz, open the Kubernetes Monitoring views under Infrastructure Monitoring. The Clusters view lists your cluster under the name you set as <CLUSTER_NAME>, and the Pods and Nodes views fill in as data arrives. Check Logs Explorer to confirm container logs and Kubernetes events are flowing.
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.yamlorcollector/deployment/deployment.yaml. It merges into the generated config, which becomes the resource'sspec.config(see custom config files). For example, to scrape kubelet metrics every 60s:spec: collector: spec: config: data: collector/agent/agent.yaml: | receivers: kubeletstats: collection_interval: 60s -
Chart values (resources, tolerations, node selector): add patches under
spec.patchesagainstcollectionagent/collector/agent/values.yamlorcollectionagent/collector/deployment/values.yaml. Each collector's values sit under/collectors/agentor/collectors/deployment. For example, to set the agent's resource requests:spec: patches: - target: collectionagent/collector/agent/values.yaml operations: - op: add path: /collectors/agent/resources value: requests: cpu: 200m memory: 256MiFor every chart value, see the opentelemetry-kube-stack chart. Each run regenerates the files under
pours/, so keep every change incasting.yaml.
Troubleshooting
foundryctl cast fails on the OpenTelemetryCollector resources
Run this on the machine where you use kubectl to check the operator's CRD and Deployment:
kubectl get crd opentelemetrycollectors.opentelemetry.io
kubectl get deployments -n opentelemetry-operator-systemCause: the OpenTelemetry Operator or its CRDs are not installed, or the operator is not ready yet. The operator's admission webhook checks every OpenTelemetryCollector resource, so the resources need a running operator.
Fix: install the operator as shown in Install the OpenTelemetry Operator, wait until its Deployment shows 1/1 under READY, then run foundryctl cast -f casting.yaml again from the directory that contains it.
After the fix, kubectl get pods -n signoz shows the collector pods.
Agent pod stays Pending
Run this on the machine where you use kubectl to see why the pod is unscheduled:
kubectl describe pod -n signoz <pod-name>Replace <pod-name> with the agent pod's name from kubectl get pods -n signoz.
Cause: another collector holds host ports 4317, 4318, 8888, and 13133 on the node, for example a K8s Infra agent.
Fix: keep one of the two agents and remove the other.
After the fix, kubectl get pods -n signoz shows one agent pod per node as Running.
foundryctl cast rejects a patch
foundryctl cast -f casting.yaml stops before it installs anything, with a message that names the patch's target.
Cause: the patch's target or path does not exist in what Foundry generates for the OpenTelemetry Operator.
Fix: target collectionagent/collector/agent/values.yaml or collectionagent/collector/deployment/values.yaml, with a path under /collectors/agent or /collectors/deployment. To see the files a patch can target, run this from the directory that contains casting.yaml and look under pours/collectionagent/collector/:
foundryctl forge -f casting.yamlThen run foundryctl cast -f casting.yaml again.
After the fix, kubectl get pods -n signoz shows the collector pods.
foundryctl cast reaches the wrong cluster or none
Run this on the machine where you run foundryctl to see which cluster it uses:
kubectl config current-contextCause: foundryctl cast applies to the cluster of your current kubectl context.
Fix: switch to the right context with kubectl config use-context <context-name>, then run foundryctl cast -f casting.yaml again from the directory that contains it. Replace <context-name> with a context from kubectl config get-contexts.
After the fix, kubectl get pods -n signoz shows the collector pods on that cluster.
Step 1: Install foundryctl
Run this on the machine where you use kubectl:
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 for your Kubernetes platform, with one document for each collector described in How it works:
apiVersion: v1alpha1
kind: CollectionAgent
metadata:
name: signoz
annotations:
foundry.signoz.io/kubernetes-collector-controller: opentelemetry-operator
spec:
deployment:
mode: kubernetes
flavor: kustomize
collector:
spec:
env:
SIGNOZ_INGESTION_ENDPOINT: https://ingest.<region>.signoz.cloud:443
SIGNOZ_INGESTION_KEY: <your-ingestion-key>
K8S_CLUSTER_NAME: <CLUSTER_NAME>
OTEL_RESOURCE_ATTRIBUTES: deployment.environment=<DEPLOYMENT_ENVIRONMENT>
config:
data:
collector/agent/agent.yaml: |
exporters:
otlphttp/signoz:
headers:
signoz-ingestion-key: ${env:SIGNOZ_INGESTION_KEY}
---
apiVersion: v1alpha1
kind: CollectionAgent
metadata:
name: signoz
annotations:
foundry.signoz.io/kubernetes-collector-controller: opentelemetry-operator
spec:
deployment:
mode: kubernetes
flavor: kustomize
collector:
kind: deployment
spec:
env:
SIGNOZ_INGESTION_ENDPOINT: https://ingest.<region>.signoz.cloud:443
SIGNOZ_INGESTION_KEY: <your-ingestion-key>
K8S_CLUSTER_NAME: <CLUSTER_NAME>
OTEL_RESOURCE_ATTRIBUTES: deployment.environment=<DEPLOYMENT_ENVIRONMENT>
config:
data:
collector/deployment/deployment.yaml: |
exporters:
otlphttp/signoz:
headers:
signoz-ingestion-key: ${env:SIGNOZ_INGESTION_KEY}Verify these values:
<region>: Your SigNoz Cloud region.<your-ingestion-key>: Your SigNoz Cloud ingestion key. It is set as a plain environment variable on the collector pods.<CLUSTER_NAME>: A name for this cluster, unique across the clusters that send to the same SigNoz. Use the same value in both documents. It becomesk8s.cluster.nameon every signal and names the cluster in the SigNoz Kubernetes views.<DEPLOYMENT_ENVIRONMENT>: Your deployment environment, for examplestagingorproduction. It becomesdeployment.environmenton the collected telemetry.
For every option of this casting, see the Kubernetes Kustomize example for the OpenTelemetry Operator.
apiVersion: v1alpha1
kind: CollectionAgent
metadata:
name: signoz
annotations:
foundry.signoz.io/kubernetes-collector-controller: opentelemetry-operator
spec:
deployment:
platform: aws
mode: kubernetes
flavor: kustomize
collector:
spec:
env:
SIGNOZ_INGESTION_ENDPOINT: https://ingest.<region>.signoz.cloud:443
SIGNOZ_INGESTION_KEY: <your-ingestion-key>
K8S_CLUSTER_NAME: <CLUSTER_NAME>
OTEL_RESOURCE_ATTRIBUTES: deployment.environment=<DEPLOYMENT_ENVIRONMENT>
config:
data:
collector/agent/agent.yaml: |
exporters:
otlphttp/signoz:
headers:
signoz-ingestion-key: ${env:SIGNOZ_INGESTION_KEY}
---
apiVersion: v1alpha1
kind: CollectionAgent
metadata:
name: signoz
annotations:
foundry.signoz.io/kubernetes-collector-controller: opentelemetry-operator
spec:
deployment:
platform: aws
mode: kubernetes
flavor: kustomize
collector:
kind: deployment
spec:
env:
SIGNOZ_INGESTION_ENDPOINT: https://ingest.<region>.signoz.cloud:443
SIGNOZ_INGESTION_KEY: <your-ingestion-key>
K8S_CLUSTER_NAME: <CLUSTER_NAME>
OTEL_RESOURCE_ATTRIBUTES: deployment.environment=<DEPLOYMENT_ENVIRONMENT>
config:
data:
collector/deployment/deployment.yaml: |
exporters:
otlphttp/signoz:
headers:
signoz-ingestion-key: ${env:SIGNOZ_INGESTION_KEY}Verify these values:
<region>: Your SigNoz Cloud region.<your-ingestion-key>: Your SigNoz Cloud ingestion key. It is set as a plain environment variable on the collector pods.<CLUSTER_NAME>: A name for this cluster, unique across the clusters that send to the same SigNoz. Use the same value in both documents. It becomesk8s.cluster.nameon every signal and names the cluster in the SigNoz Kubernetes views.<DEPLOYMENT_ENVIRONMENT>: Your deployment environment, for examplestagingorproduction. It becomesdeployment.environmenton the collected telemetry.
For every option of this casting, see the Kubernetes Kustomize example for the OpenTelemetry Operator.
apiVersion: v1alpha1
kind: CollectionAgent
metadata:
name: signoz
annotations:
foundry.signoz.io/kubernetes-collector-controller: opentelemetry-operator
spec:
deployment:
platform: gcp
mode: kubernetes
flavor: kustomize
collector:
spec:
env:
SIGNOZ_INGESTION_ENDPOINT: https://ingest.<region>.signoz.cloud:443
SIGNOZ_INGESTION_KEY: <your-ingestion-key>
K8S_CLUSTER_NAME: <CLUSTER_NAME>
OTEL_RESOURCE_ATTRIBUTES: deployment.environment=<DEPLOYMENT_ENVIRONMENT>
config:
data:
collector/agent/agent.yaml: |
exporters:
otlphttp/signoz:
headers:
signoz-ingestion-key: ${env:SIGNOZ_INGESTION_KEY}
---
apiVersion: v1alpha1
kind: CollectionAgent
metadata:
name: signoz
annotations:
foundry.signoz.io/kubernetes-collector-controller: opentelemetry-operator
spec:
deployment:
platform: gcp
mode: kubernetes
flavor: kustomize
collector:
kind: deployment
spec:
env:
SIGNOZ_INGESTION_ENDPOINT: https://ingest.<region>.signoz.cloud:443
SIGNOZ_INGESTION_KEY: <your-ingestion-key>
K8S_CLUSTER_NAME: <CLUSTER_NAME>
OTEL_RESOURCE_ATTRIBUTES: deployment.environment=<DEPLOYMENT_ENVIRONMENT>
config:
data:
collector/deployment/deployment.yaml: |
exporters:
otlphttp/signoz:
headers:
signoz-ingestion-key: ${env:SIGNOZ_INGESTION_KEY}Verify these values:
<region>: Your SigNoz Cloud region.<your-ingestion-key>: Your SigNoz Cloud ingestion key. It is set as a plain environment variable on the collector pods.<CLUSTER_NAME>: A name for this cluster, unique across the clusters that send to the same SigNoz. Use the same value in both documents. It becomesk8s.cluster.nameon every signal and names the cluster in the SigNoz Kubernetes views.<DEPLOYMENT_ENVIRONMENT>: Your deployment environment, for examplestagingorproduction. It becomesdeployment.environmenton the collected telemetry.
For every option of this casting, see the Kubernetes Kustomize example for the OpenTelemetry Operator.
apiVersion: v1alpha1
kind: CollectionAgent
metadata:
name: signoz
annotations:
foundry.signoz.io/kubernetes-collector-controller: opentelemetry-operator
spec:
deployment:
platform: azure
mode: kubernetes
flavor: kustomize
collector:
spec:
env:
SIGNOZ_INGESTION_ENDPOINT: https://ingest.<region>.signoz.cloud:443
SIGNOZ_INGESTION_KEY: <your-ingestion-key>
K8S_CLUSTER_NAME: <CLUSTER_NAME>
OTEL_RESOURCE_ATTRIBUTES: deployment.environment=<DEPLOYMENT_ENVIRONMENT>
config:
data:
collector/agent/agent.yaml: |
exporters:
otlphttp/signoz:
headers:
signoz-ingestion-key: ${env:SIGNOZ_INGESTION_KEY}
---
apiVersion: v1alpha1
kind: CollectionAgent
metadata:
name: signoz
annotations:
foundry.signoz.io/kubernetes-collector-controller: opentelemetry-operator
spec:
deployment:
platform: azure
mode: kubernetes
flavor: kustomize
collector:
kind: deployment
spec:
env:
SIGNOZ_INGESTION_ENDPOINT: https://ingest.<region>.signoz.cloud:443
SIGNOZ_INGESTION_KEY: <your-ingestion-key>
K8S_CLUSTER_NAME: <CLUSTER_NAME>
OTEL_RESOURCE_ATTRIBUTES: deployment.environment=<DEPLOYMENT_ENVIRONMENT>
config:
data:
collector/deployment/deployment.yaml: |
exporters:
otlphttp/signoz:
headers:
signoz-ingestion-key: ${env:SIGNOZ_INGESTION_KEY}Verify these values:
<region>: Your SigNoz Cloud region.<your-ingestion-key>: Your SigNoz Cloud ingestion key. It is set as a plain environment variable on the collector pods.<CLUSTER_NAME>: A name for this cluster, unique across the clusters that send to the same SigNoz. Use the same value in both documents. It becomesk8s.cluster.nameon every signal and names the cluster in the SigNoz Kubernetes views.<DEPLOYMENT_ENVIRONMENT>: Your deployment environment, for examplestagingorproduction. It becomesdeployment.environmenton the collected telemetry.
For every option of this casting, see the Kubernetes Kustomize example for the OpenTelemetry Operator.
Step 3: Deploy
Run this from the directory that contains casting.yaml:
foundryctl cast -f casting.yamlThis command:
- writes one kustomize root per collector,
pours/collectionagent/collector/agentandpours/collectionagent/collector/deployment; - applies each root with
kubectl apply -kto the cluster of your currentkubectlcontext; - creates the
signoznamespace on the first apply, since each root holds the namespace, the collector's service account and RBAC, and itsOpenTelemetryCollectorresource.
The operator then creates the collector workloads from the two resources. Run the same command again after editing casting.yaml to apply the change.
Step 4: Verify the Collection Agent
Run this on the machine where you use kubectl to check that the pods are running:
kubectl get pods -n signozThe output should look similar to the following, with one signoz-collector-agent-collector pod per node. The operator names each workload after its OpenTelemetryCollector resource with a -collector suffix. Pod suffixes vary, and if SigNoz runs in the same namespace its pods are listed too:
NAME READY STATUS RESTARTS AGE
signoz-collector-agent-collector-7xk2p 1/1 Running 0 2m
signoz-collector-agent-collector-q9m4d 1/1 Running 0 2m
signoz-collector-deployment-collector-6d9c7b8f5c-k2x9p 1/1 Running 0 2mIn SigNoz, open the Kubernetes Monitoring views under Infrastructure Monitoring. The Clusters view lists your cluster under the name you set as <CLUSTER_NAME>, and the Pods and Nodes views fill in as data arrives. Check Logs Explorer to confirm container logs and Kubernetes events are flowing.
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.yamlorcollector/deployment/deployment.yaml. It merges into the generated config, which becomes the resource'sspec.config(see custom config files). For example, to scrape kubelet metrics every 60s:spec: collector: spec: config: data: collector/agent/agent.yaml: | receivers: kubeletstats: collection_interval: 60s -
Manifests (resources, tolerations, node selector): add patches under
spec.patchesagainstcollectionagent/collector/agent/opentelemetrycollector.yamlorcollectionagent/collector/deployment/opentelemetrycollector.yaml, the collectors'OpenTelemetryCollectorresources, with paths under/spec. For example, to set the agent's resource requests:spec: patches: - target: collectionagent/collector/agent/opentelemetrycollector.yaml operations: - op: replace path: /spec/resources value: requests: cpu: 200m memory: 256MiFor every field of the resource, see the OpenTelemetryCollector API reference. Each run regenerates the files under
pours/, so keep every change incasting.yaml.
Troubleshooting
foundryctl cast fails on the OpenTelemetryCollector resources
Run this on the machine where you use kubectl to check the operator's CRD and Deployment:
kubectl get crd opentelemetrycollectors.opentelemetry.io
kubectl get deployments -n opentelemetry-operator-systemCause: the OpenTelemetry Operator or its CRDs are not installed, or the operator is not ready yet. The operator's admission webhook checks every OpenTelemetryCollector resource, so the resources need a running operator.
Fix: install the operator as shown in Install the OpenTelemetry Operator, wait until its Deployment shows 1/1 under READY, then run foundryctl cast -f casting.yaml again from the directory that contains it.
After the fix, kubectl get pods -n signoz shows the collector pods.
Agent pod stays Pending
Run this on the machine where you use kubectl to see why the pod is unscheduled:
kubectl describe pod -n signoz <pod-name>Replace <pod-name> with the agent pod's name from kubectl get pods -n signoz.
Cause: another collector holds host ports 4317, 4318, 8888, and 13133 on the node, for example a K8s Infra agent.
Fix: keep one of the two agents and remove the other.
After the fix, kubectl get pods -n signoz shows one agent pod per node as Running.
foundryctl cast rejects a patch
foundryctl cast -f casting.yaml stops before it applies anything, with a message that names the patch's target.
Cause: the patch's target or path does not exist in what Foundry generates for the OpenTelemetry Operator.
Fix: target collectionagent/collector/agent/opentelemetrycollector.yaml or collectionagent/collector/deployment/opentelemetrycollector.yaml, with a path under /spec. To see the files a patch can target, run this from the directory that contains casting.yaml and look under pours/collectionagent/collector/:
foundryctl forge -f casting.yamlThen run foundryctl cast -f casting.yaml again.
After the fix, kubectl get pods -n signoz shows the collector pods.
foundryctl cast reaches the wrong cluster or none
Run this on the machine where you run foundryctl to see which cluster it uses:
kubectl config current-contextCause: foundryctl cast applies to the cluster of your current kubectl context.
Fix: switch to the right context with kubectl config use-context <context-name>, then run foundryctl cast -f casting.yaml again from the directory that contains it. Replace <context-name> with a context from kubectl config get-contexts.
After the fix, kubectl get pods -n signoz shows the collector pods on that cluster.
Send data from your applications
Node, pod, and container metrics, container logs, and Kubernetes events flow as soon as the collector pods are running. To send traces, metrics, and logs from your applications through the agent, see Send Data from Applications to the Collector.