Skip to content

Commit 656455a

Browse files
committed
[YUNIKORN-3193] Quota preemption to be turned off by default (#1061)
Quota preemption is a new functionality. Quota preemption is turned off by default at the partition level via a config. To use quota preemption the 'QuotaPreemptionEnabled' flag in the partition preemption config must be set top 'true'. ---- partitions: - name: default preemption: quotapreemptionenabled: true ---- When turned on the delay for quota preemption is set via the queue property: `preemption.quota.delay`, The property uses the same syntax as the preemption delay: a Golang duration in string form. The default delay is set to '0s' and no preemption will be triggered. Quota preemption is only supported on managed queues not on dynamic queues. Closes: #1061 Signed-off-by: Wilfred Spiegelenburg <[email protected]> (cherry picked from commit 9883272)
1 parent 10f50b2 commit 656455a

File tree

14 files changed

+615
-687
lines changed

14 files changed

+615
-687
lines changed

pkg/common/configs/config.go

Lines changed: 18 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -32,14 +32,14 @@ import (
3232
"github.com/apache/yunikorn-core/pkg/log"
3333
)
3434

35-
// The configuration can contain multiple partitions. Each partition contains the queue definition for a logical
35+
// SchedulerConfig can contain multiple partitions. Each partition contains the queue definition for a logical
3636
// set of scheduler resources.
3737
type SchedulerConfig struct {
3838
Partitions []PartitionConfig
3939
Checksum string `yaml:",omitempty" json:",omitempty"`
4040
}
4141

42-
// The partition object for each partition:
42+
// PartitionConfig for each partition:
4343
// - the name of the partition
4444
// - a list of sub or child queues
4545
// - a list of placement rule definition objects
@@ -60,12 +60,13 @@ type UserGroupResolver struct {
6060
Type string `yaml:"type,omitempty" json:"type,omitempty"`
6161
}
6262

63-
// The partition preemption configuration
63+
// PartitionPreemptionConfig defines global flags for both preemption types
6464
type PartitionPreemptionConfig struct {
65-
Enabled *bool `yaml:",omitempty" json:",omitempty"`
65+
Enabled *bool `yaml:",omitempty" json:",omitempty"`
66+
QuotaPreemptionEnabled *bool `yaml:",omitempty" json:",omitempty"`
6667
}
6768

68-
// The queue object for each queue:
69+
// QueueConfig object for each queue:
6970
// - the name of the queue
7071
// - a resources object to specify resource limits on the queue
7172
// - the maximum number of applications that can run in the queue
@@ -84,20 +85,16 @@ type QueueConfig struct {
8485
ChildTemplate ChildTemplate `yaml:",omitempty" json:",omitempty"`
8586
Queues []QueueConfig `yaml:",omitempty" json:",omitempty"`
8687
Limits []Limit `yaml:",omitempty" json:",omitempty"`
87-
Preemption Preemption `yaml:",omitempty" json:",omitempty"`
88-
}
89-
90-
type Preemption struct {
91-
Delay uint64 `yaml:",omitempty" json:",omitempty"`
9288
}
9389

90+
// ChildTemplate set on a parent queue with settings to be applied to the child created via a placement rule.
9491
type ChildTemplate struct {
9592
MaxApplications uint64 `yaml:",omitempty" json:",omitempty"`
9693
Properties map[string]string `yaml:",omitempty" json:",omitempty"`
9794
Resources Resources `yaml:",omitempty" json:",omitempty"`
9895
}
9996

100-
// The resource limits to set on the queue. The definition allows for an unlimited number of types to be used.
97+
// The Resources limit to apply on the queue. The definition allows for an unlimited number of types to be used.
10198
// The mapping to "known" resources is not handled here.
10299
// - guaranteed resources
103100
// - max resources
@@ -106,12 +103,12 @@ type Resources struct {
106103
Max map[string]string `yaml:",omitempty" json:",omitempty"`
107104
}
108105

109-
// The queue placement rule definition
106+
// The PlacementRule definition:
110107
// - the name of the rule
111108
// - create flag: can the rule create a queue
112109
// - user and group filter to be applied on the callers
113110
// - rule link to allow setting a rule to generate the parent
114-
// - value a generic value interpreted depending on the rule type (i.e queue name for the "fixed" rule
111+
// - value a generic value interpreted depending on the rule type (i.e. queue name for the "fixed" rule
115112
// or the application label name for the "tag" rule)
116113
type PlacementRule struct {
117114
Name string
@@ -121,7 +118,7 @@ type PlacementRule struct {
121118
Value string `yaml:",omitempty" json:",omitempty"`
122119
}
123120

124-
// The user and group filter for a rule.
121+
// Filter for users and groups for a PlacementRule.
125122
// - type of filter (allow or deny filter, empty means allow)
126123
// - list of users to filter (maybe empty)
127124
// - list of groups to filter (maybe empty)
@@ -132,13 +129,13 @@ type Filter struct {
132129
Groups []string `yaml:",omitempty" json:",omitempty"`
133130
}
134131

135-
// A list of limit objects to define limits for a partition or queue
132+
// Limits is a list of Limit objects to define user and group limits for a partition or queue.
136133
type Limits struct {
137134
Limit []Limit
138135
}
139136

140-
// The limit object to specify user and or group limits at different levels in the partition or queues
141-
// Different limits for the same user or group may be defined at different levels in the hierarchy
137+
// A Limit object to specify user and or group limits at different levels in the partition or queues.
138+
// Different limits for the same user or group may be defined at different levels in the hierarchy:
142139
// - limit description (optional)
143140
// - list of users (maybe empty)
144141
// - list of groups (maybe empty)
@@ -152,8 +149,10 @@ type Limit struct {
152149
MaxApplications uint64 `yaml:",omitempty" json:",omitempty"`
153150
}
154151

155-
// Global Node Sorting Policy section
156-
// - type: different type of policies supported (binpacking, fair etc)
152+
// NodeSortingPolicy to be applied globally.
153+
// - type: different type of policies supported (binpacking, fair etc.)
154+
// - resource weight: factor to be applied to comparisons of different resource types when sorting nodes. Types not
155+
// mentioned have a weight of 1.0.
157156
type NodeSortingPolicy struct {
158157
Type string
159158
ResourceWeights map[string]float64 `yaml:",omitempty" json:",omitempty"`

pkg/common/configs/config_test.go

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -626,6 +626,7 @@ partitions:
626626
- name: root
627627
preemption:
628628
enabled: true
629+
quotapreemptionenabled: true
629630
- name: "partition-0"
630631
queues:
631632
- name: root
@@ -637,22 +638,26 @@ partitions:
637638
- name: root
638639
preemption:
639640
enabled: false
641+
quotapreemptionenabled: false
640642
- name: "partition-0"
641643
queues:
642644
- name: root
643645
`
644646
// validate the config and check after the update
645647
conf, err := CreateConfig(data)
646648
assert.NilError(t, err, "should expect no error")
647-
assert.Assert(t, conf.Partitions[0].Preemption.Enabled == nil, "default should be nil")
649+
assert.Assert(t, conf.Partitions[0].Preemption.Enabled == nil, "default preemption should be nil")
650+
assert.Assert(t, conf.Partitions[0].Preemption.QuotaPreemptionEnabled == nil, "default quota preemption should be nil")
648651

649652
conf, err = CreateConfig(dataEnabled)
650653
assert.NilError(t, err, "should expect no error")
651654
assert.Assert(t, *conf.Partitions[0].Preemption.Enabled, "preemption should be enabled")
655+
assert.Assert(t, *conf.Partitions[0].Preemption.QuotaPreemptionEnabled, "quota preemption should be enabled")
652656

653657
conf, err = CreateConfig(dataDisabled)
654658
assert.NilError(t, err, "should expect no error")
655659
assert.Assert(t, !*conf.Partitions[0].Preemption.Enabled, "preemption should be disabled")
660+
assert.Assert(t, !*conf.Partitions[0].Preemption.QuotaPreemptionEnabled, "quota preemption should be disabled")
656661
}
657662

658663
func TestParseRule(t *testing.T) {

pkg/common/configs/configvalidator.go

Lines changed: 18 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ const (
4141
DotReplace = "_dot_"
4242
DefaultPartition = "default"
4343

44+
// constants defining the names for properties
4445
ApplicationSortPolicy = "application.sort.policy"
4546
ApplicationSortPriority = "application.sort.priority"
4647
ApplicationUnschedulableAsksBackoff = "application.unschedasks.backoff"
@@ -49,6 +50,7 @@ const (
4950
PriorityOffset = "priority.offset"
5051
PreemptionPolicy = "preemption.policy"
5152
PreemptionDelay = "preemption.delay"
53+
QuotaPreemptionDelay = "preemption.quota.delay"
5254

5355
// app sort priority values
5456
ApplicationSortPriorityEnabled = "enabled"
@@ -61,35 +63,39 @@ const (
6163
errLastQueueLeaf
6264
)
6365

64-
type placementPathCheckResult int
65-
66-
// Priority
66+
// MinPriority and MaxPriority used in offset calculations. K8s uses an int32 value for priorities, internal calculations
67+
// use int64.
6768
var MinPriority int32 = math.MinInt32
6869
var MaxPriority int32 = math.MaxInt32
6970

71+
// DefaultQuotaPreemptionDelay is 0, no quota preemption by default
72+
var DefaultQuotaPreemptionDelay time.Duration = 0
73+
74+
// DefaultPreemptionDelay is 30 seconds, guaranteed resources must be set to trigger preemption
7075
var DefaultPreemptionDelay = 30 * time.Second
7176
var DefaultAskBackOffDelay = 30 * time.Second
7277

73-
// A queue can be a username with the dot replaced. Most systems allow a 32 character user name.
78+
// QueueNameRegExp to validate the name of a queue.
79+
// A queue can be a username with the dot replaced. Most systems allow a 32 character username.
7480
// The queue name must thus allow for at least that length with the replacement of dots.
7581
var QueueNameRegExp = regexp.MustCompile(`^[a-zA-Z0-9_:#/@-]{1,64}$`)
7682

77-
// User and group name check: systems allow different things POSIX is the base but we need to be lenient and allow more.
78-
// A username must start with a letter(uppercase or lowercase),
79-
// followed by any number of letter(uppercase or lowercase), digits, ':', '#', '/', '_', '.', '@', '-', and may end with '$'.
83+
// UserRegExp to validate a username. Systems allow different things POSIX is the base, but we need to be lenient and allow more.
84+
// A username must start with a letter(uppercase or lowercase), followed by any number of letter(uppercase or lowercase),
85+
// digits, ':', '#', '/', '_', '.', '@', '-', and may end with '$'.
86+
// This supports OIDC compliant names.
8087
var UserRegExp = regexp.MustCompile(`^[_a-zA-Z][a-zA-Z0-9:#/_.@-]*[$]?$`)
8188

82-
// Groups should have a slightly more restrictive regexp (no # / @ or $ at the end)
89+
// GroupRegExp is similar to UserRegExp, groups have a slightly more restrictive regexp (no # / @ or $ at the end)
8390
var GroupRegExp = regexp.MustCompile(`^[_a-zA-Z][a-zA-Z0-9:_.-]*$`)
8491

85-
// all characters that make a name different from a regexp
92+
// SpecialRegExp matches all characters that make a name different from a regexp
8693
var SpecialRegExp = regexp.MustCompile(`[\^$*+?()\[{}|]`)
8794

88-
// The rule maps to a go identifier check that regexp only
95+
// RuleNameRegExp as rule names must map to a go identifier check that regexp only
8996
var RuleNameRegExp = regexp.MustCompile(`^[_a-zA-Z][a-zA-Z0-9_]*$`)
9097

91-
// Minimum Quota change preemption delay
92-
var minQuotaChangePreemptionDelay uint64 = 60
98+
type placementPathCheckResult int
9399

94100
type placementStaticPath struct {
95101
path string
@@ -668,9 +674,6 @@ func checkQueues(queue *QueueConfig, level int) error {
668674
return fmt.Errorf("duplicate child name found with name '%s', level %d", child.Name, level)
669675
}
670676
queueMap[strings.ToLower(child.Name)] = true
671-
if queue.Preemption.Delay != 0 && queue.Preemption.Delay <= minQuotaChangePreemptionDelay {
672-
return fmt.Errorf("invalid preemption delay %d, must be between %d and %d", queue.Preemption.Delay, minQuotaChangePreemptionDelay, uint64(math.MaxUint64))
673-
}
674677
}
675678

676679
// recurse into the depth if this level passed

pkg/common/configs/configvalidator_test.go

Lines changed: 0 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -2327,34 +2327,6 @@ func TestCheckQueues(t *testing.T) { //nolint:funlen
23272327
assert.Equal(t, 2, len(q.Queues), "Expected two queues")
23282328
},
23292329
},
2330-
{
2331-
name: "Invalid Preemption delay for leaf queue",
2332-
queue: &QueueConfig{
2333-
Name: "root",
2334-
Queues: []QueueConfig{
2335-
{Name: "leaf",
2336-
Preemption: Preemption{
2337-
Delay: 10,
2338-
},
2339-
},
2340-
},
2341-
Preemption: Preemption{
2342-
Delay: 10,
2343-
},
2344-
},
2345-
level: 1,
2346-
expectedErrorMsg: "invalid preemption delay 10, must be between 60 and 18446744073709551615",
2347-
},
2348-
{
2349-
name: "Setting Preemption delay on root queue would be ignored",
2350-
queue: &QueueConfig{
2351-
Name: "root",
2352-
Preemption: Preemption{
2353-
Delay: 10,
2354-
},
2355-
},
2356-
level: 0,
2357-
},
23582330
}
23592331

23602332
for _, tc := range testCases {

pkg/scheduler/objects/preemption_utilities_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,7 @@ func resetQueue(queue *Queue) {
158158
queue.maxResource = nil
159159
queue.allocatedResource = nil
160160
queue.guaranteedResource = nil
161-
queue.isQuotaChangePreemptionRunning = false
161+
queue.isQuotaPreemptionRunning = false
162162
queue.preemptingResource = nil
163163
}
164164

0 commit comments

Comments
 (0)