How to Use Beyla: The Beginner's Guide (First Auto-Instrumented App, the OTLP Lesson, First Dashboard, and the Kubernetes Arc)

CodexFuse Team · 2026-11-06T16:43:12.805Z · 18 min read min read

What Is Beyla?

Beyla is Grafana's open-source eBPF auto-instrumentation tool, and learning how to use Grafana Beyla means learning to attach it to a running service and watch traces and metrics appear with no code changes. It observes your application from the Linux kernel, captures HTTP and gRPC requests as RED metrics and trace spans, and exports them as OpenTelemetry data or Prometheus metrics. As of November 2026, the latest stable release is Beyla v3.40.0, published 2026-10-26, and this Beyla tutorial pins every command to that release.

The mental model is simple: Beyla eBPF probes attach to the kernel and watch the network calls your app already makes, instead of asking you to rewrite the app. It reads the requests flowing in and out of your service and turns them into the same request rate, error, and duration signals you would get from hand-written instrumentation. This is zero code instrumentation Beyla delivers without touching your code, and Beyla is the reference case for eBPF auto instrumentation OpenTelemetry users reach for first.

That promise has a limit you should hear once and clearly: Beyla does not create business context or spans for your internal functions, so add OpenTelemetry SDK spans where you need in-code detail. Beyla sees the request at the boundary of your service, not the function calls inside it, and a trace that stops at the boundary is still a trace worth having. The boundary view is enough for the questions most teams ask first, which are which service is slow and which endpoint is failing.

Beyla works at the application level, one service at a time, while Groundcover watches the whole cluster: nodes, network, and logs. The two are complementary, never rivals, and the Groundcover beginner guide covers the infrastructure side of the same observability story. If your question is which service is slow, Beyla answers it; if your question is which node is sick, Groundcover answers it.

Beyla is free and open source under the Apache License 2.0, and there is no paid tier to quote. The project began at Grafana Labs and was donated to the OpenTelemetry project in 2025 as OpenTelemetry eBPF Instrumentation, known as OBI. The repository had 2,154 stars and 205 forks when this guide was written, with 93 open issues, which works out to 10.51 stars per fork and a 9.5 percent fork ratio, and the code is written in Go.

The repository was created 2023-02-20, which makes it 1,355 days old as of this writing, and it is actively maintained: the last push landed 2026-11-06, the day this guide was written. Six releases shipped in the 30 days before that, with gaps of 14, 3, 4, 2, and 7 days between them, an average of one release every 6.0 days. That pace is why this guide pins a version instead of saying latest: v3.41.0 appeared 2026-11-04, only 2 days before this writing, but it is marked as a pre-release, so the latest stable release is v3.40.0, published 2026-10-26 and 11 days old.

How to Use Beyla in 7 Steps

This Beyla tutorial follows one arc from zero to a working dashboard. Each step below has its own section later in the guide, so use this list as the map and the sections as the detail.

  1. Check your kernel and install Beyla.
  2. Start a demo service on a known port.
  3. Run Beyla against that port with the trace printer on.
  4. Watch spans print in the terminal and metrics appear on the Prometheus endpoint.
  5. Point Beyla at an OpenTelemetry endpoint and send real traces.
  6. Open the metrics and traces in Grafana.
  7. Deploy Beyla as a DaemonSet in Kubernetes.

What You Need Before You Start

Beyla needs Linux kernel 5.8 or newer with BTF enabled, which you can check by looking for the file /sys/kernel/btf/vmlinux on the machine. Most distributions have shipped BTF by default since kernel 5.14, so a modern Ubuntu, Debian, Fedora, or RHEL host usually passes the check without any work. RHEL 8, CentOS 8, Rocky 8, and AlmaLinux 8 are supported on their 4.18 kernel with eBPF backports.

Trace context propagation needs kernel 5.17 or newer, because it relies on the bpf_loop helper that older kernels do not have. On a 5.8 to 5.16 kernel Beyla still produces metrics and single-span traces, but it cannot stitch spans across services into one distributed trace. Check uname -r before you start so a missing feature is a known limit, not a surprise.

Beyla instruments Go, Java, .NET, Node.js, Python, Ruby, Rust, and C and C++ services, and Go applications must be built with Go 1.17 or newer. Beyla supports Go releases no more than 3 versions behind the current stable release, and older Go builds are treated as non-Go programs. Go services get full distributed traces, while other languages get single-span traces per request.

This guide teaches the upstream tool on your own machines. CodexFuse offers no Beyla tool, so every command here runs Beyla itself, not a CodexFuse service.

