Skip to content

feat: per-namespace overlay isolation#24

Merged
miguelgila merged 12 commits intomainfrom
feat/namespace-overlay-isolation
Feb 28, 2026
Merged

feat: per-namespace overlay isolation#24
miguelgila merged 12 commits intomainfrom
feat/namespace-overlay-isolation

Conversation

@miguelgila
Copy link
Owner

Summary

  • Isolates overlay filesystems per Kubernetes namespace so workloads in different namespaces cannot see each other's overlay writes
  • Shim extracts io.kubernetes.cri.sandbox-namespace (with fallback to io.kubernetes.pod.namespace) from OCI annotations and passes --namespace to the runtime
  • Runtime creates separate overlay upper/work dirs, mount namespace, and lock file per K8s namespace under /run/reaper/overlay/<ns>/
  • Opt out with REAPER_OVERLAY_ISOLATION=node to use the legacy shared overlay

Changes

  • overlay.rs: OverlayIsolation enum, parameterized read_config() with per-namespace paths
  • state.rs: namespace field in ContainerState for start/exec to join correct overlay
  • main.rs (runtime): --namespace CLI arg on create, threaded through start/exec
  • main.rs (shim): extract_k8s_namespace() reads CRI annotation, passes --namespace to runtime
  • CLAUDE.md / OVERLAY_DESIGN.md: Updated documentation
  • tests: Rust integration tests for isolation + node-mode compat, Phase 4 Kind test verifying cross-namespace isolation

Test plan

  • cargo test --bin containerd-shim-reaper-v2 — all 37 unit tests pass
  • cargo test --test integration_overlay_isolation — Rust integration tests (Linux+root)
  • ./scripts/run-integration-tests.sh --verbose — all 30 Phase 4 tests pass, including new "Per-namespace overlay isolation" test
  • Existing overlay tests updated with REAPER_OVERLAY_ISOLATION=node to preserve behavior

🤖 Generated with Claude Code

miguelgila and others added 12 commits February 28, 2026 11:38
… isolation

Add `namespace: Option<String>` to ContainerState with serde defaults
for backward compatibility. Old state files without the field deserialize
to None. Includes round-trip and backward-compat tests.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Introduce OverlayIsolation::Namespace (default) and OverlayIsolation::Node
modes. read_config() now takes Option<&str> for K8s namespace:
- Namespace mode: scoped paths under /run/reaper/overlay/<ns>/, etc.
- Node mode: legacy flat layout, ignores namespace arg

Add merged_dir to OverlayConfig (was hardcoded). Add namespace path
validation. Update do_start() and do_exec() callers. Comprehensive tests
for isolation mode, per-NS paths, and validation.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Thread the K8s namespace from CLI through do_create() into
ContainerState. do_start() and do_exec() read it back from state
to pass to overlay::read_config() for per-namespace isolation.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…espace

Shim reads io.kubernetes.pod.namespace from config.json annotations
and passes --namespace <ns> to reaper-runtime create. This enables
the runtime to scope overlay paths per K8s namespace.

Includes tests for present/missing/absent annotations and missing config.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…tegration tests

Existing integration tests use node-wide shared overlay. With the new
default of per-namespace isolation, they need explicit node mode to
continue working without --namespace. Also gate container_namespace
variables with #[cfg(target_os = "linux")] to avoid unused-variable
warnings on macOS.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
New test file covering:
- Namespace mode without --namespace fails hard (refuses to start)
- Node mode backward compat (different namespaces share overlay)
- Helper supports both isolation modes and --namespace arg

Tests require Linux root + CAP_SYS_ADMIN; skipped gracefully elsewhere.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Update CLAUDE.md with new path layout, REAPER_OVERLAY_ISOLATION config.
Add Namespace Isolation section to OVERLAY_DESIGN.md with data flow,
path layout, legacy mode, and upgrade path. Mark TODO item as done.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
containerd CRI writes `io.kubernetes.cri.sandbox-namespace` not
`io.kubernetes.pod.namespace`. Try the CRI key first with fallback
to the pod key for compatibility.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Deploys a writer pod in the default namespace and a reader pod in a
separate namespace, then verifies the reader cannot see the writer's
overlay files — confirming overlays are isolated per K8s namespace.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Allow up to 1% project coverage decrease without failing the check.
Require 70% coverage on new code (patch).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Tests calling unwrap_err() require Debug on the Ok type.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@codecov
Copy link

codecov bot commented Feb 28, 2026

Codecov Report

❌ Patch coverage is 90.62500% with 3 lines in your changes missing coverage. Please review.
✅ Project coverage is 88.26%. Comparing base (c7ef98f) to head (8eb6442).
⚠️ Report is 1 commits behind head on main.

Files with missing lines Patch % Lines
src/bin/containerd-shim-reaper-v2/main.rs 60.00% 2 Missing ⚠️
src/bin/reaper-runtime/overlay.rs 96.15% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main      #24      +/-   ##
==========================================
+ Coverage   85.94%   88.26%   +2.31%     
==========================================
  Files           5        5              
  Lines         185      213      +28     
==========================================
+ Hits          159      188      +29     
+ Misses         26       25       -1     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@miguelgila miguelgila merged commit 389a642 into main Feb 28, 2026
10 checks passed
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