[toc]
Pod创建流程代码版本kubelet篇
1. 前言
在k8s的面试中Pod的创建流程是一个常问的问题,而kubelet则无疑重中之重,之前也写过一篇Pod的运行,不过没有涉及到具体的代码,本文尝试用代码的方式,来复数整个核心的流程,同时为了方便记忆,又将整个过程分为:准备、配置、清理、构建运行四个阶段,让我们一起来看下吧, 文末有大图总结
2. 准备阶段
当获取到Pod添加的事件的时候,首先会进行一些基础的工作,我吧这个过程称为准备阶段,准备阶段主要做的事情有如 下:1)加入PodManager 2)准入控制检查 3)分发事件 4)根据Pod添加对应的探针, 让我们一起来看下关键实现
2.1 加入PodManager
PodManager中的功能除了存储Pod的信息,还会进行对应Pod的configMap和secret的管理,当心加入Pod的时候,会检查对应的Pod是否有对应的configMap和secret配置,如果有则就会创建对应的监听器,监听资源的变化,进行本地缓存
除此之外,如果对应的Pod的BootstrapCheckpointAnnotationKey有设定,则还会创建对应的checkpoint,即将pod的配置数据写入到本地磁盘
kl.podManager.AddPod(pod)
2.2 准入控制检查
准入控制检查主要是在运行Pod之前在kubelet上进行Pod运行条件的检查,检查当前节点在scheduler决策完成后到感知到Pod运行这段时间资源是否依旧满足,并且检查Pod的一些特殊资源比如比如sysctl、security等检查,这里我感觉比较重要的两个分别是eviction和predicate, 如果不满足准入检查,则会直接拒绝
2.2.1 eviction准入检查
如果当前节点只存在内存压力,则会根据对应的Pod的QOS等级来判断,如果说不是BestEffort或者容忍内存压力的污点,则会允许,否则则会拒绝运行
nodeOnlyHasMemoryPressureCondition := hasNodeCondition(m.nodeConditions, v1.NodeMemoryPressure) && len(m.nodeConditions) == 1
if nodeOnlyHasMemoryPressureCondition {
// 如果不是PodQOSBestEffort, 则都会尝试运行
notBestEffort := v1.PodQOSBestEffort != v1qos.GetPodQOS(attrs.Pod)
if notBestEffort {
return lifecycle.PodAdmitResult{Admit: true}
}
// 如果对应的Pod容忍内存压力的污点 ,则就可以继续进行其他准入控制器的检查
if v1helper.TolerationsTolerateTaint(attrs.Pod.Spec.Tolerations, &v1.Taint{
Key: v1.TaintNodeMemoryPressure,
Effect: v1.TaintEffectNoSchedule,
}) {
return lifecycle.PodAdmitResult{Admit: true}
}
}
2.2.2 predicate准入检查
predicate准入控制器中的逻辑主要是分为两个部分:1)检查对应的资源是否满足分配请求,同时会记录缺少的资源2)如果是Critical类型的Pod则会按照QOS等级来进行资源的抢占,满足这些高优先的Pod这里的Critical类型的Pod主要包含如下三类:静态Pod、镜像Pod、高优先Pod(优先级高于2000000000)
func (w *predicateAdmitHandler) Admit(attrs *PodAdmitAttributes) PodAdmitResult {
node, err := w.getNodeAnyWayFunc()
// 踢出扩展资源,只进行内存和CPU资源的检查
podWithoutMissingExtendedResources := removeMissingExtendedResources(admitPod, nodeInfo)
// 进行预选算法筛选, 筛选出那些资源不足的资源
fit, reasons, err := predicates.GeneralPredicates(podWithoutMissingExtendedResources, nil, nodeInfo)
if !fit {
// 如果预选失败,则尝试进行抢占
fit, reasons, err = w.admissionFailureHandler.HandleAdmissionFailure(admitPod, reasons)
}
}
2.3 探针管理
k8s里面的探针主要分为三类:startup、readiness、liveness,在Pod通过准入控制检查后,会根据Pod的探针配置创建对应的探针,但是这里的探针并不会真正的进行探测,因为当前还无法感知到对应的pod的状态
kl.probeManager.AddPod(pod)