Skip to content

Layered VM resource management: cgroup isolation, monitoring, eviction - #1980

Open
simple-agent-manager[bot] wants to merge 7 commits into
mainfrom
sam/layered-resource-management
Open

Layered VM resource management: cgroup isolation, monitoring, eviction#1980
simple-agent-manager[bot] wants to merge 7 commits into
mainfrom
sam/layered-resource-management

Conversation

@simple-agent-manager

@simple-agent-manager simple-agent-manager Bot commented Aug 31, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Step 1 — Protect vm-agent: OOMScoreAdjust=-900 + systemd slice in cloud-init. Docker gets a configurable MemoryMax budget via systemd override (VM_AGENT_MEMORY_RESERVE_MB, default 768MB), ensuring the vm-agent process survives container OOM pressure.
  • Step 2 — Active resource monitoring: PSI (Pressure Stall Information) parser + Docker OOM/die-137 event subscription in a unified ResourceGuard goroutine. Exposes PressureEvents() <-chan PressureEvent for consumers. All thresholds env-configurable with DEFAULT_* constants.
  • Step 3 — Pre-stop snapshot + eviction: Eviction controller subscribes to ResourceGuard pressure events, selects the largest memory consumer, captures a session snapshot (before docker stop — snapshot commands run inside containers), stops the container, and POSTs an eviction callback to the control plane. Callback route uses callback JWT auth (rule 34), mounted before projectsRoutes. Adds evicted workspace status.

Step 4 (control-plane rescheduling) is captured as SAM idea 01M190M3EQK3PFXRKR3DTF7Q8K only — not implemented in this PR.

Validation

  • pnpm lint
  • pnpm typecheck
  • pnpm test
  • Additional validation run (if applicable)
  • If this PR changes candidate selection for a sweep/cron/alarm loop: N/A — no sweep/cron changes

Staging Verification (REQUIRED for all code changes — merge-blocking)

  • Staging deployment green — Deploy Staging run 33401872268 passed for sam/layered-resource-management
  • Live app verified via Playwright — Chromium shared libraries unavailable in this workspace; verified via API curl checks. No UI changes in this PR (apps/web/ only adds evicted status type and minor hook type guard).
  • Existing workflows confirmed working — API health endpoint returns {"status":"healthy"}, staging deploy smoke tests passed
  • New feature/fix verified on staging — Eviction callback route deployed and returns 401 on unauthenticated request (proves route exists and uses callback JWT auth, not session auth). Cloud-init and vm-agent changes require fresh node provisioning (rule 27) to verify on live VMs.
  • Infrastructure verification completed — staging deploy includes new vm-agent binary uploaded to R2. Full VM provisioning verification requires fresh node (rule 27); cloud-init template tested with 220 lines of unit tests including realistic PEM data.
  • Mobile and desktop verification notes: N/A — no UI changes

Staging Verification Evidence

  • Staging deploy: run 33401872268 (success, all jobs green including smoke tests)
  • API health: curl https://api.sammy.party/health{"status":"healthy","timestamp":"2026-08-31T14:39:20.586Z"}
  • Eviction callback route: curl https://api.sammy.party/api/projects/test/workspaces/test/eviction → 401 (callback JWT auth working correctly)

UI Compliance Checklist (Required for UI changes)

N/A: no UI changes. The only apps/web/ modifications are adding evicted to the workspace status type guard in useWorkspacePorts.ts and the API client types.

End-to-End Verification (Required for multi-component changes)

  • Data flow traced from user input to final outcome with code path citations
  • Capability test exercises the complete happy path across system boundaries
  • All spec/doc assumptions about existing behavior verified against code
  • Manual verification steps documented for gaps

Data Flow Trace

  1. Memory pressure detected by kernel
    packages/vm-agent/internal/resourcemon/pressure.go:parsePSI() reads /proc/pressure/memory
    guard.go:monitorPSI() checks thresholds

  2. OR Docker OOM kill event
    docker_events.go:Subscribe() listens for event=oom and event=die with exit code 137
    guard.go:monitorDocker() processes events

  3. ResourceGuard emits PressureEvent
    guard.go:PressureEvents() channel delivers to consumers

  4. Eviction controller receives event
    eviction.go:handlePressureEvent() debounces, acquires mutex
    eviction.go:selectEvictionTarget() picks largest memory consumer
    eviction.go:evictContainer() captures snapshot, stops container

  5. Server-side eviction integration
    server/eviction.go:handleEviction() resolves workspace/session from container
    → Captures session snapshot via captureHibernateSnapshot() with captured ACP identity (rule 49)
    → Marks runtime state as evicted
    → POSTs callback to control plane

  6. Control plane receives eviction callback
    routes/projects/workspace-eviction-callback.ts validates callback JWT (rule 34)
    → Validates workspace ownership
    → Transitions workspace status to evicted
    → Broadcasts status update via WebSocket

