Skip to content

feat: integrate ModelServing revision history - #1767

Closed
acsoto wants to merge 5 commits into
volcano-sh:mainfrom
acsoto:feature/modelserving-revision-controller-review
Closed

acsoto wants to merge 5 commits into
volcano-sh:mainfrom
acsoto:feature/modelserving-revision-controller-review

Conversation

@acsoto

@acsoto acsoto commented Sep 12, 2026 •

Copy link
Copy Markdown
Member

What type of PR is this?

/kind feature

What this PR does / why we need it:

Extend the ModelServing revision core from #1643 with immutable ControllerRevision lifecycle handling, partition-protected historical recovery, durable revision retention during recovery and cleanup, and deterministic plugin rendering for historical workloads.

Which issue(s) this PR fixes:

Refs #1643 #1607

Bug evidence (required for bug-related PRs):

N/A

Special notes for your reviewer:

This is the second part of the implementation.

This PR was written in part with the assistance of generative AI.

Tested with:

make test
go test ./pkg/model-serving-controller/...
go vet ./pkg/model-serving-controller/...
GOTOOLCHAIN=go1.26.0 bin/golangci-lint run ./pkg/model-serving-controller/...

Does this PR introduce a user-facing change?:

Upgrading to this version changes ModelServing revision tracking and triggers a one-time rolling replacement of existing workloads, even when the ModelServing spec is unchanged. This affects both ServingGroupRollingUpdate and RoleRollingUpdate and respects the configured rollout partitions and rolling update settings. Plan the controller upgrade accordingly, as workload replacement may temporarily reduce serving capacity.

@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

@acsoto
acsoto force-pushed the feature/modelserving-revision-controller-review branch 4 times, most recently from fa5bd6f to 3cc7520 Compare September 12, 2026 09:23
@acsoto
acsoto force-pushed the feature/modelserving-revision-controller-review branch from 4ee987c to 49b2f7c Compare September 14, 2026 07:59
@acsoto

acsoto commented Sep 15, 2026 •

Copy link
Copy Markdown
Member Author

@LiZhenCheng9527 LiZhenCheng9527 moved this from Accepted to Planned in Release v1.1 in Kthena Release Tracking Sep 16, 2026
if err != nil {
return fmt.Errorf("build ModelServing revision data: %w", err)
}
controllerRevision, collisionCount, err := utils.RecordModelServingRevision(ctx, c.kubeClientSet, ms, revisionData)

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.

This switches the revision identity from ModelServingRevision(ms) (hash of roles only) to RevisionDataHash over the full revision data, so an unchanged spec gets a different revision label after the controller upgrade (verified with the same fixture: 5c8649477c → 6bc4bb5bc9). For workloads created by a released controller (e.g. v1.0.0):

  • Under the default ServingGroupRollingUpdate, isServingGroupOutdated compares pod revision labels against the new value, so every existing serving group is treated as outdated and rolled even though nothing in its spec changed.
  • Under RoleRollingUpdate, newRoleUpdateCheck unconditionally returns outdated for pre-V1 ControllerRevisions (no revision-data-version annotation), so all roles are restarted as well.

If a one-time full restart on upgrade is intended, could this be called out in a release note / upgrade doc (the PR is currently marked release-note NONE)? Otherwise, consider keeping a legacy comparison path that hashes the roles stored in pre-V1 revisions so unchanged workloads are not restarted.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

I think for this part, restart.
Before the release, if this is unacceptable, we can create a patch
if it’s acceptable, we’ll include it in the release notes.

Signed-off-by: Zhou Zihang <z@mcac.cc>
Signed-off-by: Zhou Zihang <z@mcac.cc>
Signed-off-by: Zhou Zihang <z@mcac.cc>
Signed-off-by: Zhou Zihang <z@mcac.cc>
@acsoto
acsoto force-pushed the feature/modelserving-revision-controller-review branch from 5487641 to b8da6b8 Compare September 22, 2026 02:30
@acsoto

acsoto commented Sep 22, 2026

Copy link
Copy Markdown
Member Author

@LiZhenCheng9527

@acsoto

acsoto commented Sep 22, 2026

Copy link
Copy Markdown
Member Author

@VanderChen

@kube-gopher

Copy link
Copy Markdown
Member

Annotate: within the inplace range.

Comment on lines +1172 to +1173
if err := c.CreatePodsByRole(ctx, *roleToApply.DeepCopy(), workloadToApply, roleIndex, servingGroupOrdinal, replicaRevision, hashToUse); err != nil {
return fmt.Errorf("recreate pods for role %s/%s in ServingGroup %s: %w", targetRole.Name, roleObj.Name, groupName, err)

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.

Increasing workerReplicas (for example, from 0 to 1) makes an existing, unprotected replica enter this missing-Pod branch. CreatePodsByRole then tries to create its entry Pod using the desired revision, but the same-named entry Pod still belongs to the previous revision, so createPod returns an identity-mismatch error.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

#1799 now covers most of this work, so I suggest consolidating there

klog.V(4).Infof("scaleUpServingGroups: creating/updating PodGroup for ServingGroup=%s", groupName)
// Ensure a PodGroup exists for the new ServingGroup when gang scheduling is enabled.
if err := c.createOrUpdatePodGroupByServingGroup(ctx, ms, groupName); err != nil {
if err := c.createOrUpdatePodGroupByServingGroup(ctx, workload, groupName); err != nil {

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.

Passing the historical workload here correctly initializes the recovered group's PodGroup, but syncServingGroupReplicas subsequently iterates over every non-deleting group and calls createOrUpdatePodGroupByServingGroup(ctx, ms, servingGroup.Name) with the current spec. Once the PodGroup is observed, that path overwrites its historical requirements.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

as above

@acsoto

acsoto commented Oct 13, 2026

Copy link
Copy Markdown
Member Author

Closing in favor of #1799 to consolidate the revision work into one implementation. The outstanding review findings and recovery coverage from this PR should be carried over there.

@acsoto acsoto closed this Oct 13, 2026
@github-project-automation github-project-automation Bot moved this from Planned in Release v1.1 to Done in Kthena Release Tracking Oct 13, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

5 participants