Skip to content

feat(api): Add terminationGracePeriodSeconds to PodSpecPatch in TrainJob#3324

Merged
google-oss-prow[bot] merged 1 commit into
kubeflow:masterfrom
krishdef7:feat/termination-grace-period-patch
May 26, 2026
Merged

feat(api): Add terminationGracePeriodSeconds to PodSpecPatch in TrainJob#3324
google-oss-prow[bot] merged 1 commit into
kubeflow:masterfrom
krishdef7:feat/termination-grace-period-patch

Conversation

@krishdef7

Copy link
Copy Markdown
Contributor

What this PR does / why we need it

Adds terminationGracePeriodSeconds to PodSpecPatch so users can configure pod termination grace period per TrainJob via RuntimePatches, without requiring cluster-admin access to modify the TrainingRuntime.

This is needed for distributed training with PyTorch Elastic (torchrun). When a TrainJob is paused or a node is drained, Kubelet sends SIGTERM to the pod. The TorchElastic agent propagates this to worker processes, which perform JIT checkpointing before shutdown. For large models (70B+ parameters), the default 30-second grace period is insufficient to complete checkpoint saves to disk or remote storage (S3/PVC).

Users need to set terminationGracePeriodSeconds alongside TORCH_ELASTIC_SHUTDOWN_TIMEOUT (configurable since pytorch/pytorch#172596) to give workers enough time to save state before SIGKILL.

Previously, this field could only be set in the TrainingRuntime template, affecting all jobs using that runtime. This PR exposes it as a per-TrainJob override consistent with other PodSpecPatch fields like nodeSelector and tolerations.

No changes to merge logic in trainingruntime.go are required — the existing StrategicMergePatch applied at batchv1.JobTemplateSpec level already handles this field automatically.

Which issue(s) this PR fixes

Fixes #3285

Changes

  • Add TerminationGracePeriodSeconds *int64 to PodSpecPatch with // +kubebuilder:validation:Minimum=0 marker
  • Regenerate zz_generated.deepcopy.go, zz_generated.openapi.go, podspecpatch.go applyconfiguration, Python client model, and CRD
  • Add TerminationGracePeriodSeconds helper to JobSetWrapper in test utilities
  • Add integration test verifying propagation to JobSet pods
  • Add webhook tests for valid (300s) and invalid (-1) values

Checklist

  • Docs included if any changes are user facing

Copilot AI review requested due to automatic review settings March 13, 2026 10:55
@github-actions

Copy link
Copy Markdown

🎉 Welcome to the Kubeflow Trainer! 🎉

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-trainer-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! 🙏

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.

Pull request overview

This PR extends the TrainJob RuntimePatches API to allow per-TrainJob overrides of terminationGracePeriodSeconds via PodSpecPatch, enabling longer graceful shutdowns for workloads like PyTorch Elastic that need time to checkpoint on SIGTERM.

Changes:

  • Add TerminationGracePeriodSeconds *int64 (Minimum=0) to PodSpecPatch and propagate it through generated Go/OpenAPI/CRD artifacts.
  • Update the Python client model to include terminationGracePeriodSeconds.
  • Add integration + webhook coverage to validate schema enforcement and verify the field propagates into JobSet pod specs.

Reviewed changes

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

Show a summary per file
File Description
pkg/apis/trainer/v1alpha1/trainjob_types.go Adds the new PodSpecPatch field with kubebuilder minimum validation.
manifests/base/crds/trainer.kubeflow.org_trainjobs.yaml Exposes the field in the TrainJob CRD schema (min 0).
pkg/client/applyconfiguration/trainer/v1alpha1/podspecpatch.go Extends server-side apply configuration with a WithTerminationGracePeriodSeconds builder.
pkg/apis/trainer/v1alpha1/zz_generated.deepcopy.go Regenerates deepcopy logic to include the new pointer field.
pkg/apis/trainer/v1alpha1/zz_generated.openapi.go Regenerates OpenAPI schema to include the new field.
api/python_api/kubeflow_trainer_api/models/trainer_v1alpha1_pod_spec_patch.py Updates the Python client model to support the new field.
pkg/util/testing/wrapper.go Adds a JobSetWrapper helper to set terminationGracePeriodSeconds in expected JobSet pod specs.
test/integration/webhooks/trainjob_test.go Adds webhook validation tests for valid and invalid (negative) values.
test/integration/controller/trainjob_controller_test.go Adds integration coverage ensuring the patch propagates into the created JobSet pod specs.

@krishdef7 krishdef7 force-pushed the feat/termination-grace-period-patch branch 5 times, most recently from 8a3aa76 to 6095a15 Compare March 14, 2026 05:11

@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 @krishdef7, the API changes look good.
/assign @tenzen-y @astefanutti @efazal @kaisoz

// terminationGracePeriodSeconds patches the termination grace period for Pods
// in the target job templates. This allows users to configure sufficient time
// for checkpoint saving on TrainJob completion or node drain.
// +kubebuilder:validation:Minimum=0

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.

Should it be 1 as min?

@krishdef7 krishdef7 May 19, 2026

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.

Keeping minimum: 0, Kubernetes itself treats 0 as a valid value meaning immediate termination via SIGKILL with no grace period. Setting minimum: 1 would prevent users from disabling the grace period entirely, which is a valid use case (e.g. forcing immediate pod termination on drain).

@google-oss-prow

Copy link
Copy Markdown

@andreyvelich: GitHub didn't allow me to assign the following users: efazal.

Note that only kubeflow members with read permissions, repo collaborators and people who have commented on this issue/PR can be assigned. Additionally, issues/PRs can only have 10 assignees at the same time.
For more information please see the contributor guide

Details

In response to this:

Thanks @krishdef7, the API changes looks good.
/assign @tenzen-y @astefanutti @efazal @kaisoz

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.

// in the target job templates. This allows users to configure sufficient time
// for checkpoint saving on TrainJob completion or node drain.
// +kubebuilder:validation:Minimum=0
// +optional

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.

Should this field be immutable too?

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 immutability via +kubebuilder:validation:XValidation:rule="self == oldSelf" consistent with other PodSpecPatch fields like serviceAccountName. Also added a webhook integration test ("Should fail to update TrainJob terminationGracePeriodSeconds after creation") to verify the update is rejected.

@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 contribution! The implementation looks solid — correct type, appropriate validation, and good test coverage. Review performed with AI tools.

// for checkpoint saving on TrainJob completion or node drain.
// +kubebuilder:validation:Minimum=0
// +optional
TerminationGracePeriodSeconds *int64 `json:"terminationGracePeriodSeconds,omitempty"`

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.

Suggestion: Consider adding terminationGracePeriodSeconds to the existing unit test in pkg/runtime/core/trainingruntime_test.go (the "succeeded to build JobSet with TrainJob's RuntimePatches" test case around line 191) alongside the other PodSpecPatch fields tested there (ServiceAccountName, Tolerations, etc.). This would provide faster regression detection at the unit level without needing the full integration environment.

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.

Done, added TerminationGracePeriodSeconds: ptr.To(int64(300)) to the input patch and TerminationGracePeriodSeconds(constants.Node, 300) to the expected output in the "succeeded to build JobSet with TrainJob's RuntimePatches" test case.

Obj()
},
testingutil.BeInvalidError()),
)

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.

