Skip to content

Commit

Permalink
support service profiling manager
Browse files Browse the repository at this point in the history
  • Loading branch information
luomingmeng committed May 23, 2023
1 parent 4bfefb0 commit 04b7d8e
Show file tree
Hide file tree
Showing 4 changed files with 67 additions and 26 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import (
"k8s.io/apimachinery/pkg/api/errors"

"github.com/kubewharf/katalyst-core/pkg/metaserver"
"github.com/kubewharf/katalyst-core/pkg/metaserver/spd"
)

// PodEnableReclaim checks whether the pod can be reclaimed,
Expand All @@ -43,14 +44,14 @@ func PodEnableReclaim(ctx context.Context, metaServer *metaserver.MetaServer,
return false, err
}

// check whether the pod is degraded
degraded, err := metaServer.ServiceBusinessPerformanceDegraded(ctx, pod)
// get current service performance level of the pod
pLevel, err := metaServer.ServiceBusinessPerformanceLevel(ctx, pod)
if err != nil && !errors.IsNotFound(err) {
return false, err
} else if err != nil {
return true, nil
}

// if pod is degraded, it can not be reclaimed
return !degraded, nil
// if performance level not poor, it can not be reclaimed
return pLevel != spd.PerformanceLevelPoor, nil
}
57 changes: 44 additions & 13 deletions pkg/metaserver/spd/manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,20 @@ import (
"github.com/kubewharf/katalyst-core/pkg/util"
)

// PerformanceLevel is an enumeration type, the smaller the
// positive value, the better the performance
type PerformanceLevel int

const (
PerformanceLevelUnknown PerformanceLevel = -1
PerformanceLevelPerfect PerformanceLevel = 0
PerformanceLevelGood PerformanceLevel = 1
PerformanceLevelPoor PerformanceLevel = 2
)

