From 026a082a7ff2f94053c1cfb8382e8417e27fab84 Mon Sep 17 00:00:00 2001 From: Yang Guo Date: Mon, 31 Jul 2017 18:01:11 -0700 Subject: [PATCH] Add node e2e test for Docker's shared PID namespace --- test/e2e_node/BUILD | 5 +- test/e2e_node/docker_test.go | 73 +++++++++++++++++++ test/e2e_node/docker_util.go | 62 ++++++++++++++++ test/e2e_node/garbage_collector_test.go | 2 - .../e2e_node/jenkins/image-config-serial.yaml | 6 +- test/e2e_node/jenkins/image-config.yaml | 6 +- test/e2e_node/security_context_test.go | 20 +---- 7 files changed, 153 insertions(+), 21 deletions(-) create mode 100644 test/e2e_node/docker_test.go create mode 100644 test/e2e_node/docker_util.go diff --git a/test/e2e_node/BUILD b/test/e2e_node/BUILD index 57421ca310f..57c95b9c9c4 100644 --- a/test/e2e_node/BUILD +++ b/test/e2e_node/BUILD @@ -14,6 +14,7 @@ go_library( "benchmark_util.go", "container.go", "doc.go", + "docker_util.go", "gpus.go", "image_list.go", "node_problem_detector_linux.go", @@ -39,6 +40,8 @@ go_library( "//test/e2e/metrics:go_default_library", "//test/e2e/perftype:go_default_library", "//test/e2e_node/perftype:go_default_library", + "//vendor/github.com/blang/semver:go_default_library", + "//vendor/github.com/docker/docker/client:go_default_library", "//vendor/github.com/golang/glog:go_default_library", "//vendor/github.com/google/cadvisor/client/v2:go_default_library", "//vendor/github.com/google/cadvisor/info/v2:go_default_library", @@ -71,6 +74,7 @@ go_test( "critical_pod_test.go", "density_test.go", "disk_eviction_test.go", + "docker_test.go", "dockershim_checkpoint_test.go", "dynamic_kubelet_configuration_test.go", "e2e_node_suite_test.go", @@ -118,7 +122,6 @@ go_test( "//test/e2e_node/services:go_default_library", "//test/e2e_node/system:go_default_library", "//test/utils:go_default_library", - "//vendor/github.com/blang/semver:go_default_library", "//vendor/github.com/coreos/go-systemd/util:go_default_library", "//vendor/github.com/davecgh/go-spew/spew:go_default_library", "//vendor/github.com/golang/glog:go_default_library", diff --git a/test/e2e_node/docker_test.go b/test/e2e_node/docker_test.go new file mode 100644 index 00000000000..8c79604fb14 --- /dev/null +++ b/test/e2e_node/docker_test.go @@ -0,0 +1,73 @@ +/* +Copyright 2017 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package e2e_node + +import ( + "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/kubernetes/test/e2e/framework" + + . "github.com/onsi/ginkgo" +) + +var _ = framework.KubeDescribe("Docker features [Feature:Docker]", func() { + f := framework.NewDefaultFramework("docker-feature-test") + + BeforeEach(func() { + framework.RunIfContainerRuntimeIs("docker") + }) + + Context("when shared PID namespace is enabled", func() { + It("processes in different containers of the same pod should be able to see each other", func() { + // TODO(yguo0905): Change this test to run unless the runtime is + // Docker and its version is <1.13. + By("Check whether shared PID namespace is enabled.") + isEnabled, err := isSharedPIDNamespaceEnabled() + framework.ExpectNoError(err) + if !isEnabled { + framework.Skipf("Skipped because shared PID namespace is not enabled.") + } + + By("Create a pod with two containers.") + f.PodClient().CreateSync(&v1.Pod{ + ObjectMeta: metav1.ObjectMeta{Name: "shared-pid-ns-test-pod"}, + Spec: v1.PodSpec{ + Containers: []v1.Container{ + { + Name: "test-container-1", + Image: "gcr.io/google_containers/busybox:1.24", + Command: []string{"/bin/top"}, + }, + { + Name: "test-container-2", + Image: "gcr.io/google_containers/busybox:1.24", + Command: []string{"/bin/sleep"}, + Args: []string{"10000"}, + }, + }, + }, + }) + + By("Check if the process in one container is visible to the process in the other.") + pid1 := f.ExecCommandInContainer("shared-pid-ns-test-pod", "test-container-1", "/bin/pidof", "top") + pid2 := f.ExecCommandInContainer("shared-pid-ns-test-pod", "test-container-2", "/bin/pidof", "top") + if pid1 != pid2 { + framework.Failf("PIDs are not the same in different containers: test-container-1=%v, test-container-2=%v", pid1, pid2) + } + }) + }) +}) diff --git a/test/e2e_node/docker_util.go b/test/e2e_node/docker_util.go new file mode 100644 index 00000000000..b8bc2497083 --- /dev/null +++ b/test/e2e_node/docker_util.go @@ -0,0 +1,62 @@ +/* +Copyright 2017 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package e2e_node + +import ( + "context" + "fmt" + + "github.com/blang/semver" + "github.com/docker/docker/client" +) + +const ( + defaultDockerEndpoint = "unix:///var/run/docker.sock" +) + +// getDockerAPIVersion returns the Docker's API version. +func getDockerAPIVersion() (semver.Version, error) { + c, err := client.NewClient(defaultDockerEndpoint, "", nil, nil) + if err != nil { + return semver.Version{}, fmt.Errorf("failed to create docker client: %v", err) + } + version, err := c.ServerVersion(context.Background()) + if err != nil { + return semver.Version{}, fmt.Errorf("failed to get docker info: %v", err) + } + return semver.MustParse(version.APIVersion + ".0"), nil +} + +// isSharedPIDNamespaceEnabled returns true if the Docker version is 1.13.1+ +// (API version 1.26+), and false otherwise. +func isSharedPIDNamespaceEnabled() (bool, error) { + version, err := getDockerAPIVersion() + if err != nil { + return false, err + } + return version.GTE(semver.MustParse("1.26.0")), nil +} + +// isDockerNoNewPrivilegesSupported returns true if Docker version is 1.11+ +// (API version 1.23+), and false otherwise. +func isDockerNoNewPrivilegesSupported() (bool, error) { + version, err := getDockerAPIVersion() + if err != nil { + return false, err + } + return version.GTE(semver.MustParse("1.23.0")), nil +} diff --git a/test/e2e_node/garbage_collector_test.go b/test/e2e_node/garbage_collector_test.go index 12505349609..0bc4852ddd7 100644 --- a/test/e2e_node/garbage_collector_test.go +++ b/test/e2e_node/garbage_collector_test.go @@ -32,8 +32,6 @@ import ( ) const ( - defaultDockerEndpoint = "unix:///var/run/docker.sock" - //TODO (dashpole): Once dynamic config is possible, test different values for maxPerPodContainer and maxContainers // Currently using default values for maxPerPodContainer and maxTotalContainers maxPerPodContainer = 1 diff --git a/test/e2e_node/jenkins/image-config-serial.yaml b/test/e2e_node/jenkins/image-config-serial.yaml index 04991988a75..12da0f85f4e 100644 --- a/test/e2e_node/jenkins/image-config-serial.yaml +++ b/test/e2e_node/jenkins/image-config-serial.yaml @@ -12,7 +12,7 @@ images: containervm: image: e2e-node-containervm-v20161208-image # docker 1.11.2 project: kubernetes-node-e2e-images - gci: + cos-stable: image_regex: cos-stable-59-9460-64-0 # docker 1.11.2 project: cos-cloud metadata: "user-data= 1.11 thats when "no-new-privileges" was added - framework.Skipf("Skipping no_new_privs tests, docker version is < 1.11 it is %s", version.String()) + isSupported, err := isDockerNoNewPrivilegesSupported() + framework.ExpectNoError(err) + if !isSupported { + framework.Skipf("Skipping because no_new_privs is not supported in this docker") } } })