Suggestion: Consider adding a boundary test for ptr.To(int64(0)) with gomega.Succeed(). Zero is a valid value per the CRD (minimum: 0) but has special Kubernetes semantics (immediate termination with no grace period). Testing this boundary documents the intent and guards against accidental Minimum=1 refactors.

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.

Done, added "Should succeed to create TrainJob with zero terminationGracePeriodSeconds" entry with ptr.To(int64(0)) and gomega.Succeed().

description: |-
terminationGracePeriodSeconds patches the termination grace period for Pods
in the target job templates. This allows users to configure sufficient time
for checkpoint saving on TrainJob completion or node drain.

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.

IMO this description should be more generic and follow the convention set by the other PodSpecPatch fields, so there's no need to have a use case example here

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.

@krishdef7 Are you still working on this PR? Or we can find a new contributors to finish it?

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.

Updated, removed the use-case example from the description, now reads: "terminationGracePeriodSeconds patches the termination grace period for Pods in the target job templates."

@kaisoz

kaisoz commented May 19, 2026

Copy link
Copy Markdown
Contributor

would it make sense to delegate PodSpec fields validation to the api server? If I'm not mistaken, this is the JobSet behaviour. Here's) the API server validation for the terminationGracePeriodSeconds field

WDYT @andreyvelich ?

