Skip to content

test: gate-refusal e2e + fix BTF mount to not block startup (ADR 0011, slice 7) - #35

Merged
kfeofantov merged 2 commits into
mainfrom
test/ebpf-gate-e2e
Aug 12, 2026
Merged

kfeofantov merged 2 commits into
mainfrom
test/ebpf-gate-e2e

Conversation

@kfeofantov

Copy link
Copy Markdown
Contributor

Slice 7 (part 1 — the local half) (plan, ADR 0011). The first live run of the ebpf node variant, plus a manifest fix the e2e forced.

Manifest fix: BTF mount must not block startup

The ebpf manifest mounted hostPath /sys/kernel/btf with type: Directory. On a kernel without BTF that directory doesn't exist, so a hostPath of a missing directory blocks the pod from starting — which defeats the whole graceful-refusal design (the node is supposed to keep running as the scanner when BTF is absent) and makes the gate e2e impossible. Fix: mount the always-present parent /sys/kernel read-only; the gate still checks /sys/kernel/btf/vmlinux under it.

Gate-refusal e2e (runs anywhere, incl. kind on macOS/linuxkit)

TestEBPFGateRefusesGracefully deploys the ebpf variant into kind and asserts the graceful path (ADR 0011 §2):

  • the pod reaches Running (proves the manifest doesn't hard-require BTF),
  • the profiler refuses with a distinct reason (btf_absent or kernel_too_old),
  • the Go-binary scanner keeps running (a scan coverage line appears).

Gated on E2E_AGENT_IMAGE; make profile-gate-e2e. This is a real e2e (graceful degradation under a no-BTF kernel), not a stub.

Checks

Compiles under -tags e2e and skips cleanly without a cluster; default go build ./... + golangci-lint ./... clean; manifest YAML validated (mount/volume names consistent, still [SYS_PTRACE, BPF, PERFMON], no privileged).

Not here

The full capture path (CPU-load pod → profile captured/filtered/spooled/valid) needs a Linux+BTF host and lands as a separate profile-capture-e2e target — the session where we spin a GCP VM (like the PGO spike) for the first real capture.

Note: I can't run kind here (Docker is yours to start) — this PR delivers the test + fix; run make profile-gate-e2e against your kind cluster to see it pass.

🤖 Generated with Claude Code

kfeofantov and others added 2 commits August 11, 2026 23:48
…, slice 7)

The first live run of the ebpf node variant, and a manifest fix the e2e forced.

- deploy/node-daemonset-ebpf.yaml: mount the always-present parent /sys/kernel
  (read-only) instead of /sys/kernel/btf directly. On a kernel without BTF the
  btf/ directory does not exist, and a hostPath of a missing directory blocks the
  pod from starting — which would defeat the graceful refusal whose whole point
  is that the node still runs as the scanner. The gate still checks
  /sys/kernel/btf/vmlinux under the mount.
- test/e2e/profile_gate_test.go: TestEBPFGateRefusesGracefully deploys the ebpf
  variant into kind and asserts the graceful path — the pod reaches Running (so
  the manifest does not hard-require BTF), the profiler refuses with a distinct
  reason (btf_absent or kernel_too_old), and the Go-binary scanner keeps running
  (a coverage line appears). It runs anywhere, including kind on Docker Desktop /
  linuxkit where there is no BTF; gated on E2E_AGENT_IMAGE.
- Makefile: a profile-gate-e2e target.

This is the gate-refusal half of the two-mode slice-7 e2e. The full capture path
needs a Linux+BTF host and lands as a separate target.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ERFMON

Running it revealed a stronger constraint than BTF: on Docker Desktop / linuxkit
the kind node cannot grant CAP_BPF/CAP_PERFMON, so the ebpf-variant pod fails at
container init (runc "unable to apply caps") before the binary runs — the
in-binary gate never gets a chance to refuse. The scanner variant (only
SYS_PTRACE) starts fine, so it is those two caps specifically.

The test now classifies the pod outcome and asserts only the case it can:
- cap-apply failure  -> Skip (the pod never starts; nothing to assert)
- gate reported ready -> Skip (node supports eBPF; that is the capture e2e)
- gate refused + scanner coverage -> assert the reason (btf_absent/kernel_too_old)

So `make profile-gate-e2e` green-skips on Docker Desktop with a clear reason, and
becomes a real assertion on a node that grants the caps but lacks BTF (the RHEL-
style case). The live refusal/capture proof still needs a Linux+BTF host.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@kfeofantov
kfeofantov merged commit 05095ec into main Aug 12, 2026
3 checks passed
@kfeofantov
kfeofantov deleted the test/ebpf-gate-e2e branch August 12, 2026 14:17
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