diff --git a/pkg/kubelet/kubelet.go b/pkg/kubelet/kubelet.go index 3f49c3424f..b50bf50f37 100644 --- a/pkg/kubelet/kubelet.go +++ b/pkg/kubelet/kubelet.go @@ -102,7 +102,6 @@ import ( "k8s.io/kubernetes/pkg/volume/util/volumehelper" "k8s.io/kubernetes/pkg/watch" "k8s.io/kubernetes/plugin/pkg/scheduler/algorithm/predicates" - "k8s.io/kubernetes/plugin/pkg/scheduler/schedulercache" "k8s.io/kubernetes/third_party/forked/golang/expansion" ) @@ -739,7 +738,7 @@ func NewMainKubelet(kubeCfg *componentconfig.KubeletConfiguration, kubeDeps *Kub klet.appArmorValidator = apparmor.NewValidator(kubeCfg.ContainerRuntime) klet.AddPodAdmitHandler(lifecycle.NewAppArmorAdmitHandler(klet.appArmorValidator)) - + klet.AddPodAdmitHandler(lifecycle.NewPredicateAdmitHandler(klet.getNodeAnyWay)) // apply functional Option's for _, opt := range kubeDeps.Options { opt(klet) @@ -2155,15 +2154,9 @@ func (kl *Kubelet) rejectPod(pod *api.Pod, reason, message string) { // can be admitted, a brief single-word reason and a message explaining why // the pod cannot be admitted. func (kl *Kubelet) canAdmitPod(pods []*api.Pod, pod *api.Pod) (bool, string, string) { - node, err := kl.getNodeAnyWay() - if err != nil { - glog.Errorf("Cannot get Node info: %v", err) - return false, "InvalidNodeInfo", "Kubelet cannot get node info." - } // the kubelet will invoke each pod admit handler in sequence // if any handler rejects, the pod is rejected. - // TODO: move predicate check into a pod admitter // TODO: move out of disk check into a pod admitter // TODO: out of resource eviction should have a pod admitter call-out attrs := &lifecycle.PodAdmitAttributes{Pod: pod, OtherPods: pods} @@ -2172,44 +2165,6 @@ func (kl *Kubelet) canAdmitPod(pods []*api.Pod, pod *api.Pod) (bool, string, str return false, result.Reason, result.Message } } - nodeInfo := schedulercache.NewNodeInfo(pods...) - nodeInfo.SetNode(node) - fit, reasons, err := predicates.GeneralPredicates(pod, nil, nodeInfo) - if err != nil { - message := fmt.Sprintf("GeneralPredicates failed due to %v, which is unexpected.", err) - glog.Warningf("Failed to admit pod %v - %s", format.Pod(pod), message) - return fit, "UnexpectedError", message - } - if !fit { - var reason string - var message string - if len(reasons) == 0 { - message = fmt.Sprint("GeneralPredicates failed due to unknown reason, which is unexpected.") - glog.Warningf("Failed to admit pod %v - %s", format.Pod(pod), message) - return fit, "UnknownReason", message - } - // If there are failed predicates, we only return the first one as a reason. - r := reasons[0] - switch re := r.(type) { - case *predicates.PredicateFailureError: - reason = re.PredicateName - message = re.Error() - glog.V(2).Infof("Predicate failed on Pod: %v, for reason: %v", format.Pod(pod), message) - case *predicates.InsufficientResourceError: - reason = fmt.Sprintf("OutOf%s", re.ResourceName) - message := re.Error() - glog.V(2).Infof("Predicate failed on Pod: %v, for reason: %v", format.Pod(pod), message) - case *predicates.FailureReason: - reason = re.GetReason() - message = fmt.Sprintf("Failure: %s", re.GetReason()) - glog.V(2).Infof("Predicate failed on Pod: %v, for reason: %v", format.Pod(pod), message) - default: - reason = "UnexpectedPredicateFailureType" - message := fmt.Sprintf("GeneralPredicates failed due to %v, which is unexpected.", r) - glog.Warningf("Failed to admit pod %v - %s", format.Pod(pod), message) - } - return fit, reason, message - } // TODO: When disk space scheduling is implemented (#11976), remove the out-of-disk check here and // add the disk space predicate to predicates.GeneralPredicates. if kl.isOutOfDisk() { diff --git a/pkg/kubelet/kubelet_test.go b/pkg/kubelet/kubelet_test.go index af1cdd572a..3d823fb5fe 100644 --- a/pkg/kubelet/kubelet_test.go +++ b/pkg/kubelet/kubelet_test.go @@ -231,6 +231,8 @@ func newTestKubeletWithImageList( kubelet.evictionManager = evictionManager kubelet.AddPodAdmitHandler(evictionAdmitHandler) + // Add this as cleanup predicate pod admitter + kubelet.AddPodAdmitHandler(lifecycle.NewPredicateAdmitHandler(kubelet.getNodeAnyWay)) plug := &volumetest.FakeVolumePlugin{PluginName: "fake", Host: nil} kubelet.volumePluginMgr, err = diff --git a/pkg/kubelet/lifecycle/predicate.go b/pkg/kubelet/lifecycle/predicate.go new file mode 100644 index 0000000000..231ec28d30 --- /dev/null +++ b/pkg/kubelet/lifecycle/predicate.go @@ -0,0 +1,107 @@ +/* +Copyright 2016 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 lifecycle + +import ( + "fmt" + + "github.com/golang/glog" + "k8s.io/kubernetes/pkg/api" + "k8s.io/kubernetes/pkg/kubelet/util/format" + "k8s.io/kubernetes/plugin/pkg/scheduler/algorithm/predicates" + "k8s.io/kubernetes/plugin/pkg/scheduler/schedulercache" +) + +type getNodeAnyWayFuncType func() (*api.Node, error) +type predicateAdmitHandler struct { + getNodeAnyWayFunc getNodeAnyWayFuncType +} + +var _ PodAdmitHandler = &predicateAdmitHandler{} + +func NewPredicateAdmitHandler(getNodeAnyWayFunc getNodeAnyWayFuncType) *predicateAdmitHandler { + return &predicateAdmitHandler{ + getNodeAnyWayFunc, + } +} + +func (w *predicateAdmitHandler) Admit(attrs *PodAdmitAttributes) PodAdmitResult { + node, err := w.getNodeAnyWayFunc() + if err != nil { + glog.Errorf("Cannot get Node info: %v", err) + return PodAdmitResult{ + Admit: false, + Reason: "InvalidNodeInfo", + Message: "Kubelet cannot get node info.", + } + } + pod := attrs.Pod + pods := attrs.OtherPods + nodeInfo := schedulercache.NewNodeInfo(pods...) + nodeInfo.SetNode(node) + fit, reasons, err := predicates.GeneralPredicates(pod, nil, nodeInfo) + if err != nil { + message := fmt.Sprintf("GeneralPredicates failed due to %v, which is unexpected.", err) + glog.Warningf("Failed to admit pod %v - %s", format.Pod(pod), message) + return PodAdmitResult{ + Admit: fit, + Reason: "UnexpectedError", + Message: message, + } + } + if !fit { + var reason string + var message string + if len(reasons) == 0 { + message = fmt.Sprint("GeneralPredicates failed due to unknown reason, which is unexpected.") + glog.Warningf("Failed to admit pod %v - %s", format.Pod(pod), message) + return PodAdmitResult{ + Admit: fit, + Reason: "UnknownReason", + Message: message, + } + } + // If there are failed predicates, we only return the first one as a reason. + r := reasons[0] + switch re := r.(type) { + case *predicates.PredicateFailureError: + reason = re.PredicateName + message = re.Error() + glog.V(2).Infof("Predicate failed on Pod: %v, for reason: %v", format.Pod(pod), message) + case *predicates.InsufficientResourceError: + reason = fmt.Sprintf("OutOf%s", re.ResourceName) + message := re.Error() + glog.V(2).Infof("Predicate failed on Pod: %v, for reason: %v", format.Pod(pod), message) + case *predicates.FailureReason: + reason = re.GetReason() + message = fmt.Sprintf("Failure: %s", re.GetReason()) + glog.V(2).Infof("Predicate failed on Pod: %v, for reason: %v", format.Pod(pod), message) + default: + reason = "UnexpectedPredicateFailureType" + message := fmt.Sprintf("GeneralPredicates failed due to %v, which is unexpected.", r) + glog.Warningf("Failed to admit pod %v - %s", format.Pod(pod), message) + } + return PodAdmitResult{ + Admit: fit, + Reason: reason, + Message: message, + } + } + return PodAdmitResult{ + Admit: true, + } +}