Skip to content

model-serving: guard pod deletion by UID - #1427

Open
avinxshKD wants to merge 3 commits into
volcano-sh:mainfrom
avinxshKD:fix/modelserving-grace-pod-uid
Open

model-serving: guard pod deletion by UID#1427
avinxshKD wants to merge 3 commits into
volcano-sh:mainfrom
avinxshKD:fix/modelserving-grace-pod-uid

Conversation

@avinxshKD

Copy link
Copy Markdown
Contributor

What type of PR is this?

/kind bug

What this PR does / why we need it:

Prevents a stale ModelServing grace timer from deleting a replacement pod with the same name.

The controller now checks the pod UID before deleting it and uses a UID precondition on the delete request.

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

Bug evidence (required for bug-related PRs):

A ModelServing with the following configuration can hit this:

recoveryPolicy: RoleRecreate
template:
  restartGracePeriodSeconds: 60

A failed or restarted pod starts the grace timer. If that pod is deleted or replaced during the grace period, the replacement gets the same deterministic name but a different UID. The old handler previously looked up and deleted the pod by name only:

func (c *ModelServingController) handlePodAfterGraceTime(ms *workloadv1alpha1.ModelServing, errPod *corev1.Pod) {
if ms.Spec.Template.RestartGracePeriodSeconds != nil && *ms.Spec.Template.RestartGracePeriodSeconds > 0 {
// Wait for the grace period before making a decision
time.Sleep(time.Duration(*ms.Spec.Template.RestartGracePeriodSeconds) * time.Second)
klog.V(4).Infof("%s after grace time", errPod.Name)
defer c.graceMap.Delete(utils.GetNamespaceName(errPod))
newPod, err := c.podsLister.Pods(ms.Namespace).Get(errPod.Name)
if err != nil {
if apierrors.IsNotFound(err) {
klog.V(4).Infof("pod %s has been deleted after grace time", errPod.Name)
} else {
klog.Errorf("cannot get pod %s after grace time, err: %v", errPod.Name, err)
}
return
}
if !utils.IsPodRunningAndReady(newPod) {
// pod has not recovered after the grace period, needs to be rebuilt
// After this pod has been deleted, we will rebuild the ServingGroup in deletePod function
err = c.kubeClientSet.CoreV1().Pods(ms.Namespace).Delete(context.TODO(), newPod.Name, metav1.DeleteOptions{})
if err != nil {
klog.Errorf("cannot delete pod %s after grace time, err: %v", newPod.Name, err)
return
}
klog.V(2).Infof("%s been deleted after grace time", errPod.Name)
}
} else {
// grace period is not set or the grace period is 0, the deletion will be executed immediately.
defer c.graceMap.Delete(utils.GetNamespaceName(errPod))
err := c.kubeClientSet.CoreV1().Pods(ms.Namespace).Delete(context.TODO(), errPod.Name, metav1.DeleteOptions{})
if err != nil {
klog.Errorf("cannot delete pod %s when it error, err: %v", errPod.Name, err)
return
}
klog.V(2).Infof("%s been deleted without grace time", errPod.Name)
}

The added test reproduces this with separate failed and replacement pod UIDs. It also verifies UID preconditions for delayed and immediate deletion.

Tested with:

go test ./pkg/model-serving-controller/... -count=1

This was reproduced with the controller fake client, not on a live cluster.

Special notes for your reviewer:

AI assistance was used during code inspection and initial preparation. I reviewed the final diff and ran the relevant tests locally on my own.

Race tests were not run because the local Windows environment does not have gcc.

Does this PR introduce a user-facing change?:

NONE

Signed-off-by: Avinash Kumar Deepak <avinash8655279@gmail.com>
Copilot AI lite review requested due to automatic review settings July 28, 2026 11:50
@gemini-code-assist

Copy link
Copy Markdown
Contributor

Caution

The consumer version of Gemini Code Assist on GitHub has been sunset. All code review activity has officially ceased.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@volcano-sh-bot

Copy link
Copy Markdown
Contributor

[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 yaozengzeng for approval. 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

@avinxshKD

Copy link
Copy Markdown
Contributor Author

ptal @YaoZengzeng @LiZhenCheng9527 when get chance

@acsoto

acsoto commented Aug 3, 2026

Copy link
Copy Markdown
Member

/lgtm

Comment thread pkg/model-serving-controller/controller/model_serving_controller.go
Signed-off-by: Avinash Kumar Deepak <avinash8655279@gmail.com>
Copilot AI review requested due to automatic review settings August 4, 2026 08:03

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@avinxshKD

Copy link
Copy Markdown
Contributor Author

@LiZhenCheng9527 updated, we now track each pod’s grace timer using its name and UID, soo a replacement pod gets its own timer instead of being skipped because of the old pod. PTAL

@acsoto also take a look if u have time sir, as lgtm tag has been removed now.

@acsoto

acsoto commented Aug 4, 2026

Copy link
Copy Markdown
Member

/lgtm

@avinxshKD

Copy link
Copy Markdown
Contributor Author

thanks @acsoto for a lgtm 😄
@hzxuzhonghu @LiZhenCheng9527 ptal

@LiZhenCheng9527 LiZhenCheng9527 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I don't think a Grace unit test is important enough to warrant creating a new file.

}, 2*time.Second, 10*time.Millisecond)
}

func newGracePeriodTestController(t *testing.T, pod *corev1.Pod) (*ModelServingController, *kubefake.Clientset) {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

nit: Other test functions also have the need to create controllers. Can a test helper function be created that can be used by most unit tests?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Maybe you can to this in another PR.

Signed-off-by: Avinash Kumar Deepak <avinash8655279@gmail.com>
Copilot AI review requested due to automatic review settings August 10, 2026 12:43
@volcano-sh-bot

Copy link
Copy Markdown
Contributor

New changes are detected. LGTM label has been removed.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@avinxshKD

Copy link
Copy Markdown
Contributor Author

@LiZhenCheng9527 done, Grace tests moved into model_serving_controller_test.go. and
separate test file removed. PTAL

Maybe you can to this in another PR.

sure, separate PR for Shared helper refactor

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

ModelServing grace timer can delete a replacement pod with the same name

5 participants