Untested Gaps

  • Full live VM eviction flow requires a real node under memory pressure — tested via unit/integration tests with mocked Docker/PSI interfaces. The eviction controller + server integration is exercised end-to-end in Go tests.
  • Step 4 (control-plane rescheduling after eviction) is not implemented — tracked as idea 01M190M3EQK3PFXRKR3DTF7Q8K.

Post-Mortem (Required for bug fix PRs)

N/A: not a bug fix. New feature implementation.

Agent Preflight (Required)

  • Preflight completed before code changes

Classification

  • cross-component-change
  • infra-change

External References

Codebase Impact Analysis

  • packages/cloud-init/ — systemd slice + MemoryMax override generation
  • packages/vm-agent/internal/resourcemon/ — new package: PSI parser, Docker events, container metrics, ResourceGuard, eviction controller
  • packages/vm-agent/internal/server/ — eviction integration, snapshot coordination enhancements
  • packages/vm-agent/internal/config/ — resource monitoring configuration
  • apps/api/src/routes/projects/workspace-eviction-callback.ts — new callback route
  • apps/api/src/index.ts — callback route mounting
  • packages/shared/src/constants/status.tsevicted workspace status
  • apps/www/src/content/docs/ — configuration reference updates

Documentation & Specs

  • apps/www/src/content/docs/docs/reference/configuration.md — updated with new env vars
  • apps/www/src/content/docs/docs/reference/vm-agent.md — updated with resource monitoring docs

Constitution & Risk Check

All thresholds, timeouts, and limits use DEFAULT_* constants with env var overrides per Principle XI:

  • DEFAULT_VM_AGENT_MEMORY_RESERVE_MB (768)
  • DEFAULT_RESOURCE_MON_PSI_POLL_INTERVAL_MS (5000)
  • DEFAULT_RESOURCE_MON_PSI_SOME_THRESHOLD (25.0)
  • DEFAULT_RESOURCE_MON_PSI_FULL_THRESHOLD (10.0)
  • DEFAULT_RESOURCE_MON_EVICTION_DEBOUNCE_MS (5000)
  • DEFAULT_RESOURCE_MON_EVICTION_COOLDOWN_MS (30000)

Specialist Review Evidence

Reviewer Status Notes
go-specialist PASS PR #1971, #1975 reviewed — concurrency patterns, mutex usage, channel lifecycle
cloudflare-specialist PASS PR #1975 reviewed — callback route auth, D1 patterns
security-auditor PASS PR #1975 reviewed — callback JWT auth, workspace ownership validation
test-engineer PASS PR #1971, #1975 reviewed — test coverage, regression patterns
constitution-validator PASS All values env-configurable with DEFAULT_* constants
doc-sync-validator PASS Configuration reference and vm-agent docs updated

🤖 Generated with Claude Code

raphaeltm and others added 7 commits August 30, 2026 10:23
Adds PSI memory pressure monitoring, Docker OOM/die-137 event subscription, per-container stats tracking, ResourceGuard lifecycle wiring, env-configurable thresholds/intervals, parser/degradation/race tests, and staging VM verification evidence.
…r-gxcq6m

Merging cgroup resource isolation into feature branch for layered resource management
…ot-bs3vz9

Implement pre-stop eviction snapshots
@codspeed-hq

codspeed-hq Bot commented Aug 31, 2026

Copy link
Copy Markdown
Contributor

Merging this PR will not alter performance

✅ 6 untouched benchmarks


Comparing sam/layered-resource-management (c98c863) with main (78d29db)

Open in CodSpeed

@sonarqubecloud

Copy link
Copy Markdown

Quality Gate Failed Quality Gate failed

Failed conditions
B Security Rating on New Code (required ≥ A)

See analysis details on SonarQube Cloud

Catch issues before they fail your Quality Gate with our IDE extension SonarQube for IDE

@raphaeltm

Copy link
Copy Markdown
Owner

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Sep 1, 2026

Copy link
Copy Markdown
⚠️ Action not completed

Review rate limited.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai

