k8s.io/kubernetes@v1.29.3/test/e2e_node/pids_test.go (about)

     1  /*
     2  Copyright 2019 The Kubernetes Authors.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8      http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package e2enode
    18  
    19  import (
    20  	"context"
    21  	"fmt"
    22  
    23  	v1 "k8s.io/api/core/v1"
    24  	"k8s.io/apimachinery/pkg/api/resource"
    25  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    26  	"k8s.io/apimachinery/pkg/util/uuid"
    27  	admissionapi "k8s.io/pod-security-admission/api"
    28  
    29  	kubeletconfig "k8s.io/kubernetes/pkg/kubelet/apis/config"
    30  	"k8s.io/kubernetes/pkg/kubelet/cm"
    31  	"k8s.io/kubernetes/test/e2e/framework"
    32  	e2epod "k8s.io/kubernetes/test/e2e/framework/pod"
    33  	imageutils "k8s.io/kubernetes/test/utils/image"
    34  
    35  	"github.com/onsi/ginkgo/v2"
    36  )
    37  
    38  // makePodToVerifyPids returns a pod that verifies specified cgroup with pids
    39  func makePodToVerifyPids(baseName string, pidsLimit resource.Quantity) *v1.Pod {
    40  	// convert the cgroup name to its literal form
    41  	cgroupFsName := ""
    42  	cgroupName := cm.NewCgroupName(cm.RootCgroupName, defaultNodeAllocatableCgroup, baseName)
    43  	if kubeletCfg.CgroupDriver == "systemd" {
    44  		cgroupFsName = cgroupName.ToSystemd()
    45  	} else {
    46  		cgroupFsName = cgroupName.ToCgroupfs()
    47  	}
    48  
    49  	// this command takes the expected value and compares it against the actual value for the pod cgroup pids.max
    50  	command := ""
    51  	if IsCgroup2UnifiedMode() {
    52  		command = fmt.Sprintf("expected=%v; actual=$(cat /tmp/%v/pids.max); if [ \"$expected\" -ne \"$actual\" ]; then exit 1; fi; ", pidsLimit.Value(), cgroupFsName)
    53  	} else {
    54  		command = fmt.Sprintf("expected=%v; actual=$(cat /tmp/pids/%v/pids.max); if [ \"$expected\" -ne \"$actual\" ]; then exit 1; fi; ", pidsLimit.Value(), cgroupFsName)
    55  	}
    56  
    57  	framework.Logf("Pod to run command: %v", command)
    58  	pod := &v1.Pod{
    59  		ObjectMeta: metav1.ObjectMeta{
    60  			Name: "pod" + string(uuid.NewUUID()),
    61  		},
    62  		Spec: v1.PodSpec{
    63  			RestartPolicy: v1.RestartPolicyNever,
    64  			Containers: []v1.Container{
    65  				{
    66  					Image:   busyboxImage,
    67  					Name:    "container" + string(uuid.NewUUID()),
    68  					Command: []string{"sh", "-c", command},
    69  					VolumeMounts: []v1.VolumeMount{
    70  						{
    71  							Name:      "sysfscgroup",
    72  							MountPath: "/tmp",
    73  						},
    74  					},
    75  				},
    76  			},
    77  			Volumes: []v1.Volume{
    78  				{
    79  					Name: "sysfscgroup",
    80  					VolumeSource: v1.VolumeSource{
    81  						HostPath: &v1.HostPathVolumeSource{Path: "/sys/fs/cgroup"},
    82  					},
    83  				},
    84  			},
    85  		},
    86  	}
    87  	return pod
    88  }
    89  
    90  func runPodPidsLimitTests(f *framework.Framework) {
    91  	ginkgo.It("should set pids.max for Pod", func(ctx context.Context) {
    92  		ginkgo.By("by creating a G pod")
    93  		pod := e2epod.NewPodClient(f).Create(ctx, &v1.Pod{
    94  			ObjectMeta: metav1.ObjectMeta{
    95  				Name:      "pod" + string(uuid.NewUUID()),
    96  				Namespace: f.Namespace.Name,
    97  			},
    98  			Spec: v1.PodSpec{
    99  				Containers: []v1.Container{
   100  					{
   101  						Image: imageutils.GetPauseImageName(),
   102  						Name:  "container" + string(uuid.NewUUID()),
   103  						Resources: v1.ResourceRequirements{
   104  							Limits: v1.ResourceList{
   105  								v1.ResourceName("cpu"):    resource.MustParse("10m"),
   106  								v1.ResourceName("memory"): resource.MustParse("100Mi"),
   107  							},
   108  						},
   109  					},
   110  				},
   111  			},
   112  		})
   113  		podUID := string(pod.UID)
   114  		ginkgo.By("checking if the expected pids settings were applied")
   115  		verifyPod := makePodToVerifyPids("pod"+podUID, resource.MustParse("1024"))
   116  		e2epod.NewPodClient(f).Create(ctx, verifyPod)
   117  		err := e2epod.WaitForPodSuccessInNamespace(ctx, f.ClientSet, verifyPod.Name, f.Namespace.Name)
   118  		framework.ExpectNoError(err)
   119  	})
   120  }
   121  
   122  // Serial because the test updates kubelet configuration.
   123  var _ = SIGDescribe("PodPidsLimit", framework.WithSerial(), func() {
   124  	f := framework.NewDefaultFramework("pids-limit-test")
   125  	f.NamespacePodSecurityLevel = admissionapi.LevelPrivileged
   126  	ginkgo.Context("With config updated with pids limits", func() {
   127  		tempSetCurrentKubeletConfig(f, func(ctx context.Context, initialConfig *kubeletconfig.KubeletConfiguration) {
   128  			initialConfig.PodPidsLimit = int64(1024)
   129  		})
   130  		runPodPidsLimitTests(f)
   131  	})
   132  })