Change:
pull-kubernetes-e2e-kind-ipv6 Kubernetes e2e suite.[It] [sig-node] Probing container should mark readiness on pods to false and disable liveness probes while pod is in progress of terminating See also, possibly related: Kubernetes e2e suite.[It] [sig-node] Probing container should mark readiness on pods to false while pod is in progress of terminating when a pod has a readiness probe Not sure. At least as of July 27, 2022, but probably earlier than that. No response ! /sig node
This issue is currently awaiting triage. If a SIG or subproject determines this is a relevant issue, they will accept it by applying the label and provide further guidance. The label can be by org members by writing in a comment. <detailsInstructions for interacting with me using PR comments are available . If you have questions or suggestions related to my behavior, please file an issue against the repository. </details
/sig node
/assign we should use listwatch to monitor pod status changes accurately, this interval 2s may lose pod change and cause the test failure
we did the same recently in another test, didn't we? I can't find the PR
sorry, i have not committed yet. do you plan to fix this test again? if so, I can unassign
he, no sorry for the confusion, I thought you were the one that fixed it, maybe it was ? There was one e2e that was flake and was solved using a listwatch instead of polling it every few seconds, I was trying to find the PR to show you , in case it can give you some idea ... please go ahead and fix it :)
this one?
yeah, so my memory was good then, I've identified the right author :smile:
I didn't understand what you said at first, but now I understand :smile:

Discussion:
"strings" "time" <ins> "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/watch" clientset "k8s.io/client-go/kubernetes" "k8s.io/client-go/tools/cache" </ins> v1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/fields" "k8s.io/apimachinery/pkg/util/intstr" "k8s.io/apimachinery/pkg/util/uuid" <del> "k8s.io/apimachinery/pkg/util/wait" </del> podutil "k8s.io/kubernetes/pkg/api/v1/pod" "k8s.io/kubernetes/pkg/kubelet/events" "k8s.io/kubernetes/test/e2e/framework"

// Shutdown pod. Readiness should change to false podClient.Delete(context.Background(), podName, metav1.DeleteOptions{}) <del> err = wait.PollImmediate(framework.Poll, f.Timeouts.PodDelete, func() (bool, error) { pod, err := podClient.Get(context.Background(), podName, metav1.GetOptions{}) if err != nil { return false, err </del> <ins> err = waitForPodStatusByInformer(f.ClientSet, f.Namespace.Name, podName, f.Timeouts.PodDelete, func(pod *v1.Pod) (bool, error) { if !podutil.IsPodReady(pod) { return true, nil </ins> } <del> // verify the pod ready status has reported not ready return !podutil.IsPodReady(pod), nil </del> <ins> framework.Logf("pod %s/%s is still ready, waiting until is not ready", pod.Namespace, pod.Name) return false, nil </ins> }) framework.ExpectNoError(err) })

podClient.Delete(context.Background(), podName, metav1.DeleteOptions{}) // Wait for pod to go unready <del> err = wait.PollImmediate(framework.Poll, f.Timeouts.PodDelete, func() (bool, error) { pod, err := podClient.Get(context.Background(), podName, metav1.GetOptions{}) if err != nil { return false, err </del> <ins> err = waitForPodStatusByInformer(f.ClientSet, f.Namespace.Name, podName, f.Timeouts.PodDelete, func(pod *v1.Pod) (bool, error) { if !podutil.IsPodReady(pod) { return true, nil </ins> } <del> // verify the pod ready status has reported not ready return !podutil.IsPodReady(pod), nil </del> <ins> framework.Logf("pod %s/%s is still ready, waiting until is not ready", pod.Namespace, pod.Name) return false, nil </ins> }) framework.ExpectNoError(err)

}) }) <ins> // waitForPodStatusByInformer waits pod status change by informer func waitForPodStatusByInformer(c clientset.Interface, podNamespace, podName string, timeout time.Duration, condition func(pod *v1.Pod) (bool, error)) error { stopCh := make(chan struct{}) checkPodStatusFunc := func(pod *v1.Pod) { if ok, _ := condition(pod); ok { close(stopCh) } } controller := newInformerWatchPod(c, podNamespace, podName, checkPodStatusFunc) go controller.Run(stopCh) after := time.After(timeout) select { case <-stopCh: return nil case <-after: defer close(stopCh) return fmt.Errorf("timeout to wait pod status ready") } } // newInformerWatchPod creates a informer for given pod func newInformerWatchPod(c clientset.Interface, podNamespace, podName string, checkPodStatusFunc func(p *v1.Pod)) cache.Controller { _, controller := cache.NewInformer( &cache.ListWatch{ ListFunc: func(options metav1.ListOptions) (runtime.Object, error) { options.FieldSelector = fields.SelectorFromSet(fields.Set{"metadata.name": podName}).String() obj, err := c.CoreV1().Pods(podNamespace).List(context.TODO(), options) return runtime.Object(obj), err }, WatchFunc: func(options metav1.ListOptions) (watch.Interface, error) { options.FieldSelector = fields.SelectorFromSet(fields.Set{"metadata.name": podName}).String() return c.CoreV1().Pods(podNamespace).Watch(context.TODO(), options) }, }, &v1.Pod{}, 0, cache.ResourceEventHandlerFuncs{ AddFunc: func(obj interface{}) { p, ok := obj.(*v1.Pod) if ok { checkPodStatusFunc(p) } }, UpdateFunc: func(oldObj, newObj interface{}) { p, ok := newObj.(*v1.Pod) if ok { checkPodStatusFunc(p) } }, DeleteFunc: func(obj interface{}) { p, ok := obj.(*v1.Pod) if ok { checkPodStatusFunc(p) } }, }, ) return controller } </ins> // GetContainerStartedTime returns the time when the given container started and error if any func GetContainerStartedTime(p *v1.Pod, containerName string) (time.Time, error) { for _, status := range p.Status.ContainerStatuses {