RequirementMinimumHow to check
Linux kernel5.8 or newer with BTFls /sys/kernel/btf/vmlinux
Kernel for trace propagation5.17 or neweruname -r
Go applicationsGo 1.17 or newergo version
Privilegesroot, sudo, or Linux capabilitiesid, then capsh --print
Operating systemLinux, on a host, in a container, or in Kubernetesuname -a

How to Install Beyla

Beyla ships as a Linux binary, a Docker image, and a Helm chart, and the right route depends on where your service runs. The binary is the fastest way to learn on your own machine, Docker is the fastest way to learn with a demo service, and Helm is the route for a real cluster. The setup docs list only Docker, Helm and Kubernetes, and Alloy routes, so the binary path in this section follows the GitHub README and the releases page instead.

Download the latest stable tarball from the GitHub releases page, extract it, and run the beyla executable. The file is named beyla-linux-amd64-3.40.0.tar.gz for the pinned release, and v3.41.0 also added experimental DEB packages if you prefer a system package. Pin v3.40.0 for now, because v3.41.0 is a pre-release.

curl -LO https://github.com/grafana/beyla/releases/download/v3.40.0/beyla-linux-amd64-v3.40.0.tar.gz
tar -xzf beyla-linux-amd64-v3.40.0.tar.gz
./beyla --help

The Docker image is grafana/beyla:latest on Docker Hub, and it runs privileged with access to the target container's process namespace. The Docker beginner guide covers containers from zero if Docker itself is new to you. Beyla needs at least one exporter to start, and the trace printer counts as one, so a first run needs no backend at all.

docker run --rm --name beyla --privileged --pid="container:demo" \
  -e BEYLA_OPEN_PORT=5678 -e BEYLA_TRACE_PRINTER=text \
  grafana/beyla:latest
Install routeBest forCommand
Linux binaryLearning on your own machineDownload the tarball, extract, run ./beyla
Docker imageDemo service in a containerdocker run grafana/beyla:latest
Helm chartA real Kubernetes clusterhelm install beyla grafana/beyla
Grafana AlloyBeyla as part of an Alloy pipelinebeyla.ebpf component in Alloy

Your First Auto-Instrumented App

Beyla needs a running network service to instrument, so start the example service from the Beyla repository or any HTTP service on a known port. The README example is a small Go program that listens on port 8080, and any service on a fixed port works the same way. Generate traffic with curl in a loop so Beyla has requests to observe.

curl -OL https://raw.githubusercontent.com/grafana/beyla/main/examples/example-http-service/example-http-service.go
go run ./example-http-service.go
watch curl -s http://localhost:8080

Run Beyla with the port of your service and a Prometheus port of your own, then watch the metrics endpoint. The README quickstart uses BEYLA_OPEN_PORT=8080 and BEYLA_PROMETHEUS_PORT=9400, and it runs Beyla with sudo -E so the environment variables survive. Metrics appear at http://localhost:9400/metrics, and the trace printer shows spans in the terminal when BEYLA_TRACE_PRINTER=text is set.

export BEYLA_PROMETHEUS_PORT=9400
export BEYLA_OPEN_PORT=8080
sudo -E ./beyla

The first spans show the method, path, status code, and duration of each request, and the metrics endpoint exposes counters such as http_server_request_duration_seconds_count. That is the whole first run: no code changed, no SDK installed, no restart of your service. If nothing appears, check that traffic is actually hitting the port, because Beyla can only observe requests that exist.

How Beyla Finds Your App

Beyla selects its target by network port, executable path, or language, and the port is the simplest selector for a first run. BEYLA_OPEN_PORT takes a comma list or ranges, such as 80,443,8000-8999, and Beyla instruments every service it finds listening on those ports. When several services share a machine, narrow the target with BEYLA_AUTO_TARGET_EXE, which matches the full executable path as a glob.

BEYLA_EXECUTABLE_PATH does not exist in the current configuration, so never type it: the current selector is BEYLA_AUTO_TARGET_EXE, and the older BEYLA_EXECUTABLE_NAME is deprecated in favour of it. The service name and namespace options are deprecated too, and the name now goes in the discovery.instrument section of a YAML config file. An older guide that prints the old names teaches a config surface that no longer exists.

The dev.to walkthrough from 2025-11-07 is the clearest example of that drift: it is 364 days old, and its YAML keys listen:, otlp:, service:, instrumentation:, sampling:, and filters: do not exist in the current config. Its command beyla run --config does not exist either, because the current form is beyla -config. Use that post for the shape of the arc, never for the config text.

