mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-08-05 18:24:07 +00:00
Merge pull request #115768 from AxeZhan/volumebinding
feature(volumebinding): Implement PreScore for VolumeBinding plugin to skip score
This commit is contained in:
commit
c02f5bc0f8
@ -260,6 +260,7 @@ leaderElection:
|
||||
{Name: "NodePorts"},
|
||||
}
|
||||
plugins.PreScore.Enabled = []config.Plugin{
|
||||
{Name: "VolumeBinding"},
|
||||
{Name: "NodeResourcesFit"},
|
||||
{Name: "InterPodAffinity"},
|
||||
{Name: "TaintToleration"},
|
||||
|
@ -107,6 +107,7 @@ var ExpandedPluginsV1 = &config.Plugins{
|
||||
{Name: names.TaintToleration},
|
||||
{Name: names.NodeAffinity},
|
||||
{Name: names.NodeResourcesFit},
|
||||
{Name: names.VolumeBinding},
|
||||
{Name: names.PodTopologySpread},
|
||||
{Name: names.InterPodAffinity},
|
||||
{Name: names.NodeResourcesBalancedAllocation},
|
||||
|
@ -53,6 +53,9 @@ type stateData struct {
|
||||
// it's initialized in the PreFilter phase
|
||||
podVolumesByNode map[string]*PodVolumes
|
||||
podVolumeClaims *PodVolumeClaims
|
||||
// hasStaticBindings declares whether the pod contains one or more StaticBinding.
|
||||
// If not, vloumeBinding will skip score extension point.
|
||||
hasStaticBindings bool
|
||||
sync.Mutex
|
||||
}
|
||||
|
||||
@ -74,6 +77,7 @@ var _ framework.PreFilterPlugin = &VolumeBinding{}
|
||||
var _ framework.FilterPlugin = &VolumeBinding{}
|
||||
var _ framework.ReservePlugin = &VolumeBinding{}
|
||||
var _ framework.PreBindPlugin = &VolumeBinding{}
|
||||
var _ framework.PreScorePlugin = &VolumeBinding{}
|
||||
var _ framework.ScorePlugin = &VolumeBinding{}
|
||||
var _ framework.EnqueueExtensions = &VolumeBinding{}
|
||||
|
||||
@ -258,10 +262,26 @@ func (pl *VolumeBinding) Filter(ctx context.Context, cs *framework.CycleState, p
|
||||
// multiple goroutines call `Filter` on different nodes simultaneously and the `CycleState` may be duplicated, so we must use a local lock here
|
||||
state.Lock()
|
||||
state.podVolumesByNode[node.Name] = podVolumes
|
||||
state.hasStaticBindings = state.hasStaticBindings || (podVolumes != nil && len(podVolumes.StaticBindings) > 0)
|
||||
state.Unlock()
|
||||
return nil
|
||||
}
|
||||
|
||||
// PreScore invoked at the preScore extension point. It checks whether volumeBinding can skip Score
|
||||
func (pl *VolumeBinding) PreScore(ctx context.Context, cs *framework.CycleState, pod *v1.Pod, nodes []*v1.Node) *framework.Status {
|
||||
if pl.scorer == nil {
|
||||
return framework.NewStatus(framework.Skip)
|
||||
}
|
||||
state, err := getStateData(cs)
|
||||
if err != nil {
|
||||
return framework.AsStatus(err)
|
||||
}
|
||||
if state.hasStaticBindings {
|
||||
return nil
|
||||
}
|
||||
return framework.NewStatus(framework.Skip)
|
||||
}
|
||||
|
||||
// Score invoked at the score extension point.
|
||||
func (pl *VolumeBinding) Score(ctx context.Context, cs *framework.CycleState, pod *v1.Pod, nodeName string) (int64, *framework.Status) {
|
||||
if pl.scorer == nil {
|
||||
|
@ -85,6 +85,7 @@ func TestVolumeBinding(t *testing.T) {
|
||||
wantStateAfterPreFilter *stateData
|
||||
wantFilterStatus []*framework.Status
|
||||
wantScores []int64
|
||||
wantPreScoreStatus *framework.Status
|
||||
}{
|
||||
{
|
||||
name: "pod has not pvcs",
|
||||
@ -96,9 +97,7 @@ func TestVolumeBinding(t *testing.T) {
|
||||
wantFilterStatus: []*framework.Status{
|
||||
nil,
|
||||
},
|
||||
wantScores: []int64{
|
||||
0,
|
||||
},
|
||||
wantPreScoreStatus: framework.NewStatus(framework.Skip),
|
||||
},
|
||||
{
|
||||
name: "all bound",
|
||||
@ -125,9 +124,7 @@ func TestVolumeBinding(t *testing.T) {
|
||||
wantFilterStatus: []*framework.Status{
|
||||
nil,
|
||||
},
|
||||
wantScores: []int64{
|
||||
0,
|
||||
},
|
||||
wantPreScoreStatus: framework.NewStatus(framework.Skip),
|
||||
},
|
||||
{
|
||||
name: "all bound with local volumes",
|
||||
@ -164,9 +161,7 @@ func TestVolumeBinding(t *testing.T) {
|
||||
wantFilterStatus: []*framework.Status{
|
||||
nil,
|
||||
},
|
||||
wantScores: []int64{
|
||||
0,
|
||||
},
|
||||
wantPreScoreStatus: framework.NewStatus(framework.Skip),
|
||||
},
|
||||
{
|
||||
name: "PVC does not exist",
|
||||
@ -239,9 +234,7 @@ func TestVolumeBinding(t *testing.T) {
|
||||
wantFilterStatus: []*framework.Status{
|
||||
framework.NewStatus(framework.UnschedulableAndUnresolvable, string(ErrReasonBindConflict)),
|
||||
},
|
||||
wantScores: []int64{
|
||||
0,
|
||||
},
|
||||
wantPreScoreStatus: framework.NewStatus(framework.Skip),
|
||||
},
|
||||
{
|
||||
name: "bound and unbound unsatisfied",
|
||||
@ -279,9 +272,7 @@ func TestVolumeBinding(t *testing.T) {
|
||||
wantFilterStatus: []*framework.Status{
|
||||
framework.NewStatus(framework.UnschedulableAndUnresolvable, string(ErrReasonNodeConflict), string(ErrReasonBindConflict)),
|
||||
},
|
||||
wantScores: []int64{
|
||||
0,
|
||||
},
|
||||
wantPreScoreStatus: framework.NewStatus(framework.Skip),
|
||||
},
|
||||
{
|
||||
name: "pvc not found",
|
||||
@ -320,9 +311,7 @@ func TestVolumeBinding(t *testing.T) {
|
||||
wantFilterStatus: []*framework.Status{
|
||||
framework.NewStatus(framework.UnschedulableAndUnresolvable, `node(s) unavailable due to one or more pvc(s) bound to non-existent pv(s)`),
|
||||
},
|
||||
wantScores: []int64{
|
||||
0,
|
||||
},
|
||||
wantPreScoreStatus: framework.NewStatus(framework.Skip),
|
||||
},
|
||||
{
|
||||
name: "pv not found claim lost",
|
||||
@ -878,6 +867,15 @@ func TestVolumeBinding(t *testing.T) {
|
||||
assert.Equal(t, item.wantFilterStatus[i], gotStatus)
|
||||
}
|
||||
|
||||
t.Logf("Verify: call PreScore and check status")
|
||||
gotPreScoreStatus := p.PreScore(ctx, state, item.pod, item.nodes)
|
||||
if diff := cmp.Diff(item.wantPreScoreStatus, gotPreScoreStatus); diff != "" {
|
||||
t.Errorf("state got after prescore does not match (-want,+got):\n%s", diff)
|
||||
}
|
||||
if !gotPreScoreStatus.IsSuccess() {
|
||||
return
|
||||
}
|
||||
|
||||
t.Logf("Verify: Score")
|
||||
for i, node := range item.nodes {
|
||||
score, status := p.Score(ctx, state, item.pod, node.Name)
|
||||
|
Loading…
Reference in New Issue
Block a user