kubernetes: activeDeadlineSeconds not working correctly for Jobs in 1.24.0
What happened?
Prior to 1.24.0 setting spec.adctiveDeadlineSeconds
in a Job object (batch/v1
) would kill the Job and Pods if they ran longer than the integer specified. I tested today with 1.24.0 and it’s not working. The Job defined below (for testing) should be killed 10 seconds, but isn’t. It’s actually being terminated after about 55 seconds.
apiVersion: batch/v1
kind: Job
metadata:
name: test
spec:
activeDeadlineSeconds: 10
ttlSecondsAfterFinished: 120
completions: 5
parallelism: 1
backoffLimit: 4
template:
spec:
restartPolicy: Never
containers:
- name: ctr
image: alpine:latest
command: ['sh', '-c', 'echo "TEST" && sleep 60']
What did you expect to happen?
The Job to be killed after 10 seconds as per activeDeadlineSeconds: 10
. It’s worked like this in 1.23.x.
How can we reproduce it (as minimally and precisely as possible)?
On a cluster running 1.24.0 with the following YAML file called job.yml
.
job.yml
apiVersion: batch/v1
kind: Job
metadata:
name: test
spec:
activeDeadlineSeconds: 10
ttlSecondsAfterFinished: 120
completions: 5
parallelism: 1
backoffLimit: 4
template:
spec:
restartPolicy: Never
containers:
- name: ctr
image: alpine:latest
command: ['sh', '-c', 'echo "TEST" && sleep 60']
Create the Job.
kubectl apply -f job.yml
On Kubernetes clusters earlier than 1.24.0 it would fail after 10 seconds and the following command should show Warning DeadlineExceeded Xs job-controller Job was active longer than specified deadline
in the events 10 seconds after the Pod is created.
kubectl describe job test
<SNIP>
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal SuccessfulCreate 16s job-controller Created pod: ckad1-kk6jt
Normal SuccessfulDelete 6s job-controller Deleted pod: ckad1-kk6jt
Warning DeadlineExceeded 6s job-controller Job was active longer than specified deadline
In K8s 1.24.0 it’s terminated after about a minute instead of 10 seconds. It works as expected in 1.23.6 and other point versions of 1.23.
Anything else we need to know?
It works as expected, and documented, in all versions of 1.23 I’ve tested on.
Docs: https://kubernetes.io/docs/concepts/workloads/controllers/job/#job-termination-and-cleanup
Kubernetes version
$ kubectl version
Client Version: version.Info{Major:"1", Minor:"24", GitVersion:"v1.24.0", GitCommit:"4ce5a8954017644c5420bae81d72b09b735c21f0", GitTreeState:"clean", BuildDate:"2022-05-03T13:46:05Z", GoVersion:"go1.18.1", Compiler:"gc", Platform:"darwin/arm64"}
Kustomize Version: v4.5.4
Server Version: version.Info{Major:"1", Minor:"24", GitVersion:"v1.24.0", GitCommit:"4ce5a8954017644c5420bae81d72b09b735c21f0", GitTreeState:"clean", BuildDate:"2022-05-03T13:38:19Z", GoVersion:"go1.18.1", Compiler:"gc", Platform:"linux/arm64"}
Cloud provider
OS version
Install tools
Container runtime (CRI) and version (if applicable)
Related plugins (CNI, CSI, …) and versions (if applicable)
About this issue
- Original URL
- State: closed
- Created 2 years ago
- Comments: 16 (11 by maintainers)
I think I have figured out why this happened. It is a side effect of
JobReadyPods
feature gate (thanks @harshanarayana ).background: when we call
queue.AddAfter(key, duration)
withduration > 0
multiple times, the workqueue will only keep the duration that will be triggered nearest from now.previously (when there is no
JobReadyPods
feature gate or do not enable it): job-controller mainly relies on the first time sync to add the job after itsActiveDeadlineSeconds
:https://github.com/kubernetes/kubernetes/blob/92263ee0dd2588978dd2d99a952a1d463e3a88a3/pkg/controller/job/job_controller.go#L751-L760
(unless the
ActiveDeadlineSeconds
field has been changed then it will be add after here).JobReadyPods
feature gate makesjm.podUpdateBatchPeriod
to be1s
and it will be add after for the job when a pod of it has been updated. Then theActiveDeadlineSeconds
duration which has been added after in the first time sync will be overwrite to1s
. And after the next syncJob, there will be no one to addAfter the job again.https://github.com/kubernetes/kubernetes/blob/92263ee0dd2588978dd2d99a952a1d463e3a88a3/pkg/controller/job/job_controller.go#L482-L506
WDYT @harshanarayana @liggitt @alculquicondor
just add it back to the queue every time there is a job sync. It’s a noop if the item is already there.
@harshanarayana Emm… Usually it is not suggested to have multiple active queues in one controller, which will cause an object to be handled by multiple workers at the same time and also make the progress more complicated.
My suggestion is do
queue.AddAfter
at the end of syncJob every time an unfinished job is reconciled, the duration should beActiveDeadlineSeconds - time.Since(job.Status.StartTime)
. This is clear for everyone to understand, brings less change and no extra burden on the controller.The job controller for sure has the code for cleanup on active deadline still in place https://github.com/kubernetes/kubernetes/blob/f3264dd0b33ba4450c453436e3ebd5a287712a1a/pkg/controller/job/job_controller.go#L762-L799
+1 from me as well. The behavior for sure is not the same on 1.23.x vs 1.24.0 using the same job manifest. And the documentation v/s the behavior is not the same.