mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-21 02:41:25 +00:00
e2e-scheduling: add basic PodOverhead test
Add a test to verify that Overhead is being considered during predication. Signed-off-by: Eric Ernst <eric.ernst@intel.com>
This commit is contained in:
parent
e5760015d2
commit
1d896db61c
@ -22,6 +22,7 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
v1 "k8s.io/api/core/v1"
|
v1 "k8s.io/api/core/v1"
|
||||||
|
nodev1beta1 "k8s.io/api/node/v1beta1"
|
||||||
"k8s.io/apimachinery/pkg/api/resource"
|
"k8s.io/apimachinery/pkg/api/resource"
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
"k8s.io/apimachinery/pkg/util/sets"
|
"k8s.io/apimachinery/pkg/util/sets"
|
||||||
@ -61,6 +62,7 @@ type pausePodConfig struct {
|
|||||||
Affinity *v1.Affinity
|
Affinity *v1.Affinity
|
||||||
Annotations, Labels, NodeSelector map[string]string
|
Annotations, Labels, NodeSelector map[string]string
|
||||||
Resources *v1.ResourceRequirements
|
Resources *v1.ResourceRequirements
|
||||||
|
RuntimeClassHandler *string
|
||||||
Tolerations []v1.Toleration
|
Tolerations []v1.Toleration
|
||||||
NodeName string
|
NodeName string
|
||||||
Ports []v1.ContainerPort
|
Ports []v1.ContainerPort
|
||||||
@ -196,6 +198,116 @@ var _ = SIGDescribe("SchedulerPredicates [Serial]", func() {
|
|||||||
verifyResult(cs, podsNeededForSaturation, 1, ns)
|
verifyResult(cs, podsNeededForSaturation, 1, ns)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// This test verifies we don't allow scheduling of pods in a way that sum of limits +
|
||||||
|
// associated overhead is greater than machine's capacity.
|
||||||
|
// It assumes that cluster add-on pods stay stable and cannot be run in parallel
|
||||||
|
// with any other test that touches Nodes or Pods.
|
||||||
|
// Because of this we need to have precise control on what's running in the cluster.
|
||||||
|
// Test scenario:
|
||||||
|
// 1. Find the first ready node on the system, and add a fake resource for test
|
||||||
|
// 2. Create one with affinity to the particular node that uses 70% of the fake resource.
|
||||||
|
// 3. Wait for the pod to be scheduled.
|
||||||
|
// 4. Create another pod with affinity to the particular node that needs 20% of the fake resource and
|
||||||
|
// an overhead set as 25% of the fake resource.
|
||||||
|
// 5. Make sure this additional pod is not scheduled.
|
||||||
|
|
||||||
|
ginkgo.Context("validates pod overhead is considered along with resource limits of pods that are allowed to run", func() {
|
||||||
|
var testNodeName string
|
||||||
|
var handler string
|
||||||
|
var beardsecond v1.ResourceName = "example.com/beardsecond"
|
||||||
|
|
||||||
|
ginkgo.BeforeEach(func() {
|
||||||
|
WaitForStableCluster(cs, masterNodes)
|
||||||
|
ginkgo.By("Add RuntimeClass and fake resource")
|
||||||
|
|
||||||
|
// find a node which can run a pod:
|
||||||
|
testNodeName = GetNodeThatCanRunPod(f)
|
||||||
|
|
||||||
|
// Get node object:
|
||||||
|
node, err := cs.CoreV1().Nodes().Get(context.TODO(), testNodeName, metav1.GetOptions{})
|
||||||
|
framework.ExpectNoError(err, "unable to get node object for node %v", testNodeName)
|
||||||
|
|
||||||
|
// update Node API object with a fake resource
|
||||||
|
nodeCopy := node.DeepCopy()
|
||||||
|
nodeCopy.ResourceVersion = "0"
|
||||||
|
|
||||||
|
nodeCopy.Status.Capacity[beardsecond] = resource.MustParse("1000")
|
||||||
|
_, err = cs.CoreV1().Nodes().UpdateStatus(context.TODO(), nodeCopy, metav1.UpdateOptions{})
|
||||||
|
framework.ExpectNoError(err, "unable to apply fake resource to %v", testNodeName)
|
||||||
|
|
||||||
|
// Register a runtimeClass with overhead set as 25% of the available beard-seconds
|
||||||
|
handler = e2enode.PreconfiguredRuntimeClassHandler(framework.TestContext.ContainerRuntime)
|
||||||
|
|
||||||
|
rc := &nodev1beta1.RuntimeClass{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{Name: handler},
|
||||||
|
Handler: handler,
|
||||||
|
Overhead: &nodev1beta1.Overhead{
|
||||||
|
PodFixed: v1.ResourceList{
|
||||||
|
beardsecond: resource.MustParse("250"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
_, err = cs.NodeV1beta1().RuntimeClasses().Create(context.TODO(), rc, metav1.CreateOptions{})
|
||||||
|
framework.ExpectNoError(err, "failed to create RuntimeClass resource")
|
||||||
|
})
|
||||||
|
|
||||||
|
ginkgo.AfterEach(func() {
|
||||||
|
ginkgo.By("Remove fake resource and RuntimeClass")
|
||||||
|
// remove fake resource:
|
||||||
|
if testNodeName != "" {
|
||||||
|
// Get node object:
|
||||||
|
node, err := cs.CoreV1().Nodes().Get(context.TODO(), testNodeName, metav1.GetOptions{})
|
||||||
|
framework.ExpectNoError(err, "unable to get node object for node %v", testNodeName)
|
||||||
|
|
||||||
|
nodeCopy := node.DeepCopy()
|
||||||
|
// force it to update
|
||||||
|
nodeCopy.ResourceVersion = "0"
|
||||||
|
delete(nodeCopy.Status.Capacity, beardsecond)
|
||||||
|
_, err = cs.CoreV1().Nodes().UpdateStatus(context.TODO(), nodeCopy, metav1.UpdateOptions{})
|
||||||
|
framework.ExpectNoError(err, "unable to update node %v", testNodeName)
|
||||||
|
}
|
||||||
|
|
||||||
|
// remove RuntimeClass
|
||||||
|
cs.NodeV1beta1().RuntimeClasses().Delete(context.TODO(), e2enode.PreconfiguredRuntimeClassHandler(framework.TestContext.ContainerRuntime), nil)
|
||||||
|
})
|
||||||
|
|
||||||
|
ginkgo.It("verify pod overhead is accounted for", func() {
|
||||||
|
framework.ExpectEqual(testNodeName != "", true)
|
||||||
|
|
||||||
|
ginkgo.By("Starting Pod to consume most of the node's resource.")
|
||||||
|
|
||||||
|
// Create pod which requires 70% of the available beard-seconds.
|
||||||
|
fillerPod := createPausePod(f, pausePodConfig{
|
||||||
|
Name: "filler-pod-" + string(uuid.NewUUID()),
|
||||||
|
Resources: &v1.ResourceRequirements{
|
||||||
|
Requests: v1.ResourceList{beardsecond: resource.MustParse("700")},
|
||||||
|
Limits: v1.ResourceList{beardsecond: resource.MustParse("700")},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
// Wait for filler pod to schedule.
|
||||||
|
framework.ExpectNoError(e2epod.WaitForPodRunningInNamespace(cs, fillerPod))
|
||||||
|
|
||||||
|
ginkgo.By("Creating another pod that requires unavailable amount of resources.")
|
||||||
|
// Create another pod that requires 20% of available beard-seconds, but utilizes the RuntimeClass
|
||||||
|
// which defines a pod overhead that requires an additional 25%.
|
||||||
|
// This pod should remain pending as at least 70% of beard-second in
|
||||||
|
// the node are already consumed.
|
||||||
|
podName := "additional-pod" + string(uuid.NewUUID())
|
||||||
|
conf := pausePodConfig{
|
||||||
|
RuntimeClassHandler: &handler,
|
||||||
|
Name: podName,
|
||||||
|
Labels: map[string]string{"name": "additional"},
|
||||||
|
Resources: &v1.ResourceRequirements{
|
||||||
|
Limits: v1.ResourceList{beardsecond: resource.MustParse("200")},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
WaitForSchedulerAfterAction(f, createPausePodAction(f, conf), ns, podName, false)
|
||||||
|
verifyResult(cs, 1, 1, ns)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
// This test verifies we don't allow scheduling of pods in a way that sum of
|
// This test verifies we don't allow scheduling of pods in a way that sum of
|
||||||
// resource requests of pods is greater than machines capacity.
|
// resource requests of pods is greater than machines capacity.
|
||||||
// It assumes that cluster add-on pods stay stable and cannot be run in parallel
|
// It assumes that cluster add-on pods stay stable and cannot be run in parallel
|
||||||
@ -715,6 +827,7 @@ func initPausePod(f *framework.Framework, conf pausePodConfig) *v1.Pod {
|
|||||||
NodeSelector: conf.NodeSelector,
|
NodeSelector: conf.NodeSelector,
|
||||||
Affinity: conf.Affinity,
|
Affinity: conf.Affinity,
|
||||||
TopologySpreadConstraints: conf.TopologySpreadConstraints,
|
TopologySpreadConstraints: conf.TopologySpreadConstraints,
|
||||||
|
RuntimeClassName: conf.RuntimeClassHandler,
|
||||||
Containers: []v1.Container{
|
Containers: []v1.Container{
|
||||||
{
|
{
|
||||||
Name: conf.Name,
|
Name: conf.Name,
|
||||||
|
Loading…
Reference in New Issue
Block a user