diff --git a/pkg/controller/job/backoff_utils.go b/pkg/controller/job/backoff_utils.go index fd03dfe4670..ea388562e72 100644 --- a/pkg/controller/job/backoff_utils.go +++ b/pkg/controller/job/backoff_utils.go @@ -22,6 +22,7 @@ import ( "time" v1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/util/sets" "k8s.io/client-go/tools/cache" "k8s.io/klog/v2" apipod "k8s.io/kubernetes/pkg/api/v1/pod" @@ -183,16 +184,27 @@ func getFinishedTime(p *v1.Pod) time.Time { } func getFinishTimeFromContainers(p *v1.Pod) *time.Time { - finishTime := latestFinishTime(nil, p.Status.ContainerStatuses) + finishTime := latestFinishTime(nil, p.Status.ContainerStatuses, nil) // We need to check InitContainerStatuses here also, // because with the sidecar (restartable init) containers, // sidecar containers will always finish later than regular containers. - return latestFinishTime(finishTime, p.Status.InitContainerStatuses) + names := sets.New[string]() + for _, c := range p.Spec.InitContainers { + if c.RestartPolicy != nil && *c.RestartPolicy == v1.ContainerRestartPolicyAlways { + names.Insert(c.Name) + } + } + return latestFinishTime(finishTime, p.Status.InitContainerStatuses, func(status v1.ContainerStatus) bool { + return names.Has(status.Name) + }) } -func latestFinishTime(prevFinishTime *time.Time, cs []v1.ContainerStatus) *time.Time { +func latestFinishTime(prevFinishTime *time.Time, cs []v1.ContainerStatus, check func(status v1.ContainerStatus) bool) *time.Time { var finishTime = prevFinishTime for _, containerState := range cs { + if check != nil && !check(containerState) { + continue + } if containerState.State.Terminated == nil || containerState.State.Terminated.FinishedAt.Time.IsZero() { return nil diff --git a/pkg/controller/job/backoff_utils_test.go b/pkg/controller/job/backoff_utils_test.go index f402ab681b8..d686e3bc66e 100644 --- a/pkg/controller/job/backoff_utils_test.go +++ b/pkg/controller/job/backoff_utils_test.go @@ -202,6 +202,7 @@ func TestNewBackoffRecord(t *testing.T) { func TestGetFinishedTime(t *testing.T) { defaultTestTime := time.Date(2009, time.November, 10, 23, 0, 0, 0, time.UTC) defaultTestTimeMinus30s := defaultTestTime.Add(-30 * time.Second) + containerRestartPolicyAlways := v1.ContainerRestartPolicyAlways testCases := map[string]struct { pod v1.Pod wantFinishTime time.Time @@ -358,8 +359,16 @@ func TestGetFinishedTime(t *testing.T) { // In this case, init container is stopped after the regular containers. // This is because with the sidecar (restartable init) containers, // sidecar containers will always finish later than regular containers. - "Pod with init container and all containers terminated": { + "Pod with sidecar container and all containers terminated": { pod: v1.Pod{ + Spec: v1.PodSpec{ + InitContainers: []v1.Container{ + { + Name: "sidecar", + RestartPolicy: &containerRestartPolicyAlways, + }, + }, + }, Status: v1.PodStatus{ ContainerStatuses: []v1.ContainerStatus{ { @@ -370,6 +379,7 @@ func TestGetFinishedTime(t *testing.T) { }, InitContainerStatuses: []v1.ContainerStatus{ { + Name: "sidecar", State: v1.ContainerState{ Terminated: &v1.ContainerStateTerminated{FinishedAt: metav1.NewTime(defaultTestTime)}, },