Add "reserve" and "prebind" plugin interfaces for the scheduling framework.

pull/564/head
Bobby (Babak) Salamat 2018-11-08 18:06:15 -08:00
parent 30d61f2f71
commit 7221589dde
5 changed files with 318 additions and 0 deletions

View File

@ -0,0 +1,62 @@
/*
Copyright 2018 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package examples
import (
"fmt"
"k8s.io/api/core/v1"
plugins "k8s.io/kubernetes/pkg/scheduler/plugins/v1alpha1"
)
// MultipointCommunicatingPlugin is an example of a plugin that implements two
// extension points. It communicates through pluginContext with another function.
type MultipointCommunicatingPlugin struct{}
var _ = plugins.ReservePlugin(MultipointCommunicatingPlugin{})
// Name returns name of the plugin. It is used in logs, etc.
func (mc MultipointCommunicatingPlugin) Name() string {
return "multipoint-communicating-plugin"
}
// Reserve is the functions invoked by the framework at "reserve" extension point.
func (mc MultipointCommunicatingPlugin) Reserve(ps plugins.PluginSet, pod *v1.Pod, nodeName string) error {
if pod == nil {
return fmt.Errorf("pod cannot be nil")
}
if pod.Name == "my-test-pod" {
ps.Data().Ctx.SyncWrite(plugins.ContextKey(pod.Name), "never bind")
}
return nil
}
// Prebind is the functions invoked by the framework at "prebind" extension point.
func (mc MultipointCommunicatingPlugin) Prebind(ps plugins.PluginSet, pod *v1.Pod, nodeName string) (bool, error) {
if pod == nil {
return false, fmt.Errorf("pod cannot be nil")
}
if v, e := ps.Data().Ctx.SyncRead(plugins.ContextKey(pod.Name)); e == nil && v == "never bind" {
return false, nil
}
return true, nil
}
// NewMultipointCommunicatingPlugin initializes a new plugin and returns it.
func NewMultipointCommunicatingPlugin() *MultipointCommunicatingPlugin {
return &MultipointCommunicatingPlugin{}
}

View File

@ -0,0 +1,48 @@
/*
Copyright 2018 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package examples
import (
"fmt"
"k8s.io/api/core/v1"
plugins "k8s.io/kubernetes/pkg/scheduler/plugins/v1alpha1"
)
// StatelessPrebindExample is an example of a simple plugin that has no state
// and implements only one hook for prebind.
type StatelessPrebindExample struct{}
var _ = plugins.PrebindPlugin(StatelessPrebindExample{})
// Name returns name of the plugin. It is used in logs, etc.
func (sr StatelessPrebindExample) Name() string {
return "stateless-prebind-plugin-example"
}
// Prebind is the functions invoked by the framework at "prebind" extension point.
func (sr StatelessPrebindExample) Prebind(ps plugins.PluginSet, pod *v1.Pod, nodeName string) (bool, error) {
if pod == nil {
return false, fmt.Errorf("pod cannot be nil")
}
return true, nil
}
// NewStatelessPrebindExample initializes a new plugin and returns it.
func NewStatelessPrebindExample() *StatelessPrebindExample {
return &StatelessPrebindExample{}
}

View File

@ -0,0 +1,68 @@
/*
Copyright 2018 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package examples
import (
"fmt"
"k8s.io/klog"
"k8s.io/api/core/v1"
plugins "k8s.io/kubernetes/pkg/scheduler/plugins/v1alpha1"
)
// StatefulMultipointExample is an example plugin that is executed at multiple extension points.
// This plugin is stateful. It receives arguments at initialization (NewMultipointPlugin)
// and changes its state when it is executed.
type StatefulMultipointExample struct {
mpState map[int]string
numRuns int
}
var _ = plugins.ReservePlugin(&StatefulMultipointExample{})
var _ = plugins.PrebindPlugin(&StatefulMultipointExample{})
// Name returns name of the plugin. It is used in logs, etc.
func (mp *StatefulMultipointExample) Name() string {
return "multipoint-plugin-example"
}
// Reserve is the functions invoked by the framework at "reserve" extension point.
func (mp *StatefulMultipointExample) Reserve(ps plugins.PluginSet, pod *v1.Pod, nodeName string) error {
mp.numRuns++
return nil
}
// Prebind is the functions invoked by the framework at "prebind" extension point.
func (mp *StatefulMultipointExample) Prebind(ps plugins.PluginSet, pod *v1.Pod, nodeName string) (bool, error) {
mp.numRuns++
if pod == nil {
return false, fmt.Errorf("pod must not be nil")
}
return true, nil
}
// NewStatefulMultipointExample initializes a new plugin and returns it.
func NewStatefulMultipointExample(initState ...interface{}) *StatefulMultipointExample {
if len(initState) == 0 {
klog.Error("StatefulMultipointExample needs exactly one argument for initialization")
return nil
}
mp := StatefulMultipointExample{
mpState: initState[0].(map[int]string),
}
return &mp
}

View File

@ -0,0 +1,77 @@
/*
Copyright 2018 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package plugins
import (
"k8s.io/kubernetes/pkg/scheduler/internal/cache"
plugins "k8s.io/kubernetes/pkg/scheduler/plugins/v1alpha1"
)
// DefaultPluginSet is the default plugin registrar used by the default scheduler.
type DefaultPluginSet struct {
data *plugins.PluginData
reservePlugins []plugins.ReservePlugin
prebindPlugins []plugins.PrebindPlugin
}
var _ = plugins.PluginSet(&DefaultPluginSet{})
// ReservePlugins returns a slice of default reserve plugins.
func (r *DefaultPluginSet) ReservePlugins() []plugins.ReservePlugin {
return r.reservePlugins
}
// PrebindPlugins returns a slice of default prebind plugins.
func (r *DefaultPluginSet) PrebindPlugins() []plugins.PrebindPlugin {
return r.prebindPlugins
}
// Data returns a pointer to PluginData.
func (r *DefaultPluginSet) Data() *plugins.PluginData {
return r.data
}
// NewDefaultPluginSet initializes default plugin set and returns its pointer.
func NewDefaultPluginSet(ctx *plugins.PluginContext, schedulerCache *cache.Cache) *DefaultPluginSet {
defaultRegistrar := DefaultPluginSet{
data: &plugins.PluginData{
Ctx: ctx,
SchedulerCache: schedulerCache,
},
}
defaultRegistrar.registerReservePlugins()
defaultRegistrar.registerPrebindPlugins()
return &defaultRegistrar
}
func (r DefaultPluginSet) registerReservePlugins() {
r.reservePlugins = []plugins.ReservePlugin{
// Init functions of all reserve plugins go here. They are called in the
// same order that they are registered.
// Example:
// examples.NewStatefulMultipointExample(map[int]string{1: "test1", 2: "test2"}),
}
}
func (r DefaultPluginSet) registerPrebindPlugins() {
r.prebindPlugins = []plugins.PrebindPlugin{
// Init functions of all prebind plugins go here. They are called in the
// same order that they are registered.
// Example:
// examples.NewStatelessPrebindExample(),
}
}

View File

@ -0,0 +1,63 @@
/*
Copyright 2018 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// This file defines the scheduling framework plugin interfaces.
package v1alpha1
import (
"k8s.io/api/core/v1"
"k8s.io/kubernetes/pkg/scheduler/internal/cache"
)
// PluginData carries information that plugins may need.
type PluginData struct {
Ctx *PluginContext
SchedulerCache *cache.Cache
// We may want to add the scheduling queue here too.
}
// Plugin is the parent type for all the scheduling framework plugins.
type Plugin interface {
Name() string
}
// ReservePlugin is an interface for Reserve plugins. These plugins are called
// at the reservation point, AKA "assume". These are meant to updated the state
// of the plugin. They do not return any value (other than error).
type ReservePlugin interface {
Plugin
// Reserve is called by the scheduling framework when the scheduler cache is
// updated.
Reserve(ps PluginSet, p *v1.Pod, nodeName string) error
}
// PrebindPlugin is an interface that must be implemented by "prebind" plugins.
// These plugins are called before a pod being scheduled
type PrebindPlugin interface {
Plugin
// Prebind is called before binding a pod. All prebind plugins must return
// or the pod will not be sent for binding.
Prebind(ps PluginSet, p *v1.Pod, nodeName string) (bool, error)
}
// PluginSet registers plugins used by the scheduling framework.
// The plugins registered are called at specified points in an scheduling cycle.
type PluginSet interface {
Data() *PluginData
ReservePlugins() []ReservePlugin
PrebindPlugins() []PrebindPlugin
}