Skip to content

Commit cfd949e

Browse files
authored
Merge pull request kubernetes#124942 from AxeZhan/getFinishTimeFromContainers
[Sidecar Containers] Sidecar containers finish time needs to be accounted for in job controller
2 parents c707c43 + d972820 commit cfd949e

File tree

2 files changed

+66
-5
lines changed

2 files changed

+66
-5
lines changed

pkg/controller/job/backoff_utils.go

Lines changed: 28 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,12 @@ import (
2222
"time"
2323

2424
v1 "k8s.io/api/core/v1"
25+
"k8s.io/apimachinery/pkg/util/sets"
26+
utilfeature "k8s.io/apiserver/pkg/util/feature"
2527
"k8s.io/client-go/tools/cache"
2628
"k8s.io/klog/v2"
2729
apipod "k8s.io/kubernetes/pkg/api/v1/pod"
30+
"k8s.io/kubernetes/pkg/features"
2831
"k8s.io/utils/clock"
2932
"k8s.io/utils/ptr"
3033
)
@@ -183,12 +186,32 @@ func getFinishedTime(p *v1.Pod) time.Time {
183186
}
184187

185188
func getFinishTimeFromContainers(p *v1.Pod) *time.Time {
186-
var finishTime *time.Time
187-
for _, containerState := range p.Status.ContainerStatuses {
188-
if containerState.State.Terminated == nil {
189-
return nil
189+
finishTime := latestFinishTime(nil, p.Status.ContainerStatuses, nil)
190+
if utilfeature.DefaultFeatureGate.Enabled(features.SidecarContainers) {
191+
// We need to check InitContainerStatuses here also,
192+
// because with the sidecar (restartable init) containers,
193+
// sidecar containers will always finish later than regular containers.
194+
names := sets.New[string]()
195+
for _, c := range p.Spec.InitContainers {
196+
if c.RestartPolicy != nil && *c.RestartPolicy == v1.ContainerRestartPolicyAlways {
197+
names.Insert(c.Name)
198+
}
199+
}
200+
finishTime = latestFinishTime(finishTime, p.Status.InitContainerStatuses, func(status v1.ContainerStatus) bool {
201+
return names.Has(status.Name)
202+
})
203+
}
204+
return finishTime
205+
}
206+
207+
func latestFinishTime(prevFinishTime *time.Time, cs []v1.ContainerStatus, check func(status v1.ContainerStatus) bool) *time.Time {
208+
var finishTime = prevFinishTime
209+
for _, containerState := range cs {
210+
if check != nil && !check(containerState) {
211+
continue
190212
}
191-
if containerState.State.Terminated.FinishedAt.Time.IsZero() {
213+
if containerState.State.Terminated == nil ||
214+
containerState.State.Terminated.FinishedAt.Time.IsZero() {
192215
return nil
193216
}
194217
if finishTime == nil || finishTime.Before(containerState.State.Terminated.FinishedAt.Time) {

pkg/controller/job/backoff_utils_test.go

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,10 @@ import (
2323
"github.com/google/go-cmp/cmp"
2424
v1 "k8s.io/api/core/v1"
2525
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
26+
utilfeature "k8s.io/apiserver/pkg/util/feature"
27+
featuregatetesting "k8s.io/component-base/featuregate/testing"
2628
"k8s.io/klog/v2/ktesting"
29+
"k8s.io/kubernetes/pkg/features"
2730
clocktesting "k8s.io/utils/clock/testing"
2831
"k8s.io/utils/ptr"
2932
)
@@ -200,8 +203,10 @@ func TestNewBackoffRecord(t *testing.T) {
200203
}
201204

202205
func TestGetFinishedTime(t *testing.T) {
206+
featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.SidecarContainers, true)
203207
defaultTestTime := time.Date(2009, time.November, 10, 23, 0, 0, 0, time.UTC)
204208
defaultTestTimeMinus30s := defaultTestTime.Add(-30 * time.Second)
209+
containerRestartPolicyAlways := v1.ContainerRestartPolicyAlways
205210
testCases := map[string]struct {
206211
pod v1.Pod
207212
wantFinishTime time.Time
@@ -355,6 +360,39 @@ func TestGetFinishedTime(t *testing.T) {
355360
},
356361
wantFinishTime: defaultTestTime,
357362
},
363+
// In this case, init container is stopped after the regular containers.
364+
// This is because with the sidecar (restartable init) containers,
365+
// sidecar containers will always finish later than regular containers.
366+
"Pod with sidecar container and all containers terminated": {
367+
pod: v1.Pod{
368+
Spec: v1.PodSpec{
369+
InitContainers: []v1.Container{
370+
{
371+
Name: "sidecar",
372+
RestartPolicy: &containerRestartPolicyAlways,
373+
},
374+
},
375+
},
376+
Status: v1.PodStatus{
377+
ContainerStatuses: []v1.ContainerStatus{
378+
{
379+
State: v1.ContainerState{
380+
Terminated: &v1.ContainerStateTerminated{FinishedAt: metav1.NewTime(defaultTestTime.Add(-1 * time.Second))},
381+
},
382+
},
383+
},
384+
InitContainerStatuses: []v1.ContainerStatus{
385+
{
386+
Name: "sidecar",
387+
State: v1.ContainerState{
388+
Terminated: &v1.ContainerStateTerminated{FinishedAt: metav1.NewTime(defaultTestTime)},
389+
},
390+
},
391+
},
392+
},
393+
},
394+
wantFinishTime: defaultTestTime,
395+
},
358396
}
359397

360398
for name, tc := range testCases {

0 commit comments

Comments
 (0)