type ServiceProfilingManager interface {
// ServiceBusinessPerformanceDegraded returns whether the service performance is degraded
ServiceBusinessPerformanceDegraded(ctx context.Context, pod *v1.Pod) (bool, error)
// ServiceBusinessPerformanceLevel returns the service business performance level for the given pod
ServiceBusinessPerformanceLevel(ctx context.Context, pod *v1.Pod) (PerformanceLevel, error)

// ServiceBusinessPerformanceScore returns the service business performance score for the given pod
// The score is in range [0, 100]
Expand All @@ -43,8 +54,8 @@ type ServiceProfilingManager interface {

type DummyServiceProfilingManager struct{}

func (d *DummyServiceProfilingManager) ServiceBusinessPerformanceDegraded(_ context.Context, _ *v1.Pod) (bool, error) {
return false, nil
func (d *DummyServiceProfilingManager) ServiceBusinessPerformanceLevel(_ context.Context, _ *v1.Pod) (PerformanceLevel, error) {
return PerformanceLevelPerfect, nil
}

func (d *DummyServiceProfilingManager) ServiceBusinessPerformanceScore(_ context.Context, _ *v1.Pod) (float64, error) {
Expand Down Expand Up @@ -76,35 +87,55 @@ func (m *serviceProfilingManager) ServiceBusinessPerformanceScore(_ context.Cont
return 1., nil
}

func (m *serviceProfilingManager) ServiceBusinessPerformanceDegraded(ctx context.Context, pod *v1.Pod) (bool, error) {
// ServiceBusinessPerformanceLevel gets the service business performance level by spd, and use the poorest business indicator
// performance level as the service business performance level.
func (m *serviceProfilingManager) ServiceBusinessPerformanceLevel(ctx context.Context, pod *v1.Pod) (PerformanceLevel, error) {
spd, err := m.fetcher.GetSPD(ctx, pod)
if err != nil {
return false, err
return PerformanceLevelUnknown, err
}

indicatorTarget, err := util.GetServiceBusinessIndicatorTarget(spd)
if err != nil {
return false, err
return PerformanceLevelUnknown, err
}

indicatorValue, err := util.GetServiceBusinessIndicatorValue(spd)
if err != nil {
return false, err
return PerformanceLevelUnknown, err
}

indicatorLevelMap := make(map[string]PerformanceLevel)
for indicatorName, target := range indicatorTarget {
if _, ok := indicatorValue[indicatorName]; !ok {
indicatorLevelMap[indicatorName] = PerformanceLevelUnknown
continue
}

if target.UpperBound != nil && indicatorValue[indicatorName] > *target.UpperBound {
return true, nil
indicatorLevelMap[indicatorName] = PerformanceLevelPoor
} else if target.LowerBound != nil && indicatorValue[indicatorName] < *target.LowerBound {
indicatorLevelMap[indicatorName] = PerformanceLevelPerfect
} else {
indicatorLevelMap[indicatorName] = PerformanceLevelGood
}
}

if target.LowerBound != nil && indicatorValue[indicatorName] < *target.LowerBound {
return true, nil
// calculate the poorest performance level of indicator as the final performance level
result := PerformanceLevelUnknown
for indicator, level := range indicatorLevelMap {
// if indicator level unknown just return error because indicator current value not found
if level == PerformanceLevelUnknown {
return PerformanceLevelUnknown, fmt.Errorf("indicator %s current value not found", indicator)
}

return false, nil
// choose the higher value of performance level, which is has poorer performance
if result < level {
result = level
}
}

return false, nil
return result, nil
}

func (m *serviceProfilingManager) Run(ctx context.Context) {
Expand Down
18 changes: 9 additions & 9 deletions pkg/metaserver/spd/manager_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ import (
"github.com/kubewharf/katalyst-core/pkg/metrics"
)

func Test_serviceProfilingManager_ServiceBusinessPerformanceDegraded(t *testing.T) {
func Test_serviceProfilingManager_ServiceBusinessPerformanceLevel(t *testing.T) {
type fields struct {
nodeName string
spd *workloadapis.ServiceProfileDescriptor
Expand All @@ -50,11 +50,11 @@ func Test_serviceProfilingManager_ServiceBusinessPerformanceDegraded(t *testing.
name string
fields fields
args args
want bool
want PerformanceLevel
wantErr bool
}{
{
name: "service performance no degraded",
name: "service performance is good",
fields: fields{
nodeName: "node-1",
spd: &workloadapis.ServiceProfileDescriptor{
Expand Down Expand Up @@ -117,7 +117,7 @@ func Test_serviceProfilingManager_ServiceBusinessPerformanceDegraded(t *testing.
},
},
},
want: false,
want: PerformanceLevelGood,
},
{
name: "service performance large than upper bound",
Expand Down Expand Up @@ -179,7 +179,7 @@ func Test_serviceProfilingManager_ServiceBusinessPerformanceDegraded(t *testing.
},
},
},
want: true,
want: PerformanceLevelPoor,
},
{
name: "service performance lower than lower bound",
Expand Down Expand Up @@ -241,7 +241,7 @@ func Test_serviceProfilingManager_ServiceBusinessPerformanceDegraded(t *testing.
},
},
},
want: true,
want: PerformanceLevelPerfect,
},
}
for _, tt := range tests {
Expand All @@ -267,13 +267,13 @@ func Test_serviceProfilingManager_ServiceBusinessPerformanceDegraded(t *testing.

go m.Run(context.Background())

got, err := m.ServiceBusinessPerformanceDegraded(context.Background(), tt.args.pod)
got, err := m.ServiceBusinessPerformanceLevel(context.Background(), tt.args.pod)
if (err != nil) != tt.wantErr {
t.Errorf("ServiceBusinessPerformanceDegraded() error = %v, wantErr %v", err, tt.wantErr)
t.Errorf("ServiceBusinessPerformanceLevel() error = %v, wantErr %v", err, tt.wantErr)
return
}
if got != tt.want {
t.Errorf("ServiceBusinessPerformanceDegraded() got = %v, want %v", got, tt.want)
t.Errorf("ServiceBusinessPerformanceLevel() got = %v, want %v", got, tt.want)
}
})
}
Expand Down
9 changes: 9 additions & 0 deletions pkg/util/spd_indicator.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,15 @@ func GetServiceBusinessIndicatorTarget(spd *workloadapis.ServiceProfileDescripto
continue
}
}

// check whether target indicator is validated
if targetIndicator.LowerBound != nil && targetIndicator.UpperBound != nil &&
*targetIndicator.LowerBound > *targetIndicator.UpperBound {
errList = append(errList, fmt.Errorf("lower bound %v is higher than uppoer bound %v for indicator %s",
*targetIndicator.LowerBound, *targetIndicator.UpperBound, indicator.Name))
continue
}

indicators[string(indicator.Name)] = targetIndicator
}

Expand Down

0 comments on commit 04b7d8e

Please sign in to comment.