123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210 |
- /*
- Copyright 2014 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 common
- import (
- "k8s.io/api/core/v1"
- metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
- "k8s.io/apimachinery/pkg/util/uuid"
- "k8s.io/kubernetes/pkg/kubelet/sysctl"
- "k8s.io/kubernetes/test/e2e/framework"
- imageutils "k8s.io/kubernetes/test/utils/image"
- . "github.com/onsi/ginkgo"
- . "github.com/onsi/gomega"
- )
- var _ = framework.KubeDescribe("Sysctls [NodeFeature:Sysctls]", func() {
- f := framework.NewDefaultFramework("sysctl")
- var podClient *framework.PodClient
- testPod := func() *v1.Pod {
- podName := "sysctl-" + string(uuid.NewUUID())
- pod := v1.Pod{
- ObjectMeta: metav1.ObjectMeta{
- Name: podName,
- Annotations: map[string]string{},
- },
- Spec: v1.PodSpec{
- Containers: []v1.Container{
- {
- Name: "test-container",
- Image: imageutils.GetE2EImage(imageutils.BusyBox),
- },
- },
- RestartPolicy: v1.RestartPolicyNever,
- },
- }
- return &pod
- }
- BeforeEach(func() {
- podClient = f.PodClient()
- })
- It("should support sysctls", func() {
- pod := testPod()
- pod.Spec.SecurityContext = &v1.PodSecurityContext{
- Sysctls: []v1.Sysctl{
- {
- Name: "kernel.shm_rmid_forced",
- Value: "1",
- },
- },
- }
- pod.Spec.Containers[0].Command = []string{"/bin/sysctl", "kernel.shm_rmid_forced"}
- By("Creating a pod with the kernel.shm_rmid_forced sysctl")
- pod = podClient.Create(pod)
- By("Watching for error events or started pod")
- // watch for events instead of termination of pod because the kubelet deletes
- // failed pods without running containers. This would create a race as the pod
- // might have already been deleted here.
- ev, err := f.PodClient().WaitForErrorEventOrSuccess(pod)
- framework.ExpectNoError(err)
- if ev != nil && ev.Reason == sysctl.UnsupportedReason {
- framework.Skipf("No sysctl support in Docker <1.12")
- }
- Expect(ev).To(BeNil())
- By("Waiting for pod completion")
- err = f.WaitForPodNoLongerRunning(pod.Name)
- framework.ExpectNoError(err)
- pod, err = podClient.Get(pod.Name, metav1.GetOptions{})
- framework.ExpectNoError(err)
- By("Checking that the pod succeeded")
- Expect(pod.Status.Phase).To(Equal(v1.PodSucceeded))
- By("Getting logs from the pod")
- log, err := framework.GetPodLogs(f.ClientSet, f.Namespace.Name, pod.Name, pod.Spec.Containers[0].Name)
- framework.ExpectNoError(err)
- By("Checking that the sysctl is actually updated")
- Expect(log).To(ContainSubstring("kernel.shm_rmid_forced = 1"))
- })
- It("should support unsafe sysctls which are actually whitelisted", func() {
- pod := testPod()
- pod.Spec.SecurityContext = &v1.PodSecurityContext{
- Sysctls: []v1.Sysctl{
- {
- Name: "kernel.shm_rmid_forced",
- Value: "1",
- },
- },
- }
- pod.Spec.Containers[0].Command = []string{"/bin/sysctl", "kernel.shm_rmid_forced"}
- By("Creating a pod with the kernel.shm_rmid_forced sysctl")
- pod = podClient.Create(pod)
- By("Watching for error events or started pod")
- // watch for events instead of termination of pod because the kubelet deletes
- // failed pods without running containers. This would create a race as the pod
- // might have already been deleted here.
- ev, err := f.PodClient().WaitForErrorEventOrSuccess(pod)
- framework.ExpectNoError(err)
- if ev != nil && ev.Reason == sysctl.UnsupportedReason {
- framework.Skipf("No sysctl support in Docker <1.12")
- }
- Expect(ev).To(BeNil())
- By("Waiting for pod completion")
- err = f.WaitForPodNoLongerRunning(pod.Name)
- framework.ExpectNoError(err)
- pod, err = podClient.Get(pod.Name, metav1.GetOptions{})
- framework.ExpectNoError(err)
- By("Checking that the pod succeeded")
- Expect(pod.Status.Phase).To(Equal(v1.PodSucceeded))
- By("Getting logs from the pod")
- log, err := framework.GetPodLogs(f.ClientSet, f.Namespace.Name, pod.Name, pod.Spec.Containers[0].Name)
- framework.ExpectNoError(err)
- By("Checking that the sysctl is actually updated")
- Expect(log).To(ContainSubstring("kernel.shm_rmid_forced = 1"))
- })
- It("should reject invalid sysctls", func() {
- pod := testPod()
- pod.Spec.SecurityContext = &v1.PodSecurityContext{
- Sysctls: []v1.Sysctl{
- // Safe parameters
- {
- Name: "foo-",
- Value: "bar",
- },
- {
- Name: "kernel.shmmax",
- Value: "100000000",
- },
- {
- Name: "safe-and-unsafe",
- Value: "100000000",
- },
- {
- Name: "bar..",
- Value: "42",
- },
- },
- }
- By("Creating a pod with one valid and two invalid sysctls")
- client := f.ClientSet.CoreV1().Pods(f.Namespace.Name)
- _, err := client.Create(pod)
- Expect(err).NotTo(BeNil())
- Expect(err.Error()).To(ContainSubstring(`Invalid value: "foo-"`))
- Expect(err.Error()).To(ContainSubstring(`Invalid value: "bar.."`))
- Expect(err.Error()).NotTo(ContainSubstring(`safe-and-unsafe`))
- Expect(err.Error()).NotTo(ContainSubstring("kernel.shmmax"))
- })
- It("should not launch unsafe, but not explicitly enabled sysctls on the node", func() {
- pod := testPod()
- pod.Spec.SecurityContext = &v1.PodSecurityContext{
- Sysctls: []v1.Sysctl{
- {
- Name: "kernel.msgmax",
- Value: "10000000000",
- },
- },
- }
- By("Creating a pod with a greylisted, but not whitelisted sysctl on the node")
- pod = podClient.Create(pod)
- By("Watching for error events or started pod")
- // watch for events instead of termination of pod because the kubelet deletes
- // failed pods without running containers. This would create a race as the pod
- // might have already been deleted here.
- ev, err := f.PodClient().WaitForErrorEventOrSuccess(pod)
- framework.ExpectNoError(err)
- if ev != nil && ev.Reason == sysctl.UnsupportedReason {
- framework.Skipf("No sysctl support in Docker <1.12")
- }
- By("Checking that the pod was rejected")
- Expect(ev).ToNot(BeNil())
- Expect(ev.Reason).To(Equal("SysctlForbidden"))
- })
- })
|