mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-22 19:31:44 +00:00
Add requirements based scheduling.
This commit is contained in:
parent
dc7e3d6601
commit
5d4d60783d
@ -141,7 +141,7 @@ func runTest(t *testing.T, codec runtime.Codec, source runtime.Object) {
|
||||
return
|
||||
} else {
|
||||
if !reflect.DeepEqual(source, obj2) {
|
||||
t.Errorf("1: %v: diff: %v", name, util.ObjectDiff(source, obj2))
|
||||
t.Errorf("1: %v: diff: %v\nCodec: %v\nData: %s\nSource: %#v", name, util.ObjectDiff(source, obj2), codec, string(data), source)
|
||||
return
|
||||
}
|
||||
}
|
||||
@ -152,7 +152,7 @@ func runTest(t *testing.T, codec runtime.Codec, source runtime.Object) {
|
||||
return
|
||||
} else {
|
||||
if !reflect.DeepEqual(source, obj3) {
|
||||
t.Errorf("3: %v: diff: %v", name, util.ObjectDiff(source, obj3))
|
||||
t.Errorf("3: %v: diff: %v\nCodec: %v", name, util.ObjectDiff(source, obj3), codec)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
@ -424,6 +424,8 @@ type Pod struct {
|
||||
|
||||
DesiredState PodState `json:"desiredState,omitempty" yaml:"desiredState,omitempty"`
|
||||
CurrentState PodState `json:"currentState,omitempty" yaml:"currentState,omitempty"`
|
||||
// NodeSelector is a selector which must be true for the pod to fit on a node
|
||||
NodeSelector map[string]string `json:"nodeSelector,omitempty" yaml:"nodeSelector,omitempty"`
|
||||
}
|
||||
|
||||
// ReplicationControllerState is the state of a replication controller, either input (create, update) or as output (list, get).
|
||||
@ -531,6 +533,8 @@ type Minion struct {
|
||||
HostIP string `json:"hostIP,omitempty" yaml:"hostIP,omitempty"`
|
||||
// Resources available on the node
|
||||
NodeResources NodeResources `json:"resources,omitempty" yaml:"resources,omitempty"`
|
||||
// Labels for the node
|
||||
Labels map[string]string `json:"labels,omitempty" yaml:"labels,omitempty"`
|
||||
}
|
||||
|
||||
// MinionList is a list of minions.
|
||||
|
@ -177,6 +177,10 @@ func init() {
|
||||
if err := s.Convert(&in.CurrentState, &out.CurrentState, 0); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := s.Convert(&in.NodeSelector, &out.NodeSelector, 0); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
},
|
||||
func(in *Pod, out *newer.Pod, s conversion.Scope) error {
|
||||
@ -196,6 +200,10 @@ func init() {
|
||||
if err := s.Convert(&in.CurrentState, &out.CurrentState, 0); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := s.Convert(&in.NodeSelector, &out.NodeSelector, 0); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
},
|
||||
|
||||
@ -348,6 +356,9 @@ func init() {
|
||||
if err := s.Convert(&in.ObjectMeta, &out.TypeMeta, 0); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.Convert(&in.Labels, &out.Labels, 0); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
out.HostIP = in.HostIP
|
||||
return s.Convert(&in.NodeResources, &out.NodeResources, 0)
|
||||
@ -359,6 +370,9 @@ func init() {
|
||||
if err := s.Convert(&in.TypeMeta, &out.ObjectMeta, 0); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.Convert(&in.Labels, &out.Labels, 0); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
out.HostIP = in.HostIP
|
||||
return s.Convert(&in.NodeResources, &out.NodeResources, 0)
|
||||
|
@ -395,6 +395,8 @@ type Pod struct {
|
||||
Labels map[string]string `json:"labels,omitempty" yaml:"labels,omitempty"`
|
||||
DesiredState PodState `json:"desiredState,omitempty" yaml:"desiredState,omitempty"`
|
||||
CurrentState PodState `json:"currentState,omitempty" yaml:"currentState,omitempty"`
|
||||
// NodeSelector is a selector which must be true for the pod to fit on a node
|
||||
NodeSelector map[string]string `json:"nodeSelector,omitempty" yaml:"nodeSelector,omitempty"`
|
||||
}
|
||||
|
||||
// ReplicationControllerState is the state of a replication controller, either input (create, update) or as output (list, get).
|
||||
@ -491,6 +493,8 @@ type Minion struct {
|
||||
HostIP string `json:"hostIP,omitempty" yaml:"hostIP,omitempty"`
|
||||
// Resources available on the node
|
||||
NodeResources NodeResources `json:"resources,omitempty" yaml:"resources,omitempty"`
|
||||
// Labels for the node
|
||||
Labels map[string]string `json:"labels,omitempty" yaml:"labels,omitempty"`
|
||||
}
|
||||
|
||||
// MinionList is a list of minions.
|
||||
|
@ -108,6 +108,10 @@ func init() {
|
||||
if err := s.Convert(&in.CurrentState, &out.CurrentState, 0); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := s.Convert(&in.NodeSelector, &out.NodeSelector, 0); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
},
|
||||
func(in *Pod, out *newer.Pod, s conversion.Scope) error {
|
||||
@ -127,6 +131,10 @@ func init() {
|
||||
if err := s.Convert(&in.CurrentState, &out.CurrentState, 0); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := s.Convert(&in.NodeSelector, &out.NodeSelector, 0); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
},
|
||||
|
||||
@ -279,6 +287,9 @@ func init() {
|
||||
if err := s.Convert(&in.ObjectMeta, &out.TypeMeta, 0); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.Convert(&in.Labels, &out.Labels, 0); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
out.HostIP = in.HostIP
|
||||
return s.Convert(&in.NodeResources, &out.NodeResources, 0)
|
||||
@ -290,6 +301,9 @@ func init() {
|
||||
if err := s.Convert(&in.TypeMeta, &out.ObjectMeta, 0); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.Convert(&in.Labels, &out.Labels, 0); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
out.HostIP = in.HostIP
|
||||
return s.Convert(&in.NodeResources, &out.NodeResources, 0)
|
||||
|
@ -360,6 +360,8 @@ type Pod struct {
|
||||
Labels map[string]string `json:"labels,omitempty" yaml:"labels,omitempty"`
|
||||
DesiredState PodState `json:"desiredState,omitempty" yaml:"desiredState,omitempty"`
|
||||
CurrentState PodState `json:"currentState,omitempty" yaml:"currentState,omitempty"`
|
||||
// NodeSelector is a selector which must be true for the pod to fit on a node
|
||||
NodeSelector map[string]string `json:"nodeSelector,omitempty" yaml:"nodeSelector,omitempty"`
|
||||
}
|
||||
|
||||
// ReplicationControllerState is the state of a replication controller, either input (create, update) or as output (list, get).
|
||||
@ -456,6 +458,8 @@ type Minion struct {
|
||||
HostIP string `json:"hostIP,omitempty" yaml:"hostIP,omitempty"`
|
||||
// Resources available on the node
|
||||
NodeResources NodeResources `json:"resources,omitempty" yaml:"resources,omitempty"`
|
||||
// Labels for the node
|
||||
Labels map[string]string `json:"labels,omitempty" yaml:"labels,omitempty"`
|
||||
}
|
||||
|
||||
// MinionList is a list of minions.
|
||||
|
@ -432,6 +432,8 @@ type PodSpec struct {
|
||||
Volumes []Volume `json:"volumes" yaml:"volumes"`
|
||||
Containers []Container `json:"containers" yaml:"containers"`
|
||||
RestartPolicy RestartPolicy `json:"restartPolicy,omitempty" yaml:"restartPolicy,omitempty"`
|
||||
// NodeSelector is a selector which must be true for the pod to fit on a node
|
||||
NodeSelector map[string]string `json:"nodeSelector,omitempty" yaml:"nodeSelector,omitempty"`
|
||||
}
|
||||
|
||||
// PodStatus represents information about the status of a pod. Status may trail the actual
|
||||
|
@ -79,7 +79,7 @@ func testPrinter(t *testing.T, printer ResourcePrinter, unmarshalFunc func(data
|
||||
t.Errorf("Unexpeted error: %#v", err)
|
||||
}
|
||||
if !reflect.DeepEqual(obj, &objOut) {
|
||||
t.Errorf("Unexpected inequality: %#v vs %#v", obj, &objOut)
|
||||
t.Errorf("Unexpected inequality:\n%#v \nvs\n%#v", obj, &objOut)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -139,6 +139,29 @@ func NewResourceFitPredicate(info NodeInfo) FitPredicate {
|
||||
return fit.PodFitsResources
|
||||
}
|
||||
|
||||
func NewSelectorMatchPredicate(info NodeInfo) FitPredicate {
|
||||
selector := &NodeSelector{
|
||||
info: info,
|
||||
}
|
||||
return selector.PodSelectorMatches
|
||||
}
|
||||
|
||||
type NodeSelector struct {
|
||||
info NodeInfo
|
||||
}
|
||||
|
||||
func (n *NodeSelector) PodSelectorMatches(pod api.Pod, existingPods []api.Pod, node string) (bool, error) {
|
||||
if len(pod.NodeSelector) == 0 {
|
||||
return true, nil
|
||||
}
|
||||
selector := labels.SelectorFromSet(pod.NodeSelector)
|
||||
minion, err := n.info.GetNodeInfo(node)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
return selector.Matches(labels.Set(minion.Labels)), nil
|
||||
}
|
||||
|
||||
func PodFitsPorts(pod api.Pod, existingPods []api.Pod, node string) (bool, error) {
|
||||
for _, scheduledPod := range existingPods {
|
||||
for _, container := range pod.DesiredState.Manifest.Containers {
|
||||
|
@ -234,3 +234,77 @@ func TestDiskConflicts(t *testing.T) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestPodFitsSelector(t *testing.T) {
|
||||
tests := []struct {
|
||||
pod api.Pod
|
||||
labels map[string]string
|
||||
fits bool
|
||||
test string
|
||||
}{
|
||||
{
|
||||
pod: api.Pod{},
|
||||
fits: true,
|
||||
test: "no selector",
|
||||
},
|
||||
{
|
||||
pod: api.Pod{
|
||||
NodeSelector: map[string]string{
|
||||
"foo": "bar",
|
||||
},
|
||||
},
|
||||
fits: false,
|
||||
test: "missing labels",
|
||||
},
|
||||
{
|
||||
pod: api.Pod{
|
||||
NodeSelector: map[string]string{
|
||||
"foo": "bar",
|
||||
},
|
||||
},
|
||||
labels: map[string]string{
|
||||
"foo": "bar",
|
||||
},
|
||||
fits: true,
|
||||
test: "same labels",
|
||||
},
|
||||
{
|
||||
pod: api.Pod{
|
||||
NodeSelector: map[string]string{
|
||||
"foo": "bar",
|
||||
},
|
||||
},
|
||||
labels: map[string]string{
|
||||
"foo": "bar",
|
||||
"baz": "blah",
|
||||
},
|
||||
fits: true,
|
||||
test: "node labels are superset",
|
||||
},
|
||||
{
|
||||
pod: api.Pod{
|
||||
NodeSelector: map[string]string{
|
||||
"foo": "bar",
|
||||
"baz": "blah",
|
||||
},
|
||||
},
|
||||
labels: map[string]string{
|
||||
"foo": "bar",
|
||||
},
|
||||
fits: false,
|
||||
test: "node labels are subset",
|
||||
},
|
||||
}
|
||||
for _, test := range tests {
|
||||
node := api.Minion{Labels: test.labels}
|
||||
|
||||
fit := NodeSelector{FakeNodeInfo(node)}
|
||||
fits, err := fit.PodSelectorMatches(test.pod, []api.Pod{}, "machine")
|
||||
if err != nil {
|
||||
t.Errorf("unexpected error: %v", err)
|
||||
}
|
||||
if fits != test.fits {
|
||||
t.Errorf("%s: expected: %v got %v", test.test, test.fits, fits)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user