Configuration can come from environment variables or a YAML file passed with -config or BEYLA_CONFIG_PATH, and environment variables take priority over the file. The current YAML keys are open_port, otel_traces_export, otel_metrics_export, and discovery, which is the shape the current docs teach. Keep one source of truth per deployment so a variable and a file never disagree silently.

open_port: 8080
discovery:
  instrument:
    - service_name: demo-service
otel_traces_export:
  endpoint: http://localhost:4318
otel_metrics_export:
  endpoint: http://localhost:4318
SelectorWhat it matchesStatus
BEYLA_OPEN_PORTListening ports, such as 8080 or 80,443,8000-8999Current
BEYLA_AUTO_TARGET_EXEFull executable path as a globCurrent
BEYLA_AUTO_TARGET_LANGUAGERuntime language of the targetCurrent
BEYLA_EXECUTABLE_NAMEExecutable nameDeprecated, use BEYLA_AUTO_TARGET_EXE
BEYLA_SERVICE_NAMEService nameDeprecated, use discovery.instrument

The OTLP Lesson: Where Your Telemetry Goes

Beyla speaks OpenTelemetry, which is the standard the rest of the observability world already uses. That is the whole point of the Beyla OTLP lesson: your traces and metrics leave Beyla in OTLP format, so any backend that accepts OTLP can receive them. Set OTEL_EXPORTER_OTLP_ENDPOINT to the collector or backend address and OTEL_EXPORTER_OTLP_PROTOCOL to http/protobuf or grpc, and Beyla pushes both traces and metrics to that endpoint.

Beyla exports in two modes, Direct and Alloy. In Direct mode Beyla pushes OTLP to a remote endpoint and can also expose a Prometheus endpoint for scraping, while Alloy mode sends everything to Grafana Alloy on the local host for authentication and forwarding to Mimir and Tempo. The Alloy default local port is 4318, and the YAML keys are otel_metrics_export and otel_traces_export with an endpoint: value.

Export modeHow data flowsAuthentication
DirectBeyla pushes OTLP to the endpoint, plus an optional Prometheus pull endpointYou configure credentials on Beyla
AlloyBeyla sends to Grafana Alloy on port 4318, Alloy forwards to Mimir and TempoAlloy manages the credentials

An OpenTelemetry Collector in the middle lets you route Beyla's output to any backend, and the HyperDX beginner guide covers one such backend from zero. HyperDX receives the telemetry Beyla produces, so the two fit together as producer and backend. If you already run a collector, point Beyla at it and keep the rest of your pipeline unchanged.

OTLP is a wire protocol, not a product, and the endpoints, headers, and payloads travel over ordinary HTTP. The what an API is guide explains that transport layer if the terms endpoint and protocol are new to you. Beyla also exposes a health endpoint when you set BEYLA_HEALTH_CHECK_PORT, which answers /healthz for a load balancer or a readiness probe.

Your First Dashboard

With Beyla exposing metrics, point Prometheus at the endpoint and watch the RED metrics arrive: request rate, error rate, and duration for every instrumented service. The README quickstart exposes them on port 9400, while the Kubernetes Helm chart exposes them on port 9090, so keep the two ports straight. A scraper must set honor_labels: true to preserve Beyla's per-process instance identifiers.

scrape_configs:
  - job_name: beyla
    honor_labels: true
    static_configs:
      - targets: ['localhost:9400']

In Grafana, chart http_server_request_duration_seconds_count for request rate and the matching duration histogram for latency, then group by service name and route. The Grafana Alloy blog from 2024 shows the same RED metrics flowing through Alloy, and the pattern is identical when Beyla exports directly. A first dashboard needs only three panels: requests per second, error rate, and latency by percentile.

Traces land in Tempo or Jaeger when Beyla exports OTLP, and a slow trace shows which service in the chain added the time. Beyla can generate span and service-graph metrics directly without generating traces, so you can head-sample traces or disable them entirely while the RED metrics stay correct. That separation is what makes Beyla cheap to run in production: metrics always on, traces sampled.

The Privileges Lesson: Why Beyla Needs Kernel Access

eBPF programs run inside the kernel, so Beyla needs privileges that an ordinary process does not have. The simplest route is root or sudo, which is what every quickstart uses, and the least-privilege route is granting only the capabilities each feature needs with setcap. Teach this as a design fact, not a footnote: a Beyla that cannot attach its probes logs a warning and keeps running, and it may malfunction silently.

