123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307 |
- /*
- Copyright 2016 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 e2enode
- import (
- "context"
- "strings"
- "k8s.io/api/core/v1"
- "k8s.io/apimachinery/pkg/api/resource"
- metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
- "k8s.io/apimachinery/pkg/util/uuid"
- "k8s.io/kubernetes/pkg/kubelet/cm"
- "k8s.io/kubernetes/test/e2e/framework"
- e2epod "k8s.io/kubernetes/test/e2e/framework/pod"
- imageutils "k8s.io/kubernetes/test/utils/image"
- "github.com/onsi/ginkgo"
- "k8s.io/klog"
- )
- // getResourceList returns a ResourceList with the
- // specified cpu and memory resource values
- func getResourceList(cpu, memory string) v1.ResourceList {
- res := v1.ResourceList{}
- if cpu != "" {
- res[v1.ResourceCPU] = resource.MustParse(cpu)
- }
- if memory != "" {
- res[v1.ResourceMemory] = resource.MustParse(memory)
- }
- return res
- }
- // getResourceRequirements returns a ResourceRequirements object
- func getResourceRequirements(requests, limits v1.ResourceList) v1.ResourceRequirements {
- res := v1.ResourceRequirements{}
- res.Requests = requests
- res.Limits = limits
- return res
- }
- const (
- // Kubelet internal cgroup name for burstable tier
- burstableCgroup = "burstable"
- // Kubelet internal cgroup name for besteffort tier
- bestEffortCgroup = "besteffort"
- )
- // makePodToVerifyCgroups returns a pod that verifies the existence of the specified cgroups.
- func makePodToVerifyCgroups(cgroupNames []string) *v1.Pod {
- // convert the names to their literal cgroupfs forms...
- cgroupFsNames := []string{}
- rootCgroupName := cm.NewCgroupName(cm.RootCgroupName, defaultNodeAllocatableCgroup)
- for _, baseName := range cgroupNames {
- // Add top level cgroup used to enforce node allocatable.
- cgroupComponents := strings.Split(baseName, "/")
- cgroupName := cm.NewCgroupName(rootCgroupName, cgroupComponents...)
- cgroupFsNames = append(cgroupFsNames, toCgroupFsName(cgroupName))
- }
- klog.Infof("expecting %v cgroups to be found", cgroupFsNames)
- // build the pod command to either verify cgroups exist
- command := ""
- for _, cgroupFsName := range cgroupFsNames {
- localCommand := "if [ ! -d /tmp/memory/" + cgroupFsName + " ] || [ ! -d /tmp/cpu/" + cgroupFsName + " ]; then exit 1; fi; "
- command += localCommand
- }
- pod := &v1.Pod{
- ObjectMeta: metav1.ObjectMeta{
- Name: "pod" + string(uuid.NewUUID()),
- },
- Spec: v1.PodSpec{
- RestartPolicy: v1.RestartPolicyNever,
- Containers: []v1.Container{
- {
- Image: busyboxImage,
- Name: "container" + string(uuid.NewUUID()),
- Command: []string{"sh", "-c", command},
- VolumeMounts: []v1.VolumeMount{
- {
- Name: "sysfscgroup",
- MountPath: "/tmp",
- },
- },
- },
- },
- Volumes: []v1.Volume{
- {
- Name: "sysfscgroup",
- VolumeSource: v1.VolumeSource{
- HostPath: &v1.HostPathVolumeSource{Path: "/sys/fs/cgroup"},
- },
- },
- },
- },
- }
- return pod
- }
- // makePodToVerifyCgroupRemoved verfies the specified cgroup does not exist.
- func makePodToVerifyCgroupRemoved(baseName string) *v1.Pod {
- components := strings.Split(baseName, "/")
- cgroupName := cm.NewCgroupName(cm.RootCgroupName, components...)
- cgroupFsName := toCgroupFsName(cgroupName)
- pod := &v1.Pod{
- ObjectMeta: metav1.ObjectMeta{
- Name: "pod" + string(uuid.NewUUID()),
- },
- Spec: v1.PodSpec{
- RestartPolicy: v1.RestartPolicyOnFailure,
- Containers: []v1.Container{
- {
- Image: busyboxImage,
- Name: "container" + string(uuid.NewUUID()),
- Command: []string{"sh", "-c", "for i in `seq 1 10`; do if [ ! -d /tmp/memory/" + cgroupFsName + " ] && [ ! -d /tmp/cpu/" + cgroupFsName + " ]; then exit 0; else sleep 10; fi; done; exit 1"},
- VolumeMounts: []v1.VolumeMount{
- {
- Name: "sysfscgroup",
- MountPath: "/tmp",
- },
- },
- },
- },
- Volumes: []v1.Volume{
- {
- Name: "sysfscgroup",
- VolumeSource: v1.VolumeSource{
- HostPath: &v1.HostPathVolumeSource{Path: "/sys/fs/cgroup"},
- },
- },
- },
- },
- }
- return pod
- }
- var _ = framework.KubeDescribe("Kubelet Cgroup Manager", func() {
- f := framework.NewDefaultFramework("kubelet-cgroup-manager")
- ginkgo.Describe("QOS containers", func() {
- ginkgo.Context("On enabling QOS cgroup hierarchy", func() {
- ginkgo.It("Top level QoS containers should have been created [NodeConformance]", func() {
- if !framework.TestContext.KubeletConfig.CgroupsPerQOS {
- return
- }
- cgroupsToVerify := []string{burstableCgroup, bestEffortCgroup}
- pod := makePodToVerifyCgroups(cgroupsToVerify)
- f.PodClient().Create(pod)
- err := e2epod.WaitForPodSuccessInNamespace(f.ClientSet, pod.Name, f.Namespace.Name)
- framework.ExpectNoError(err)
- })
- })
- })
- ginkgo.Describe("Pod containers [NodeConformance]", func() {
- ginkgo.Context("On scheduling a Guaranteed Pod", func() {
- ginkgo.It("Pod containers should have been created under the cgroup-root", func() {
- if !framework.TestContext.KubeletConfig.CgroupsPerQOS {
- return
- }
- var (
- guaranteedPod *v1.Pod
- podUID string
- )
- ginkgo.By("Creating a Guaranteed pod in Namespace", func() {
- guaranteedPod = f.PodClient().Create(&v1.Pod{
- ObjectMeta: metav1.ObjectMeta{
- Name: "pod" + string(uuid.NewUUID()),
- Namespace: f.Namespace.Name,
- },
- Spec: v1.PodSpec{
- Containers: []v1.Container{
- {
- Image: imageutils.GetPauseImageName(),
- Name: "container" + string(uuid.NewUUID()),
- Resources: getResourceRequirements(getResourceList("100m", "100Mi"), getResourceList("100m", "100Mi")),
- },
- },
- },
- })
- podUID = string(guaranteedPod.UID)
- })
- ginkgo.By("Checking if the pod cgroup was created", func() {
- cgroupsToVerify := []string{"pod" + podUID}
- pod := makePodToVerifyCgroups(cgroupsToVerify)
- f.PodClient().Create(pod)
- err := e2epod.WaitForPodSuccessInNamespace(f.ClientSet, pod.Name, f.Namespace.Name)
- framework.ExpectNoError(err)
- })
- ginkgo.By("Checking if the pod cgroup was deleted", func() {
- gp := int64(1)
- err := f.PodClient().Delete(context.TODO(), guaranteedPod.Name, &metav1.DeleteOptions{GracePeriodSeconds: &gp})
- framework.ExpectNoError(err)
- pod := makePodToVerifyCgroupRemoved("pod" + podUID)
- f.PodClient().Create(pod)
- err = e2epod.WaitForPodSuccessInNamespace(f.ClientSet, pod.Name, f.Namespace.Name)
- framework.ExpectNoError(err)
- })
- })
- })
- ginkgo.Context("On scheduling a BestEffort Pod", func() {
- ginkgo.It("Pod containers should have been created under the BestEffort cgroup", func() {
- if !framework.TestContext.KubeletConfig.CgroupsPerQOS {
- return
- }
- var (
- podUID string
- bestEffortPod *v1.Pod
- )
- ginkgo.By("Creating a BestEffort pod in Namespace", func() {
- bestEffortPod = f.PodClient().Create(&v1.Pod{
- ObjectMeta: metav1.ObjectMeta{
- Name: "pod" + string(uuid.NewUUID()),
- Namespace: f.Namespace.Name,
- },
- Spec: v1.PodSpec{
- Containers: []v1.Container{
- {
- Image: imageutils.GetPauseImageName(),
- Name: "container" + string(uuid.NewUUID()),
- Resources: getResourceRequirements(getResourceList("", ""), getResourceList("", "")),
- },
- },
- },
- })
- podUID = string(bestEffortPod.UID)
- })
- ginkgo.By("Checking if the pod cgroup was created", func() {
- cgroupsToVerify := []string{"besteffort/pod" + podUID}
- pod := makePodToVerifyCgroups(cgroupsToVerify)
- f.PodClient().Create(pod)
- err := e2epod.WaitForPodSuccessInNamespace(f.ClientSet, pod.Name, f.Namespace.Name)
- framework.ExpectNoError(err)
- })
- ginkgo.By("Checking if the pod cgroup was deleted", func() {
- gp := int64(1)
- err := f.PodClient().Delete(context.TODO(), bestEffortPod.Name, &metav1.DeleteOptions{GracePeriodSeconds: &gp})
- framework.ExpectNoError(err)
- pod := makePodToVerifyCgroupRemoved("besteffort/pod" + podUID)
- f.PodClient().Create(pod)
- err = e2epod.WaitForPodSuccessInNamespace(f.ClientSet, pod.Name, f.Namespace.Name)
- framework.ExpectNoError(err)
- })
- })
- })
- ginkgo.Context("On scheduling a Burstable Pod", func() {
- ginkgo.It("Pod containers should have been created under the Burstable cgroup", func() {
- if !framework.TestContext.KubeletConfig.CgroupsPerQOS {
- return
- }
- var (
- podUID string
- burstablePod *v1.Pod
- )
- ginkgo.By("Creating a Burstable pod in Namespace", func() {
- burstablePod = f.PodClient().Create(&v1.Pod{
- ObjectMeta: metav1.ObjectMeta{
- Name: "pod" + string(uuid.NewUUID()),
- Namespace: f.Namespace.Name,
- },
- Spec: v1.PodSpec{
- Containers: []v1.Container{
- {
- Image: imageutils.GetPauseImageName(),
- Name: "container" + string(uuid.NewUUID()),
- Resources: getResourceRequirements(getResourceList("100m", "100Mi"), getResourceList("200m", "200Mi")),
- },
- },
- },
- })
- podUID = string(burstablePod.UID)
- })
- ginkgo.By("Checking if the pod cgroup was created", func() {
- cgroupsToVerify := []string{"burstable/pod" + podUID}
- pod := makePodToVerifyCgroups(cgroupsToVerify)
- f.PodClient().Create(pod)
- err := e2epod.WaitForPodSuccessInNamespace(f.ClientSet, pod.Name, f.Namespace.Name)
- framework.ExpectNoError(err)
- })
- ginkgo.By("Checking if the pod cgroup was deleted", func() {
- gp := int64(1)
- err := f.PodClient().Delete(context.TODO(), burstablePod.Name, &metav1.DeleteOptions{GracePeriodSeconds: &gp})
- framework.ExpectNoError(err)
- pod := makePodToVerifyCgroupRemoved("burstable/pod" + podUID)
- f.PodClient().Create(pod)
- err = e2epod.WaitForPodSuccessInNamespace(f.ClientSet, pod.Name, f.Namespace.Name)
- framework.ExpectNoError(err)
- })
- })
- })
- })
- })
|