Skip to content

Commit 51883d5

Browse files
committed
sidecar containers restart on definition change
1 parent e9f0ea6 commit 51883d5

File tree

3 files changed

+1382
-71
lines changed

3 files changed

+1382
-71
lines changed

pkg/kubelet/kuberuntime/kuberuntime_container.go

Lines changed: 35 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1082,6 +1082,9 @@ func (m *kubeGenericRuntimeManager) computeInitContainerActions(pod *v1.Pod, pod
10821082
continue
10831083
}
10841084

1085+
message := fmt.Sprintf("Init container %s", container.Name)
1086+
var reason containerKillReason
1087+
restartContainer := false
10851088
switch status.State {
10861089
case kubecontainer.ContainerStateCreated:
10871090
// The main sync loop should have created and started the container
@@ -1107,13 +1110,9 @@ func (m *kubeGenericRuntimeManager) computeInitContainerActions(pod *v1.Pod, pod
11071110
if startup == proberesults.Failure {
11081111
// If the restartable init container failed the startup probe,
11091112
// restart it.
1110-
changes.ContainersToKill[status.ID] = containerToKillInfo{
1111-
name: container.Name,
1112-
container: container,
1113-
message: fmt.Sprintf("Init container %s failed startup probe", container.Name),
1114-
reason: reasonStartupProbe,
1115-
}
1116-
changes.InitContainersToStart = append(changes.InitContainersToStart, i)
1113+
message = fmt.Sprintf("%s failed startup probe, will be restarted", message)
1114+
reason = reasonStartupProbe
1115+
restartContainer = true
11171116
}
11181117
break
11191118
}
@@ -1127,6 +1126,13 @@ func (m *kubeGenericRuntimeManager) computeInitContainerActions(pod *v1.Pod, pod
11271126
changes.InitContainersToStart = append(changes.InitContainersToStart, i+1)
11281127
}
11291128

1129+
// Restart running sidecar containers which have had their definition changed.
1130+
if _, _, changed := containerChanged(container, status); changed {
1131+
message = fmt.Sprintf("%s definition changed, will be restarted", message)
1132+
restartContainer = true
1133+
break
1134+
}
1135+
11301136
// A restartable init container does not have to take into account its
11311137
// liveness probe when it determines to start the next init container.
11321138
if container.LivenessProbe != nil {
@@ -1138,15 +1144,13 @@ func (m *kubeGenericRuntimeManager) computeInitContainerActions(pod *v1.Pod, pod
11381144
if liveness == proberesults.Failure {
11391145
// If the restartable init container failed the liveness probe,
11401146
// restart it.
1141-
changes.ContainersToKill[status.ID] = containerToKillInfo{
1142-
name: container.Name,
1143-
container: container,
1144-
message: fmt.Sprintf("Init container %s failed liveness probe", container.Name),
1145-
reason: reasonLivenessProbe,
1146-
}
1147-
changes.InitContainersToStart = append(changes.InitContainersToStart, i)
1147+
message = fmt.Sprintf("%s failed liveness probe, will be restarted", message)
1148+
reason = reasonLivenessProbe
1149+
restartContainer = true
1150+
break
11481151
}
11491152
}
1153+
11501154
} else { // init container
11511155
// nothing do to but wait for it to finish
11521156
break
@@ -1180,14 +1184,9 @@ func (m *kubeGenericRuntimeManager) computeInitContainerActions(pod *v1.Pod, pod
11801184
default: // kubecontainer.ContainerStatusUnknown or other unknown states
11811185
if types.IsRestartableInitContainer(container) {
11821186
// If the restartable init container is in unknown state, restart it.
1183-
changes.ContainersToKill[status.ID] = containerToKillInfo{
1184-
name: container.Name,
1185-
container: container,
1186-
message: fmt.Sprintf("Init container is in %q state, try killing it before restart",
1187-
status.State),
1188-
reason: reasonUnknown,
1189-
}
1190-
changes.InitContainersToStart = append(changes.InitContainersToStart, i)
1187+
message = fmt.Sprintf("%s is in %q state, try killing it before restart", message, status.State)
1188+
reason = reasonUnknown
1189+
restartContainer = true
11911190
} else { // init container
11921191
if !isInitContainerFailed(status) {
11931192
klog.V(4).InfoS("This should not happen, init container is in unknown state but not failed", "pod", klog.KObj(pod), "containerStatus", status)
@@ -1200,17 +1199,23 @@ func (m *kubeGenericRuntimeManager) computeInitContainerActions(pod *v1.Pod, pod
12001199
}
12011200

12021201
// If the init container is in unknown state, restart it.
1203-
changes.ContainersToKill[status.ID] = containerToKillInfo{
1204-
name: container.Name,
1205-
container: container,
1206-
message: fmt.Sprintf("Init container is in %q state, try killing it before restart",
1207-
status.State),
1208-
reason: reasonUnknown,
1209-
}
1210-
changes.InitContainersToStart = append(changes.InitContainersToStart, i)
1202+
message = fmt.Sprintf("%s is in %q state, try killing it before restart", message, status.State)
1203+
reason = reasonUnknown
1204+
restartContainer = true
12111205
}
12121206
}
12131207

1208+
if restartContainer {
1209+
changes.ContainersToKill[status.ID] = containerToKillInfo{
1210+
name: container.Name,
1211+
container: container,
1212+
message: message,
1213+
reason: reason,
1214+
}
1215+
changes.InitContainersToStart = append(changes.InitContainersToStart, i)
1216+
klog.V(4).InfoS("Message for Init Container of pod", "containerName", container.Name, "containerStatusID", status.ID, "pod", klog.KObj(pod), "containerMessage", message)
1217+
}
1218+
12141219
if !isPreviouslyInitialized {
12151220
// the one before this init container has been initialized
12161221
isPreviouslyInitialized = true

pkg/kubelet/kuberuntime/kuberuntime_manager_test.go

Lines changed: 29 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1221,6 +1221,19 @@ func getKillMapWithInitContainers(pod *v1.Pod, status *kubecontainer.PodStatus,
12211221
return m
12221222
}
12231223

1224+
func modifyKillMapContainerImage(containersToKill map[kubecontainer.ContainerID]containerToKillInfo, status *kubecontainer.PodStatus, cIndexes []int, imageNames []string) map[kubecontainer.ContainerID]containerToKillInfo {
1225+
for idx, i := range cIndexes {
1226+
containerKillInfo := containersToKill[status.ContainerStatuses[i].ID]
1227+
updatedContainer := containerKillInfo.container.DeepCopy()
1228+
updatedContainer.Image = imageNames[idx]
1229+
containersToKill[status.ContainerStatuses[i].ID] = containerToKillInfo{
1230+
container: updatedContainer,
1231+
name: containerKillInfo.name,
1232+
}
1233+
}
1234+
return containersToKill
1235+
}
1236+
12241237
func verifyActions(t *testing.T, expected, actual *podActions, desc string) {
12251238
if actual.ContainersToKill != nil {
12261239
// Clear the message and reason fields since we don't need to verify them.
@@ -1507,12 +1520,12 @@ func makeBasePodAndStatusWithInitContainers() (*v1.Pod, *kubecontainer.PodStatus
15071520
{
15081521
ID: kubecontainer.ContainerID{ID: "initid2"},
15091522
Name: "init2", State: kubecontainer.ContainerStateExited,
1510-
Hash: kubecontainer.HashContainer(&pod.Spec.InitContainers[0]),
1523+
Hash: kubecontainer.HashContainer(&pod.Spec.InitContainers[1]),
15111524
},
15121525
{
15131526
ID: kubecontainer.ContainerID{ID: "initid3"},
15141527
Name: "init3", State: kubecontainer.ContainerStateExited,
1515-
Hash: kubecontainer.HashContainer(&pod.Spec.InitContainers[0]),
1528+
Hash: kubecontainer.HashContainer(&pod.Spec.InitContainers[2]),
15161529
},
15171530
}
15181531
return pod, status
@@ -1685,6 +1698,18 @@ func TestComputePodActionsWithRestartableInitContainers(t *testing.T) {
16851698
m.startupManager.Remove(status.ContainerStatuses[2].ID)
16861699
},
16871700
},
1701+
"kill and recreate the restartable init container if the container definition changes": {
1702+
mutatePodFn: func(pod *v1.Pod) {
1703+
pod.Spec.RestartPolicy = v1.RestartPolicyAlways
1704+
pod.Spec.InitContainers[2].Image = "foo-image"
1705+
},
1706+
actions: podActions{
1707+
SandboxID: baseStatus.SandboxStatuses[0].Id,
1708+
InitContainersToStart: []int{2},
1709+
ContainersToKill: modifyKillMapContainerImage(getKillMapWithInitContainers(basePod, baseStatus, []int{2}), baseStatus, []int{2}, []string{"foo-image"}),
1710+
ContainersToStart: []int{0, 1, 2},
1711+
},
1712+
},
16881713
"restart terminated restartable init container and next init container": {
16891714
mutatePodFn: func(pod *v1.Pod) { pod.Spec.RestartPolicy = v1.RestartPolicyAlways },
16901715
mutateStatusFn: func(pod *v1.Pod, status *kubecontainer.PodStatus) {
@@ -1911,12 +1936,12 @@ func makeBasePodAndStatusWithRestartableInitContainers() (*v1.Pod, *kubecontaine
19111936
{
19121937
ID: kubecontainer.ContainerID{ID: "initid2"},
19131938
Name: "restartable-init-2", State: kubecontainer.ContainerStateRunning,
1914-
Hash: kubecontainer.HashContainer(&pod.Spec.InitContainers[0]),
1939+
Hash: kubecontainer.HashContainer(&pod.Spec.InitContainers[1]),
19151940
},
19161941
{
19171942
ID: kubecontainer.ContainerID{ID: "initid3"},
19181943
Name: "restartable-init-3", State: kubecontainer.ContainerStateRunning,
1919-
Hash: kubecontainer.HashContainer(&pod.Spec.InitContainers[0]),
1944+
Hash: kubecontainer.HashContainer(&pod.Spec.InitContainers[2]),
19201945
},
19211946
}
19221947
return pod, status

0 commit comments

Comments
 (0)