mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-20 02:11:09 +00:00
Add limitrange e2e test for LocalStorageCapacityIsolation feature
This commit is contained in:
parent
65b8f5bd98
commit
1633cdde05
@ -57,6 +57,7 @@ go_library(
|
|||||||
"//pkg/controller:go_default_library",
|
"//pkg/controller:go_default_library",
|
||||||
"//pkg/controller/deployment/util:go_default_library",
|
"//pkg/controller/deployment/util:go_default_library",
|
||||||
"//pkg/controller/node:go_default_library",
|
"//pkg/controller/node:go_default_library",
|
||||||
|
"//pkg/features:go_default_library",
|
||||||
"//pkg/kubectl:go_default_library",
|
"//pkg/kubectl:go_default_library",
|
||||||
"//pkg/kubelet/apis/kubeletconfig:go_default_library",
|
"//pkg/kubelet/apis/kubeletconfig:go_default_library",
|
||||||
"//pkg/kubelet/apis/stats/v1alpha1:go_default_library",
|
"//pkg/kubelet/apis/stats/v1alpha1:go_default_library",
|
||||||
@ -128,6 +129,7 @@ go_library(
|
|||||||
"//vendor/k8s.io/apimachinery/pkg/version:go_default_library",
|
"//vendor/k8s.io/apimachinery/pkg/version:go_default_library",
|
||||||
"//vendor/k8s.io/apimachinery/pkg/watch:go_default_library",
|
"//vendor/k8s.io/apimachinery/pkg/watch:go_default_library",
|
||||||
"//vendor/k8s.io/apiserver/pkg/authentication/serviceaccount:go_default_library",
|
"//vendor/k8s.io/apiserver/pkg/authentication/serviceaccount:go_default_library",
|
||||||
|
"//vendor/k8s.io/apiserver/pkg/util/feature:go_default_library",
|
||||||
"//vendor/k8s.io/client-go/discovery:go_default_library",
|
"//vendor/k8s.io/client-go/discovery:go_default_library",
|
||||||
"//vendor/k8s.io/client-go/dynamic:go_default_library",
|
"//vendor/k8s.io/client-go/dynamic:go_default_library",
|
||||||
"//vendor/k8s.io/client-go/informers:go_default_library",
|
"//vendor/k8s.io/client-go/informers:go_default_library",
|
||||||
|
@ -73,6 +73,7 @@ import (
|
|||||||
"k8s.io/client-go/tools/clientcmd"
|
"k8s.io/client-go/tools/clientcmd"
|
||||||
clientcmdapi "k8s.io/client-go/tools/clientcmd/api"
|
clientcmdapi "k8s.io/client-go/tools/clientcmd/api"
|
||||||
|
|
||||||
|
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
||||||
clientset "k8s.io/client-go/kubernetes"
|
clientset "k8s.io/client-go/kubernetes"
|
||||||
"k8s.io/kubernetes/pkg/api"
|
"k8s.io/kubernetes/pkg/api"
|
||||||
"k8s.io/kubernetes/pkg/api/legacyscheme"
|
"k8s.io/kubernetes/pkg/api/legacyscheme"
|
||||||
@ -86,6 +87,7 @@ import (
|
|||||||
gcecloud "k8s.io/kubernetes/pkg/cloudprovider/providers/gce"
|
gcecloud "k8s.io/kubernetes/pkg/cloudprovider/providers/gce"
|
||||||
"k8s.io/kubernetes/pkg/controller"
|
"k8s.io/kubernetes/pkg/controller"
|
||||||
nodectlr "k8s.io/kubernetes/pkg/controller/node"
|
nodectlr "k8s.io/kubernetes/pkg/controller/node"
|
||||||
|
"k8s.io/kubernetes/pkg/features"
|
||||||
"k8s.io/kubernetes/pkg/kubectl"
|
"k8s.io/kubernetes/pkg/kubectl"
|
||||||
"k8s.io/kubernetes/pkg/kubelet/util/format"
|
"k8s.io/kubernetes/pkg/kubelet/util/format"
|
||||||
"k8s.io/kubernetes/pkg/master/ports"
|
"k8s.io/kubernetes/pkg/master/ports"
|
||||||
@ -318,6 +320,12 @@ func SkipIfProviderIs(unsupportedProviders ...string) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func SkipUnlessLocalEphemeralStorageEnabled() {
|
||||||
|
if !utilfeature.DefaultFeatureGate.Enabled(features.LocalStorageCapacityIsolation) {
|
||||||
|
Skipf("Only supported when %v feature is enabled", features.LocalStorageCapacityIsolation)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func SkipUnlessSSHKeyPresent() {
|
func SkipUnlessSSHKeyPresent() {
|
||||||
if _, err := GetSigner(TestContext.Provider); err != nil {
|
if _, err := GetSigner(TestContext.Provider); err != nil {
|
||||||
Skipf("No SSH Key for provider %s: '%v'", TestContext.Provider, err)
|
Skipf("No SSH Key for provider %s: '%v'", TestContext.Provider, err)
|
||||||
|
@ -108,6 +108,137 @@ var _ = SIGDescribe("LimitRange", func() {
|
|||||||
|
|
||||||
})
|
})
|
||||||
|
|
||||||
|
var _ = framework.KubeDescribe("LimitRange", func() {
|
||||||
|
f := framework.NewDefaultFramework("limitrange")
|
||||||
|
|
||||||
|
BeforeEach(func() {
|
||||||
|
// only run the tests when LocalStorageCapacityIsolation feature is enabled
|
||||||
|
framework.SkipUnlessLocalEphemeralStorageEnabled()
|
||||||
|
})
|
||||||
|
|
||||||
|
It("should create a LimitRange with default ephemeral storage and ensure pod has the default applied.", func() {
|
||||||
|
By("Creating a LimitRange")
|
||||||
|
|
||||||
|
min := getEphemeralStorageResourceList("100Mi")
|
||||||
|
max := getEphemeralStorageResourceList("500Mi")
|
||||||
|
defaultLimit := getEphemeralStorageResourceList("500Mi")
|
||||||
|
defaultRequest := getEphemeralStorageResourceList("200Mi")
|
||||||
|
maxLimitRequestRatio := v1.ResourceList{}
|
||||||
|
limitRange := newLimitRange("limit-range", v1.LimitTypeContainer,
|
||||||
|
min, max,
|
||||||
|
defaultLimit, defaultRequest,
|
||||||
|
maxLimitRequestRatio)
|
||||||
|
limitRange, err := f.ClientSet.CoreV1().LimitRanges(f.Namespace.Name).Create(limitRange)
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
|
||||||
|
defer func() {
|
||||||
|
By("Removing limitrange")
|
||||||
|
err = f.ClientSet.CoreV1().Pods(f.Namespace.Name).Delete(limitRange.Name, nil)
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
}()
|
||||||
|
|
||||||
|
By("Fetching the LimitRange to ensure it has proper values")
|
||||||
|
limitRange, err = f.ClientSet.CoreV1().LimitRanges(f.Namespace.Name).Get(limitRange.Name, metav1.GetOptions{})
|
||||||
|
expected := v1.ResourceRequirements{Requests: defaultRequest, Limits: defaultLimit}
|
||||||
|
actual := v1.ResourceRequirements{Requests: limitRange.Spec.Limits[0].DefaultRequest, Limits: limitRange.Spec.Limits[0].Default}
|
||||||
|
err = equalResourceRequirement(expected, actual)
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
|
||||||
|
By("Creating a Pod with no resource requirements")
|
||||||
|
pod := f.NewTestPod("pod-no-resources", v1.ResourceList{}, v1.ResourceList{})
|
||||||
|
pod, err = f.ClientSet.CoreV1().Pods(f.Namespace.Name).Create(pod)
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
|
||||||
|
defer func() {
|
||||||
|
By("Removing pod")
|
||||||
|
err = f.ClientSet.CoreV1().Pods(f.Namespace.Name).Delete(pod.Name, nil)
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
}()
|
||||||
|
|
||||||
|
By("Ensuring Pod has resource requirements applied from LimitRange")
|
||||||
|
pod, err = f.ClientSet.CoreV1().Pods(f.Namespace.Name).Get(pod.Name, metav1.GetOptions{})
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
for i := range pod.Spec.Containers {
|
||||||
|
err = equalResourceRequirement(expected, pod.Spec.Containers[i].Resources)
|
||||||
|
if err != nil {
|
||||||
|
// Print the pod to help in debugging.
|
||||||
|
framework.Logf("Pod %+v does not have the expected requirements", pod)
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
By("Creating a Pod with request")
|
||||||
|
pod = f.NewTestPod("pod-partial-resources", getEphemeralStorageResourceList("150m"), v1.ResourceList{})
|
||||||
|
pod, err = f.ClientSet.CoreV1().Pods(f.Namespace.Name).Create(pod)
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
|
||||||
|
defer func() {
|
||||||
|
By("Removing pod")
|
||||||
|
err = f.ClientSet.CoreV1().Pods(f.Namespace.Name).Delete(pod.Name, nil)
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
}()
|
||||||
|
|
||||||
|
By("Ensuring Pod has merged resource requirements applied from LimitRange")
|
||||||
|
pod, err = f.ClientSet.CoreV1().Pods(f.Namespace.Name).Get(pod.Name, metav1.GetOptions{})
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
// If you specify a Request, and no Limit, the Limit will be set to default limit
|
||||||
|
expected = v1.ResourceRequirements{Requests: getEphemeralStorageResourceList("150Mi"), Limits: defaultLimit}
|
||||||
|
for i := range pod.Spec.Containers {
|
||||||
|
err = equalResourceRequirement(expected, pod.Spec.Containers[i].Resources)
|
||||||
|
if err != nil {
|
||||||
|
// Print the pod to help in debugging.
|
||||||
|
framework.Logf("Pod %+v does not have the expected requirements", pod)
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
By("Creating a Pod with limit")
|
||||||
|
pod = f.NewTestPod("pod-partial-resources", v1.ResourceList{}, getEphemeralStorageResourceList("300m"))
|
||||||
|
pod, err = f.ClientSet.CoreV1().Pods(f.Namespace.Name).Create(pod)
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
|
||||||
|
defer func() {
|
||||||
|
By("Removing pod")
|
||||||
|
err = f.ClientSet.CoreV1().Pods(f.Namespace.Name).Delete(pod.Name, nil)
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
}()
|
||||||
|
|
||||||
|
By("Ensuring Pod has merged resource requirements applied from LimitRange")
|
||||||
|
pod, err = f.ClientSet.CoreV1().Pods(f.Namespace.Name).Get(pod.Name, metav1.GetOptions{})
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
// If you specify a Limit, and no Request, the Limit will default to the Request
|
||||||
|
// This means that the LimitRange.DefaultRequest will ONLY take affect if a container.resources.limit is not supplied
|
||||||
|
expected = v1.ResourceRequirements{Requests: getEphemeralStorageResourceList("300Mi"), Limits: getEphemeralStorageResourceList("300Mi")}
|
||||||
|
for i := range pod.Spec.Containers {
|
||||||
|
err = equalResourceRequirement(expected, pod.Spec.Containers[i].Resources)
|
||||||
|
if err != nil {
|
||||||
|
// Print the pod to help in debugging.
|
||||||
|
framework.Logf("Pod %+v does not have the expected requirements", pod)
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
By("Failing to create a Pod with less than min resources")
|
||||||
|
pod = f.NewTestPod(podName, getEphemeralStorageResourceList("50Mi"), v1.ResourceList{})
|
||||||
|
pod, err = f.ClientSet.CoreV1().Pods(f.Namespace.Name).Create(pod)
|
||||||
|
Expect(err).To(HaveOccurred())
|
||||||
|
|
||||||
|
By("Failing to create a Pod with more than max resources")
|
||||||
|
pod = f.NewTestPod(podName, getEphemeralStorageResourceList("600Mi"), v1.ResourceList{})
|
||||||
|
pod, err = f.ClientSet.CoreV1().Pods(f.Namespace.Name).Create(pod)
|
||||||
|
Expect(err).To(HaveOccurred())
|
||||||
|
})
|
||||||
|
|
||||||
|
})
|
||||||
|
|
||||||
|
func getEphemeralStorageResourceList(ephemeralStorage string) v1.ResourceList {
|
||||||
|
res := v1.ResourceList{}
|
||||||
|
if ephemeralStorage != "" {
|
||||||
|
res[v1.ResourceEphemeralStorage] = resource.MustParse(ephemeralStorage)
|
||||||
|
}
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
|
||||||
func equalResourceRequirement(expected v1.ResourceRequirements, actual v1.ResourceRequirements) error {
|
func equalResourceRequirement(expected v1.ResourceRequirements, actual v1.ResourceRequirements) error {
|
||||||
framework.Logf("Verifying requests: expected %v with actual %v", expected.Requests, actual.Requests)
|
framework.Logf("Verifying requests: expected %v with actual %v", expected.Requests, actual.Requests)
|
||||||
err := equalResourceList(expected.Requests, actual.Requests)
|
err := equalResourceList(expected.Requests, actual.Requests)
|
||||||
|
Loading…
Reference in New Issue
Block a user