Skip to content

Commit 61dbc03

Browse files
authored
Merge pull request kubernetes#127471 from macsko/add_deletepodsop_to_scheduler_perf
Add deletePodsOp to scheduler_perf
2 parents a872159 + 287b619 commit 61dbc03

File tree

2 files changed

+85
-19
lines changed

2 files changed

+85
-19
lines changed

test/integration/scheduler_perf/config/performance-config.yaml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1333,7 +1333,13 @@
13331333
# Create pods that will be gradually deleted after being scheduled.
13341334
- opcode: createPods
13351335
countParam: $deletingPods
1336+
# Delete scheduled pods, which will generate many AssignedPodDelete events.
1337+
# Each of them will be processed by the scheduling queue.
1338+
# But, the scheduling throughput should only be minimally impacted by the number of gated Pods.
1339+
- opcode: deletePods
1340+
namespace: namespace-3
13361341
deletePodsPerSecond: 50
1342+
skipWaitToCompletion: true
13371343
- opcode: createPods
13381344
countParam: $measurePods
13391345
collectMetrics: true
@@ -1402,7 +1408,10 @@
14021408
countParam: $deletingPods
14031409
podTemplatePath: config/templates/pod-with-finalizer.yaml
14041410
skipWaitToCompletion: true
1411+
- opcode: deletePods
1412+
namespace: namespace-1
14051413
deletePodsPerSecond: 100
1414+
skipWaitToCompletion: true
14061415
- opcode: createPods
14071416
countParam: $measurePods
14081417
collectMetrics: true

test/integration/scheduler_perf/scheduler_perf.go

