feat(compute): add AWS Lambda MicroVMs ComputeStrategy backend — P1 (#645) - #689
feat(compute): add AWS Lambda MicroVMs ComputeStrategy backend — P1 (#645)#689dreamorosi wants to merge 4 commits into
Conversation
…ws-samples#645) Implement Phase P1 of ADR-021: the lambda-microvm compute backend (start/poll/stop), its CDK infrastructure, bootstrap policy, CLI support, and regional-availability enforcement. Suspend/resume (P3) and agent-side hook serving / smoke parity (P2) follow separately; a P1-built image is documented as not yet runnable end to end. Handlers (cdk/src/handlers): - ComputeType widens to 'agentcore' | 'ecs' | 'lambda-microvm'; SessionHandle gains {microvmId, endpoint}; SessionStatus gains 'suspended'; resolveComputeStrategy keeps the exhaustive-never gate - LambdaMicrovmComputeStrategy: RunMicrovm with idlePolicy omitted (auto-suspend disabled by construction) and maximumDurationInSeconds=28800 (AgentCore 8h parity); payload inline in runHookPayload up to exactly 16384 bytes, S3 pointer above; GetMicrovm poll maps the six-state MicrovmState enum mechanically (no task-state interpretation in the strategy); TerminateMicrovm best-effort with differentiated error handling; errors wrapped with a MicroVM marker so classifier entries cannot leak retry semantics onto other backends (regression-pinned) - Orchestrator: persists {microvmId, endpoint} to compute_metadata; cross-references substrate state vs DynamoDB (terminal + non- terminal -> failed with confirm re-read; suspended + non- AWAITING_APPROVAL -> anomaly event, no fail-fast); finalization and cancellation terminate the MicroVM (cancel branch ordered before the AgentCore RUNTIME_ARN fallback to avoid stopping an unrelated runtime in mixed deployments) Infra (cdk/src/constructs, stacks, bootstrap): - LambdaMicrovmCompute construct: CfnMicrovmImage + CfnNetworkConnector L1s (platform-VPC egress, 443-only SG), build/ execution roles trusted by lambda.amazonaws.com with sts:TagSession + aws:SourceAccount, execution role admitted via AgentSessionRole.admitComputeRole, payload bucket (1-day expiry, execution-role read-only, orchestrator put-only), three documented image-config states with mutually exclusive synth warnings - IAM scoped to the exact image ARN (+ ':*' version hedge; image names cannot contain ':') — no microvm-image:* wildcard anywhere; orchestrator gets only RunMicrovm/GetMicrovm/TerminateMicrovm/ PassNetworkConnector + scoped iam:PassRole; cancel Lambda gets TerminateMicrovm only; no Suspend/Resume/auth-token grants (P3) - Synth-time region gate (5 launch regions) with microvm_region_override escape hatch; token regions skipped - Bootstrap: conditional IaCRole-ABCA-Compute-LambdaMicrovms policy behind ComputeTypes (1.2.0 -> 1.3.0), deploy-time actions only; DEPLOYMENT_ROLES.md golden block [5] + golden-baseline parity test - abca:compute-backend=lambda-microvm cost tags; scripts/package-microvm-artifact.sh for the zip+Dockerfile flow CLI (cli/src): - Onboarding probes availability (ListManagedMicrovmImages) on the EFFECTIVE compute type (flag ?? stored ?? default) before any write, rejecting with launch-region list + agentcore/ecs remedy - platform doctor check when an active blueprint uses the backend (access-denied -> warn per checkBedrockModel precedent); runtime status groups the substrate like ECS ADR-021 refined in place (proposed): six-state poll mapping table, GetMicrovm NotFound -> completed rationale, microvmId vs microvmIdentifier seam, per-hook phasing table and the explicit "P1 image is not runnable end to end" consequence. Verification: cdk 141 suites / 2744 tests; cli 52 suites / 651 tests; tsc + eslint clean in both; types-sync green; knip at baseline (78); bootstrap generation and docs sync deterministic. Refs aws-samples#645 Co-authored-by: Claude <noreply@anthropic.com>
|
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #689 +/- ##
=======================================
Coverage ? 90.81%
=======================================
Files ? 246
Lines ? 61358
Branches ? 6529
=======================================
Hits ? 55721
Misses ? 5637
Partials ? 0 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
|
I'll address the CI comments tomorrow |
…utions The lock regenerated while adding @aws-sdk/client-lambda-microvms did not honor the root resolutions field, reintroducing vulnerable brace-expansion pins (GHSA-mh99-v99m-4gvg, cleared on main in aws-samples#658) and drifting from the resolution shape CI's install produces (yaml dedupe to 2.9.0, strnum/xml-naming entries), which tripped the fail-on-mutation gate. Regenerated with Node 22.23.2 + Yarn 1.22.22 (CI-equivalent) via yarn install --check-files: brace-expansion collapses to patched 5.0.9 everywhere, osv-scanner 2.4.0 reports no issues, second install is byte-identical, and both workspaces stay green (cdk 2744, cli 651; tsc clean). Refs aws-samples#645 Co-authored-by: Claude <noreply@anthropic.com>
Close the 14 uncovered patch lines on PR aws-samples#689: platform-doctor repo lookup failure shapes (non-Error throw, missing table output, lookup error, empty active-repo list) and non-Error MicroVM probe formatting; orchestrate-task reconciliation task-failure path; and the agent stack's defensive missing-image-ARN invariant. Tests only, no production changes; no unreachable lines found. cli 655, cdk 2746, tsc + eslint clean in both. Refs aws-samples#645 Co-authored-by: Claude <noreply@anthropic.com>
The create-microvm-image call must match the Lambda MicroVMs API model (the AWS CLI is generated from it): architecture is ARM_64 and hooks are enable flags (run: ENABLED) with service-defined paths - not the CFN L1's string shapes the script had copied. The construct is intentionally unchanged: CFN fields are unconstrained strings with their own spec conventions, validated at deploy time. Caught while drafting the P1 verification runbook; offline tests cannot exercise API payload shapes. bash -n clean; cdk suite green. Refs aws-samples#645 Co-authored-by: Claude <noreply@anthropic.com>
krokoko
left a comment
There was a problem hiding this comment.
Thanks for this — Phase P1 of ADR-021 is thoughtfully scoped, and the write-up makes the intentional non-goals (P2 hooks / P3 suspend) easy to review against. Strategy-vs-orchestrator split, image-ARN IAM scoping, cancel ordering before the RUNTIME_ARN fallback, and the layered regional gates all look solid. CI green + strong test coverage help a lot.
Request changes
Onboard should gate on ComputeSubstrate for lambda-microvm (parity with ECS)
In cli/src/commands/repo.ts, ECS already refuses onboard when the stack wasn’t deployed with the ECS substrate. MicroVM currently only probes regional availability (ListManagedMicrovmImages), so an operator can still write compute_type=lambda-microvm against an agentcore-only stack and only fail later at RunMicrovm.
Suggest mirroring the ECS check (and the onboard note) for lambda-microvm when ComputeSubstrate is present and not lambda-microvm. The agent stack already emits that output value.
Suggestions (non-blocking / nice-to-have in this PR)
-
microvm_suspend_anomalyspam —reconcileMicrovmSubstrateStateemits on every poll (~30s) while suspended outsideAWAITING_APPROVAL. Rare in P1 (no Suspend grants), but once it hits it can flood events for a long window. Emitting once per task (e.g. aPollStateflag) would keep “no fail-fast” without the noise — especially useful before P3. -
Orphan MicroVM if persist fails after
RunMicrovm—start-sessionstarts the VM, then writescompute_metadata; the catch pathfailTasks withoutTerminateMicrovm. Same race as AgentCore/ECS, but MicroVM cost/quota makes the leak more expensive. Best-effort terminate from the in-memory handle in the catch would close it. Fine as a follow-up issue if you’d rather not expand this PR. -
Shared payload-bucket read —
payloadBucket.grantRead(executionRole)is bucket-wide (incl. list), same shape as ECS #502. Scoping to the task key / droppingList*would improve isolation when this backend is enabled; also fine as follow-up. -
Incomplete
RunMicrovmresponse — the missingmicrovmId/endpointthrow isn’t wrapped withwrapMicrovmError, so it may miss the MicroVM classifier marker. Small consistency fix.
What looks great
- Exact 16 384 inline/S3 payload split,
idlePolicyomitted, 28800s max duration - Terminal substrate + DDB re-read before fail; suspend + approval treated as healthy
- No Suspend/Resume/auth-token grants; bootstrap deploy-time only with golden policy block
- Packaging script API shapes aligned with the service model
- Knip unexports are fine hygiene
Happy to re-review quickly once the onboard gate lands — and open to deferring 2–3 to tracked follow-ups if you prefer to keep this PR tight.
Implements Phase P1 of ADR-021 (#688): the
lambda-microvmcompute backend — strategy (start/poll/stop), CDK infrastructure, bootstrap policy, CLI support, and layered regional-availability enforcement. AgentCore remains the default. Suspend/resume is P3; agent-side hook serving and smoke parity are P2 — the ADR and the construct both warn explicitly that a P1-built image is not runnable end to end.Strategy reports, orchestrator interprets
LambdaMicrovmComputeStrategy.pollSessionmaps the six-stateMicrovmStateenum mechanically (SessionStatusgains'suspended'); the orchestrator cross-references DynamoDB — substrate-terminal + non-terminal status → failed (with a confirm re-read to avoid failing a successful fast teardown),suspended+ non-AWAITING_APPROVAL→ anomaly event, no fail-fast.RunMicrovmalways omitsidlePolicy(auto-suspend disabled by construction, asserted by tests) and pinsmaximumDurationInSecondsat 28 800 s (AgentCore 8 h parity). Strategy errors carry aMicroVM <op> failedmarker so the new classifier entries cannot change agentcore/ECS retry semantics — pinned by regression tests against the pre-changeUNKNOWNshape.No image wildcards in IAM
Every grant is scoped to the exact image ARN (bare names are resolved via
formatArn; a':*'sibling covers version-qualified forms — image names cannot contain:).microvmConfig.imageArnis compiler-required, so the account-wide fallback cannot return silently. Orchestrator gets exactlyRunMicrovm/GetMicrovm/TerminateMicrovm/PassNetworkConnector+ scopediam:PassRole; the cancel Lambda getsTerminateMicrovmonly; no Suspend/Resume/auth-token grants anywhere (P3), asserted by tests including on the generated bootstrap JSON.Regional availability enforced in layers
Synth-time gate on the 5 launch regions with a
microvm_region_overrideescape hatch (token regions skipped, documented); CLI onboarding probesListManagedMicrovmImageson the effective compute type (flag ?? stored ?? default) before any write;platform doctorprobes when an active blueprint uses the backend; orchestration-time classification is non-retryable with a configuration remedy.Cancellation ordering fix worth reviewer attention
The new
lambda-microvmbranch incancel-task.tsis deliberately placed before theagentRuntimeArnfallback:RUNTIME_ARNis set stack-wide whenever AgentCore stop is wired, so a MicroVM task would otherwise have invokedStopRuntimeSessionagainst an unrelated runtime in mixed deployments. Pinned by a regression test.ADR-021 refined in place (
proposed): six-state poll-mapping table,GetMicrovmNotFound →completedrationale,microvmId/microvmIdentifierseam, per-hook phasing table.Verification: cdk 141 suites / 2 744 tests, cli 52 / 651, tsc + eslint clean in both, types-sync green, knip at baseline (78), bootstrap generation and docs sync deterministic.
DEPLOYMENT_ROLES.mdgains golden policy block [5] with test parity.Refs #645