Deploy OpenTelemetry Collector on Kubernetes with Helm

Configure a version-pinned Collector Helm chart, choose DaemonSet or Deployment, and verify trace export to a matching DataKit endpoint.

Best practices
Illustration of connected application signals and engineering workflows

The official OpenTelemetry Collector Helm chart packages Kubernetes workloads, configuration, services, and supporting permissions. It is a practical way to deploy a Collector, but the chart cannot infer your backend's protocol, authentication, network path, or required telemetry pipeline.

Start by choosing the workload mode, inspecting the chart defaults, and making the exporter contract explicit. The example below pins chart 0.176.0 and Collector Contrib 0.162.0 and configures a trace-only DaemonSet. Check compatibility again before adopting a different version.

Understand values, presets, and environment substitution

Values configure the chart. Keep your overrides in a version-controlled values file rather than modifying downloaded templates. Helm merges maps, while lists generally replace the corresponding list. Unwanted default configuration may need an explicit null; defining a trace pipeline alone does not remove the default logs and metrics pipelines. Inspect the rendered configuration after every meaningful change.

Presets configure related resources together. For example, kubernetesAttributes adds the Kubernetes metadata processor and supporting RBAC. It does not guarantee a successful Pod association for every event. The processor must be able to identify the originating Pod, and its permissions and network access must work. A gateway seeing another Collector's connection may need resource attributes identifying the original Pod.

Collector environment substitution happens at runtime. A value such as ${env:DATAKIT_TRACES_URL} refers to the container environment. Inject credentials through an appropriate Kubernetes Secret or secret-management integration; do not commit them to the values file. Environment variables do not by themselves make a secret invisible to everyone with administrative access.

See the official Collector chart guide and the versioned chart values.

Choose DaemonSet or Deployment deliberately

Mode Useful property Typical role
DaemonSet Runs a Collector on each eligible node, subject to scheduling rules Node logs, host metrics, and local application traffic
Deployment Runs a configurable number of replicas behind a service Central gateway for aggregation, routing, or shared processing

A common topology uses a DaemonSet as the Agent tier and a Deployment as the Gateway tier. That adds a network hop and another capacity boundary, so use it when it serves a concrete need. Do not collect the same signal twice unintentionally, and preserve resource identity through the tiers.

The workload mode alone does not turn on host metrics or file collection. Those require suitable receivers or presets, filesystem access, and permissions. A DaemonSet also does not necessarily run on every cluster node: selectors, taints, tolerations, and resource availability affect placement.

Prepare the chart and backend contract

Use a Kubernetes version supported by the selected chart and your platform, compatible Helm tooling, and permission to manage the rendered resources. A historical “Kubernetes 1.16+” minimum is not an adequate compatibility check for a current chart.

helm repo add open-telemetry https://open-telemetry.github.io/opentelemetry-helm-charts
helm repo update
helm show values open-telemetry/opentelemetry-collector --version 0.176.0

For a DataKit destination, first enable and verify its OpenTelemetry input using the DataKit OpenTelemetry documentation. Determine the complete HTTP trace-ingestion URL, including the actual port and path. Do not assume that DataKit listens on 4318 merely because that is a common OTLP/HTTP port.

The following values expect an existing Secret named datakit-otlp-endpoint in the release namespace, with a traces-url key containing that complete URL. Provision it through your organization's normal secret-management process. If the receiver requires authentication, add the exact supported header or authentication extension separately. A made-up Authorization: Token ... header is not a substitute for the receiver's documented contract.

Configure a trace-only Collector

Save this as values.yaml:

mode: daemonset
image:
  repository: otel/opentelemetry-collector-contrib
  tag: "0.162.0"
command:
  name: otelcol-contrib

presets:
  kubernetesAttributes:
    enabled: true

extraEnvs:
  - name: DATAKIT_TRACES_URL
    valueFrom:
      secretKeyRef:
        name: datakit-otlp-endpoint
        key: traces-url

resources:
  requests:
    cpu: 100m
    memory: 256Mi
  limits:
    cpu: "1"
    memory: 1Gi

ports:
  otlp:
    enabled: true
    hostPort: 4317
  otlp-http:
    enabled: true
    hostPort: 4318
  jaeger-compact:
    enabled: false
  jaeger-thrift:
    enabled: false
  jaeger-grpc:
    enabled: false
  zipkin:
    enabled: false

config:
  receivers:
    jaeger: null
    prometheus: null
    zipkin: null
    otlp:
      protocols:
        grpc:
          endpoint: ${env:MY_POD_IP}:4317
        http:
          endpoint: ${env:MY_POD_IP}:4318
  processors:
    memory_limiter:
      check_interval: 5s
      limit_percentage: null
      spike_limit_percentage: null
      limit_mib: 800
      spike_limit_mib: 150
    batch:
      send_batch_size: 8192
      timeout: 5s
  exporters:
    debug: null
    otlp_http/datakit:
      traces_endpoint: ${env:DATAKIT_TRACES_URL}
  service:
    pipelines:
      logs: null
      metrics: null
      traces:
        receivers: [otlp]
        processors: [memory_limiter, k8s_attributes, batch]
        exporters: [otlp_http/datakit]

The explicit image and command select a distribution containing the required components. This chart/image pair uses the newer k8s_attributes and otlp_http component names; older examples often use k8sattributes and otlphttp. Component aliases and the chart's rewriting behavior are version-sensitive, so check the selected image when migrating old values.

The preset supplies the k8s_attributes configuration. Listing it explicitly in the pipeline also fixes its position after memory_limiter and before batch. The chart's health-check extension remains enabled; removing it without replacing the probes' target would break readiness and liveness checks.

This configuration accepts traces through gRPC or HTTP and exports them over HTTP. A gRPC exporter and an HTTP endpoint are different contracts. traces_endpoint supplies the complete destination URL directly, avoiding an accidental standard /v1/traces suffix on a backend-specific route. TLS and authentication must match the actual destination.

The values deliberately remove the default application logs and metrics pipelines. Collector self-observation is a separate concern: expose or scrape its internal metrics deliberately rather than treating this trace-only example as a complete monitoring installation.

Render, inspect, and then install

Render without contacting the cluster:

helm template otel-collector open-telemetry/opentelemetry-collector \
  --version 0.176.0 --namespace observability -f values.yaml > rendered.yaml

Inspect the ConfigMap, processor order, image, host ports, Secret reference, service account, and RBAC. A successful render proves template processing, not backend reachability or live Collector behavior. Validate the configuration with the selected Collector distribution and test in a suitable cluster before production use.

When the namespace and referenced Secret are ready and the rendered resources match the intended deployment:

helm upgrade --install otel-collector open-telemetry/opentelemetry-collector \
  --version 0.176.0 --namespace observability --create-namespace -f values.yaml

Inspect the workload status and Collector logs, send a controlled trace, and verify the receiving backend. Check service name, trace continuity, and Pod/namespace attributes before shifting application traffic. A running Pod with no exporter errors is useful evidence, but it does not alone prove that the intended data arrived and can be queried.

For a gateway Deployment, use a separately reviewed overlay such as:

mode: deployment
replicaCount: 2
service:
  enabled: true
ports:
  otlp:
    hostPort: null
  otlp-http:
    hostPort: null

Point producers at the generated Service and verify its actual name and DNS path. Remove node-specific assumptions and review metadata association across the network hop. Do not blindly switch an existing release's workload kind during a live migration; plan the handover and rollback.

Explain the processing and network limits

Place memory_limiter early so it can apply backpressure before more processing allocates memory. It rejects data as memory approaches configured thresholds; it does not guarantee that the process can never be OOM-killed. Memory spikes between checks, other allocations, and exporter queues still matter. Size it together with container limits and observe refused data, process memory, and export failures.

batch groups telemetry for export. Its size and timeout trade request frequency against memory and delivery latency. The values above preserve the tutorial's starting figures, not a measured capacity recommendation.

Kubernetes enrichment depends on correct association, not merely enabling the preset. Verify what the receiver sees as the connection source and whether resource attributes such as Pod UID or IP are available. For an Agent-to-Gateway path, enrich near the original source or configure the gateway's association rules appropriately.

If a browser sends OTLP/HTTP directly, configure explicit allowed CORS origins where supported. CORS is not authentication and does not protect an exposed ingestion service from arbitrary non-browser clients. Assess credentials, abuse controls, and data exposure before adopting direct browser delivery.

Use DataKit as the receiving backend

Deploy or configure DataKit according to the Kubernetes deployment guide. If using a manifest generated for your workspace, review it before applying:

kubectl apply -f datakit.yaml

That file is deployment-specific, not included in this example. Confirm the workspace destination, access configuration, enabled OpenTelemetry input, listening address, Service routing, and network policy. The Collector's outgoing HTTP trace URL must match that listener and route.

DataKit's Kubernetes deployment can provide an integrated collection path; an existing Collector may still be useful for a team's processors or routing. Compare the required signals and responsibilities before combining them, and check for duplicate collection. Do not remove existing processors merely because a single test trace arrived.

Common questions

How does an application find a node-local DaemonSet Collector?

One option injects status.hostIP through the Downward API and uses the node address as the OTLP destination. This works only when the chosen port is exposed on the node, reachable under the cluster's networking rules, and backed by a Collector on that node. The example explicitly configures host ports, which can conflict with other listeners. A Service is another option, but its routing policy must match any locality requirement. Node-local placement does not establish a universal latency advantage.

Will a chart upgrade preserve the configuration?

Keeping values in Git makes intent reproducible; it does not guarantee that a new chart or image interprets them identically. Pin versions, compare defaults and release notes, render the proposed upgrade with the saved values, and test the resulting Collector configuration. Plan rollback with attention to configuration and component compatibility.

What resource limits should I start with?

The example requests 100 millicores and 256 MiB and limits the container to one CPU and 1 GiB. These are illustrative starting values, not capacity results. Measure throughput, memory, CPU throttling, queue pressure, refused data, and export latency under representative traffic. See the Collector monitoring guide, currently in Chinese.

How should multiple clusters share configuration?

Keep a common base and cluster-specific overlays, with later -f files overriding earlier ones. Remember that lists replace rather than append. GitOps tools such as Argo CD or Flux can reconcile those desired resources, but version review, secret handling, and per-cluster validation still apply.

Continue with OpenTelemetry for Go. The Prometheus backend guide, Collector overview, and OpenTelemetry best practices are currently in Chinese. Browse the guides index for the rest of the series.

Get a tailored plan

Contact us

Join the community

Scan with WeChat
to join the community

Try Guance

Start online and pay only for what you use.

Get started

Choose a Guance plan

Code hosting