From f9e4a015e223b1076f61accda48583d92aa3ea33 Mon Sep 17 00:00:00 2001 From: Claudiu Belu Date: Tue, 6 Apr 2021 19:08:58 -0700 Subject: [PATCH] tests: Spawn poststart / prestop pods on the same node as the http pod In the case of multinode clusters, the http server pod and the test cluster can spawn on different nodes, which can be problematic for poststart / prestop hooks, as they are executed by the kubelet itself, and the cross-node lifecycle hook might fail (according to the Kubernetes network model, it is not mandatory for kubelet to be able to access pods on a different node). This commit ensures that the test pod spawns on the same node as the http server pod. --- test/conformance/testdata/conformance.yaml | 12 +++++------ test/e2e/common/node/lifecycle_hook.go | 23 +++++++++++++++++++--- 2 files changed, 26 insertions(+), 9 deletions(-) diff --git a/test/conformance/testdata/conformance.yaml b/test/conformance/testdata/conformance.yaml index 982702d0eba1b..83dbc82999983 100755 --- a/test/conformance/testdata/conformance.yaml +++ b/test/conformance/testdata/conformance.yaml @@ -1618,9 +1618,9 @@ hook should execute poststart http hook properly [NodeConformance] [Conformance]' description: When a post start handler is specified in the container lifecycle using a HttpGet action, then the handler MUST be invoked after the start of the container. - A server pod is created that will serve http requests, create a second pod with - a container lifecycle specifying a post start that invokes the server pod to validate - that the post start is executed. + A server pod is created that will serve http requests, create a second pod on + the same node with a container lifecycle specifying a post start that invokes + the server pod to validate that the post start is executed. release: v1.9 file: test/e2e/common/node/lifecycle_hook.go - testname: Pod Lifecycle, prestop exec hook @@ -1638,9 +1638,9 @@ hook should execute prestop http hook properly [NodeConformance] [Conformance]' description: When a pre-stop handler is specified in the container lifecycle using a 'HttpGet' action, then the handler MUST be invoked before the container is terminated. - A server pod is created that will serve http requests, create a second pod with - a container lifecycle specifying a pre-stop that invokes the server pod to validate - that the pre-stop is executed. + A server pod is created that will serve http requests, create a second pod on + the same node with a container lifecycle specifying a pre-stop that invokes the + server pod to validate that the pre-stop is executed. release: v1.9 file: test/e2e/common/node/lifecycle_hook.go - testname: Container Runtime, TerminationMessage, from log output of succeeding container diff --git a/test/e2e/common/node/lifecycle_hook.go b/test/e2e/common/node/lifecycle_hook.go index 9c230dfa44d7e..eab0452cc306d 100644 --- a/test/e2e/common/node/lifecycle_hook.go +++ b/test/e2e/common/node/lifecycle_hook.go @@ -25,6 +25,7 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/util/intstr" "k8s.io/kubernetes/test/e2e/framework" + e2enode "k8s.io/kubernetes/test/e2e/framework/node" e2epod "k8s.io/kubernetes/test/e2e/framework/pod" imageutils "k8s.io/kubernetes/test/utils/image" @@ -41,7 +42,7 @@ var _ = SIGDescribe("Container Lifecycle Hook", func() { preStopWaitTimeout = 30 * time.Second ) ginkgo.Context("when create a pod with lifecycle hook", func() { - var targetIP, targetURL string + var targetIP, targetURL, targetNode string ports := []v1.ContainerPort{ { ContainerPort: 8080, @@ -50,6 +51,13 @@ var _ = SIGDescribe("Container Lifecycle Hook", func() { } podHandleHookRequest := e2epod.NewAgnhostPod("", "pod-handle-http-request", nil, nil, ports, "netexec") ginkgo.BeforeEach(func() { + node, err := e2enode.GetRandomReadySchedulableNode(f.ClientSet) + framework.ExpectNoError(err) + targetNode = node.Name + nodeSelection := e2epod.NodeSelection{} + e2epod.SetAffinity(&nodeSelection, targetNode) + e2epod.SetNodeSelection(&podHandleHookRequest.Spec, nodeSelection) + podClient = f.PodClient() ginkgo.By("create the container to handle the HTTPGet hook request.") newPod := podClient.CreateSync(podHandleHookRequest) @@ -93,6 +101,7 @@ var _ = SIGDescribe("Container Lifecycle Hook", func() { }, } podWithHook := getPodWithHook("pod-with-poststart-exec-hook", imageutils.GetE2EImage(imageutils.Agnhost), lifecycle) + testPodWithHook(podWithHook) }) /* @@ -114,7 +123,7 @@ var _ = SIGDescribe("Container Lifecycle Hook", func() { /* Release: v1.9 Testname: Pod Lifecycle, post start http hook - Description: When a post start handler is specified in the container lifecycle using a HttpGet action, then the handler MUST be invoked after the start of the container. A server pod is created that will serve http requests, create a second pod with a container lifecycle specifying a post start that invokes the server pod to validate that the post start is executed. + Description: When a post start handler is specified in the container lifecycle using a HttpGet action, then the handler MUST be invoked after the start of the container. A server pod is created that will serve http requests, create a second pod on the same node with a container lifecycle specifying a post start that invokes the server pod to validate that the post start is executed. */ framework.ConformanceIt("should execute poststart http hook properly [NodeConformance]", func() { lifecycle := &v1.Lifecycle{ @@ -127,12 +136,16 @@ var _ = SIGDescribe("Container Lifecycle Hook", func() { }, } podWithHook := getPodWithHook("pod-with-poststart-http-hook", imageutils.GetPauseImageName(), lifecycle) + // make sure we spawn the test pod on the same node as the webserver. + nodeSelection := e2epod.NodeSelection{} + e2epod.SetAffinity(&nodeSelection, targetNode) + e2epod.SetNodeSelection(&podWithHook.Spec, nodeSelection) testPodWithHook(podWithHook) }) /* Release: v1.9 Testname: Pod Lifecycle, prestop http hook - Description: When a pre-stop handler is specified in the container lifecycle using a 'HttpGet' action, then the handler MUST be invoked before the container is terminated. A server pod is created that will serve http requests, create a second pod with a container lifecycle specifying a pre-stop that invokes the server pod to validate that the pre-stop is executed. + Description: When a pre-stop handler is specified in the container lifecycle using a 'HttpGet' action, then the handler MUST be invoked before the container is terminated. A server pod is created that will serve http requests, create a second pod on the same node with a container lifecycle specifying a pre-stop that invokes the server pod to validate that the pre-stop is executed. */ framework.ConformanceIt("should execute prestop http hook properly [NodeConformance]", func() { lifecycle := &v1.Lifecycle{ @@ -145,6 +158,10 @@ var _ = SIGDescribe("Container Lifecycle Hook", func() { }, } podWithHook := getPodWithHook("pod-with-prestop-http-hook", imageutils.GetPauseImageName(), lifecycle) + // make sure we spawn the test pod on the same node as the webserver. + nodeSelection := e2epod.NodeSelection{} + e2epod.SetAffinity(&nodeSelection, targetNode) + e2epod.SetNodeSelection(&podWithHook.Spec, nodeSelection) testPodWithHook(podWithHook) }) })