-
判断network plugin是否就绪,如果没有就绪,则只有使用hostnework的pod可以进行下面的步骤
go// if err := kl.runtimeState.networkErrors(); err != nil && !kubecontainer.IsHostNetworkPod(pod) { kl.recorder.Eventf(pod, v1.EventTypeWarning, events.NetworkNotReady, "%s: %v", NetworkNotReadyErrorMsg, err) return false, fmt.Errorf("%s: %v", NetworkNotReadyErrorMsg, err) }
-
将pod使用secret和configmap添加到 secret管理器和configmap管理器,让 kubelet的 secret管理器和configmap管理器知道哪些pod在使用改secret或者configmap
scss// 确保kubelet知道pod使用的secret和configmap if !kl.podWorkers.IsPodTerminationRequested(pod.UID) { if kl.secretManager != nil { kl.secretManager.RegisterPod(pod) } if kl.configMapManager != nil { kl.configMapManager.RegisterPod(pod) } }
-
更新或者创建cgroup
goif err := kl.containerManager.UpdateQOSCgroups(); err != nil { klog.V(2).InfoS("Failed to update QoS cgroups while syncing pod", "pod", klog.KObj(pod), "err", err) } // //EnsureExists将pod作为参数,并确保 ////如果启用了qos cgroup层次结构标志,则存在pod cgroup。 ////如果pod cgroup还不存在,这个方法会创建它。 if err := pcm.EnsureExists(pod); err != nil { kl.recorder.Eventf(pod, v1.EventTypeWarning, events.FailedToCreatePodContainer, "unable to ensure pod container exists: %v", err) return false, fmt.Errorf("failed to ensure that the pod: %v cgroups exist and are correctly applied: %v", pod.UID, err) }
-
为pod创建数据目录
go// 创建数据目录,pod所在在的路径,包括volunes,plugins if err := kl.makePodDataDirs(pod); err != nil { kl.recorder.Eventf(pod, v1.EventTypeWarning, events.FailedToMakePodDataDirectories, "error making pod data directories: %v", err) klog.ErrorS(err, "Unable to make pod data directories for pod", "pod", klog.KObj(pod)) return false, err }
-
判断volume是否挂载,等待挂载: volume管理器会持续监听状态,将pv挂载到pod对于卷类型的目录【目录默认是/var/lib/kubelet/pods//{podID}/volumes/{kubernetes.io~卷类型}/{pv名称}】
go// 等待全部的volumes挂载到pod if err := kl.volumeManager.WaitForAttachAndMount(pod); err != nil { kl.recorder.Eventf(pod, v1.EventTypeWarning, events.FailedMountVolume, "Unable to attach or mount volumes: %v", err) klog.ErrorS(err, "Unable to attach or mount volumes for pod; skipping pod", "pod", klog.KObj(pod)) return false, err }
-
调用 cri接口创建沙箱
这里区分k8s版本: 如果是1.24之前
cri由docker-shim实现,docker-shim会调用docker
1、拉取pause镜像
goimage := defaultSandboxImage podSandboxImage := ds.podSandboxImage if len(podSandboxImage) != 0 { image = podSandboxImage } // 检查镜像是否存在,不存在则拉取 if err := ensureSandboxImageExists(ds.client, image); err != nil { return nil, err }
2、创建沙箱【就是容器pause】
csscreateResp, err := ds.client.CreateContainer(*createConfig)
3、创建沙箱检查点
iniif err = ds.checkpointManager.CreateCheckpoint(createResp.ID, constructPodSandboxCheckpoint(config));
4、开始沙箱【pause这个容器】
inierr = ds.client.StartContainer(createResp.ID)
5、设置网络: 调用cni接口设置沙箱网络
arduinoerr = ds.network.SetUpPod(config.GetMetadata().Namespace, config.GetMetadata().Name, cID, config.Annotations, networkOptions)
1.24及之后
【假设是containerd】,则在containerd端实现的cri接口内部还会调用 cni接口配置网络
1、拉取镜像
arduinoimage, err := c.ensureImageExists(ctx, c.config.SandboxImage, config)
2、创建容器
gocontainer, err := c.client.NewContainer(ctx, id, opts...) if err != nil { return nil, fmt.Errorf("failed to create containerd container: %w", err) } // 创建沙箱运行的rootDir sandboxRootDir := c.getSandboxRootDir(id) // 准备沙箱运行的必要文件,只有linux有实际实现: 有resolv.conf,hosts,/dev/shm if err = c.setupSandboxFiles(id, config); // 更新沙箱的网络命名空间路径 c.updateNetNamespacePath(spec, sandbox.NetNSPath) if err := container.Update(ctx,...),
3、调用cni接口设置网络
go// 调用cni设置网络 if err := c.setupPodNetwork(ctx, &sandbox); err != nil { return nil, fmt.Errorf("failed to setup network for sandbox %q: %w", id, err) }
scss// 创建一个沙盒,实际就是pause容器,后续可以将其他的容器加入这个沙盒 podSandboxID, msg, err = m.createPodSandbox(pod, podContainerChanges.Attempt) //
-
开始临时容器【临时容器的的使用需要k8s集群开启临时容器的功能特性】
goif utilfeature.DefaultFeatureGate.Enabled(features.EphemeralContainers) { for _, idx := range podContainerChanges.EphemeralContainersToStart { start("ephemeral container", metrics.EphemeralContainer, ephemeralContainerStartSpec(&pod.Spec.EphemeralContainers[idx])) } }
-
启动初始化容器。需要等待上一个初始化容器执行结束
go// 启动初始化容器 if container := podContainerChanges.NextInitContainerToStart; container != nil { // Start the next init container. if err := start("init container", metrics.InitContainer, containerStartSpec(container)); err != nil { return } // Successfully started the container; clear the entry in the failure klog.V(4).InfoS("Completed init container for pod", "containerName", container.Name, "pod", klog.KObj(pod)) }
-
启动业务容器
go// 启动业务容器 for _, idx := range podContainerChanges.ContainersToStart { start("container", metrics.Container, containerStartSpec(&pod.Spec.Containers[idx])) }
k8s深入:源码分析pod调度完成后kubelet都干了什么?,包含k8s1.24之前和之后的逻辑区别
Coding专栏2024-03-29 14:57
相关推荐
福大大架构师每日一题2 小时前
22.1 k8s不同role级别的服务发现weixin_453965003 小时前
[单master节点k8s部署]30.ceph分布式存储(一)weixin_453965003 小时前
[单master节点k8s部署]32.ceph分布式存储(三)tangdou3690986553 小时前
1分钟搞懂K8S中的NodeSelectorlater_rql6 小时前
k8s-集群部署1weixin_453965008 小时前
[单master节点k8s部署]31.ceph分布式存储(二)大G哥11 小时前
记一次K8S 环境应用nginx stable-alpine 解析内部域名失败排查思路妍妍的宝贝11 小时前
k8s 中微服务之 MetailLB 搭配 ingress-nginx 实现七层负载福大大架构师每日一题13 小时前
23.1 k8s监控中标签relabel的应用和原理程序那点事儿13 小时前
k8s 之动态创建pv失败(踩坑)