Skip to content

node: emit a sandbox OOM kill metric that separates node memory pressure from the sandbox's own limit - #1576

Open
shehan-pplx wants to merge 1 commit into
mainfrom
shehan/oom-kill-attribution
Open

shehan-pplx wants to merge 1 commit into
mainfrom
shehan/oom-kill-attribution

Conversation

@shehan-pplx

@shehan-pplx shehan-pplx commented Nov 5, 2026 •

Copy link
Copy Markdown
Member

Summary

Sandbox memory kills can now be told apart in metrics. At the moment the node only sees that a VM's process or cgroup is gone, so a sandbox that reached its own memory limit looks the same as one killed because the node ran out of memory.

When a sandbox cgroup is removed, the node reads its hierarchical memory.events. If the kernel OOM killer ended any process in it, the node counts those kills once in node_memory.sandbox_oom_kills, tagged with cgroup (vm, sidecar) and cause:

  • sandbox_limit: the cgroup, or one inside it, reached its own memory.max.
  • node_pressure: the sandbox stayed within its own limit, so the kill came from above it (the sandbox parent's cap or a host-wide OOM).

The node also logs a sandbox cgroup had OOM kills warning with the sandbox id, cause, kill count and limit hits. The counting happens in remove_cgroup_path, so both normal teardown and orphan reclaim report. It only reports after the directory is actually removed, so a retried removal never counts the same kills twice. docs/observability.md documents the metric.

Validation

  • cargo test -p pplx-space-node-runtime-core --features host-runtime --lib cgroup:: (21 passed). This includes new tests for parsing kernel memory.events, classifying the cause, and the counter's tags for vm and sidecar cgroups.
  • cargo clippy with -D warnings on the changed crates.

Not validated on a real cgroup v2 host with an actual OOM kill. The fixtures use the kernel's memory.events format.

Severity and risk

Severity: medium. Without this, the cause of a memory kill can only be found in the kernel log.

Risk: low. This only adds observability. A missing or unreadable events file skips reporting with a debug log and does not change removal. One known limit: a sandbox that ever hit its own limit is counted as sandbox_limit, even if a later kill came from node pressure. To roll back, revert this change.

Not covered

OOM kills inside the guest happen in the guest kernel and are not counted here.

AI assistance: Perplexity Computer drafted the code, tests, docs and this description.

@coderabbitai

coderabbitai Bot commented Nov 5, 2026 •

Copy link
Copy Markdown

Explain Change →

Automatic approval withheld

Assessment Current risk Maximum for approval
Merge risk Moderate Low

Why: OOM reporting adds a read to sandbox teardown. Confirm its effect on removal in the supported host environment before merging.

Commit: 2ac0de8d9335.

No actionable comments were generated in the recent review.

Walkthrough

The runtime reads memory.events before removing a sandbox cgroup. After successful removal, it reports positive OOM-kill counts with cgroup and cause tags. The cause is classified as sandbox_limit or node_pressure. The change also adds tests and observability documentation.

Possibly related PRs

Merge Risk: Moderate · up to 2ac0d

OOM reporting adds a read to sandbox teardown. Confirm its effect on removal in the supported host environment before merging.

Security architecture risk: Low · up to 2ac0d

The change adds bounded observability without changing sandbox memory limits or cleanup permissions. No new security exposure was identified. Remaining uncertainty concerns real-host reporting behavior and the accuracy of cause attribution, rather than a demonstrated isolation failure.

Retained concerns
No architecture-level concerns identified.

Security review details

Security Blast Radius

  • observed — The reporting hook covers normal sandbox termination and node-local orphan reclaim through their shared removal helper. It reports host-side VM and sidecar cgroup events; OOM kills within the guest kernel are outside this metric.

Trust Boundaries and Controls

  • observed — Normal cleanup derives paths from a typed SandboxId and checks quiescence before removal. Orphan discovery accepts directory names only when their stripped identity parses as SandboxId, excludes tracked sandboxes, and checks population before reclamation. The PR leaves these selection controls unchanged.

Resilience and Maintainability Implications

  • inferred — Telemetry failure does not veto cleanup, and failed or interrupted removals do not emit a report. Successful-removal gating avoids duplicate reports from ordinary retries, but it is not a durable exactly-once guarantee: process interruption after directory removal and before emission can lose the report.
Pre-merge checks: Passed 5

Check name Status Explanation
Title check Passed The title identifies the node area and summarizes the sandbox OOM kill metric. It meets the specified format requirements.
Description Follows The Pr Template Passed The PR description contains all four required items: Summary, Validation with a test result, Severity and risk, and an AI assistance line that names the tool and its contributions.
Bug Fixes Name A Regression Test Passed The PR adds OOM-kill observability. The diff does not show a fix for an application behavior defect, so the check does not apply.
Weakened Safeguards Are Justified Passed The diff does not remove or weaken a test, assertion, lint, CI check, or repository guard. It adds tests and replaces an empty successful-removal branch with metric reporting.
Public-Safe Content Passed The diff, title, and description contain no content covered by the failure criteria. The paths in the diff are generic test paths.
Recent review info

Automatic approval policy

Commit: 2ac0de8d9335.

Setting Effective value Source
Automatic approvals Enabled Global configuration
Merge risk Low Override 2
Security risk Not set Global configuration

Matching overrides (numbered as in the resolved configuration):

  • Override 2 — any author; paths: **, !ui/**; merge risk: Low.

Any matching disabled override withholds approval, regardless of risk. Otherwise, the strictest explicitly set limit wins for each score. Limits omitted by all matching overrides inherit the global configuration.

Not set means no limit was configured after inheritance. Use @coderabbitai configuration to inspect the resolved settings and their sources.

Run configuration

Commits

Reviewing files that changed from the base of the PR and between baecf31 and 2ac0de8.

Files selected for processing: 6

  • crates/l40_api/node/runtime/core/Cargo.toml
  • crates/l40_api/node/runtime/core/src/cgroup.rs
  • crates/l40_api/node/runtime/core/src/cgroup/tests.rs
  • crates/libs/metrics/src/lib.rs
  • crates/libs/metrics/src/node_memory.rs
  • docs/observability.md

Included review availability: This review used your included allowance. Your plan provides up to 12 included reviews per hour; 11 remain after this review.

Count OOM kills in each sandbox cgroup once, when it is removed, tagged by
whether the sandbox reached its own memory limit or the kill came from node
memory pressure.
@shehan-pplx
shehan-pplx force-pushed the shehan/oom-kill-attribution branch from fdf91f2 to 2ac0de8 Compare November 5, 2026 22:17
@shehan-pplx shehan-pplx changed the title node: report sandbox OOM kills by cause node: emit a sandbox OOM kill metric that separates node memory pressure from the sandbox's own limit Nov 5, 2026
@shehan-pplx
shehan-pplx marked this pull request as ready for review November 5, 2026 23:18

This branch has not been deployed

No deployments
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