From 7782a900f4b71a490a948c1d730a0853428c130e Mon Sep 17 00:00:00 2001 From: Yu-Ju Hong Date: Wed, 26 Jun 2019 18:19:27 -0700 Subject: [PATCH] kubelet: retry pod sandbox creation when containers were never created If kubelet never gets past sandbox creation (i.e., never attempted to create containers for a pod), it should retry the sandbox creation on failure, regardless of the restart policy of the pod. --- .../kuberuntime/kuberuntime_manager.go | 6 ++- .../kuberuntime/kuberuntime_manager_test.go | 50 +++++++++++++++++++ 2 files changed, 55 insertions(+), 1 deletion(-) diff --git a/pkg/kubelet/kuberuntime/kuberuntime_manager.go b/pkg/kubelet/kuberuntime/kuberuntime_manager.go index b6313fb8bd..4676a3548a 100644 --- a/pkg/kubelet/kuberuntime/kuberuntime_manager.go +++ b/pkg/kubelet/kuberuntime/kuberuntime_manager.go @@ -477,11 +477,15 @@ func (m *kubeGenericRuntimeManager) computePodActions(pod *v1.Pod, podStatus *ku // If we need to (re-)create the pod sandbox, everything will need to be // killed and recreated, and init containers should be purged. if createPodSandbox { - if !shouldRestartOnFailure(pod) && attempt != 0 { + if !shouldRestartOnFailure(pod) && attempt != 0 && len(podStatus.ContainerStatuses) != 0 { // Should not restart the pod, just return. // we should not create a sandbox for a pod if it is already done. // if all containers are done and should not be started, there is no need to create a new sandbox. // this stops confusing logs on pods whose containers all have exit codes, but we recreate a sandbox before terminating it. + // + // If ContainerStatuses is empty, we assume that we've never + // successfully created any containers. In this case, we should + // retry creating the sandbox. changes.CreateSandbox = false return changes } diff --git a/pkg/kubelet/kuberuntime/kuberuntime_manager_test.go b/pkg/kubelet/kuberuntime/kuberuntime_manager_test.go index 8de68a7e4b..5102cec441 100644 --- a/pkg/kubelet/kuberuntime/kuberuntime_manager_test.go +++ b/pkg/kubelet/kuberuntime/kuberuntime_manager_test.go @@ -852,6 +852,26 @@ func TestComputePodActions(t *testing.T) { ContainersToKill: map[kubecontainer.ContainerID]containerToKillInfo{}, }, }, + "Verify we create a pod sandbox if no ready sandbox for pod with RestartPolicy=Never and no containers have ever been created": { + mutatePodFn: func(pod *v1.Pod) { + pod.Spec.RestartPolicy = v1.RestartPolicyNever + }, + mutateStatusFn: func(status *kubecontainer.PodStatus) { + // no ready sandbox + status.SandboxStatuses[0].State = runtimeapi.PodSandboxState_SANDBOX_NOTREADY + status.SandboxStatuses[0].Metadata.Attempt = uint32(2) + // no visible containers + status.ContainerStatuses = []*kubecontainer.ContainerStatus{} + }, + actions: podActions{ + SandboxID: baseStatus.SandboxStatuses[0].Id, + Attempt: uint32(3), + CreateSandbox: true, + KillPod: true, + ContainersToStart: []int{0, 1, 2}, + ContainersToKill: map[kubecontainer.ContainerID]containerToKillInfo{}, + }, + }, "Kill and recreate the container if the container is in unknown state": { mutatePodFn: func(pod *v1.Pod) { pod.Spec.RestartPolicy = v1.RestartPolicyNever }, mutateStatusFn: func(status *kubecontainer.PodStatus) { @@ -1028,6 +1048,36 @@ func TestComputePodActionsWithInitContainers(t *testing.T) { ContainersToKill: getKillMapWithInitContainers(basePod, baseStatus, []int{}), }, }, + "Pod sandbox not ready, init container failed, but RestartPolicy == Never; kill pod only": { + mutatePodFn: func(pod *v1.Pod) { pod.Spec.RestartPolicy = v1.RestartPolicyNever }, + mutateStatusFn: func(status *kubecontainer.PodStatus) { + status.SandboxStatuses[0].State = runtimeapi.PodSandboxState_SANDBOX_NOTREADY + }, + actions: podActions{ + KillPod: true, + CreateSandbox: false, + SandboxID: baseStatus.SandboxStatuses[0].Id, + Attempt: uint32(1), + ContainersToStart: []int{}, + ContainersToKill: getKillMapWithInitContainers(basePod, baseStatus, []int{}), + }, + }, + "Pod sandbox not ready, and RestartPolicy == Never, but no visible init containers; create a new pod sandbox": { + mutatePodFn: func(pod *v1.Pod) { pod.Spec.RestartPolicy = v1.RestartPolicyNever }, + mutateStatusFn: func(status *kubecontainer.PodStatus) { + status.SandboxStatuses[0].State = runtimeapi.PodSandboxState_SANDBOX_NOTREADY + status.ContainerStatuses = []*kubecontainer.ContainerStatus{} + }, + actions: podActions{ + KillPod: true, + CreateSandbox: true, + SandboxID: baseStatus.SandboxStatuses[0].Id, + Attempt: uint32(1), + NextInitContainerToStart: &basePod.Spec.InitContainers[0], + ContainersToStart: []int{}, + ContainersToKill: getKillMapWithInitContainers(basePod, baseStatus, []int{}), + }, + }, } { pod, status := makeBasePodAndStatusWithInitContainers() if test.mutatePodFn != nil {