CapabilityWhat it unlocks
CAP_BPFLoading eBPF programs
CAP_PERFMONReading performance events
CAP_SYS_PTRACEAttaching to running processes
CAP_NET_RAWReading raw network traffic
CAP_DAC_READ_SEARCHReading binaries and BTF data
CAP_CHECKPOINT_RESTOREInspecting process state
CAP_SYS_ADMINLibrary-level uprobe instrumentation, and AKS and EKS nodes
CAP_NET_ADMINTrace context propagation and TC-based network observability

Set BEYLA_ENFORCE_SYS_CAPS=true to make Beyla abort at startup when a capability is missing, instead of starting half-blind. The default is false, which suits a first run on a laptop and fails quietly in a cluster. AKS and EKS nodes default to kernel.perf_event_paranoid above 1, so Beyla needs CAP_SYS_ADMIN there unless the node sysctl is lowered to 1.

In Docker, run Beyla privileged or grant the needed capabilities, and share the target container's process namespace with --pid=container:demo. In Kubernetes the same idea appears as hostPID: true on the DaemonSet, because eBPF must observe processes across the whole node. Never run Beyla as an unprivileged sidecar and expect it to see the node.

Beyla in Kubernetes

Helm is the documented route for Beyla Kubernetes deployments: add the Grafana chart repository, then install the beyla chart into its own namespace. The chart deploys a DaemonSet, one Beyla pod per node, with Prometheus export on port 9090 and Kubernetes metadata enrichment on by default. The Kubernetes beginner guide covers clusters and namespaces from zero if Helm itself is new to you.

helm repo add grafana https://grafana.github.io/helm-charts
helm install beyla -n beyla --create-namespace grafana/beyla

Override the default configuration with a helm-beyla.yml file whose config.data section holds a Beyla YAML config, and pass it with -f on install or upgrade. For Grafana Cloud, pass the OTLP credentials through the OTEL_EXPORTER_OTLP_HEADERS environment variable instead of baking them into the values file. Expose the metrics with a Service and a ServiceMonitor so your Prometheus scraper discovers each Beyla pod.

config:
  data:
    open_port: 8080
    otel_traces_export:
      endpoint: https://otlp-gateway-prod-us-central-0.grafana.net/otlp

The DaemonSet is the default deployment pattern in Kubernetes, because one Beyla per node sees every service on that node. The sidecar pattern is the exception, not the default: it needs shareProcessNamespace: true, it runs one Beyla per pod, and it costs more overhead for more isolation. Choose the DaemonSet unless a pod must never share its process namespace with anything else.

Beyla vs Odigos vs Pixie

Three tools share the zero-code instrumentation idea, and they differ in scope, not in quality. Beyla is the standalone auto-instrumenter, Odigos is the Kubernetes-native operator, and Pixie is the full-stack observability platform. The comparison below follows the OneUptime comparison table published 2025-12-10, which is 331 days old as of this writing.

ToolDeploymentFocusBackends
BeylaStandalone binary or Kubernetes DaemonSetHTTP and gRPC auto-instrumentationAny OTLP or Prometheus backend
OdigosKubernetes-native operatorFull distributed tracing with context propagationAny OTLP backend
PixieKubernetes onlyFull-stack observability with in-cluster edge storageIts own UI, plus OTLP export

Beyla vs Odigos comes down to deployment: Beyla runs as a standalone binary or a DaemonSet and exports OTLP or Prometheus for any backend, while Odigos runs as a Kubernetes operator focused on full distributed tracing with context propagation. Beyla vs Pixie comes down to scope: Beyla is a lightweight instrumenter that hands telemetry to your backend, while Pixie is Kubernetes-only full-stack observability with in-cluster edge storage and its own PxL query language. All three are Apache 2.0, and both rivals are worth one line in a comparison, not their own guides.

Beyla and OBI: The 2025 Donation

Grafana Labs donated Beyla to the OpenTelemetry project in 2025 as OpenTelemetry eBPF Instrumentation, or OBI, and the donation was announced at GrafanaCON in May 2025. Beyla is Grafana's distribution of OpenTelemetry eBPF Instrumentation (OBI) since that donation, so never present Beyla and OBI as competing tools: Beyla is the distribution, OBI is the upstream project. The Beyla repository imports OBI as a library, and Beyla usually releases more often than OBI.

