-
Notifications
You must be signed in to change notification settings - Fork 5.2k
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
Backoff policy and failed pod limit #583
Changes from 4 commits
4be538d
bd5d3d9
caee494
00def1f
5b6d2ce
f719b7e
f65a602
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -18,6 +18,7 @@ Several existing issues and PRs were already created regarding that particular s | |
1. Be able to get the job status. | ||
1. Be able to specify the number of instances performing a job at any one time. | ||
1. Be able to specify the number of successfully finished instances required to finish a job. | ||
1. Be able to specify a backoff policy, when job is continuously failing. | ||
|
||
|
||
## Motivation | ||
|
@@ -26,6 +27,35 @@ Jobs are needed for executing multi-pod computation to completion; a good exampl | |
here would be the ability to implement any type of batch oriented tasks. | ||
|
||
|
||
## Backoff policy and failed pod limit | ||
|
||
By design, Jobs do not have any notion of failure, other than a pod's `restartPolicy` | ||
which is mistakenly taken as Job's restart policy ([#30243](https://github.com/kubernetes/kubernetes/issues/30243), | ||
[#[43964](https://github.com/kubernetes/kubernetes/issues/43964)]). There are | ||
situation where one wants to fail a Job after some amount of retries over a certain | ||
period of time, due to a logical error in configuration etc. To do so we are going | ||
to introduce following fields, which will control the exponential backoff when | ||
retrying a Job: number of retries and time to retry. The two fields will allow | ||
fine-grained control over the backoff policy, limiting the number of retries over | ||
a specified period of time. If only one of the two fields is supplied, an exponential | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It's not clear what happens if both fields are specified. Is only the number of retries limited or both of the fields limit each other? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ok, it's clearer after rereading the bullet points below. |
||
backoff with an intervening duration of ten seconds and a factor of two will be | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't think we should promise our users exponential backoff -- we should give ourselves the freedom to do other things in the future. Just say that we will retry at a time that the system choses, and that in any case the number of retries won't exceed the number specified by the user. |
||
applied, such that either: | ||
* the number of retries will not exceed a specified count, if present, or | ||
* the maximum time elapsed will not exceed the specified duration, if present. | ||
|
||
Additionally, to help debug the issue with a Job, and limit the impact of having | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why not also limit the number of successful pods which may takes a lot of resource either ? |
||
too many failed pods left around (as mentioned in [#30243](https://github.com/kubernetes/kubernetes/issues/30243)), | ||
we are going to introduce a field which will allow specifying the maximum number | ||
of failed pods to keep around. This number will also take effect if none of the | ||
limits described above are set. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is the intent that users will typically set this to 0 unless they expect to need to debug? Or do we typically want to keep around at least 1 failed pod so the user can get the logs? not save all pods without There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I vote to have this defaulted to 1 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 1 seems reasonable default. |
||
|
||
All of the above fields will be optional and will apply no matter which `restartPolicy` | ||
is set on a `PodTemplate`. The only difference applies to how failures are counted. | ||
For restart policy `Never` we count actual pod failures (reflected in `.status.failed` | ||
field). With restart policy `OnFailure` we look at pod restarts (calculated from | ||
`.status.containerStatuses[*].restartCount`). | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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 commentThe reason will be displayed to describe this comment to others. Learn more. This cannot be synchronous, though, so the limit has to be approximate. Document that it is precise with Never, and approximate with OnFailure? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yup, makes sense. |
||
|
||
|
||
## Implementation | ||
|
||
Job controller is similar to replication controller in that they manage pods. | ||
|
@@ -79,8 +109,21 @@ type JobSpec struct { | |
// job should be run with. Defaults to 1. | ||
Completions *int | ||
|
||
// Optional duration in seconds relative to the startTime that the job may be active | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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 commentThe reason will be displayed to describe this comment to others. Learn more. Not anymore, the def will have those in place. |
||
// before the system tries to terminate it; value must be a positive integer. | ||
ActiveDeadlineSeconds *int | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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 commentThe reason will be displayed to describe this comment to others. Learn more. We used ints, for consistency and then do appropriate validation so this is non-negative and bigger than 0. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. *int32 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Actually *int64 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can you also update the rest of the fields to their canonical types? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think this is the deadline for the entire job to complete, regardless of whether there are restarts, right? Document that. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Correct. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It clearly states it's relative to job's startTime. |
||
|
||
// Optional number of retries before marking this job failed. | ||
BackoffLimit *int | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why BackoffLimit instead of RetryLimit or TriesLimit? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I went with Backoff as a prefix for every field related to that, since we're talking about Backoff policy. |
||
|
||
// Optional time (in seconds) specifying how long a job should be retried before marking it failed. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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 commentThe reason will be displayed to describe this comment to others. Learn more. We usually require those being >= 0, it'll be checked in validation. |
||
BackoffDeadlineSeconds *int | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ProgressDeadlineSeconds to match the field in Deployments? Seems like it's the same concept although in Deployment we merely add a condition in the DeploymentStatus. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. How would a user typically use ActiveDeadlineSeconds with BackoffDeadlineSeconds? There was a problem hiding this comment. Choose a reason for hiding this commentThe 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 commentThe reason will be displayed to describe this comment to others. Learn more. @Kargakis this is different than There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @erictune @sdminonne ADS is the overall time for a Job (max life-time). Whereas BDS is counted from the moment the first failure happens. But yes, usually BDS will be smaller than ADS, otherwise you'll never hit BDS in case of a failure. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Well, PDS is not that different. We start counting from the last time we saw progress and once the deadline is exceeded we merely switch the Progressing condition to False. "Failing the deployment" should be something that a higher-level orchestrator decides based on the condition. |
||
|
||
// Optional number of failed pods to retain. | ||
FailedPodsLimit *int | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. When are pods left around? I guess when pods have restartPolicy=Never? It feels weird to add a feature that is not related directly to the failurePolicy and also is useful for a specific case in Jobs. Can we leave it out of this proposal? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is for debugging purposes. Leaving pods should allow you to figure out what went wrong. Without it and with restart policy Never you might end up with many failed pods, if you set the limits high. That was one of the original requests wrt to the backoff policy, so I think it's crucial to address it here. |
||
|
||
// Selector is a label query over pods running a job. | ||
Selector map[string]string | ||
Selector LabelSelector | ||
|
||
// Template is the object that describes the pod that will be created when | ||
// executing a job. | ||
|
@@ -109,12 +152,12 @@ type JobStatus struct { | |
// Active is the number of actively running pods. | ||
Active int | ||
|
||
// Successful is the number of pods successfully completed their job. | ||
Successful int | ||
// Succeeded is the number of pods successfully completed their job. | ||
Succeeded int | ||
|
||
// Unsuccessful is the number of pods failures, this applies only to jobs | ||
// Failed is the number of pods failures, this applies only to jobs | ||
// created with RestartPolicyNever, otherwise this value will always be 0. | ||
Unsuccessful int | ||
Failed int | ||
} | ||
|
||
type JobConditionType string | ||
|
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.