Snippets · Processors
Add Kubernetes pod, namespace and deployment to telemetry
A span or log line from a pod says nothing about which deployment, namespace or node it came from unless something adds it. The k8sattributes processor looks the sending pod up in the Kubernetes API, by the k8s.pod.ip resource attribute or the connection's source IP, and adds those names to every record.
- Category
- Kubernetes
- Source
- OTLP
- Destination
- OTLP/HTTP endpoint
OpenTelemetry Collector
receivers:
otlp:
protocols:
grpc:
endpoint: 0.0.0.0:4317
processors:
memory_limiter:
check_interval: 1s
limit_percentage: 80
spike_limit_percentage: 25
# Adds pod, namespace, deployment and node to every record, looked up from
# the Kubernetes API by the sending pod's IP. Needs RBAC: get/watch/list on
# pods, namespaces and replicasets (deployment name).
k8sattributes:
auth_type: serviceAccount
passthrough: false
extract:
metadata:
- k8s.namespace.name
- k8s.pod.name
- k8s.pod.uid
- k8s.deployment.name
- k8s.node.name
pod_association:
- sources:
- from: resource_attribute
name: k8s.pod.ip
- sources:
- from: connection
batch:
timeout: 5s
exporters:
otlphttp:
endpoint: https://your-backend:4318
service:
pipelines:
logs:
receivers: [otlp]
processors: [memory_limiter, k8sattributes, batch]
exporters: [otlphttp]
metrics:
receivers: [otlp]
processors: [memory_limiter, k8sattributes, batch]
exporters: [otlphttp]
traces:
receivers: [otlp]
processors: [memory_limiter, k8sattributes, batch]
exporters: [otlphttp]
LinkMesh
LinkMesh has no built-in template for this job. Add it as a custom processor in raw mode, with k8sattributes as the component type and this body - the same lines as under k8sattributes in the collector config:
auth_type: serviceAccount
passthrough: false
extract:
metadata:
- k8s.namespace.name
- k8s.pod.name
- k8s.pod.uid
- k8s.deployment.name
- k8s.node.name
pod_association:
- sources:
- from: resource_attribute
name: k8s.pod.ip
- sources:
- from: connection
How custom components are validated and rolled out: create a custom processor.
Download config.yamlValidated with otelcol-contrib v0.161.0 on 2026-10-26
Complete config files, each checked with the collector's own validate command (otelcol-contrib v0.161.0). Replace https://your-backend:4318 with your own OTLP endpoint before you run it.
The gotcha
validate accepts this config anywhere, but outside a cluster - or inside one without a service account - the collector does not start working. In our test it logged "unable to load k8s config, KUBERNETES_SERVICE_HOST and KUBERNETES_SERVICE_PORT must be defined", then kept running without ever reporting ready: a live process with no working pipeline. Run it in-cluster with RBAC for pods, namespaces and replicasets (needed for the deployment name).
Used in these pipelines
What it does not catch
This page has no before/after table: the processor needs a live Kubernetes API, and our CI runs the collector outside a cluster.
Manage this across a fleet
LinkMesh manages collector configuration across a fleet from one self-hosted control plane, so a change like this is made once rather than host by host. The first 25 Collectors are free after a no-card registration in the OpenSight Customer Portal (5 without one).
Doing this in LinkMesh: Onboard Kubernetes layer by layer
Related snippets
- Kubernetes pod logs to Loki, enriched with deployment and clusterEvery pod's logs into Loki over OTLP, labelled with namespace, pod, container, deployment, node and cluster.
- Scrape cAdvisor container metrics from the kubeletThe container_* metrics Kubernetes dashboards expect, scraped from each node's kubelet with the pod's service account token.
- Collect Kubernetes cluster metrics (one replica)Deployment replicas, pod phases, node conditions, restarts and resource quotas from the Kubernetes API - one collector for the whole cluster.
- Collect Kubernetes events as logsScheduling failures, image pull errors, OOM kills and probe failures as log records - kept after Kubernetes deletes the events.