Skip to content

fix(trainer): deduplicate restarted TrainJob pods - #632

Merged
google-oss-prow[bot] merged 2 commits into
kubeflow:mainfrom
reckless-sherixx:fix/deduplicate-trainjob-pods
Jul 23, 2026
Merged

fix(trainer): deduplicate restarted TrainJob pods#632
google-oss-prow[bot] merged 2 commits into
kubeflow:mainfrom
reckless-sherixx:fix/deduplicate-trainjob-pods

Conversation

@reckless-sherixx

Copy link
Copy Markdown
Contributor

Summary

Fixes #25 by returning only the newest Pod for each TrainJob component in get_job().

  • Sorts Pods by creation_timestamp descending and keeps the first occurrence.
  • Uses the component role for initializer keys and role-index for launcher/node keys.
  • Adds a parametrized restart scenario covering both node-0 and node-1, with newer Pending Pods taking precedence over older Running Pods.

Why

Kubernetes can recreate Pods under restart policies. Without de-duplication, get_job() returns stale and current Pods for the same component, producing conflicting statuses.

Validation

  • python -m uv lock --check
  • python -m uv run ruff check --show-fixes --output-format=github .
  • python -m uv run ruff format --check kubeflow
  • python -m uv run ty check kubeflow/hub
  • python -m uv run coverage run --source=kubeflow -m pytest ./kubeflow/ (629 passed)

Supersedes the focused deduplication work in #160 without its unrelated changes.

@github-actions

Copy link
Copy Markdown
Contributor

🎉 Welcome to the Kubeflow SDK! 🎉

Thanks for opening your first PR! We're happy to have you as part of our community 🚀

Here's what happens next:

  • If you haven't already, please check out our Contributing Guide for repo-specific guidelines and the Kubeflow Contributor Guide for general community standards
  • Our team will review your PR soon! cc @kubeflow/kubeflow-sdk-team

Join the community:

Feel free to ask questions in the comments if you need any help or clarification!
Thanks again for contributing to Kubeflow! 🙏

Signed-off-by: Vidyansh <ezboi2312@gmail.com>
@reckless-sherixx
reckless-sherixx force-pushed the fix/deduplicate-trainjob-pods branch from ff9e826 to fc80755 Compare July 22, 2026 16:56
@reckless-sherixx
reckless-sherixx marked this pull request as ready for review July 22, 2026 17:03
Copilot AI review requested due to automatic review settings July 22, 2026 17:03
@google-oss-prow
google-oss-prow Bot requested a review from kramaranya July 22, 2026 17: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.

@reckless-sherixx

Copy link
Copy Markdown
Contributor Author

@andreyvelich Review this

@andreyvelich andreyvelich 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.

Thanks for tackling this, @reckless-sherixx! This review was performed with the help of AI tools.

old_timestamp = datetime.datetime(2025, 6, 1, 10, 0, 0)
new_timestamp = datetime.datetime(2025, 6, 1, 11, 0, 0)
old_pods = get_mock_pod_list().items
node_1_pod = copy.deepcopy(old_pods[-1])

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.

Select the node pod by role instead of position — old_pods[-1] silently breaks if get_mock_pod_list() is ever reordered.

Suggested change
node_1_pod = copy.deepcopy(old_pods[-1])
node_0_pod = next(
p for p in old_pods if p.metadata.labels[constants.JOBSET_RJOB_NAME_LABEL] == constants.NODE
)
node_1_pod = copy.deepcopy(node_0_pod)

step.pod_name = f"{step.pod_name}-restarted"
step.status = constants.POD_PENDING

node_1_step = copy.deepcopy(train_job.steps[-1])

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.

Same positional fragility — clone the node-0 step by name rather than by index.

Suggested change
node_1_step = copy.deepcopy(train_job.steps[-1])
node_0_step = next(s for s in train_job.steps if s.name == "node-0")
node_1_step = copy.deepcopy(node_0_step)

sorted_pods = sorted(
pod_list.items,
key=lambda pod: (
pod.metadata is not None and pod.metadata.creation_timestamp is not None,

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 is not None guard exists to survive Pods with no creation_timestamp, but no test exercises it. A future simplification to key=lambda pod: pod.metadata.creation_timestamp would pass every test yet raise TypeError: '<' not supported between 'datetime' and 'NoneType' in production. Worth adding a case where one restarted Pod has creation_timestamp=None and the timestamped Pod still wins.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

added

@andreyvelich

Copy link
Copy Markdown
Member

/ok-to-test

Signed-off-by: Vidyansh <ezboi2312@gmail.com>

@andreyvelich andreyvelich 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.

Thanks for this fix @reckless-sherixx!
/lgtm
/approve

@google-oss-prow

Copy link
Copy Markdown
Contributor

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: andreyvelich

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

The pull request process is described 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

@google-oss-prow
google-oss-prow Bot merged commit c598e29 into kubeflow:main Jul 23, 2026
17 of 19 checks passed
@google-oss-prow google-oss-prow Bot added this to the v0.5 milestone Jul 23, 2026
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.

[SDK] Get the correct TrainJob components using get_job() API

3 participants