volcano.sh/volcano@v1.9.0/test/e2e/schedulingaction/allocate.go (about)

     1  /*
     2  Copyright 2021 The Volcano 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 schedulingaction
    18  
    19  import (
    20  	"context"
    21  
    22  	"github.com/onsi/ginkgo/v2"
    23  	"github.com/onsi/gomega"
    24  
    25  	corev1 "k8s.io/api/core/v1"
    26  	"k8s.io/apimachinery/pkg/api/resource"
    27  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    28  
    29  	schedulingv1beta1 "volcano.sh/apis/pkg/apis/scheduling/v1beta1"
    30  
    31  	e2eutil "volcano.sh/volcano/test/e2e/util"
    32  )
    33  
    34  var _ = ginkgo.Describe("Job E2E Test", func() {
    35  	ginkgo.It("allocate work when resource is enough", func() {
    36  		ctx := e2eutil.InitTestContext(e2eutil.Options{
    37  			NodesNumLimit: 2,
    38  			NodesResourceLimit: corev1.ResourceList{
    39  				corev1.ResourceCPU:    resource.MustParse("2000m"),
    40  				corev1.ResourceMemory: resource.MustParse("2048Mi")},
    41  		})
    42  		defer e2eutil.CleanupTestContext(ctx)
    43  
    44  		slot1 := corev1.ResourceList{
    45  			corev1.ResourceCPU:    resource.MustParse("500m"),
    46  			corev1.ResourceMemory: resource.MustParse("512Mi")}
    47  		slot2 := corev1.ResourceList{
    48  			corev1.ResourceCPU:    resource.MustParse("1000m"),
    49  			corev1.ResourceMemory: resource.MustParse("1024Mi")}
    50  
    51  		job := &e2eutil.JobSpec{
    52  			Tasks: []e2eutil.TaskSpec{
    53  				{
    54  					Img: e2eutil.DefaultNginxImage,
    55  					Req: slot1,
    56  					Min: 1,
    57  					Rep: 1,
    58  				},
    59  			},
    60  		}
    61  
    62  		job.Name = "low"
    63  		lowReqJob := e2eutil.CreateJob(ctx, job)
    64  		err := e2eutil.WaitJobReady(ctx, lowReqJob)
    65  		gomega.Expect(err).NotTo(gomega.HaveOccurred())
    66  
    67  		job.Name = "high"
    68  		job.Tasks[0].Req = slot2
    69  		highReqJob := e2eutil.CreateJob(ctx, job)
    70  		err = e2eutil.WaitJobReady(ctx, highReqJob)
    71  		gomega.Expect(err).NotTo(gomega.HaveOccurred())
    72  	})
    73  
    74  	ginkgo.It("allocate don't work when resource is NOT enough", func() {
    75  		ctx := e2eutil.InitTestContext(e2eutil.Options{
    76  			NodesNumLimit: 1,
    77  			NodesResourceLimit: corev1.ResourceList{
    78  				corev1.ResourceCPU:    resource.MustParse("2000m"),
    79  				corev1.ResourceMemory: resource.MustParse("2048Mi")},
    80  		})
    81  		defer e2eutil.CleanupTestContext(ctx)
    82  
    83  		slot1 := corev1.ResourceList{
    84  			corev1.ResourceCPU:    resource.MustParse("500m"),
    85  			corev1.ResourceMemory: resource.MustParse("512Mi")}
    86  		slot2 := corev1.ResourceList{
    87  			corev1.ResourceCPU:    resource.MustParse("1000m"),
    88  			corev1.ResourceMemory: resource.MustParse("1024Mi")}
    89  		slot3 := corev1.ResourceList{
    90  			corev1.ResourceCPU:    resource.MustParse("3000m"),
    91  			corev1.ResourceMemory: resource.MustParse("3072Mi")}
    92  
    93  		job := &e2eutil.JobSpec{
    94  			Tasks: []e2eutil.TaskSpec{
    95  				{
    96  					Img: e2eutil.DefaultNginxImage,
    97  					Req: slot2,
    98  					Min: 1,
    99  					Rep: 1,
   100  				},
   101  			},
   102  		}
   103  
   104  		job.Name = "middle"
   105  		midReqJob := e2eutil.CreateJob(ctx, job)
   106  		err := e2eutil.WaitJobReady(ctx, midReqJob)
   107  		gomega.Expect(err).NotTo(gomega.HaveOccurred())
   108  
   109  		job.Name = "low"
   110  		job.Tasks[0].Req = slot1
   111  		lowReqJob := e2eutil.CreateJob(ctx, job)
   112  		err = e2eutil.WaitJobReady(ctx, lowReqJob)
   113  		gomega.Expect(err).NotTo(gomega.HaveOccurred())
   114  
   115  		job.Name = "high"
   116  		job.Tasks[0].Req = slot3
   117  		highReqJob := e2eutil.CreateJob(ctx, job)
   118  		err = e2eutil.WaitJobPending(ctx, highReqJob)
   119  		gomega.Expect(err).NotTo(gomega.HaveOccurred())
   120  	})
   121  
   122  	ginkgo.It("allocate don't work when podgroup is pending", func() {
   123  		ctx := e2eutil.InitTestContext(e2eutil.Options{
   124  			NodesNumLimit: 2,
   125  			NodesResourceLimit: corev1.ResourceList{
   126  				corev1.ResourceCPU:    resource.MustParse("2000m"),
   127  				corev1.ResourceMemory: resource.MustParse("2048Mi")},
   128  		})
   129  		defer e2eutil.CleanupTestContext(ctx)
   130  
   131  		pgName := "pending-pg"
   132  		pg := &schedulingv1beta1.PodGroup{
   133  			ObjectMeta: metav1.ObjectMeta{
   134  				Namespace: ctx.Namespace,
   135  				Name:      pgName,
   136  			},
   137  			Spec: schedulingv1beta1.PodGroupSpec{
   138  				MinMember:    1,
   139  				MinResources: &e2eutil.ThirtyCPU,
   140  			},
   141  		}
   142  
   143  		_, err := ctx.Vcclient.SchedulingV1beta1().PodGroups(ctx.Namespace).Create(context.TODO(), pg, metav1.CreateOptions{})
   144  		gomega.Expect(err).NotTo(gomega.HaveOccurred())
   145  
   146  		slot1 := corev1.ResourceList{
   147  			corev1.ResourceCPU:    resource.MustParse("500m"),
   148  			corev1.ResourceMemory: resource.MustParse("512Mi")}
   149  
   150  		job := &e2eutil.JobSpec{
   151  			Tasks: []e2eutil.TaskSpec{
   152  				{
   153  					Img: e2eutil.DefaultNginxImage,
   154  					Req: slot1,
   155  					Min: 1,
   156  					Rep: 1,
   157  				},
   158  			},
   159  		}
   160  
   161  		job.Name = "j1"
   162  		existJob := e2eutil.CreateJob(ctx, job)
   163  		err = e2eutil.WaitJobReady(ctx, existJob)
   164  		gomega.Expect(err).NotTo(gomega.HaveOccurred())
   165  
   166  		job.Name = "j2"
   167  		allocateJob := e2eutil.CreateJobWithPodGroup(ctx, job, pgName, map[string]string{})
   168  		err = e2eutil.WaitJobPending(ctx, allocateJob)
   169  		gomega.Expect(err).NotTo(gomega.HaveOccurred())
   170  	})
   171  
   172  	ginkgo.It("allocate don't work when job NOT satisify predicates", func() {
   173  		ctx := e2eutil.InitTestContext(e2eutil.Options{
   174  			NodesNumLimit: 1,
   175  			NodesResourceLimit: corev1.ResourceList{
   176  				corev1.ResourceCPU:    resource.MustParse("2000m"),
   177  				corev1.ResourceMemory: resource.MustParse("2048Mi")},
   178  		})
   179  		defer e2eutil.CleanupTestContext(ctx)
   180  
   181  		slot1 := corev1.ResourceList{
   182  			corev1.ResourceCPU:    resource.MustParse("500m"),
   183  			corev1.ResourceMemory: resource.MustParse("512Mi")}
   184  
   185  		job := &e2eutil.JobSpec{
   186  			Tasks: []e2eutil.TaskSpec{
   187  				{
   188  					Img: e2eutil.DefaultNginxImage,
   189  					Req: slot1,
   190  					Min: 1,
   191  					Rep: 1,
   192  					Labels: map[string]string{
   193  						"job": "for-test-predicate",
   194  					},
   195  				},
   196  			},
   197  		}
   198  
   199  		job.Name = "j1"
   200  		existJob := e2eutil.CreateJob(ctx, job)
   201  		err := e2eutil.WaitJobReady(ctx, existJob)
   202  		gomega.Expect(err).NotTo(gomega.HaveOccurred())
   203  
   204  		job.Name = "j2"
   205  		job.Tasks[0].Affinity = &corev1.Affinity{
   206  			PodAntiAffinity: &corev1.PodAntiAffinity{
   207  				RequiredDuringSchedulingIgnoredDuringExecution: []corev1.PodAffinityTerm{
   208  					{
   209  						LabelSelector: &metav1.LabelSelector{
   210  							MatchExpressions: []metav1.LabelSelectorRequirement{
   211  								{
   212  									Key:      "job",
   213  									Operator: metav1.LabelSelectorOpIn,
   214  									Values: []string{
   215  										"for-test-predicate",
   216  									},
   217  								},
   218  							},
   219  						},
   220  						TopologyKey: corev1.LabelHostname,
   221  					},
   222  				},
   223  			},
   224  		}
   225  		allocateJob := e2eutil.CreateJob(ctx, job)
   226  		err = e2eutil.WaitJobPending(ctx, allocateJob)
   227  		gomega.Expect(err).NotTo(gomega.HaveOccurred())
   228  	})
   229  
   230  	ginkgo.It("allocate don't work when queue is overused", func() {
   231  		q1 := "q1"
   232  		q2 := "q2"
   233  		ctx := e2eutil.InitTestContext(e2eutil.Options{
   234  			Queues:        []string{q1, q2},
   235  			NodesNumLimit: 2,
   236  			NodesResourceLimit: corev1.ResourceList{
   237  				corev1.ResourceCPU:    resource.MustParse("2000m"),
   238  				corev1.ResourceMemory: resource.MustParse("2048Mi")},
   239  		})
   240  
   241  		defer e2eutil.CleanupTestContext(ctx)
   242  
   243  		slot1 := corev1.ResourceList{
   244  			corev1.ResourceCPU:    resource.MustParse("1000m"),
   245  			corev1.ResourceMemory: resource.MustParse("1024Mi")}
   246  		slot2 := corev1.ResourceList{
   247  			corev1.ResourceCPU:    resource.MustParse("1000m"),
   248  			corev1.ResourceMemory: resource.MustParse("1024Mi")}
   249  		slot3 := corev1.ResourceList{
   250  			corev1.ResourceCPU:    resource.MustParse("500m"),
   251  			corev1.ResourceMemory: resource.MustParse("512Mi")}
   252  		slot4 := corev1.ResourceList{
   253  			corev1.ResourceCPU:    resource.MustParse("500m"),
   254  			corev1.ResourceMemory: resource.MustParse("512Mi")}
   255  
   256  		job := &e2eutil.JobSpec{
   257  			Tasks: []e2eutil.TaskSpec{
   258  				{
   259  					Img: e2eutil.DefaultNginxImage,
   260  					Req: slot1,
   261  					Min: 1,
   262  					Rep: 1,
   263  				},
   264  			},
   265  		}
   266  
   267  		job.Name = "j1-q1"
   268  		job.Queue = q1
   269  		queue1Job1 := e2eutil.CreateJob(ctx, job)
   270  		err := e2eutil.WaitJobStateReady(ctx, queue1Job1)
   271  		gomega.Expect(err).NotTo(gomega.HaveOccurred())
   272  
   273  		job.Name = "j2-q1"
   274  		job.Queue = q1
   275  		job.Tasks[0].Req = slot2
   276  		queue1Job2 := e2eutil.CreateJob(ctx, job)
   277  		err = e2eutil.WaitJobStateReady(ctx, queue1Job2)
   278  		gomega.Expect(err).NotTo(gomega.HaveOccurred())
   279  
   280  		job.Name = "j3-q2"
   281  		job.Queue = q2
   282  		job.Tasks[0].Req = slot3
   283  		queue2Job3 := e2eutil.CreateJob(ctx, job)
   284  		err = e2eutil.WaitJobStateReady(ctx, queue2Job3)
   285  		gomega.Expect(err).NotTo(gomega.HaveOccurred())
   286  
   287  		job.Name = "j4-q1"
   288  		job.Queue = q1
   289  		job.Tasks[0].Req = slot4
   290  		queue1Job4 := e2eutil.CreateJob(ctx, job)
   291  		err = e2eutil.WaitJobPending(ctx, queue1Job4)
   292  		gomega.Expect(err).NotTo(gomega.HaveOccurred())
   293  	})
   294  })