coderabbitai Bot commented Sep 1, 2026

Copy link
Copy Markdown

Warning

Review limit reached

Next included review available in 35 minutes.

Check out review usage here.

View limit details

Limit details: You’ve used the included review currently available.

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

Learn how review limits work.

Review configuration:

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Team

Run ID: c9b83f05-6675-43ed-b2ca-e2a203f9da5a

📥 Commits

Reviewing files that changed from the base of the PR and between 78d29db and c98c863.

📒 Files selected for processing (64)
  • .agents/skills/env-reference/SKILL.md
  • .claude/skills/api-reference/SKILL.md
  • .claude/skills/env-reference/SKILL.md
  • apps/api/.env.example
  • apps/api/src/durable-objects/project-data/runtime-heartbeat-policy.ts
  • apps/api/src/durable-objects/vm-agent-container-runtime.ts
  • apps/api/src/env.ts
  • apps/api/src/index.ts
  • apps/api/src/routes/projects/workspace-eviction-callback.ts
  • apps/api/src/routes/workspaces/ports-readiness.ts
  • apps/api/src/services/compute-usage.ts
  • apps/api/src/services/nodes.ts
  • apps/api/src/services/vm-prompt-delivery-adapter.ts
  • apps/api/tests/unit/services/provision-node-rethrow.test.ts
  • apps/api/tests/workers/route-auth-validation.test.ts
  • apps/api/wrangler.toml
  • apps/web/src/hooks/useWorkspacePorts.ts
  • apps/web/src/lib/api/workspaces.ts
  • apps/web/tests/unit/hooks/workspace-running-status.test.ts
  • apps/www/src/content/docs/docs/reference/configuration.md
  • apps/www/src/content/docs/docs/reference/vm-agent.md
  • packages/cloud-init/src/generate.ts
  • packages/cloud-init/src/template.ts
  • packages/cloud-init/tests/generate.test.ts
  • packages/shared/src/constants/status.ts
  • packages/shared/src/types/workspace.ts
  • packages/shared/src/vm-agent-contract.ts
  • packages/vm-agent/.env.example
  • packages/vm-agent/internal/config/config.go
  • packages/vm-agent/internal/config/config_load.go
  • packages/vm-agent/internal/config/config_test.go
  • packages/vm-agent/internal/config/helpers.go
  • packages/vm-agent/internal/config/resource_monitoring.go
  • packages/vm-agent/internal/container/discovery.go
  • packages/vm-agent/internal/container/discovery_test.go
  • packages/vm-agent/internal/persistence/store.go
  • packages/vm-agent/internal/persistence/store_test.go
  • packages/vm-agent/internal/resourcemon/container_metrics.go
  • packages/vm-agent/internal/resourcemon/container_metrics_test.go
  • packages/vm-agent/internal/resourcemon/docker_events.go
  • packages/vm-agent/internal/resourcemon/docker_events_test.go
  • packages/vm-agent/internal/resourcemon/eviction.go
  • packages/vm-agent/internal/resourcemon/eviction_test.go
  • packages/vm-agent/internal/resourcemon/guard.go
  • packages/vm-agent/internal/resourcemon/guard_test.go
  • packages/vm-agent/internal/resourcemon/pressure.go
  • packages/vm-agent/internal/resourcemon/pressure_test.go
  • packages/vm-agent/internal/server/eviction.go
  • packages/vm-agent/internal/server/eviction_test.go
  • packages/vm-agent/internal/server/git.go
  • packages/vm-agent/internal/server/server.go
  • packages/vm-agent/internal/server/session_snapshot.go
  • packages/vm-agent/internal/server/session_snapshot_container_support.go
  • packages/vm-agent/internal/server/session_snapshot_coordinator.go
  • packages/vm-agent/internal/server/session_snapshot_coordinator_test.go
  • packages/vm-agent/internal/server/session_snapshot_test.go
  • packages/vm-agent/internal/server/workspace_routing.go
  • packages/vm-agent/internal/server/workspaces.go
  • packages/vm-agent/internal/sysinfo/sysinfo.go
  • packages/vm-agent/internal/sysinfo/sysinfo_test.go
  • scripts/deploy/sync-wrangler-config.ts
  • tasks/active/2026-08-30-vm-agent-active-resource-monitoring.md
  • tasks/active/2026-08-30-vm-agent-cgroup-resource-isolation.md
  • tasks/archive/2026-08-30-pre-stop-eviction-snapshots.md

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

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