Skip to content

Latest commit

 

History

History
189 lines (168 loc) · 5.64 KB

File metadata and controls

189 lines (168 loc) · 5.64 KB

eBPF instrumentation with the OBI receiver

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.

Collector CR

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]

Unprivileged setup

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.

Selecting workloads

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

You 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.

Kubernetes attribute enrichment

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.