feat(gateway): implement wake-on-traffic for paused sandboxes#586
feat(gateway): implement wake-on-traffic for paused sandboxes#586furykerry wants to merge 8 commits into
Conversation
|
[APPROVALNOTIFIER] This PR is NOT APPROVED This pull-request has been approved by: The full list of commands accepted by this bot can be found here. DetailsNeeds approval from an approver in each of these files:Approvers can indicate their approval by writing |
56f1d12 to
3c12d0a
Compare
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## master #586 +/- ##
==========================================
- Coverage 80.04% 79.95% -0.09%
==========================================
Files 229 230 +1
Lines 17826 18031 +205
==========================================
+ Hits 14268 14417 +149
- Misses 2975 3019 +44
- Partials 583 595 +12
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
46fd168 to
02d8fdc
Compare
eacd10c to
6d63285
Compare
6d63285 to
9e742f7
Compare
d6db638 to
b09a3d6
Compare
Implement wake-on-traffic support in the sandbox-gateway Envoy Go filter, allowing incoming HTTP requests to automatically resume paused sandboxes. Key changes: - Add wake-on-traffic annotation constants and config in sandbox-gateway - Implement Wake() flow in filter: detect paused sandbox, call sandbox.Resume(), update registry, then forward request via ORIGINAL_DST - Add informer cache fallback (HasWakeAnnotation) for annotation sync timing - Set wake annotations at sandbox creation via autoResume in create.go - Support AutoResume object format matching E2B SDK lifecycle parameter - Add comprehensive unit tests for wake filter, waker, and config - Add E2E test (test_wake_on_traffic.py) with access token auth - Exclude wake-on-traffic test from non-gateway CI runs Signed-off-by: 守辰 <shouchen.zz@alibaba-inc.com>
… test
- Add singleflight.Group to coalesce concurrent Wake calls for the
same sandbox, reducing duplicate API server Resume requests
- Use DoChan + select pattern so callers can bail out independently
while shared work continues under a detached context
- Add 3 new concurrency tests: same-sandbox coalescing, different-
sandbox isolation, and caller cancellation
- Expand E2E test to verify wake annotation lifecycle:
- Check wake-on-traffic and wake-timeout-seconds annotations
are set on the Sandbox CR after creation
- Check annotations persist after wake (not stripped by Resume)
- Add _get_sandbox_annotations() and _request_gateway_until_forwarded()
helpers for robust E2E verification
Signed-off-by: 守辰 <shouchen.zz@alibaba-inc.com>
- DecodeHeaders now launches wake in a goroutine with detached context and returns api.Running to suspend Envoy request processing - wakeAndContinue runs asynchronously: on success sets upstream metadata and calls Continue; on failure sends LocalReply (503) - Add thread-safe completion state machine (mutex-protected) to prevent double-reply when async goroutine and Destroy race - Add Destroy() to cancel in-flight wake context on stream reset - Add isEnvoyStreamGonePanic helper to detect Envoy stream-gone panics - Update mock callbacks to track Continue calls and signal completion via channel for async test synchronization - Update TestDecodeHeadersWakeOnTrafficCacheFallback to expect api.Running and wait for async completion Signed-off-by: 守辰 <shouchen.zz@alibaba-inc.com>
- TestIsEnvoyStreamGonePanic: table-driven test for panic detection - TestDestroyCancelsContext: verify Destroy cancels in-flight wake context - TestWakeAndContinueSuccess: verify async wake success path with Continue callback and upstream metadata set Coverage improved from 63.5% to 81.8% for filter package. Signed-off-by: 守辰 <shouchen.zz@alibaba-inc.com>
Add a sandboxOnly bool parameter to NewCache/NewCacheWithHealth, SetupCacheControllersWithManager, and AddIndexesToCache. When true, only Sandbox-related controllers (SandboxWaitReconciler and SandboxCustomReconciler) and Sandbox field indexes are registered, skipping Checkpoint, PVC, and SandboxSet controllers/indexes. This allows sandbox-gateway to use cache.NewCache(mgr, true) without requiring clientgoscheme registration, since corev1 types (PVC, PV) are no longer needed. Signed-off-by: 守辰 <shouchen.zz@alibaba-inc.com>
b09a3d6 to
b71f030
Compare
…affic test GET /kruise/api/sandboxes returned 405 because the sandbox-manager only registers POST /sandboxes (create) and GET /v2/sandboxes (list). The manager has a dedicated GET /health endpoint that returns 200 OK — use that instead for the gateway port-forward liveness check. The test_sandbox_with_pod_ip failure is a separate flake (sandbox pod died during pause/resume cycle), not related to this fix. Signed-off-by: 守辰 <shouchen.zz@alibaba-inc.com>
…t endpoints Remove the AutoResumeConfig struct, autoResume fields from NewSandboxRequest, NewSandboxRequestExtension, and SetTimeoutRequest. Remove updateWakeAnnotations method and its calls from ResumeSandbox and ConnectSandbox handlers. Remove related validation and annotation-setting code from create flow. Wake-on-traffic annotations are now set directly on the Sandbox CR (e.g. via kubectl) rather than through the autoResume API parameter. The E2E test is updated to set annotations via kubectl after sandbox creation. Signed-off-by: 守辰 <shouchen.zz@alibaba-inc.com>
…check The health endpoint was only registered as GET /health, not as GET /kruise/api/health. When the E2E test sends a health check through the sandbox-gateway (which forwards /kruise/api/* to the manager), the manager returned 404 because the path was not registered. Register the health handler under both /health and /kruise/api/health so it works both directly and through the gateway. Signed-off-by: 守辰 <shouchen.zz@alibaba-inc.com>
Ⅰ. Describe what this PR does
This PR implements wake-on-traffic for paused sandboxes in the sandbox-gateway. When a paused sandbox receives incoming traffic, the gateway automatically resumes it and forwards the request once the sandbox is running again.
Key changes:
pkg/sandbox-gateway/filter/filter.go): When a paused sandbox withWakeOnTraffic=truereceives traffic, the filter launches wake in a goroutine with a detached context and returnsapi.Runningto suspend Envoy request processing. ThewakeAndContinuegoroutine callsContinue(api.Continue)on success orSendLocalReply(503)on failure. Thread-safe completion state machine (mutex-protected) prevents double-reply when async goroutine andDestroyrace.wakepackage (pkg/sandbox-gateway/wake/wake.go): ImplementsWakerwith retry logic for transient states (e.g.,SandboxIsPausing). Callssandbox.Resume()to patch the spec and waits for the sandbox to reach Running state via the cache wait reconciler. Useserrors.Is()with sentinel errors for error classification (not string matching). Singleflight deduplication: concurrentWakecalls for the same sandbox are coalesced viasingleflight.Groupso only one Resume is issued to the API server. UsesDoChan+selectpattern so callers can bail out independently while shared work continues under a detached context.pkg/servers/e2b/pause_resume.go): AddsPause()that setsSpec.DesiredState=Paused(instead of deleting the sandbox), enabling the wake-on-traffic flow.updateWakeAnnotationspatches wake annotations as a separate API call after Resume.pkg/sandbox-gateway/server/server.go):handleRefreshretains routes for all states exceptdeadand empty string. This ensures the filter has full visibility (includingpaused,creating,available) for routing and wake decisions.pkg/utils/utils.go,pkg/sandbox-manager/errors/error.go): Exports sentinel errors (ErrSandboxIsPausing,ErrSandboxIsTerminating,ErrShutdownTimeReached,ErrSandboxPhaseNotAllowed) fromIsSandboxResumable. AddsUnwrap()+NewErrorWrap()tomanagererrors.Errorto enableerrors.Is()through wrapped errors.pkg/cache/cache.go): Restricts the gateway's informer cache to only Sandbox resources viaByObjectfiltering, reducing memory usage and API server load.ENABLE_WAKE_ON_TRAFFICenv var andwakeTimeoutSecondsconfig to the gateway filter.Ⅱ. Does this pull request fix one issue?
NONE
Ⅲ. Describe how to verify it
go test ./pkg/sandbox-gateway/... ./pkg/cache/... ./pkg/servers/e2b/... ./pkg/utils/...POST /sandboxes/{id}/pauseⅣ. Special notes for reviews
DecodeHeadersreturnsapi.Runningwhen wake is triggered, launchingwakeAndContinuein a goroutine. The goroutine uses a detached context (not tied to the Envoy filter lifecycle). On completion, it callsContinue(api.Continue)orSendLocalReply. TheDestroy()method cancels the in-flight wake context when Envoy destroys the filter (stream reset). A mutex-protected completion state machine prevents double-reply races.Waker.Wake()usessingleflight.GroupwithDoChan()to coalesce concurrent calls for the same sandbox. The shared Resume runs under a detached context, and callers can bail out viaselecton their own context.deadand empty-state routes are deleted from the registry. All other states (running,paused,creating,available) are retained for full filter visibility.Waker.Wake()retry loop only retries onErrSandboxIsPausing(transient state). Other errors likeErrSandboxIsTerminatingare non-retryable and return immediately.SandboxOnlymode) adds nil guards onGetSandboxController()andGetSandboxSetController()since controller handlers are not set up in that mode.Ⅴ. Test coverage
pkg/sandbox-gateway/filterpkg/sandbox-gateway/wakepkg/servers/e2bpkg/proxyAdded tests:
TestIsEnvoyStreamGonePanic: table-driven test for panic detection (7 cases)TestDestroyCancelsContext: verify Destroy cancels in-flight wake contextTestWakeAndContinueSuccess: verify async wake success path with Continue callback and upstream metadataTestWakeSingleflight*: tests for singleflight deduplicationtest_wake_on_traffic.py)