mirror of https://github.com/k3s-io/k3s
Revert "Remove FailedResourceType and return custom error"
parent
2a7656c0c0
commit
9b415f0300
|
@ -1,40 +0,0 @@
|
||||||
/*
|
|
||||||
Copyright 2016 The Kubernetes Authors All rights reserved.
|
|
||||||
|
|
||||||
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 predicates
|
|
||||||
|
|
||||||
import "fmt"
|
|
||||||
|
|
||||||
var (
|
|
||||||
ErrExceededMaxPodNumber = newInsufficientResourceError("PodCount")
|
|
||||||
ErrInsufficientFreeCPU = newInsufficientResourceError("CPU")
|
|
||||||
ErrInsufficientFreeMemory = newInsufficientResourceError("Memory")
|
|
||||||
)
|
|
||||||
|
|
||||||
// InsufficientResourceError is an error type that indicates what kind of resource limit is
|
|
||||||
// hit and caused the unfitting failure.
|
|
||||||
type InsufficientResourceError struct {
|
|
||||||
// ResourceName tells the name of the resource that is insufficient
|
|
||||||
ResourceName string
|
|
||||||
}
|
|
||||||
|
|
||||||
func newInsufficientResourceError(resourceName string) *InsufficientResourceError {
|
|
||||||
return &InsufficientResourceError{resourceName}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *InsufficientResourceError) Error() string {
|
|
||||||
return fmt.Sprintf("Node didn't have enough resource: %s", e.ResourceName)
|
|
||||||
}
|
|
|
@ -256,6 +256,8 @@ type resourceRequest struct {
|
||||||
memory int64
|
memory int64
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var FailedResourceType string
|
||||||
|
|
||||||
func getResourceRequest(pod *api.Pod) resourceRequest {
|
func getResourceRequest(pod *api.Pod) resourceRequest {
|
||||||
result := resourceRequest{}
|
result := resourceRequest{}
|
||||||
for _, container := range pod.Spec.Containers {
|
for _, container := range pod.Spec.Containers {
|
||||||
|
@ -306,7 +308,8 @@ func (r *ResourceFit) PodFitsResources(pod *api.Pod, existingPods []*api.Pod, no
|
||||||
|
|
||||||
if int64(len(existingPods))+1 > info.Status.Capacity.Pods().Value() {
|
if int64(len(existingPods))+1 > info.Status.Capacity.Pods().Value() {
|
||||||
glog.V(10).Infof("Cannot schedule Pod %+v, because Node %+v is full, running %v out of %v Pods.", podName(pod), node, len(existingPods), info.Status.Capacity.Pods().Value())
|
glog.V(10).Infof("Cannot schedule Pod %+v, because Node %+v is full, running %v out of %v Pods.", podName(pod), node, len(existingPods), info.Status.Capacity.Pods().Value())
|
||||||
return false, ErrExceededMaxPodNumber
|
FailedResourceType = "PodExceedsMaxPodNumber"
|
||||||
|
return false, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
podRequest := getResourceRequest(pod)
|
podRequest := getResourceRequest(pod)
|
||||||
|
@ -318,11 +321,13 @@ func (r *ResourceFit) PodFitsResources(pod *api.Pod, existingPods []*api.Pod, no
|
||||||
_, exceedingCPU, exceedingMemory := CheckPodsExceedingFreeResources(pods, info.Status.Capacity)
|
_, exceedingCPU, exceedingMemory := CheckPodsExceedingFreeResources(pods, info.Status.Capacity)
|
||||||
if len(exceedingCPU) > 0 {
|
if len(exceedingCPU) > 0 {
|
||||||
glog.V(10).Infof("Cannot schedule Pod %+v, because Node %v does not have sufficient CPU", podName(pod), node)
|
glog.V(10).Infof("Cannot schedule Pod %+v, because Node %v does not have sufficient CPU", podName(pod), node)
|
||||||
return false, ErrInsufficientFreeCPU
|
FailedResourceType = "PodExceedsFreeCPU"
|
||||||
|
return false, nil
|
||||||
}
|
}
|
||||||
if len(exceedingMemory) > 0 {
|
if len(exceedingMemory) > 0 {
|
||||||
glog.V(10).Infof("Cannot schedule Pod %+v, because Node %v does not have sufficient Memory", podName(pod), node)
|
glog.V(10).Infof("Cannot schedule Pod %+v, because Node %v does not have sufficient Memory", podName(pod), node)
|
||||||
return false, ErrInsufficientFreeMemory
|
FailedResourceType = "PodExceedsFreeMemory"
|
||||||
|
return false, nil
|
||||||
}
|
}
|
||||||
glog.V(10).Infof("Schedule Pod %+v on Node %+v is allowed, Node is running only %v out of %v Pods.", podName(pod), node, len(pods)-1, info.Status.Capacity.Pods().Value())
|
glog.V(10).Infof("Schedule Pod %+v on Node %+v is allowed, Node is running only %v out of %v Pods.", podName(pod), node, len(pods)-1, info.Status.Capacity.Pods().Value())
|
||||||
return true, nil
|
return true, nil
|
||||||
|
|
|
@ -80,7 +80,6 @@ func TestPodFitsResources(t *testing.T) {
|
||||||
existingPods []*api.Pod
|
existingPods []*api.Pod
|
||||||
fits bool
|
fits bool
|
||||||
test string
|
test string
|
||||||
wErr error
|
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
pod: &api.Pod{},
|
pod: &api.Pod{},
|
||||||
|
@ -89,7 +88,6 @@ func TestPodFitsResources(t *testing.T) {
|
||||||
},
|
},
|
||||||
fits: true,
|
fits: true,
|
||||||
test: "no resources requested always fits",
|
test: "no resources requested always fits",
|
||||||
wErr: nil,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
pod: newResourcePod(resourceRequest{milliCPU: 1, memory: 1}),
|
pod: newResourcePod(resourceRequest{milliCPU: 1, memory: 1}),
|
||||||
|
@ -98,7 +96,6 @@ func TestPodFitsResources(t *testing.T) {
|
||||||
},
|
},
|
||||||
fits: false,
|
fits: false,
|
||||||
test: "too many resources fails",
|
test: "too many resources fails",
|
||||||
wErr: ErrInsufficientFreeCPU,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
pod: newResourcePod(resourceRequest{milliCPU: 1, memory: 1}),
|
pod: newResourcePod(resourceRequest{milliCPU: 1, memory: 1}),
|
||||||
|
@ -107,7 +104,6 @@ func TestPodFitsResources(t *testing.T) {
|
||||||
},
|
},
|
||||||
fits: true,
|
fits: true,
|
||||||
test: "both resources fit",
|
test: "both resources fit",
|
||||||
wErr: nil,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
pod: newResourcePod(resourceRequest{milliCPU: 1, memory: 2}),
|
pod: newResourcePod(resourceRequest{milliCPU: 1, memory: 2}),
|
||||||
|
@ -116,7 +112,6 @@ func TestPodFitsResources(t *testing.T) {
|
||||||
},
|
},
|
||||||
fits: false,
|
fits: false,
|
||||||
test: "one resources fits",
|
test: "one resources fits",
|
||||||
wErr: ErrInsufficientFreeMemory,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
pod: newResourcePod(resourceRequest{milliCPU: 5, memory: 1}),
|
pod: newResourcePod(resourceRequest{milliCPU: 5, memory: 1}),
|
||||||
|
@ -125,7 +120,6 @@ func TestPodFitsResources(t *testing.T) {
|
||||||
},
|
},
|
||||||
fits: true,
|
fits: true,
|
||||||
test: "equal edge case",
|
test: "equal edge case",
|
||||||
wErr: nil,
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -134,8 +128,8 @@ func TestPodFitsResources(t *testing.T) {
|
||||||
|
|
||||||
fit := ResourceFit{FakeNodeInfo(node)}
|
fit := ResourceFit{FakeNodeInfo(node)}
|
||||||
fits, err := fit.PodFitsResources(test.pod, test.existingPods, "machine")
|
fits, err := fit.PodFitsResources(test.pod, test.existingPods, "machine")
|
||||||
if !reflect.DeepEqual(err, test.wErr) {
|
if err != nil {
|
||||||
t.Errorf("%s: unexpected error: %v, want: %v", test.test, err, test.wErr)
|
t.Errorf("unexpected error: %v", err)
|
||||||
}
|
}
|
||||||
if fits != test.fits {
|
if fits != test.fits {
|
||||||
t.Errorf("%s: expected: %v got %v", test.test, test.fits, fits)
|
t.Errorf("%s: expected: %v got %v", test.test, test.fits, fits)
|
||||||
|
@ -147,7 +141,6 @@ func TestPodFitsResources(t *testing.T) {
|
||||||
existingPods []*api.Pod
|
existingPods []*api.Pod
|
||||||
fits bool
|
fits bool
|
||||||
test string
|
test string
|
||||||
wErr error
|
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
pod: &api.Pod{},
|
pod: &api.Pod{},
|
||||||
|
@ -156,7 +149,6 @@ func TestPodFitsResources(t *testing.T) {
|
||||||
},
|
},
|
||||||
fits: false,
|
fits: false,
|
||||||
test: "even without specified resources predicate fails when there's no available ips",
|
test: "even without specified resources predicate fails when there's no available ips",
|
||||||
wErr: ErrExceededMaxPodNumber,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
pod: newResourcePod(resourceRequest{milliCPU: 1, memory: 1}),
|
pod: newResourcePod(resourceRequest{milliCPU: 1, memory: 1}),
|
||||||
|
@ -165,7 +157,6 @@ func TestPodFitsResources(t *testing.T) {
|
||||||
},
|
},
|
||||||
fits: false,
|
fits: false,
|
||||||
test: "even if both resources fit predicate fails when there's no available ips",
|
test: "even if both resources fit predicate fails when there's no available ips",
|
||||||
wErr: ErrExceededMaxPodNumber,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
pod: newResourcePod(resourceRequest{milliCPU: 5, memory: 1}),
|
pod: newResourcePod(resourceRequest{milliCPU: 5, memory: 1}),
|
||||||
|
@ -174,7 +165,6 @@ func TestPodFitsResources(t *testing.T) {
|
||||||
},
|
},
|
||||||
fits: false,
|
fits: false,
|
||||||
test: "even for equal edge case predicate fails when there's no available ips",
|
test: "even for equal edge case predicate fails when there's no available ips",
|
||||||
wErr: ErrExceededMaxPodNumber,
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
for _, test := range notEnoughPodsTests {
|
for _, test := range notEnoughPodsTests {
|
||||||
|
@ -182,8 +172,8 @@ func TestPodFitsResources(t *testing.T) {
|
||||||
|
|
||||||
fit := ResourceFit{FakeNodeInfo(node)}
|
fit := ResourceFit{FakeNodeInfo(node)}
|
||||||
fits, err := fit.PodFitsResources(test.pod, test.existingPods, "machine")
|
fits, err := fit.PodFitsResources(test.pod, test.existingPods, "machine")
|
||||||
if !reflect.DeepEqual(err, test.wErr) {
|
if err != nil {
|
||||||
t.Errorf("%s: unexpected error: %v, want: %v", test.test, err, test.wErr)
|
t.Errorf("unexpected error: %v", err)
|
||||||
}
|
}
|
||||||
if fits != test.fits {
|
if fits != test.fits {
|
||||||
t.Errorf("%s: expected: %v got %v", test.test, test.fits, fits)
|
t.Errorf("%s: expected: %v got %v", test.test, test.fits, fits)
|
||||||
|
|
|
@ -127,6 +127,7 @@ func findNodesThatFit(pod *api.Pod, machineToPods map[string][]*api.Pod, predica
|
||||||
for _, node := range nodes.Items {
|
for _, node := range nodes.Items {
|
||||||
fits := true
|
fits := true
|
||||||
for name, predicate := range predicateFuncs {
|
for name, predicate := range predicateFuncs {
|
||||||
|
predicates.FailedResourceType = ""
|
||||||
fit, err := predicate(pod, machineToPods[node.Name], node.Name)
|
fit, err := predicate(pod, machineToPods[node.Name], node.Name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return api.NodeList{}, FailedPredicateMap{}, err
|
return api.NodeList{}, FailedPredicateMap{}, err
|
||||||
|
@ -136,8 +137,8 @@ func findNodesThatFit(pod *api.Pod, machineToPods map[string][]*api.Pod, predica
|
||||||
if _, found := failedPredicateMap[node.Name]; !found {
|
if _, found := failedPredicateMap[node.Name]; !found {
|
||||||
failedPredicateMap[node.Name] = sets.String{}
|
failedPredicateMap[node.Name] = sets.String{}
|
||||||
}
|
}
|
||||||
if re, ok := err.(*predicates.InsufficientResourceError); ok {
|
if predicates.FailedResourceType != "" {
|
||||||
failedPredicateMap[node.Name].Insert(re.ResourceName)
|
failedPredicateMap[node.Name].Insert(predicates.FailedResourceType)
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
failedPredicateMap[node.Name].Insert(name)
|
failedPredicateMap[node.Name].Insert(name)
|
||||||
|
|
Loading…
Reference in New Issue