The two share the same YAML config schema, and Beyla accepts both the BEYLA_ and the OTEL_EBPF_ environment-variable prefixes. Beyla adds two features OBI does not have: process metrics for CPU, memory, disk, and network per instrumented process, and survey mode, which discovers services and languages without instrumenting them. Metric names differ for non-OTel-convention metrics: Beyla prefixes them beyla_, OBI prefixes them obi_, as in beyla_network_flow_bytes_total versus obi_network_flow_bytes_total.

No vendor-published overhead figure exists for Beyla, so this guide quotes none. An independent walkthrough claims under 1 to 2 percent CPU with no source behind the number, and repeating it would turn one author's guess into a fact. Measure overhead on your own workload before you promise it to anyone.

from datetime import date
today = date(2026, 11, 6)
repo_created = date(2023, 2, 20)
print("repo age days:", (today - repo_created).days)
print("stars per fork:", round(2154 / 205, 2))
print("fork ratio percent:", round(205 / 2154 * 100, 1))
print("v3.40.0 age days:", (today - date(2026, 10, 26)).days)
print("v3.41.0 pre-release age days:", (today - date(2026, 11, 4)).days)
print("dev.to walkthrough age days:", (today - date(2025, 11, 7)).days)
print("causely post age days:", (today - date(2025, 10, 8)).days)
print("oneuptime table age days:", (today - date(2025, 12, 10)).days)
gaps = [14, 3, 4, 2, 7]
print("release gaps days:", gaps, "sum:", sum(gaps), "average:", sum(gaps) / len(gaps))
print("open issues per 100 stars:", round(93 / 2154 * 100, 2))

Sources

The facts in this guide come from the Grafana Beyla documentation as published in November 2026: the docs landing page, the setup pages for Docker and Kubernetes with Helm, the security and requirements pages, the configuration options reference, the export modes page, and the Beyla versus OBI page. The version pin, star and fork counts, release dates, and repository age come from the GitHub repository grafana/beyla and its Releases API, checked on 2026-11-06. The pre-release status of v3.41.0 and the stable status of v3.40.0 were confirmed against the same API on the same day.

The walkthrough landscape was checked against the Grafana blog post on using Beyla in Grafana Alloy, the Causely blog post published 2025-10-08, which is 394 days old as of this writing, the OneUptime guide published 2025-12-10, and the independent dev.to walkthrough by Nabin Debnath published 2025-11-07. The comparison lines for Odigos and Pixie follow the OneUptime comparison table and the BetterStack eBPF observability guide, with background from the Medium piece by Horovits on the OpenTelemetry eBPF Instrumentation project and the Observability-360 guide on eBPF in observability.

The README quickstart, including the example service and the 9400 Prometheus port, was read from the Beyla repository on pkg.go.dev. The groundwork for the cluster and pillar links was verified live on codexfuse.dev on 2026-11-06: the Groundcover, Docker, HyperDX, Kubernetes, and what-is-an-API posts all returned live pages. No search volume data was fetched, so none is quoted anywhere in this guide.

Frequently Asked Questions

Is Beyla really zero-code?

Yes, for instrumentation: Beyla attaches to your running service and produces traces and metrics without a code change, an SDK, or a restart. It cannot see your business logic or the function calls inside your service, so add OpenTelemetry SDK spans where you need in-code detail.

What kernel version does Beyla need?

Beyla needs Linux kernel 5.8 or newer with BTF enabled, and trace context propagation across services needs kernel 5.17 or newer. On a 5.8 to 5.16 kernel you still get metrics and single-span traces, but not distributed traces stitched across services.

Does Beyla work in Kubernetes?

Yes, and Helm is the documented route: one command installs a DaemonSet that instruments every service on each node, with Prometheus export on port 9090. The DaemonSet is the default pattern, and the sidecar pattern is the exception for pods that must never share a process namespace.

Is Beyla the same thing as OBI?

Beyla is Grafana's distribution of OpenTelemetry eBPF Instrumentation, or OBI, since Grafana donated the project to OpenTelemetry in 2025. They share the same config schema, and Beyla adds process metrics and survey mode on top of the upstream project.

What does Beyla cost?

Beyla itself is free and open source under the Apache License 2.0, with no paid tier. The backends it sends data to, such as Grafana Cloud, Prometheus, or Tempo, have their own costs, which this guide does not quote.

Featured on Twelve Tools Hunt for Tools Featured on LaunchBuff Launch Llama Tools Launch your MCP Top Web Development Companies in the US - OnToplist.com Designer Listings Listed on SeeWhatNewAI Featured on SubmitMySaas Featured on AI Agents Directory Product Wing SaaS Wheel