Change:
framework.Failf("%d errors:n%v", len(errs), strings.Join(messages, "n")) } }) <ins> }) framework.KubeDescribe("Pod Container lifecycle", func() { var podClient *framework.PodClient ginkgo.BeforeEach(func() { podClient = f.PodClient() }) ginkgo.It("should not create extra sandbox if all containers are done", func() { ginkgo.By("creating the pod that should always exit 0") name := "pod-always-succeed" + string(uuid.NewUUID()) image := imageutils.GetE2EImage(imageutils.BusyBox) pod := &v1.Pod{ ObjectMeta: metav1.ObjectMeta{ Name: name, }, Spec: v1.PodSpec{ RestartPolicy: v1.RestartPolicyOnFailure, InitContainers: []v1.Container{ { Name:  "foo", Image: image, Command: []string{ "/bin/true", }, }, }, Containers: []v1.Container{ { Name:  "bar", Image: image, Command: []string{ "/bin/true", }, }, }, }, } ginkgo.By("submitting the pod to kubernetes") createdPod := podClient.Create(pod) defer func() { ginkgo.By("deleting the pod") podClient.Delete(context.TODO(), pod.Name, metav1.DeleteOptions{}) }() framework.ExpectNoError(e2epod.WaitForPodSuccessInNamespace(f.ClientSet, pod.Name, f.Namespace.Name)) var eventList *v1.EventList var err error ginkgo.By("Getting events about the pod") framework.ExpectNoError(wait.Poll(time.Second*2, time.Second*60, func() (bool, error) { selector := fields.Set{ "involvedObject.kind":      "Pod", "involvedObject.uid":       string(createdPod.UID), "involvedObject.namespace": f.Namespace.Name, "source":                   "kubelet", }.AsSelector().String() options := metav1.ListOptions{FieldSelector: selector} eventList, err = f.ClientSet.CoreV1().Events(f.Namespace.Name).List(context.TODO(), options) if err != nil { return false, err } if len(eventList.Items) > 0 { return true, nil } return false, nil })) ginkgo.By("Checking events about the pod") for _, event := range eventList.Items { if event.Reason == events.SandboxChanged { framework.Fail("Unexpected SandboxChanged event") } } }) </ins> }) })

Discussion:
<!-- Please use this template while reporting a bug and provide as much info as possible. Not doing so may result in your bug not being addressed in a timely manner. Thanks! If the matter is security related, please disclose it privately via --What happened: For a Pod with , kubelet would attempt to create a new sandbox for it even after all container succeeded. Logs as below: This issue is similar to which fixed the case of pods whose RestartPolicy are Never. It caused unnecessary CRI and CNI calls, confusing logs and conflicts between the routine that creates the new sandbox and the routine that kills the Pod. It's likely also the root cause of because sometimes the routine that creates the second sandbox and the routine that kills unwanted pod run concurrently, then the netns would be gone when calling CNI. What you expected to happen: kubelet shouldn't create a new sandbox for pod with RestartPolicyOnFailure if all containers succeeded How to reproduce it (as minimally and precisely as possible): Create a pod like this: Anything else we need to know?: Environment: Kubernetes version (use ): v1.18.2 Cloud provider or hardware configuration: OS (e.g: ): Kernel (e.g. ): Install tools: Network plugin and version (if this is a network-related bug): Others:
/sig node
Created which may fix this.
/assign