Lines changed: 76 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ const (
7777
createNamespacesOpcode operationCode = "createNamespaces"
7878
createPodsOpcode operationCode = "createPods"
7979
createPodSetsOpcode operationCode = "createPodSets"
80+
deletePodsOpcode operationCode = "deletePods"
8081
createResourceClaimsOpcode operationCode = "createResourceClaims"
8182
createResourceDriverOpcode operationCode = "createResourceDriver"
8283
churnOpcode operationCode = "churn"
@@ -407,6 +408,7 @@ func (op *op) UnmarshalJSON(b []byte) error {
407408
&createNamespacesOp{},
408409
&createPodsOp{},
409410
&createPodSetsOp{},
411+
&deletePodsOp{},
410412
&createResourceClaimsOp{},
411413
&createResourceDriverOp{},
412414
&churnOp{},
@@ -586,9 +588,6 @@ type createPodsOp struct {
586588
// Optional
587589
PersistentVolumeTemplatePath *string
588590
PersistentVolumeClaimTemplatePath *string
589-
// Number of pods to be deleted per second after they were scheduled. If set to 0, pods are not deleted.
590-
// Optional
591-
DeletePodsPerSecond int
592591
}
593592

594593
func (cpo *createPodsOp) isValid(allowParameterization bool) error {
@@ -604,9 +603,6 @@ func (cpo *createPodsOp) isValid(allowParameterization bool) error {
604603
// use-cases right now.
605604
return fmt.Errorf("collectMetrics and skipWaitToCompletion cannot be true at the same time")
606605
}
607-
if cpo.DeletePodsPerSecond < 0 {
608-
return fmt.Errorf("invalid DeletePodsPerSecond=%d; should be non-negative", cpo.DeletePodsPerSecond)
609-
}
610606
return nil
611607
}
612608

@@ -665,6 +661,46 @@ func (cpso createPodSetsOp) patchParams(w *workload) (realOp, error) {
665661
return &cpso, (&cpso).isValid(true)
666662
}
667663

664+
// deletePodsOp defines an op where previously created pods are deleted.
665+
// The test can block on the completion of this op before moving forward or
666+
// continue asynchronously.
667+
type deletePodsOp struct {
668+
// Must be "deletePods".
669+
Opcode operationCode
670+
// Namespace the pods should be deleted from.
671+
Namespace string
672+
// Labels used to filter the pods to delete.
673+
// If empty, it will delete all Pods in the namespace.
674+
// Optional.
675+
LabelSelector map[string]string
676+
// Whether or not to wait for all pods in this op to be deleted.
677+
// Defaults to false if not specified.
678+
// Optional
679+
SkipWaitToCompletion bool
680+
// Number of pods to be deleted per second.
681+
// If zero, all pods are deleted at once.
682+
// Optional
683+
DeletePodsPerSecond int
684+
}
685+
686+
func (dpo *deletePodsOp) isValid(allowParameterization bool) error {
687+
if dpo.Opcode != deletePodsOpcode {
688+
return fmt.Errorf("invalid opcode %q; expected %q", dpo.Opcode, deletePodsOpcode)
689+
}
690+
if dpo.DeletePodsPerSecond < 0 {
691+
return fmt.Errorf("invalid DeletePodsPerSecond=%d; should be non-negative", dpo.DeletePodsPerSecond)
692+
}
693+
return nil
694+
}
695+
696+
func (dpo *deletePodsOp) collectsMetrics() bool {
697+
return false
698+
}
699+
700+
func (dpo deletePodsOp) patchParams(w *workload) (realOp, error) {
701+
return &dpo, nil
702+
}
703+
668704
// churnOp defines an op where services are created as a part of a workload.
669705
type churnOp struct {
670706
// Must be "churnOp".
@@ -1227,32 +1263,53 @@ func runWorkload(tCtx ktesting.TContext, tc *testCase, w *workload, informerFact
12271263
mu.Unlock()
12281264
}
12291265

1230-
if concreteOp.DeletePodsPerSecond > 0 {
1231-
pods, err := podInformer.Lister().Pods(namespace).List(labels.Everything())
1232-
if err != nil {
1233-
tCtx.Fatalf("op %d: error in listing scheduled pods in the namespace: %v", opIndex, err)
1234-
}
1266+
case *deletePodsOp:
1267+
labelSelector := labels.ValidatedSetSelector(concreteOp.LabelSelector)
12351268

1236-
ticker := time.NewTicker(time.Second / time.Duration(concreteOp.DeletePodsPerSecond))
1237-
defer ticker.Stop()
1269+
podsToDelete, err := podInformer.Lister().Pods(concreteOp.Namespace).List(labelSelector)
1270+
if err != nil {
1271+
tCtx.Fatalf("op %d: error in listing pods in the namespace %s: %v", opIndex, concreteOp.Namespace, err)
1272+
}
12381273

1239-
wg.Add(1)
1240-
go func(opIndex int) {
1241-
defer wg.Done()
1242-
for i := 0; i < len(pods); i++ {
1274+
deletePods := func(opIndex int) {
1275+
if concreteOp.DeletePodsPerSecond > 0 {
1276+
ticker := time.NewTicker(time.Second / time.Duration(concreteOp.DeletePodsPerSecond))
1277+
defer ticker.Stop()
1278+
1279+
for i := 0; i < len(podsToDelete); i++ {
12431280
select {
12441281
case <-ticker.C:
1245-
if err := tCtx.Client().CoreV1().Pods(namespace).Delete(tCtx, pods[i].Name, metav1.DeleteOptions{}); err != nil {
1282+
if err := tCtx.Client().CoreV1().Pods(concreteOp.Namespace).Delete(tCtx, podsToDelete[i].Name, metav1.DeleteOptions{}); err != nil {
12461283
if errors.Is(err, context.Canceled) {
12471284
return
12481285
}
1249-
tCtx.Errorf("op %d: unable to delete pod %v: %v", opIndex, pods[i].Name, err)
1286+
tCtx.Errorf("op %d: unable to delete pod %v: %v", opIndex, podsToDelete[i].Name, err)
12501287
}
12511288
case <-tCtx.Done():
12521289
return
12531290
}
12541291
}
1292+
return
1293+
}
1294+
listOpts := metav1.ListOptions{
1295+
LabelSelector: labelSelector.String(),
1296+
}
1297+
if err := tCtx.Client().CoreV1().Pods(concreteOp.Namespace).DeleteCollection(tCtx, metav1.DeleteOptions{}, listOpts); err != nil {
1298+
if errors.Is(err, context.Canceled) {
1299+
return
1300+
}
1301+
tCtx.Errorf("op %d: unable to delete pods in namespace %v: %v", opIndex, concreteOp.Namespace, err)
1302+
}
1303+
}
1304+
1305+
if concreteOp.SkipWaitToCompletion {
1306+
wg.Add(1)
1307+
go func(opIndex int) {
1308+
defer wg.Done()
1309+
deletePods(opIndex)
12551310
}(opIndex)
1311+
} else {
1312+
deletePods(opIndex)
12561313
}
12571314

12581315
case *churnOp:

0 commit comments

Comments
 (0)