mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-27 13:37:30 +00:00
Merge pull request #29400 from derekwaynecarr/min-reclaim-parse
Automatic merge from submit-queue Add parsing code in kubelet for eviction-minimum-reclaim The kubelet parses the eviction-minimum-reclaim flag and validates it for correctness. The first two commits are from https://github.com/kubernetes/kubernetes/pull/29329 which has already achieved LGTM.
This commit is contained in:
commit
2e53a24889
@ -187,7 +187,7 @@ func UnsecuredKubeletConfig(s *options.KubeletServer) (*KubeletConfig, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
thresholds, err := eviction.ParseThresholdConfig(s.EvictionHard, s.EvictionSoft, s.EvictionSoftGracePeriod)
|
thresholds, err := eviction.ParseThresholdConfig(s.EvictionHard, s.EvictionSoft, s.EvictionSoftGracePeriod, s.EvictionMinimumReclaim)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -65,7 +65,7 @@ func validSignal(signal Signal) bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ParseThresholdConfig parses the flags for thresholds.
|
// ParseThresholdConfig parses the flags for thresholds.
|
||||||
func ParseThresholdConfig(evictionHard, evictionSoft, evictionSoftGracePeriod string) ([]Threshold, error) {
|
func ParseThresholdConfig(evictionHard, evictionSoft, evictionSoftGracePeriod, evictionMinimumReclaim string) ([]Threshold, error) {
|
||||||
results := []Threshold{}
|
results := []Threshold{}
|
||||||
|
|
||||||
hardThresholds, err := parseThresholdStatements(evictionHard)
|
hardThresholds, err := parseThresholdStatements(evictionHard)
|
||||||
@ -82,6 +82,10 @@ func ParseThresholdConfig(evictionHard, evictionSoft, evictionSoftGracePeriod st
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
minReclaims, err := parseMinimumReclaims(evictionMinimumReclaim)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
for i := range softThresholds {
|
for i := range softThresholds {
|
||||||
signal := softThresholds[i].Signal
|
signal := softThresholds[i].Signal
|
||||||
period, found := gracePeriods[signal]
|
period, found := gracePeriods[signal]
|
||||||
@ -91,6 +95,14 @@ func ParseThresholdConfig(evictionHard, evictionSoft, evictionSoftGracePeriod st
|
|||||||
softThresholds[i].GracePeriod = period
|
softThresholds[i].GracePeriod = period
|
||||||
}
|
}
|
||||||
results = append(results, softThresholds...)
|
results = append(results, softThresholds...)
|
||||||
|
for i := range results {
|
||||||
|
for signal, minReclaim := range minReclaims {
|
||||||
|
if results[i].Signal == signal {
|
||||||
|
results[i].MinReclaim = &minReclaim
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
return results, nil
|
return results, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -186,6 +198,38 @@ func parseGracePeriods(expr string) (map[Signal]time.Duration, error) {
|
|||||||
return results, nil
|
return results, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// parseMinimumReclaims parses the minimum reclaim statements
|
||||||
|
func parseMinimumReclaims(expr string) (map[Signal]resource.Quantity, error) {
|
||||||
|
if len(expr) == 0 {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
results := map[Signal]resource.Quantity{}
|
||||||
|
statements := strings.Split(expr, ",")
|
||||||
|
for _, statement := range statements {
|
||||||
|
parts := strings.Split(statement, "=")
|
||||||
|
if len(parts) != 2 {
|
||||||
|
return nil, fmt.Errorf("invalid eviction minimum reclaim syntax: %v, expected <signal>=<quantity>", statement)
|
||||||
|
}
|
||||||
|
signal := Signal(parts[0])
|
||||||
|
if !validSignal(signal) {
|
||||||
|
return nil, fmt.Errorf(unsupportedEvictionSignal, signal)
|
||||||
|
}
|
||||||
|
// check against duplicate statements
|
||||||
|
if _, found := results[signal]; found {
|
||||||
|
return nil, fmt.Errorf("duplicate eviction minimum reclaim specified for %v", signal)
|
||||||
|
}
|
||||||
|
quantity, err := resource.ParseQuantity(parts[1])
|
||||||
|
if quantity.Sign() < 0 {
|
||||||
|
return nil, fmt.Errorf("negative eviction minimum reclaim specified for %v", signal)
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
results[signal] = quantity
|
||||||
|
}
|
||||||
|
return results, nil
|
||||||
|
}
|
||||||
|
|
||||||
// diskUsage converts used bytes into a resource quantity.
|
// diskUsage converts used bytes into a resource quantity.
|
||||||
func diskUsage(fsStats *statsapi.FsStats) *resource.Quantity {
|
func diskUsage(fsStats *statsapi.FsStats) *resource.Quantity {
|
||||||
if fsStats == nil || fsStats.UsedBytes == nil {
|
if fsStats == nil || fsStats.UsedBytes == nil {
|
||||||
|
@ -41,6 +41,7 @@ func TestParseThresholdConfig(t *testing.T) {
|
|||||||
evictionHard string
|
evictionHard string
|
||||||
evictionSoft string
|
evictionSoft string
|
||||||
evictionSoftGracePeriod string
|
evictionSoftGracePeriod string
|
||||||
|
evictionMinReclaim string
|
||||||
expectErr bool
|
expectErr bool
|
||||||
expectThresholds []Threshold
|
expectThresholds []Threshold
|
||||||
}{
|
}{
|
||||||
@ -48,6 +49,7 @@ func TestParseThresholdConfig(t *testing.T) {
|
|||||||
evictionHard: "",
|
evictionHard: "",
|
||||||
evictionSoft: "",
|
evictionSoft: "",
|
||||||
evictionSoftGracePeriod: "",
|
evictionSoftGracePeriod: "",
|
||||||
|
evictionMinReclaim: "",
|
||||||
expectErr: false,
|
expectErr: false,
|
||||||
expectThresholds: []Threshold{},
|
expectThresholds: []Threshold{},
|
||||||
},
|
},
|
||||||
@ -55,18 +57,21 @@ func TestParseThresholdConfig(t *testing.T) {
|
|||||||
evictionHard: "memory.available<150Mi",
|
evictionHard: "memory.available<150Mi",
|
||||||
evictionSoft: "memory.available<300Mi",
|
evictionSoft: "memory.available<300Mi",
|
||||||
evictionSoftGracePeriod: "memory.available=30s",
|
evictionSoftGracePeriod: "memory.available=30s",
|
||||||
|
evictionMinReclaim: "memory.available=0",
|
||||||
expectErr: false,
|
expectErr: false,
|
||||||
expectThresholds: []Threshold{
|
expectThresholds: []Threshold{
|
||||||
{
|
{
|
||||||
Signal: SignalMemoryAvailable,
|
Signal: SignalMemoryAvailable,
|
||||||
Operator: OpLessThan,
|
Operator: OpLessThan,
|
||||||
Value: quantityMustParse("150Mi"),
|
Value: quantityMustParse("150Mi"),
|
||||||
|
MinReclaim: quantityMustParse("0"),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Signal: SignalMemoryAvailable,
|
Signal: SignalMemoryAvailable,
|
||||||
Operator: OpLessThan,
|
Operator: OpLessThan,
|
||||||
Value: quantityMustParse("300Mi"),
|
Value: quantityMustParse("300Mi"),
|
||||||
GracePeriod: gracePeriod,
|
GracePeriod: gracePeriod,
|
||||||
|
MinReclaim: quantityMustParse("0"),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -74,6 +79,7 @@ func TestParseThresholdConfig(t *testing.T) {
|
|||||||
evictionHard: "mem.available<150Mi",
|
evictionHard: "mem.available<150Mi",
|
||||||
evictionSoft: "",
|
evictionSoft: "",
|
||||||
evictionSoftGracePeriod: "",
|
evictionSoftGracePeriod: "",
|
||||||
|
evictionMinReclaim: "",
|
||||||
expectErr: true,
|
expectErr: true,
|
||||||
expectThresholds: []Threshold{},
|
expectThresholds: []Threshold{},
|
||||||
},
|
},
|
||||||
@ -81,6 +87,7 @@ func TestParseThresholdConfig(t *testing.T) {
|
|||||||
evictionHard: "memory.available<150Mi,memory.available<100Mi",
|
evictionHard: "memory.available<150Mi,memory.available<100Mi",
|
||||||
evictionSoft: "",
|
evictionSoft: "",
|
||||||
evictionSoftGracePeriod: "",
|
evictionSoftGracePeriod: "",
|
||||||
|
evictionMinReclaim: "",
|
||||||
expectErr: true,
|
expectErr: true,
|
||||||
expectThresholds: []Threshold{},
|
expectThresholds: []Threshold{},
|
||||||
},
|
},
|
||||||
@ -88,6 +95,7 @@ func TestParseThresholdConfig(t *testing.T) {
|
|||||||
evictionHard: "memory.available<150Mi,invalid.foo<150Mi",
|
evictionHard: "memory.available<150Mi,invalid.foo<150Mi",
|
||||||
evictionSoft: "",
|
evictionSoft: "",
|
||||||
evictionSoftGracePeriod: "",
|
evictionSoftGracePeriod: "",
|
||||||
|
evictionMinReclaim: "",
|
||||||
expectErr: true,
|
expectErr: true,
|
||||||
expectThresholds: []Threshold{},
|
expectThresholds: []Threshold{},
|
||||||
},
|
},
|
||||||
@ -95,6 +103,7 @@ func TestParseThresholdConfig(t *testing.T) {
|
|||||||
evictionHard: "",
|
evictionHard: "",
|
||||||
evictionSoft: "memory.available<150Mi",
|
evictionSoft: "memory.available<150Mi",
|
||||||
evictionSoftGracePeriod: "",
|
evictionSoftGracePeriod: "",
|
||||||
|
evictionMinReclaim: "",
|
||||||
expectErr: true,
|
expectErr: true,
|
||||||
expectThresholds: []Threshold{},
|
expectThresholds: []Threshold{},
|
||||||
},
|
},
|
||||||
@ -105,9 +114,25 @@ func TestParseThresholdConfig(t *testing.T) {
|
|||||||
expectErr: true,
|
expectErr: true,
|
||||||
expectThresholds: []Threshold{},
|
expectThresholds: []Threshold{},
|
||||||
},
|
},
|
||||||
|
"neg-reclaim": {
|
||||||
|
evictionHard: "",
|
||||||
|
evictionSoft: "",
|
||||||
|
evictionSoftGracePeriod: "",
|
||||||
|
evictionMinReclaim: "memory.available=-300Mi",
|
||||||
|
expectErr: true,
|
||||||
|
expectThresholds: []Threshold{},
|
||||||
|
},
|
||||||
|
"duplicate-reclaim": {
|
||||||
|
evictionHard: "",
|
||||||
|
evictionSoft: "",
|
||||||
|
evictionSoftGracePeriod: "",
|
||||||
|
evictionMinReclaim: "memory.available=-300Mi,memory.available=-100Mi",
|
||||||
|
expectErr: true,
|
||||||
|
expectThresholds: []Threshold{},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
for testName, testCase := range testCases {
|
for testName, testCase := range testCases {
|
||||||
thresholds, err := ParseThresholdConfig(testCase.evictionHard, testCase.evictionSoft, testCase.evictionSoftGracePeriod)
|
thresholds, err := ParseThresholdConfig(testCase.evictionHard, testCase.evictionSoft, testCase.evictionSoftGracePeriod, testCase.evictionMinReclaim)
|
||||||
if testCase.expectErr != (err != nil) {
|
if testCase.expectErr != (err != nil) {
|
||||||
t.Errorf("Err not as expected, test: %v, error expected: %v, actual: %v", testName, testCase.expectErr, err)
|
t.Errorf("Err not as expected, test: %v, error expected: %v, actual: %v", testName, testCase.expectErr, err)
|
||||||
}
|
}
|
||||||
@ -150,7 +175,8 @@ func thresholdEqual(a Threshold, b Threshold) bool {
|
|||||||
return a.GracePeriod == b.GracePeriod &&
|
return a.GracePeriod == b.GracePeriod &&
|
||||||
a.Operator == b.Operator &&
|
a.Operator == b.Operator &&
|
||||||
a.Signal == b.Signal &&
|
a.Signal == b.Signal &&
|
||||||
a.Value.Cmp(*b.Value) == 0
|
a.Value.Cmp(*b.Value) == 0 &&
|
||||||
|
a.MinReclaim.Cmp(*b.MinReclaim) == 0
|
||||||
}
|
}
|
||||||
|
|
||||||
// TestOrderedByQoS ensures we order BestEffort < Burstable < Guaranteed
|
// TestOrderedByQoS ensures we order BestEffort < Burstable < Guaranteed
|
||||||
|
@ -60,6 +60,8 @@ type Threshold struct {
|
|||||||
Value *resource.Quantity
|
Value *resource.Quantity
|
||||||
// GracePeriod represents the amount of time that a threshold must be met before eviction is triggered.
|
// GracePeriod represents the amount of time that a threshold must be met before eviction is triggered.
|
||||||
GracePeriod time.Duration
|
GracePeriod time.Duration
|
||||||
|
// MinReclaim represents the minimum amount of resource to reclaim if the threshold is met.
|
||||||
|
MinReclaim *resource.Quantity
|
||||||
}
|
}
|
||||||
|
|
||||||
// Manager evaluates when an eviction threshold for node stability has been met on the node.
|
// Manager evaluates when an eviction threshold for node stability has been met on the node.
|
||||||
|
Loading…
Reference in New Issue
Block a user