添加pod
1触发HandlePodAdditions函数进行创建
case kubetypes.ADD:klog.V(2).InfoS("SyncLoop ADD", "source", u.Source, "pods", klog.KObjs(u.Pods))handler.HandlePodAdditions(u.Pods)func (kl *Kubelet) HandlePodAdditions(pods []*v1.Pod) {start := kl.clock.Now()sort.Sort(sliceutils.PodsByCreationTime(pods))for _, pod := range pods {existingPods := kl.podManager.GetPods() kl.podManager.AddPod(pod)if kubetypes.IsMirrorPod(pod) {kl.handleMirrorPod(pod, start)continue}if !kl.podWorkers.IsPodTerminationRequested(pod.UID) {activePods := kl.filterOutTerminatedPods(existingPods)if ok, reason, message := kl.canAdmitPod(activePods, pod); !ok {kl.rejectPod(pod, reason, message)continue}}mirrorPod, _ := kl.podManager.GetMirrorPodByPod(pod)kl.dispatchWork(pod, kubetypes.SyncPodCreate, mirrorPod, start)kl.probeManager.AddPod(pod)}
}
2.把所有pod进行校验,留下所有已经承认或者的pod。
func (kl *Kubelet) filterOutInactivePods(pods []*v1.Pod) []*v1.Pod {filteredPods := make([]*v1.Pod, 0, len(pods))for _, p := range pods {if kl.podWorkers.IsPodKnownTerminated(p.UID) {continue}if kl.isAdmittedPodTerminal(p) && !kl.podWorkers.IsPodTerminationRequested(p.UID) {continue}filteredPods = append(filteredPods, p)}return filteredPods
}
3.校验是否能在node上创建
第四行为函数校验,这里情况比较多,不全部贴代码,大概是验证一下pod的可创建型,有以下几种函数
func (kl *Kubelet) canAdmitPod(pods []*v1.Pod, pod *v1.Pod) (bool, string, string) {attrs := &lifecycle.PodAdmitAttributes{Pod: pod, OtherPods: pods}for _, podAdmitHandler := range kl.admitHandlers {if result := podAdmitHandler.Admit(attrs); !result.Admit {return false, result.Reason, result.Message}}return true, "", ""
}
4.校验pod的几个重要函数。这个函数主要检查node是否可以
pkg/kubelet/eviction/eviction_manager.go
func (m *managerImpl) Admit(attrs *lifecycle.PodAdmitAttributes) lifecycle.PodAdmitResult {m.RLock()defer m.RUnlock()if len(m.nodeConditions) == 0 {return lifecycle.PodAdmitResult{Admit: true}}if kubelettypes.IsCriticalPod(attrs.Pod) {return lifecycle.PodAdmitResult{Admit: true}}nodeOnlyHasMemoryPressureCondition := hasNodeCondition(m.nodeConditions, v1.NodeMemoryPressure) && len(m.nodeConditions) == 1if nodeOnlyHasMemoryPressureCondition {notBestEffort := v1.PodQOSBestEffort != v1qos.GetPodQOS(attrs.Pod)if notBestEffort {return lifecycle.PodAdmitResult{Admit: true}}if v1helper.TolerationsTolerateTaint(attrs.Pod.Spec.Tolerations, &v1.Taint{Key: v1.TaintNodeMemoryPressure,Effect: v1.TaintEffectNoSchedule,}) {return lifecycle.PodAdmitResult{Admit: true}}}klog.InfoS("Failed to admit pod to node", "pod", klog.KObj(attrs.Pod), "nodeCondition", m.nodeConditions)return lifecycle.PodAdmitResult{Admit: false,Reason: Reason,Message: fmt.Sprintf(nodeConditionMessageFmt, m.nodeConditions),}
}
4.1.获得pod的QOS等级。官方文档说是每个容器的limits和requests都需要相等才是Guaranteed,其实是判断所有容器的总和
func GetPodQOS(pod *v1.Pod) v1.PodQOSClass {requests := v1.ResourceList{}limits := v1.ResourceList{}zeroQuantity := resource.MustParse("0")isGuaranteed := trueallContainers := []v1.Container{}allContainers = append(allContainers, pod.Spec.Containers...)allContainers = append(allContainers, pod.Spec.InitContainers...)for _, container := range allContainers { for name, quantity := range container.Resources.Requests {if !isSupportedQoSComputeResource(name) {continue}if quantity.Cmp(zeroQuantity) == 1 {delta := quantity.DeepCopy()if _, exists := requests[name]; !exists {requests[name] = delta} else {delta.Add(requests[name])requests[name] = delta}}}qosLimitsFound := sets.NewString()for name, quantity := range container.Resources.Limits {if !isSupportedQoSComputeResource(name) {continue}if quantity.Cmp(zeroQuantity) == 1 {qosLimitsFound.Insert(string(name))delta := quantity.DeepCopy()if _, exists := limits[name]; !exists {limits[name] = delta} else {delta.Add(limits[name])limits[name] = delta}}}if !qosLimitsFound.HasAll(string(v1.ResourceMemory), string(v1.ResourceCPU)) {isGuaranteed = false}}if len(requests) == 0 && len(limits) == 0 {return v1.PodQOSBestEffort}if isGuaranteed {for name, req := range requests {if lim, exists := limits[name]; !exists || lim.Cmp(req) != 0 {isGuaranteed = falsebreak}}}if isGuaranteed &&len(requests) == len(limits) {return v1.PodQOSGuaranteed}return v1.PodQOSBurstable
}
5.验证sysctls。有的容器需要修改系统内核,这里需要对准许修改的内核做校验
func (w *patternAllowlist) Admit(attrs *lifecycle.PodAdmitAttributes) lifecycle.PodAdmitResult {pod := attrs.Podif pod.Spec.SecurityContext == nil || len(pod.Spec.SecurityContext.Sysctls) == 0 {return lifecycle.PodAdmitResult{Admit: true,}}var hostNet, hostIPC boolif pod.Spec.SecurityContext != nil {hostNet = pod.Spec.HostNetworkhostIPC = pod.Spec.HostIPC}for _, s := range pod.Spec.SecurityContext.Sysctls {if err := w.validateSysctl(s.Name, hostNet, hostIPC); err != nil {return lifecycle.PodAdmitResult{Admit: false,Reason: ForbiddenReason,Message: fmt.Sprintf("forbidden sysctl: %v", err),}}}return lifecycle.PodAdmitResult{Admit: true,}
}
6.验证资源是否足够
func (w *predicateAdmitHandler) Admit(attrs *PodAdmitAttributes) PodAdmitResult {node, err := w.getNodeAnyWayFunc()if err != nil {klog.ErrorS(err, "Cannot get Node info")return PodAdmitResult{Admit: false,Reason: "InvalidNodeInfo",Message: "Kubelet cannot get node info.",}}admitPod := attrs.Pod //要添加的podpods := attrs.OtherPods //所有占用资源的podnodeInfo := schedulerframework.NewNodeInfo(pods...) //把pod信息存入到nodeinfo里(流程6.1)nodeInfo.SetNode(node) //把运行中的node和node的可用资源复制给nodeInfoif err = w.pluginResourceUpdateFunc(nodeInfo, attrs); err != nil { //更新插件资源message := fmt.Sprintf("Update plugin resources failed due to %v, which is unexpected.", err)klog.InfoS("Failed to admit pod", "pod", klog.KObj(admitPod), "message", message)return PodAdmitResult{Admit: false,Reason: "UnexpectedAdmissionError",Message: message,}}podWithoutMissingExtendedResources := removeMissingExtendedResources(admitPod, nodeInfo)//验证node里不符合的pod的扩展请求(requests下的)reasons := generalFilter(podWithoutMissingExtendedResources, nodeInfo)//验证pod资源是否都没问题(scheduler的函数验证)fit := len(reasons) == 0if !fit {//资源有问题,例cpu超出reasons, err = w.admissionFailureHandler.HandleAdmissionFailure(admitPod, reasons)//在检测一次是否可以接纳(判断优先级,或者是静态pod)fit = len(reasons) == 0 && err == nilif err != nil {message := fmt.Sprintf("Unexpected error while attempting to recover from admission failure: %v", err)klog.InfoS("Failed to admit pod, unexpected error while attempting to recover from admission failure", "pod", klog.KObj(admitPod), "err", err)return PodAdmitResult{Admit: fit,Reason: "UnexpectedAdmissionError",Message: message,}}}if !fit {var reason stringvar message stringif len(reasons) == 0 {message = fmt.Sprint("GeneralPredicates failed due to unknown reason, which is unexpected.")klog.InfoS("Failed to admit pod: GeneralPredicates failed due to unknown reason, which is unexpected", "pod", klog.KObj(admitPod))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 *PredicateFailureError: //算法错误类型reason = re.PredicateNamemessage = re.Error()klog.V(2).InfoS("Predicate failed on Pod", "pod", klog.KObj(admitPod), "err", message)case *InsufficientResourceError: //资源类型错误,如cpu不足,reason = fmt.Sprintf("OutOf%s", re.ResourceName)message = re.Error()klog.V(2).InfoS("Predicate failed on Pod", "pod", klog.KObj(admitPod), "err", message)default:reason = "UnexpectedPredicateFailureType"message = fmt.Sprintf("GeneralPredicates failed due to %v, which is unexpected.", r)klog.InfoS("Failed to admit pod", "pod", klog.KObj(admitPod), "err", message)}return PodAdmitResult{ //返回错误信息及其类型Admit: fit,Reason: reason,Message: message,}}if rejectPodAdmissionBasedOnOSSelector(admitPod, node) {//验证标签return PodAdmitResult{Admit: false,Reason: "PodOSSelectorNodeLabelDoesNotMatch",Message: "Failed to admit pod as the `kubernetes.io/os` label doesn't match node label",}}if rejectPodAdmissionBasedOnOSField(admitPod) {//验证pod.spec.OSreturn PodAdmitResult{Admit: false,Reason: "PodOSNotSupported",Message: "Failed to admit pod as the OS field doesn't match node OS",}}return PodAdmitResult{Admit: true,}
}
7.加入资源和亲和性
func (n *NodeInfo) AddPodInfo(podInfo *PodInfo) {res, non0CPU, non0Mem := calculateResource(podInfo.Pod)//res为总数据,non0CPU为非0的资源占比n.Requested.MilliCPU += res.MilliCPUn.Requested.Memory += res.Memoryn.Requested.EphemeralStorage += res.EphemeralStorageif n.Requested.ScalarResources == nil && len(res.ScalarResources) > 0 {n.Requested.ScalarResources = map[v1.ResourceName]int64{}}for rName, rQuant := range res.ScalarResources {n.Requested.ScalarResources[rName] += rQuant}n.NonZeroRequested.MilliCPU += non0CPUn.NonZeroRequested.Memory += non0Memn.Pods = append(n.Pods, podInfo)if podWithAffinity(podInfo.Pod) {n.PodsWithAffinity = append(n.PodsWithAffinity, podInfo)}if podWithRequiredAntiAffinity(podInfo.Pod) {n.PodsWithRequiredAntiAffinity = append(n.PodsWithRequiredAntiAffinity, podInfo)}n.updateUsedPorts(podInfo.Pod, true)n.updatePVCRefCounts(podInfo.Pod, true)n.Generation = nextGeneration()
}