// maybeDeleteTerminatingPod non-gracefully deletes pods that are terminating // that should not be gracefully terminated. func (nc *NodeController) maybeDeleteTerminatingPod(obj interface{}) { pod, ok := obj.(*api.Pod) if !ok { tombstone, ok := obj.(cache.DeletedFinalStateUnknown) if !ok { glog.Errorf("Couldn't get object from tombstone %#v", obj) return } pod, ok = tombstone.Obj.(*api.Pod) if !ok { glog.Errorf("Tombstone contained object that is not a Pod %#v", obj) return } } // consider only terminating pods if pod.DeletionTimestamp == nil { return } // delete terminating pods that have not yet been scheduled if len(pod.Spec.NodeName) == 0 { utilruntime.HandleError(nc.forcefullyDeletePod(pod)) return } nodeObj, found, err := nc.nodeStore.Store.GetByKey(pod.Spec.NodeName) if err != nil { // this can only happen if the Store.KeyFunc has a problem creating // a key for the pod. If it happens once, it will happen again so // don't bother requeuing the pod. utilruntime.HandleError(err) return } // delete terminating pods that have been scheduled on // nonexistent nodes if !found { glog.Warningf("Unable to find Node: %v, deleting all assigned Pods.", pod.Spec.NodeName) utilruntime.HandleError(nc.forcefullyDeletePod(pod)) return } // delete terminating pods that have been scheduled on // nodes that do not support graceful termination // TODO(mikedanese): this can be removed when we no longer // guarantee backwards compatibility of master API to kubelets with // versions less than 1.1.0 node := nodeObj.(*api.Node) v, err := version.Parse(node.Status.NodeInfo.KubeletVersion) if err != nil { glog.V(0).Infof("couldn't parse verions %q of minion: %v", node.Status.NodeInfo.KubeletVersion, err) utilruntime.HandleError(nc.forcefullyDeletePod(pod)) return } if gracefulDeletionVersion.GT(v) { utilruntime.HandleError(nc.forcefullyDeletePod(pod)) return } }
func summarySupported(kubeletVersion string) bool { semver, err := version.Parse(kubeletVersion) if err != nil { glog.Errorf("Unable to parse kubelet version: %q", kubeletVersion) return false } return semver.GE(minSummaryKubeletVersion) }
// nodeRunningOutdatedKubelet returns true if the kubeletVersion reported // in the nodeInfo of the given node is "outdated", meaning < 1.2.0. // Older versions were inflexible and modifying pod.Status directly through // the apiserver would result in unexpected outcomes. func nodeRunningOutdatedKubelet(node *api.Node) bool { v, err := version.Parse(node.Status.NodeInfo.KubeletVersion) if err != nil { glog.Errorf("couldn't parse version %q of node %v", node.Status.NodeInfo.KubeletVersion, err) return true } if podStatusReconciliationVersion.GT(v) { glog.Infof("Node %v running kubelet at (%v) which is less than the minimum version that allows nodecontroller to mark pods NotReady (%v).", node.Name, v, podStatusReconciliationVersion) return true } return false }
// maybeDeleteTerminatingPod non-gracefully deletes pods that are terminating // that should not be gracefully terminated. func (nc *NodeController) maybeDeleteTerminatingPod(obj interface{}) { pod, ok := obj.(*api.Pod) if !ok { return } // consider only terminating pods if pod.DeletionTimestamp == nil { return } // delete terminating pods that have not yet been scheduled if len(pod.Spec.NodeName) == 0 { nc.forcefullyDeletePod(pod) return } nodeObj, found, err := nc.nodeStore.GetByKey(pod.Spec.NodeName) if err != nil { // this can only happen if the Store.KeyFunc has a problem creating // a key for the pod. If it happens once, it will happen again so // don't bother requeuing the pod. utilruntime.HandleError(err) return } // delete terminating pods that have been scheduled on // nonexistant nodes if !found { nc.forcefullyDeletePod(pod) return } // delete terminating pods that have been scheduled on // nodes that do not support graceful termination // TODO(mikedanese): this can be removed when we no longer // guarantee backwards compatibility of master API to kubelets with // versions less than 1.1.0 node := nodeObj.(*api.Node) v, err := version.Parse(node.Status.NodeInfo.KubeletVersion) if err != nil { glog.Infof("couldn't parse verions %q of minion: %v", node.Status.NodeInfo.KubeletVersion, err) nc.forcefullyDeletePod(pod) return } if gracefulDeletionVersion.GT(v) { nc.forcefullyDeletePod(pod) return } }
// TODO: remove this function after 1.6 // returns if the user agent is is kubectl older than v1.4.0 func isOldKubectl(userAgent string) bool { // example userAgent string: kubectl-1.3/v1.3.8 (linux/amd64) kubernetes/e328d5b if !strings.Contains(userAgent, "kubectl") { return false } userAgent = strings.Split(userAgent, " ")[0] subs := strings.Split(userAgent, "/") if len(subs) != 2 { return false } kubectlVersion, versionErr := version.Parse(subs[1]) if versionErr != nil { return false } return kubectlVersion.LT(version.MustParse("v1.4.0")) }