For the complete documentation index, see llms.txt. Markdown versions are available by appending .md to documentation URLs.

OpenTelemetry Operator - Install

SigNoz Cloud - This page applies to SigNoz Cloud editions.
Self-Host - This page applies to self-hosted SigNoz editions.

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.
  • kubectl configured 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.yaml

Then run this on the same machine to check the operator:

kubectl get deployment opentelemetry-operator-controller-manager -n opentelemetry-operator-system

The operator is ready when READY shows 1/1.

Install the Collection Agent

Step 1: Install foundryctl

Run this on the machine where you use kubectl:

curl -fsSL https://signoz.io/foundry.sh | bash

For 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:

casting.yaml
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 becomes k8s.cluster.name on every signal and names the cluster in the SigNoz Kubernetes views.
  • <DEPLOYMENT_ENVIRONMENT>: Your deployment environment, for example staging or production. It becomes deployment.environment on 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.yaml

This 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 signoz

The 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          2m

In 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, keyed collector/agent/agent.yaml or collector/deployment/deployment.yaml. It merges into the generated config, which becomes the resource's spec.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.patches against collectionagent/collector/agent/values.yaml or collectionagent/collector/deployment/values.yaml. Each collector's values sit under /collectors/agent or /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: 256Mi

    For every chart value, see the opentelemetry-kube-stack chart. Each run regenerates the files under pours/, so keep every change in casting.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-system

Cause: 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.yaml

Then 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-context

Cause: 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.

Next Steps

Is this page helpful

Last updated—October 26, 2026

Edit on GitHub