Skip to content

feat: eBPF readiness gate + ebpf-profile capabilities (ADR 0011, slice 2) - #27

Merged
kfeofantov merged 1 commit into
mainfrom
feat/ebpf-gate
Aug 11, 2026
Merged

kfeofantov merged 1 commit into
mainfrom
feat/ebpf-gate

Conversation

@kfeofantov

Copy link
Copy Markdown
Contributor

Slice 2 of the eBPF node-profiling feature (plan, ADR 0011). Gates the node's ebpf profile on the kernel and grants its capabilities — before any profiler exists, so slice 3 just plugs in.

What it does

  • internal/ebpfgate.Probe(procRoot, sysRoot) — kernel version from <procRoot>/sys/kernel/osrelease, BTF from <sysRoot>/kernel/btf/vmlinux; returns a Result{Reason, KernelVersion, Major, Minor, BTFPresent}.
    • Reasons are split — supported / kernel_too_old / btf_absent / kernel_unknown — so fleet counts show why nodes declined (constraint b). Version dominates BTF, so a RHEL-backport kernel (BTF present but < 5.8) is visibly refused on version — exactly what we'd relax first for a RHEL customer.
  • -enable-ebpf master switch (+ -sys root) in runNode: evaluates the gate once at startup, logs a clear ready/refused line, records a per-reason in-process counter (surfaced to the report stream when the profiler ships — slice 6). A refusal degrades to scanner-only — never an escalation to privileged, never a node failure.
  • deploy/node-daemonset-ebpf.yaml — the ebpf-profile variant: adds exactly CAP_BPF + CAP_PERFMON and one read-only /sys/kernel/btf mount and -enable-ebpf, keeping drop:[ALL], privileged:false, and the zero-RBAC identity. Alternative to the scanner manifest, not additive.
  • deploy/node-daemonset.yaml — the absolute "no eBPF capabilities" comments are now variant-dependent.

Guarantees / invariants held

  • No privileged. Verified: base caps [SYS_PTRACE], ebpf caps [SYS_PTRACE, BPF, PERFMON], both privileged:false.
  • Graceful degradation tested: -enable-ebpf on an unsupported kernel still runs the scanner to completion and returns nil.
  • No symbol egress: the gate logs only kernel version + BTF — nothing derived from a workload. No profiler, no capture, no new data leaves the cluster in this slice.

Tests

internal/ebpfgate: table over 5.4 / 5.7 / 5.8 / 5.15 / 6.8 / 4.18-rhel / malformed / missing × BTF present/absent, plus precedence and parseKernelVersion. cmd/agent: gate supported/refused (counter + log asserts) and the refusal-doesn't-stop-the-node guard. go test -race ./... and golangci-lint clean.

Not in this slice

The profiler library + reporter (slice 3), symbol filtering (4), validation+spool (5), targeting (6), e2e (7).

🤖 Generated with Claude Code

…e 2)

Gate the node role's eBPF profile on the kernel before any profiler exists,
and give the ebpf install profile its capabilities — without privileged.

- internal/ebpfgate: Probe(procRoot, sysRoot) reads the kernel version from
  <procRoot>/sys/kernel/osrelease and BTF from <sysRoot>/kernel/btf/vmlinux,
  returning a Result with a low-cardinality Reason. Reasons are split
  (kernel_too_old / btf_absent / kernel_unknown / supported) so fleet counts
  show why nodes declined; version dominates BTF so a RHEL-backport kernel
  (BTF present, < 5.8) is visibly refused on version. Table tests cover the
  matrix incl. the RHEL and precedence cases.
- cmd/agent/node.go: -enable-ebpf master switch + -sys root. When set, the
  node evaluates the gate once at startup, logs a clear ready/refused line,
  and records a per-reason in-process counter (surfaced to the report stream
  when the profiler ships). A refusal degrades to scanner-only — never an
  escalation to privileged, never a node failure. The gate logs only kernel
  version + BTF, nothing derived from a workload.
- deploy/node-daemonset-ebpf.yaml: the ebpf-profile variant — adds exactly
  CAP_BPF + CAP_PERFMON and a read-only /sys/kernel/btf mount and the
  -enable-ebpf switch, keeping drop:[ALL], privileged:false, and zero RBAC.
- deploy/node-daemonset.yaml: correct the absolute "no eBPF capabilities"
  comments to be variant-dependent.

No profiler, no capture, no new data leaves the cluster in this slice.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@kfeofantov
kfeofantov merged commit 97c3e1e into main Aug 11, 2026
3 checks passed
@kfeofantov
kfeofantov deleted the feat/ebpf-gate branch August 11, 2026 18:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant