Skip to content

fix(statefulset): delete pod on storage mismatch instead of in-place …#2388

Open
shivansh-gohem wants to merge 1 commit intoopenkruise:masterfrom
shivansh-gohem:fix/statefulset-vct-storage-mismatch
Open

fix(statefulset): delete pod on storage mismatch instead of in-place …#2388
shivansh-gohem wants to merge 1 commit intoopenkruise:masterfrom
shivansh-gohem:fix/statefulset-vct-storage-mismatch

Conversation

@shivansh-gohem
Copy link
Copy Markdown

What this PR does / why we need it:
When a new VolumeClaimTemplate is added to an existing Advanced StatefulSet, the controller correctly detects the storage mismatch via storageMatches(). However, it previously fell through to UpdateStatefulPod, attempting an in-place update of the pod's spec.volumes. Because spec.volumes is immutable on running pods in Kubernetes, the API server rejected this with a Forbidden error, causing the controller to enter an infinite FailedUpdate retry loop.

This PR fixes the issue by intercepting the storage mismatch in processReplica. If the storage does not match and the pod is not already terminating, the controller explicitly calls DeleteStatefulPod. By deleting the pod, we rely on the native StatefulSet reconciliation loop (CreateStatefulPod) on the next tick to automatically provision the new PVC and reconstruct the pod from scratch.

Which issue(s) this PR fixes:
Fixes #2343

Special notes for the reviewer:

  • Architectural Choice: Rather than manually pre-creating PVCs before deletion, this fix relies entirely on the standard processReplica -> CreateStatefulPod -> createPersistentVolumeClaims flow on the subsequent reconcile tick. This keeps the fix minimal and native to standard StatefulSet lifecycle management.
  • Guardrail: Included an !isTerminating(replicas[i]) check to ensure the controller does not spam DELETE requests to the API server while waiting for the pod to gracefully terminate.
  • Coverage: Added TestProcessReplicaStorageMismatch to stateful_set_control_test.go to ensure this exact path is covered by CI.

How to verify it:

  1. Unit tests: go test ./pkg/controller/statefulset/... -run TestProcessReplicaStorageMismatch passes.
  2. Verified on a local kind cluster:
    • Deployed a StatefulSet with 1 VolumeClaimTemplate.
    • Updated the StatefulSet spec to include a 2nd VolumeClaimTemplate.
    • Verified via kubectl describe that the controller successfully emits SuccessfulDelete -> SuccessfulCreate events, and both PVCs bind correctly without any FailedUpdate errors.

Copilot AI review requested due to automatic review settings March 6, 2026 05:43
@kruise-bot kruise-bot requested review from Fei-Guo and zmberg March 6, 2026 05:43
@kruise-bot
Copy link
Copy Markdown

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by:
Once this PR has been reviewed and has the lgtm label, please assign veophi for approval by writing /assign @veophi in a comment. For more information see:The Kubernetes Code Review Process.

The full list of commands accepted by this bot can be found here.

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@kruise-bot kruise-bot added the size/M size/M: 30-99 label Mar 6, 2026
@shivansh-gohem shivansh-gohem force-pushed the fix/statefulset-vct-storage-mismatch branch from 4f667f9 to a433044 Compare March 6, 2026 05:44
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Fixes Advanced StatefulSet reconciliation when storageMatches() detects a pod storage layout mismatch (e.g., adding a new VolumeClaimTemplate) by deleting the mismatching pod instead of attempting a forbidden in-place spec.volumes update, and adds a regression unit test for the scenario.

Changes:

  • In processReplica, intercept !storageMatches() and delete the pod to trigger recreation with the correct volumes/PVCs.
  • Add TestProcessReplicaStorageMismatch to assert the controller issues a delete rather than an in-place update attempt.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.

File Description
pkg/controller/statefulset/stateful_set_control.go Deletes pods on storage mismatch to avoid immutable spec.volumes update failures.
pkg/controller/statefulset/stateful_set_control_test.go Adds a unit test to validate the storage-mismatch deletion behavior.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread pkg/controller/statefulset/stateful_set_control.go Outdated
// Delete the pod so it gets recreated; the standard creation path will handle
// creating any missing PVCs before the new pod is scheduled.
if !storageMatches(set, replicas[i]) {
if !isTerminating(replicas[i]) {
Copy link

Copilot AI Mar 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This storage-mismatch deletion doesn't apply the scaleMaxUnavailable budget (other branches use decreaseAndCheckMaxUnavailable(scaleMaxUnavailable) before deleting/creating). In burst/parallel mode this can delete more pods than allowed, increasing disruption. Add the same max-unavailable check before calling delete and return shouldBreak when the budget is exhausted.

Suggested change
if !isTerminating(replicas[i]) {
if !isTerminating(replicas[i]) {
// Respect the scaleMaxUnavailable budget before deleting for storage mismatch.
if decreaseAndCheckMaxUnavailable(scaleMaxUnavailable) {
logger.V(4).Info(
"StatefulSet pod is unavailable due to storage mismatch, and break pods scale",
"statefulSet", klog.KObj(set), "pod", klog.KObj(replicas[i]))
// No mutation yet (pod not deleted); signal caller to stop further scaling.
return false, true, nil
}

Copilot uses AI. Check for mistakes.
@codecov
Copy link
Copy Markdown

codecov Bot commented Mar 6, 2026

Codecov Report

❌ Patch coverage is 68.75000% with 5 lines in your changes missing coverage. Please review.
✅ Project coverage is 48.68%. Comparing base (bba2621) to head (ca72080).

Files with missing lines Patch % Lines
pkg/controller/statefulset/stateful_set_control.go 68.75% 4 Missing and 1 partial ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##           master    #2388      +/-   ##
==========================================
+ Coverage   48.66%   48.68%   +0.02%     
==========================================
  Files         324      324              
  Lines       27920    27935      +15     
==========================================
+ Hits        13587    13600      +13     
- Misses      12794    12795       +1     
- Partials     1539     1540       +1     
Flag Coverage Δ
unittests 48.68% <68.75%> (+0.02%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@shivansh-gohem shivansh-gohem force-pushed the fix/statefulset-vct-storage-mismatch branch from a433044 to c44b839 Compare March 6, 2026 06:39
…update

When a new VolumeClaimTemplate is added to an existing Advanced StatefulSet,
processReplica falls through to UpdateStatefulPod which tries to patch spec.volumes —
Kubernetes forbids this, causing a repeated Forbidden error loop (bug openkruise#2343).
Fix: detect storage mismatch before the identity/retention check and call
DeleteStatefulPod so the pod gets recreated on the next reconcile. The standard
creation path (CreateStatefulPod) naturally handles PVC creation.
Fixes openkruise#2343

Signed-off-by: Shivansh Sahu <sahushivansh142@gmail.com>
@shivansh-gohem shivansh-gohem force-pushed the fix/statefulset-vct-storage-mismatch branch from c44b839 to ca72080 Compare March 7, 2026 04:17
@kruise-bot kruise-bot added size/L size/L: 100-499 and removed size/M size/M: 30-99 labels Mar 7, 2026
@shivansh-gohem
Copy link
Copy Markdown
Author

/cc @Fei-Guo @FillZpp

@kruise-bot kruise-bot requested a review from FillZpp March 7, 2026 04:26
@shivansh-gohem
Copy link
Copy Markdown
Author

shivansh-gohem commented Apr 7, 2026

/cc @FillZpp @Fei-Guo

@kruise-bot
Copy link
Copy Markdown

@shivansh-gohem: GitHub didn't allow me to request PR reviews from the following users: technosophos.

Note that only openkruise members and repo collaborators can review this PR, and authors cannot review their own PRs.

Details

In response to this:

/cc @FillZpp @Fei-Guo @technosophos

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes/test-infra repository.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size/L size/L: 100-499

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[BUG] add new a VolumeClaimTemplate to StatefulSet failed

3 participants