fix(sandbox): avoid triggering in-place update for metadata-only changes#557
Merged
kruise-bot merged 12 commits intoJun 25, 2026
Merged
Conversation
…box ready When a claim request includes label/metadata changes that trigger an in-place update, the sandbox could be reported as ready before the controller processed the update, leading to premature readiness. - Add requireInplaceUpdateCompletion parameter to NewSandboxWaitReadyTask - Propagate request labels via InplaceUpdate.Metadata in the claim path so waitForSandboxReady waits for the InplaceUpdate condition to become True before reporting ready - Keep the clone path unchanged (creates a new pod, no in-place update) - Add InplaceUpdateMetadataOptions to config for label propagation - Update tests to cover the new wait behavior Signed-off-by: 守辰 <shouchen@U-TP9524M5-2100.local>
…Options.Metadata - Add isMetadataOnlyChange helper in handleInPlaceUpdateCommon to detect metadata-only changes (labels/annotations without image/resources diffs) - For metadata-only changes, directly patch pod metadata via control.Update without setting InplaceUpdate/Ready=False conditions - Update requireInplaceUpdateCompletion in claim.go to only be true when image or resources changed (not metadata-only) - Add fast-fail for InplaceUpdate Failed condition in NewSandboxWaitReadyTask to return error immediately instead of waiting for timeout - Remove Metadata field and InplaceUpdateMetadataOptions from config/infra.go since metadata-only updates are now handled separately by the controller - Move pod label propagation to basicSandboxCreateModifier for both claim and clone paths, replacing InplaceUpdate.Metadata usage - Add MergePodLabels/MergePodAnnotations helpers and SetPodAnnotations/ GetPodAnnotations on Sandbox interface (annotations helpers later removed as dead code after Metadata removal) - Add unit tests for requireInplaceUpdateCompletion and metadata-only change Signed-off-by: 守辰 <shouchen@U-TP9524M5-2100.local> Signed-off-by: 守辰 <shouchen.zz@alibaba-inc.com>
The TestSandboxManager_ClaimSandbox/Claim_with_inplace_update test was failing in CI because requireInplaceUpdateCompletion=true requires the InplaceUpdate condition to be set by the controller, but the test had no controller simulation. Add simulateInplaceUpdateControllerForApiTest goroutine and increase ClaimTimeout to 2s for InplaceUpdate test cases. Signed-off-by: 守辰 <shouchen.zz@alibaba-inc.com>
- Remove check for InplaceUpdating reason to avoid premature blocking - Limit in-place update readiness check to image or resources changes only - Return error immediately if InplaceUpdate condition is Failed - Skip in-place update condition check when requireInplaceUpdateCompletion is false Signed-off-by: 守辰 <shouchen.zz@alibaba-inc.com>
dfe30c8 to
712dff2
Compare
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## master #557 +/- ##
==========================================
+ Coverage 79.71% 79.77% +0.05%
==========================================
Files 195 202 +7
Lines 14107 14721 +614
==========================================
+ Hits 11246 11744 +498
- Misses 2457 2549 +92
- Partials 404 428 +24
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:
|
…iles - Add a comprehensive Python demo script demonstrating Qoder CLI usage via E2B SDK - Provide a Dockerfile for building a sandbox-ready image with Qoder CLI and dev tools - Include detailed README in English and Chinese documenting setup, deployment, and usage - Add SandboxSet YAML manifest for deploying Qoder CLI warm pool with persistent storage refactor(pkg/controller/checkpoint): use inplaceupdate.ResourcesEqual for resource check - Replace reflect.DeepEqual with ResourcesEqual for accurate resource comparisons test(pkg/controller/sandbox/core): add tests for metadata-only change detection - Cover various cases verifying metadata-only pod updates vs image/resource changes fix(pkg/controller/sandbox/core): treat metadata-only updates without inplace update flow - Patch pod metadata directly if only labels/annotations changed, ignoring injected resources test(pkg/sandbox-manager): enhance simulateInplaceUpdateController with resource version handling - Prevent stale update conflicts by fetching latest object before status update test(pkg/sandbox-manager): add test case for claim with metadata-only label modifications - Verify pod labels are merged via Modifier without triggering inplace update test(pkg/sandbox-manager/infra/sandboxcr): add tests for MergePodLabels utility - Check merging behavior with nil, empty, overlapping labels ensuring correct overrides refactor(pkg/utils/inplaceupdate): replace reflect.DeepEqual with ResourcesEqual consistently - Use ResourcesEqual function for semantic resource requirement equality ignoring injected fields
…e update flow - Enhance NewSandboxWaitReadyTask to optionally require inplace update completion - Add isMetadataOnlyChange helper to detect changes limited to labels/annotations - Patch pod metadata directly for metadata-only changes without setting InplaceUpdate condition - Update handleInPlaceUpdateCommon to apply direct metadata patch when only metadata changes - Add MergePodLabels utility to merge labels into sandbox pod template - Modify claim logic to distinguish metadata-only updates and skip waiting for inplace update completion - Simulate inplace update controller in tests to handle real inplace updates asynchronously - Add comprehensive tests for metadata-only changes and wait task behavior with inplace update flag - Fix minor doc improvements and error message clarification for inplace update validation - Replace reflect.DeepEqual with proper resource comparison helper for resource changes detection
Signed-off-by: 守辰 <shouchen.zz@alibaba-inc.com>
Signed-off-by: 守辰 <shouchen.zz@alibaba-inc.com>
…place-update # Conflicts: # pkg/sandbox-manager/infra/sandboxcr/sandbox_test.go
…yTask Remove the requireInplaceUpdateCompletion parameter and all related logic from NewSandboxWaitReadyTask. Restore the original InplaceUpdating reason check that blocks readiness only while an in-place update is in progress. - Revert NewSandboxWaitReadyTask signature in pkg/cache/interface.go and pkg/cache/tasks.go to remove the bool parameter - Restore the original InplaceUpdating condition check in the readiness predicate (blocks when reason == InplaceUpdating, passes otherwise) - Remove TestNewSandboxWaitReadyTask_RequireInplaceUpdateCompletion test - Remove requireInplaceUpdateCompletion logic from claim.go and clone.go waitForSandboxReady callers - Remove pre-set InplaceUpdate=True condition from core_test.go pool sandboxes that was added to satisfy the removed check Signed-off-by: shouchen <shouchen.zz@alibaba-inc.com> Signed-off-by: 守辰 <shouchen.zz@alibaba-inc.com>
Add missing edge cases to TestMergePodLabels table: - both empty maps - no change - empty string value - valid label - overwrite all existing labels - kubernetes-style dotted label keys - single label added to multiple existing Add TestMergePodLabels_NilTemplate to verify no panic when the sandbox's pod template is nil (SetPodLabels is a no-op, labels silently dropped). Add TestMergePodLabels_Idempotent to verify that calling MergePodLabels twice with the same labels produces the same result as calling once. Signed-off-by: shouchen <shouchen.zz@alibaba-inc.com> Signed-off-by: 守辰 <shouchen.zz@alibaba-inc.com>
zmberg
reviewed
Jun 25, 2026
| return false | ||
| } | ||
| if !resourcesEqual(c.Resources, *status.Resources) { | ||
| if !reflect.DeepEqual(c.Resources, *status.Resources) { |
…ove tests - Replace reflect.DeepEqual with ResourcesEqual in isPodResourceResizeCompleted for consistent subset-based resource comparison, and remove unused reflect import - Convert TestIsPodResourceResizeCompleted to table-driven format with 7 cases including new edge cases: spec has more resource types than status, and status has more resource types than spec - Move MergePodLabels tests from sandboxcr/sandbox_test.go to infra/interface_test.go using a mockSandboxForLabels mock, co-locating tests with the MergePodLabels function definition Signed-off-by: shouchen <shouchen.zz@alibaba-inc.com> Signed-off-by: 守辰 <shouchen.zz@alibaba-inc.com>
Member
|
/lgtm |
|
[APPROVALNOTIFIER] This PR is APPROVED This pull-request has been approved by: zmberg The full list of commands accepted by this bot can be found here. The pull request process is described here DetailsNeeds approval from an approver in each of these files:
Approvers can indicate their approval by writing |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Ⅰ. Describe what this PR does
This PR optimizes the in-place update flow so that metadata-only changes (labels/annotations) bypass the full InplaceUpdate condition, preventing unnecessary Ready=False transitions for sandbox claims.
Key changes:
Metadata-only update detection (
common_inplace_update_handler.go): NewisMetadataOnlyChangefunction detects when only labels/annotations differ between the pod and sandbox template (no image or resource changes). When detected, the controller patches pod metadata directly without setting the InplaceUpdate condition, avoiding blocked sandbox readiness.Export
ResourcesEqual(inplace_update.go): RenamedresourcesEqualto exportedResourcesEqualand replaced allreflect.DeepEqualusages with it inDefaultGeneratePatchBodyFunc,DefaultGenerateResizeSubresourceBody, andisPodResourceResizeCompleted. The subset-based comparison ignores system-injected resources (e.g., ephemeral-storage from LimitRanger) so they don't trigger false in-place updates.Checkpoint utils consistency (
checkpoint/utils.go): Uses exportedResourcesEqualinstead ofreflect.DeepEqualfor consistent resource comparison.MergePodLabelsutility (interface.go,create.go): NewMergePodLabels(sandbox, labels)function centralizes pod label propagation.create.gorefactored to use it.Claim validation message (
claim.go): Updated error message to "requires at least one of image or resources to be set".Ⅱ. Does this pull request fix one issue?
NONE
Ⅲ. Describe how to verify it
Ⅳ. Special notes for reviews
isMetadataOnlyChangeuses subset-basedResourcesEqualcomparison — extra resources injected into the pod by admission webhooks are ignored so metadata-only changes are not mistakenly treated as in-place updatesisPodResourceResizeCompletednow usesResourcesEqual(subset-based) instead ofreflect.DeepEqual(exact match), consistent with the rest of the in-place update codeMergePodLabelstests are co-located ininterface_test.gousing amockSandboxForLabelsmock that implements the fullSandboxinterfaceTestIsPodResourceResizeCompletedis table-driven with 7 cases including edge cases for subset comparisonAppendix: Incidental Changes
pkg/cache/tasks.go(added trailing period)pkg/sandbox-manager/config/infra.goclarifying metadata handling