diff --git a/test/e2e/common/BUILD b/test/e2e/common/BUILD index be73bd777a2..22f491fc0e1 100644 --- a/test/e2e/common/BUILD +++ b/test/e2e/common/BUILD @@ -48,6 +48,7 @@ go_library( "//pkg/client/clientset_generated/internalclientset:go_default_library", "//pkg/client/conditions:go_default_library", "//pkg/kubelet:go_default_library", + "//pkg/kubelet/events:go_default_library", "//pkg/kubelet/images:go_default_library", "//pkg/kubelet/sysctl:go_default_library", "//pkg/security/apparmor:go_default_library", diff --git a/test/e2e/common/container_probe.go b/test/e2e/common/container_probe.go index 9988a29919e..f4b8f224be1 100644 --- a/test/e2e/common/container_probe.go +++ b/test/e2e/common/container_probe.go @@ -18,13 +18,16 @@ package common import ( "fmt" + "net/url" "time" 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" podutil "k8s.io/kubernetes/pkg/api/v1/pod" + "k8s.io/kubernetes/pkg/kubelet/events" "k8s.io/kubernetes/test/e2e/framework" testutils "k8s.io/kubernetes/test/utils" @@ -305,6 +308,82 @@ var _ = framework.KubeDescribe("Probing container", func() { }, }, 1, defaultObservationTimeout) }) + + /* + Release : v1.14 + Testname: Pod http liveness probe, redirected to a local address + Description: A Pod is created with liveness probe on http endpoint /redirect?loc=healthz. The http handler on the /redirect will redirect to the /healthz endpoint, which will return a http error after 10 seconds since the Pod is started. This MUST result in liveness check failure. The Pod MUST now be killed and restarted incrementing restart count to 1. + */ + It("should be restarted with a local redirect http liveness probe", func() { + runLivenessTest(f, &v1.Pod{ + ObjectMeta: metav1.ObjectMeta{ + Name: "liveness-http-redirect", + Labels: map[string]string{"test": "liveness"}, + }, + Spec: v1.PodSpec{ + Containers: []v1.Container{ + { + Name: "liveness", + Image: imageutils.GetE2EImage(imageutils.Liveness), + Command: []string{"/server"}, + LivenessProbe: &v1.Probe{ + Handler: v1.Handler{ + HTTPGet: &v1.HTTPGetAction{ + Path: "/redirect?loc=" + url.QueryEscape("/healthz"), + Port: intstr.FromInt(8080), + }, + }, + InitialDelaySeconds: 15, + FailureThreshold: 1, + }, + }, + }, + }, + }, 1, defaultObservationTimeout) + }) + + /* + Release : v1.14 + Testname: Pod http liveness probe, redirected to a non-local address + Description: A Pod is created with liveness probe on http endpoint /redirect with a redirect to http://0.0.0.0/. The http handler on the /redirect should not follow the redirect, but instead treat it as a success and generate an event. + */ + It("should *not* be restarted with a non-local redirect http liveness probe", func() { + pod := &v1.Pod{ + ObjectMeta: metav1.ObjectMeta{ + Name: "liveness-http-redirect", + Labels: map[string]string{"test": "liveness"}, + }, + Spec: v1.PodSpec{ + Containers: []v1.Container{ + { + Name: "liveness", + Image: imageutils.GetE2EImage(imageutils.Liveness), + Command: []string{"/server"}, + LivenessProbe: &v1.Probe{ + Handler: v1.Handler{ + HTTPGet: &v1.HTTPGetAction{ + Path: "/redirect?loc=" + url.QueryEscape("http://0.0.0.0/"), + Port: intstr.FromInt(8080), + }, + }, + InitialDelaySeconds: 15, + FailureThreshold: 1, + }, + }, + }, + }, + } + runLivenessTest(f, pod, 0, defaultObservationTimeout) + // Expect an event of type "ProbeWarning". + expectedEvent := fields.Set{ + "involvedObject.kind": "Pod", + "involvedObject.name": pod.Name, + "involvedObject.namespace": f.Namespace.Name, + "reason": events.ContainerProbeWarning, + }.AsSelector().String() + framework.ExpectNoError(framework.WaitTimeoutForPodEvent( + f.ClientSet, pod.Name, f.Namespace.Name, expectedEvent, "0.0.0.0", framework.PodEventTimeout)) + }) }) func getContainerStartedTime(p *v1.Pod, containerName string) (time.Time, error) { diff --git a/test/images/liveness/VERSION b/test/images/liveness/VERSION index d3827e75a5c..9459d4ba2a0 100644 --- a/test/images/liveness/VERSION +++ b/test/images/liveness/VERSION @@ -1 +1 @@ -1.0 +1.1 diff --git a/test/images/liveness/server.go b/test/images/liveness/server.go index a32ac926766..7b6d7118a10 100644 --- a/test/images/liveness/server.go +++ b/test/images/liveness/server.go @@ -22,6 +22,7 @@ import ( "fmt" "log" "net/http" + "net/url" "time" ) @@ -42,5 +43,13 @@ func main() { w.Write([]byte("ok")) } }) + http.HandleFunc("/redirect", func(w http.ResponseWriter, r *http.Request) { + loc, err := url.QueryUnescape(r.URL.Query().Get("loc")) + if err != nil { + http.Error(w, fmt.Sprintf("invalid redirect: %q", r.URL.Query().Get("loc")), http.StatusBadRequest) + return + } + http.Redirect(w, r, loc, http.StatusFound) + }) log.Fatal(http.ListenAndServe(":8080", nil)) } diff --git a/test/utils/image/manifest.go b/test/utils/image/manifest.go index 26f3e4b1c97..2f9e3b40b1d 100644 --- a/test/utils/image/manifest.go +++ b/test/utils/image/manifest.go @@ -215,7 +215,7 @@ func initImageConfigs() map[int]Config { configs[Iperf] = Config{e2eRegistry, "iperf", "1.0"} configs[JessieDnsutils] = Config{e2eRegistry, "jessie-dnsutils", "1.0"} configs[Kitten] = Config{e2eRegistry, "kitten", "1.0"} - configs[Liveness] = Config{e2eRegistry, "liveness", "1.0"} + configs[Liveness] = Config{e2eRegistry, "liveness", "1.1"} configs[LogsGenerator] = Config{e2eRegistry, "logs-generator", "1.0"} configs[Mounttest] = Config{e2eRegistry, "mounttest", "1.0"} configs[MounttestUser] = Config{e2eRegistry, "mounttest-user", "1.0"}