@andreyvelich

Copy link
Copy Markdown
Member

would it make sense to delegate PodSpec fields validation to the api server? If I'm not mistaken, this is the JobSet behaviour. Here's) the API server validation for the terminationGracePeriodSeconds field

WDYT @andreyvelich ?

I think, we have discussion about it here: kubernetes-sigs/jobset#1211 (comment)
As @kannon92 pointed out, we might have scalability concern if we validate PodSpec via API calls.
We can explore kubectl-validation SDK for that, but this is not ideal too.

@krishdef7 krishdef7 force-pushed the feat/termination-grace-period-patch branch 5 times, most recently from 6dc5d79 to 0516d95 Compare May 19, 2026 14:43
Adds terminationGracePeriodSeconds field to PodSpecPatch so users can
configure pod termination grace period per TrainJob via RuntimePatches.

This is needed for distributed training with PyTorch Elastic (torchrun)
where large models (70B+ parameters) require more than the default 30s
to complete JIT checkpointing before SIGKILL on node drain or TrainJob
pause.

No changes to merge logic in trainingruntime.go are required since the
existing StrategicMergePatch applied at batchv1.JobTemplateSpec level
already handles this field automatically.

Closes kubeflow#3285

Signed-off-by: krishdef7 <[email protected]>
@krishdef7 krishdef7 force-pushed the feat/termination-grace-period-patch branch from 0516d95 to 5ab2b1e Compare May 19, 2026 14:53
@krishdef7

Copy link
Copy Markdown
Contributor Author

@kaisoz @andreyvelich @astefanutti @tenzen-y, all comments are addressed, the CRD description is now generic, the immutability XValidation rule is in place, the boundary test for ptr.To(int64(0)) is added, and the unit test in trainingruntime_test.go covers the RuntimePatches path. All CI checks are passing. Could someone issue a /lgtm and /approve when you get a chance?

@kaisoz

kaisoz commented May 20, 2026

Copy link
Copy Markdown
Contributor

/lgtm

All the comments were addressed and I agree on keeping the minimum set to 0 (reason). I'll leave it to @andreyvelich for the final approval

@google-oss-prow google-oss-prow Bot added the lgtm label May 20, 2026

@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 @krishdef7!
/lgtm
/approve
/hold

/assign @astefanutti @akshaychitneni @robert-bell @tenzen-y in case you have any followup questions.

@google-oss-prow

Copy link
Copy Markdown

[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

Copy link
Copy Markdown

@robert-bell: changing LGTM is restricted to collaborators

Details

In response to this:

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.

@andreyvelich

Copy link
Copy Markdown
Member

/hold cancel

@google-oss-prow google-oss-prow Bot merged commit 7c161d0 into kubeflow:master May 26, 2026
30 checks passed
@google-oss-prow google-oss-prow Bot added this to the v2.3 milestone May 26, 2026
@krishdef7 krishdef7 deleted the feat/termination-grace-period-patch branch June 4, 2026 12:42
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.

Add terminationGracePeriodSeconds to PodSpecPatch in TrainJob

7 participants