OBI (OpenTelemetry eBPF Instrumentation) uses eBPF to instrument applications at the kernel level. Without any code changes OBI inspects processes and the OS networking stack.
The OBI receiver uses eBPF to automatically instrument applications at the kernel level, producing distributed traces without code changes or language-specific agents.
Starting with collector contrib version 0.156.0, OBI is included as a collector receiver. This combines OBI's zero-code eBPF instrumentation with the Collector's processing capabilities (tail-based sampling, data filtering, multi-backend export)
Outlined here are examples of how the OpenTelemetry Operator OpenTelemetryCollector CR can be configured to use the OBI receiver.
For detailed OBI configuration, security requirements, and capability breakdowns, see the upstream OBI documentation.
OBI requires a DaemonSet with hostPID: true and elevated privileges to load eBPF programs. The simplest approach is a privileged container, which works across most environments:
apiVersion: v1
kind: ServiceAccount
metadata:
name: obi-collector
namespace: obi-system
# ...
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: obi
rules:
- apiGroups: ['apps']
resources: ['replicasets']
verbs: ['list', 'watch']
- apiGroups: ['']
resources: ['pods', 'services', 'nodes']
verbs: ['list', 'watch']
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: obi
subjects:
- kind: ServiceAccount
name: obi-collector
namespace: obi-system
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: obi
---
apiVersion: opentelemetry.io/v1beta1
kind: OpenTelemetryCollector
metadata:
name: obi-collector
namespace: obi-system
spec:
mode: daemonset
image: ghcr.io/open-telemetry/opentelemetry-collector-releases/opentelemetry-collector-contrib:latest
serviceAccount: obi-collector
hostPID: true # Required to access the processes on the host
securityContext:
runAsUser: 0
privileged: true
config:
receivers:
obi:
discovery:
instrument:
- k8s_namespace: my-application
k8s_pod_labels:
obi.instrument: "true"
attributes:
kubernetes:
enable: "true"
exporters:
debug:
verbosity: detailed
service:
pipelines:
traces:
receivers: [obi]
exporters: [debug]Instead of granting full privileges, you can run OBI with only the Linux capabilities it needs. For more information see [Deploy OBI unprivileged] (https://opentelemetry.io/docs/zero-code/obi/setup/kubernetes/#deploy-obi-unprivileged).
apiVersion: opentelemetry.io/v1beta1
kind: OpenTelemetryCollector
metadata:
name: obi-collector
namespace: obi-system
spec:
mode: daemonset
image: ghcr.io/open-telemetry/opentelemetry-collector-releases/opentelemetry-collector-contrib:latest
serviceAccount: obi-collector
hostPID: true
securityContext:
runAsUser: 0
readOnlyRootFilesystem: true
capabilities:
add:
- BPF
- SYS_PTRACE
- NET_RAW
- CHECKPOINT_RESTORE
- DAC_READ_SEARCH
- PERFMON
drop:
- ALL
volumes:
- name: var-run-obi
emptyDir: {}
- name: cgroup
hostPath:
path: /sys/fs/cgroup
volumeMounts:
- name: var-run-obi
mountPath: /var/run/obi
- name: cgroup
mountPath: /sys/fs/cgroup
config:
receivers:
obi:
discovery:
instrument:
- k8s_namespace: my-application
k8s_pod_labels:
obi.instrument: "true"
attributes:
kubernetes:
enable: "true"
exporters:
debug:
verbosity: detailed
service:
pipelines:
traces:
receivers: [obi]
exporters: [debug]The ServiceAccount, ClusterRole, and ClusterRoleBinding are the same as the privileged setup above.
The discovery.instrument list controls which processes OBI attaches to. The example below filters by namespace and pod labels — only pods matching all fields are instrumented:
receivers:
obi:
discovery:
instrument:
- k8s_namespace: frontend
k8s_pod_labels:
obi.instrument: "true"
- k8s_namespace: backend
k8s_pod_labels:
obi.instrument: "true"Add the matching label to workload pod templates to opt them in:
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-app
namespace: frontend
spec:
template:
metadata:
labels:
obi.instrument: "true"
spec:
containers:
- name: my-app
image: my-app:latestYou can also use k8s_pod_annotations in place of k8s_pod_labels to match on pod annotations instead.
For further information, see the OBI service discovery docs.
Setting attributes.kubernetes.enable: "true" adds resource attributes like k8s.namespace.name, k8s.pod.name, and service.name to traces. The collector ServiceAccount needs list and watch on pods, nodes, services, replicationcontrollers, deployments, replicasets, statefulsets, and daemonsets — see the OBI Kubernetes setup guide for the full RBAC requirements.