Handle resource.Quantity changes in eviction thresholds

This commit is contained in:
Clayton Coleman 2016-05-18 10:27:59 -04:00
parent 5e4308f91d
commit e3c8c4c22b
No known key found for this signature in database
GPG Key ID: 3D16906B4F1C5CB3
4 changed files with 23 additions and 22 deletions

View File

@ -148,7 +148,7 @@ func parseThresholdStatement(statement string) (Threshold, error) {
return Threshold{ return Threshold{
Signal: signal, Signal: signal,
Operator: operator, Operator: operator,
Value: quantity, Value: &quantity,
}, nil }, nil
} }
@ -213,14 +213,10 @@ func podUsage(podStats statsapi.PodStats) (api.ResourceList, error) {
// disk usage (if known) // disk usage (if known)
// TODO: need to handle volumes // TODO: need to handle volumes
for _, fsStats := range []*statsapi.FsStats{container.Rootfs, container.Logs} { for _, fsStats := range []*statsapi.FsStats{container.Rootfs, container.Logs} {
if err := disk.Add(*diskUsage(fsStats)); err != nil { disk.Add(*diskUsage(fsStats))
return nil, err
}
} }
// memory usage (if known) // memory usage (if known)
if err := memory.Add(*memoryUsage(container.Memory)); err != nil { memory.Add(*memoryUsage(container.Memory))
return nil, err
}
} }
return api.ResourceList{ return api.ResourceList{
api.ResourceMemory: memory, api.ResourceMemory: memory,
@ -430,7 +426,7 @@ func makeSignalObservations(summaryProvider stats.SummaryProvider) (signalObserv
statsFunc := cachedStatsFunc(summary.Pods) statsFunc := cachedStatsFunc(summary.Pods)
// build an evaluation context for current eviction signals // build an evaluation context for current eviction signals
result := signalObservations{} result := signalObservations{}
result[SignalMemoryAvailable] = *resource.NewQuantity(int64(*summary.Node.Memory.AvailableBytes), resource.BinarySI) result[SignalMemoryAvailable] = resource.NewQuantity(int64(*summary.Node.Memory.AvailableBytes), resource.BinarySI)
return result, statsFunc, nil return result, statsFunc, nil
} }
@ -446,7 +442,7 @@ func thresholdsMet(thresholds []Threshold, observations signalObservations) []Th
} }
// determine if we have met the specified threshold // determine if we have met the specified threshold
thresholdMet := false thresholdMet := false
thresholdResult := threshold.Value.Cmp(observed) thresholdResult := threshold.Value.Cmp(*observed)
switch threshold.Operator { switch threshold.Operator {
case OpLessThan: case OpLessThan:
thresholdMet = thresholdResult > 0 thresholdMet = thresholdResult > 0
@ -538,7 +534,7 @@ func hasNodeCondition(inputs []api.NodeConditionType, item api.NodeConditionType
// hasThreshold returns true if the node condition is in the input list // hasThreshold returns true if the node condition is in the input list
func hasThreshold(inputs []Threshold, item Threshold) bool { func hasThreshold(inputs []Threshold, item Threshold) bool {
for _, input := range inputs { for _, input := range inputs {
if input.GracePeriod == item.GracePeriod && input.Operator == item.Operator && input.Signal == item.Signal && input.Value.Cmp(item.Value) == 0 { if input.GracePeriod == item.GracePeriod && input.Operator == item.Operator && input.Signal == item.Signal && input.Value.Cmp(*item.Value) == 0 {
return true return true
} }
} }

View File

@ -30,6 +30,11 @@ import (
"k8s.io/kubernetes/pkg/types" "k8s.io/kubernetes/pkg/types"
) )
func quantityMustParse(value string) *resource.Quantity {
q := resource.MustParse(value)
return &q
}
func TestParseThresholdConfig(t *testing.T) { func TestParseThresholdConfig(t *testing.T) {
gracePeriod, _ := time.ParseDuration("30s") gracePeriod, _ := time.ParseDuration("30s")
testCases := map[string]struct { testCases := map[string]struct {
@ -55,12 +60,12 @@ func TestParseThresholdConfig(t *testing.T) {
{ {
Signal: SignalMemoryAvailable, Signal: SignalMemoryAvailable,
Operator: OpLessThan, Operator: OpLessThan,
Value: resource.MustParse("150Mi"), Value: quantityMustParse("150Mi"),
}, },
{ {
Signal: SignalMemoryAvailable, Signal: SignalMemoryAvailable,
Operator: OpLessThan, Operator: OpLessThan,
Value: resource.MustParse("300Mi"), Value: quantityMustParse("300Mi"),
GracePeriod: gracePeriod, GracePeriod: gracePeriod,
}, },
}, },
@ -145,7 +150,7 @@ 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
} }
// TestOrderedByQoS ensures we order BestEffort < Burstable < Guaranteed // TestOrderedByQoS ensures we order BestEffort < Burstable < Guaranteed
@ -348,7 +353,7 @@ func TestThresholdsMet(t *testing.T) {
hardThreshold := Threshold{ hardThreshold := Threshold{
Signal: SignalMemoryAvailable, Signal: SignalMemoryAvailable,
Operator: OpLessThan, Operator: OpLessThan,
Value: resource.MustParse("1Gi"), Value: quantityMustParse("1Gi"),
} }
testCases := map[string]struct { testCases := map[string]struct {
thresholds []Threshold thresholds []Threshold
@ -363,14 +368,14 @@ func TestThresholdsMet(t *testing.T) {
"threshold-met": { "threshold-met": {
thresholds: []Threshold{hardThreshold}, thresholds: []Threshold{hardThreshold},
observations: signalObservations{ observations: signalObservations{
SignalMemoryAvailable: resource.MustParse("500Mi"), SignalMemoryAvailable: quantityMustParse("500Mi"),
}, },
result: []Threshold{hardThreshold}, result: []Threshold{hardThreshold},
}, },
"threshold-not-met": { "threshold-not-met": {
thresholds: []Threshold{hardThreshold}, thresholds: []Threshold{hardThreshold},
observations: signalObservations{ observations: signalObservations{
SignalMemoryAvailable: resource.MustParse("2Gi"), SignalMemoryAvailable: quantityMustParse("2Gi"),
}, },
result: []Threshold{}, result: []Threshold{},
}, },
@ -387,7 +392,7 @@ func TestThresholdsFirstObservedAt(t *testing.T) {
hardThreshold := Threshold{ hardThreshold := Threshold{
Signal: SignalMemoryAvailable, Signal: SignalMemoryAvailable,
Operator: OpLessThan, Operator: OpLessThan,
Value: resource.MustParse("1Gi"), Value: quantityMustParse("1Gi"),
} }
now := unversioned.Now() now := unversioned.Now()
oldTime := unversioned.NewTime(now.Time.Add(-1 * time.Minute)) oldTime := unversioned.NewTime(now.Time.Add(-1 * time.Minute))
@ -435,12 +440,12 @@ func TestThresholdsMetGracePeriod(t *testing.T) {
hardThreshold := Threshold{ hardThreshold := Threshold{
Signal: SignalMemoryAvailable, Signal: SignalMemoryAvailable,
Operator: OpLessThan, Operator: OpLessThan,
Value: resource.MustParse("1Gi"), Value: quantityMustParse("1Gi"),
} }
softThreshold := Threshold{ softThreshold := Threshold{
Signal: SignalMemoryAvailable, Signal: SignalMemoryAvailable,
Operator: OpLessThan, Operator: OpLessThan,
Value: resource.MustParse("2Gi"), Value: quantityMustParse("2Gi"),
GracePeriod: 1 * time.Minute, GracePeriod: 1 * time.Minute,
} }
oldTime := unversioned.NewTime(now.Time.Add(-2 * time.Minute)) oldTime := unversioned.NewTime(now.Time.Add(-2 * time.Minute))

View File

@ -103,7 +103,7 @@ func TestMemoryPressure(t *testing.T) {
{ {
Signal: SignalMemoryAvailable, Signal: SignalMemoryAvailable,
Operator: OpLessThan, Operator: OpLessThan,
Value: resource.MustParse("1Gi"), Value: quantityMustParse("1Gi"),
}, },
}, },
} }

View File

@ -55,7 +55,7 @@ type Threshold struct {
// Operator represents a relationship of a signal to a value. // Operator represents a relationship of a signal to a value.
Operator ThresholdOperator Operator ThresholdOperator
// value is a quantity associated with the signal that is evaluated against the specified operator. // value is a quantity associated with the signal that is evaluated against the specified operator.
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
} }
@ -88,7 +88,7 @@ type statsFunc func(pod *api.Pod) (statsapi.PodStats, bool)
type rankFunc func(pods []*api.Pod, stats statsFunc) type rankFunc func(pods []*api.Pod, stats statsFunc)
// signalObservations maps a signal to an observed quantity // signalObservations maps a signal to an observed quantity
type signalObservations map[Signal]resource.Quantity type signalObservations map[Signal]*resource.Quantity
// thresholdsObservedAt maps a threshold to a time that it was observed // thresholdsObservedAt maps a threshold to a time that it was observed
type thresholdsObservedAt map[Threshold]time.Time type thresholdsObservedAt map[Threshold]time.Time