-
Notifications
You must be signed in to change notification settings - Fork 696
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
KEP-2170: Add the TrainJob state transition design #2298
base: master
Are you sure you want to change the base?
Conversation
[APPROVALNOTIFIER] This PR is NOT APPROVED This pull-request has been approved by: The full list of commands accepted by this bot can be found here.
Needs approval from an approver in each of these files:
Approvers can indicate their approval by writing |
/hold |
Pull Request Test Coverage Report for Build 11430149305Details
💛 - Coveralls |
851738c
to
069345f
Compare
069345f
to
39bfab2
Compare
Signed-off-by: Yuki Iwai <yuki.iwai.tz@gmail.com>
39bfab2
to
8ba2206
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you for this @tenzen-y!
Please take a look @kubeflow/wg-training-leads @kannon92 @akshaychitneni @varshaprasad96 @ahg-g @vsoch @danielvegamyhre
// TrainJobSuspended means the TrainJob is suspended. | ||
TrainJobSuspended string = "Suspended" | ||
|
||
// TrainJobCompleted means that the actual jobs have completed its execution. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should it be TrainJob, and similar for other statuses ?
// TrainJobCompleted means that the actual jobs have completed its execution. | |
// TrainJobCompleted means that the TrainJob has completed its execution. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
@@ -279,6 +279,43 @@ type TrainJob struct { | |||
Status TrainJobStatus `json:"status,omitempty"` | |||
} | |||
|
|||
const ( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we define those consts as TrainJobConditionType
similar to Batch/Job: https://github.com/kubernetes/api/blob/master/batch/v1/types.go#L617 ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think so since our conditions typed are metav1.Condition
and the Type
is typed string.
The batch/v1 Job uses the typed JobConditionType
since Job conditions typed are dedicated JobCondition
: https://github.com/kubernetes/api/blob/2be23f6c5a7184af9846ff458a11751765ea2bde/batch/v1/types.go#L662
When we use the dedicated typed TrainJobConditionType
, we need to cast the TrainJobConditionType
to string everywhere. That is not ideal.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh, you are right.
|
||
// TrainJobResumedReason is the "Suspended" condition reason. | ||
// When the TrainJob suspension is changed from True to False, this is added. | ||
TrainJobResumedReason string = "Resumed" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, we have. In the batch/v1 Job level, JobResumed
is used as a reason for the Suspended
condition type.
In the JobSet level, ResumeJobs
is used as a reason for the Suspended
condition type.
// TrainJobJobsCreationSucceededReason is the "Created" condition reason. | ||
// When the creating objects succeeded after building succeeded, this is added. | ||
TrainJobJobsCreationSucceededReason string = "JobsCreationSucceeded" | ||
|
||
// TrainJobJobsBuildFailedReason is the "Created" condition reason. | ||
// When the building objects based on the TrainJob and the specified runtime failed, | ||
// this is added. | ||
TrainJobJobsBuildFailedReason string = "JobsBuildFailed" | ||
|
||
// TrainJobJobsCreationFailedReason is "Created" condition reason. | ||
// When the creating objects failed even though building succeeded, this is added. | ||
TrainJobJobsCreationFailedReason string = "JobsCreationFailed" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we introduce those conditions in the 2nd iteration ?
I think, we should discuss if users really want to decouple conditions when TrainJob's object creation failed and when TrainJob fails.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These are reasons, so we use these in the following. Additionally, if we do not distinguish JobCreationFailed
and JobBuildFailed
, it is hard to understand which part failed. So, these reasons must be included in the first phase.
- JobsBuildFailed:
objs, err := run.NewObjects(ctx, trainJob) - JobsCreationFailed:
return creationErr
status:
conditions:
- type: Created
status: false
reason: JobsCreationFailed
status:
conditions:
- type: Created
status: false
reason: JobsBuildFailed
status:
conditions:
- type: Created
status: true
reason: JobsCreationSucceeded
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since we have validation webhook, what is the use-case you see when we can hit the JobsBuildFailed reason ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We can not validate in advance if NewObject succeed since we can not know in advance what happens during the NewObject.
Only during reconciling, we can know the actual error.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So, I guess one of the examples could be if NewObject calls Kubernetes API server and this call fails.
In that case, we want to transition TrainJob to JobsBuildFailed status.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In that case, we want to transition TrainJob to JobsBuildFailed status.
Yes, that's right. In the current JobSet plugin, the building error could happen in the following:
return nil, err return nil, err
Additionally, every plugin could return errors during Kubeflow Job Pipeline Framerowk.
- type: JobSetSuspended | ||
status: false | ||
- type: JobSetCompleted | ||
status: true |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why do we need to propagate JobSet conditions to the TrainJob ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I propagated these JobSet conditions so that runtimes can be propagated to the arbitrary conditions.
But, in the JobSet case, these seem to be slightly redundant. So, I'm wondering if we only extend the runtime interface so that the plugin can propagate arbitrary conditions, but JobSet plugin does not propagate own conditions, then TrainJob does not have the JobSet conditions.
But, I guess that the JobSet StartupPolocy conditions could help to understand what happens in the actual Jobs.
So, we can propagate only StartupPolicyInProgress
and StartupPolicyCompleted
.
@andreyvelich WDYT?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So, I'm wondering if we only extend the runtime interface so that the plugin can propagate arbitrary conditions, but JobSet plugin does not propagate own conditions, then TrainJob does not have the JobSet conditions.
I would suggest that we add those once we have initial implementation of TrainJob status.
I think, this is valid option, but we should discuss what conditions be be propagated by runtime plugins.
Any thoughts @tenzen-y ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would suggest that we add those once we have initial implementation of TrainJob status.
I think, this is valid option, but we should discuss what conditions be be propagated by runtime plugins.
I think that we need to implement the conditions propagation mechanism, but it's not clear in the JobSet situation. Especially, which conditions should be propagated to the TrainJob. So, I would propose that we extend the runtime interface so that plugins can propagate the conditions to TrainJob. But, in the first status implementation, we do not propagate any JobSet conditions to the TrainJob.
What do you think? @andreyvelich
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So, I would propose that we extend the runtime interface so that plugins can propagate the conditions to TrainJob.
Sure, we can have this. Maybe we should create a tracking issue to implement it ?
I don't think is has a high priority compare to other tasks.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, sure. I will open the issue.
But, let me mention the propagation mechanism in this KEP.
[...] | ||
status: | ||
conditions: | ||
- type: Created |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would it be helpful to add transition time and also reason for failure within conditions? I believe it would be help debugging failures
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is pseudo conditions. So, we actually support all fields supported in metav1.Conditions including transition time as you can see there:
training-operator/pkg/apis/kubeflow.org/v2alpha1/trainjob_types.go
Lines 261 to 262 in 66ebecd
// Conditions for the TrainJob. | |
Conditions []metav1.Condition `json:"conditions,omitempty"` |
What this PR does / why we need it:
I added the TrainJob state machine design.
Which issue(s) this PR fixes (optional, in
Fixes #<issue number>, #<issue number>, ...
format, will close the issue(s) when PR gets merged):Part-of #2207
Relates to: #2170
Checklist: