k8s深入:源码分析pod调度完成后kubelet都干了什么?,包含k8s1.24之前和之后的逻辑区别
判断volume是否挂载,等待挂载: volume管理器会持续监听状态,将pv挂载到pod对于卷类型的目录【目录默认是/var/lib/kubelet/pods//{podID}/volumes/{kubernetes.io~卷类型}/{pv名称}】将pod使用secret和configmap添加到 secret管理器和configmap管理器,让 kubelet的 secret管理器和confi
原文连接: 学一下 (suxueit.com)https://suxueit.com/article_detail/tNU6iI4BWZdDRfKqWP3e
-
判断network plugin是否就绪,如果没有就绪,则只有使用hostnework的pod可以进行下面的步骤
// 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
// 确保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
if 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创建数据目录
// 创建数据目录,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名称}】
// 等待全部的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镜像
image := defaultSandboxImage podSandboxImage := ds.podSandboxImage if len(podSandboxImage) != 0 { image = podSandboxImage } // 检查镜像是否存在,不存在则拉取 if err := ensureSandboxImageExists(ds.client, image); err != nil { return nil, err }
2、创建沙箱【就是容器pause】
createResp, err := ds.client.CreateContainer(*createConfig)
3、创建沙箱检查点
if err = ds.checkpointManager.CreateCheckpoint(createResp.ID, constructPodSandboxCheckpoint(config));
4、开始沙箱【pause这个容器】
err = ds.client.StartContainer(createResp.ID)
5、设置网络: 调用cni接口设置沙箱网络
err = ds.network.SetUpPod(config.GetMetadata().Namespace, config.GetMetadata().Name, cID, config.Annotations, networkOptions)
1.24及之后
【假设是containerd】,则在containerd端实现的cri接口内部还会调用 cni接口配置网络
1、拉取镜像
image, err := c.ensureImageExists(ctx, c.config.SandboxImage, config)
2、创建容器
container, 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接口设置网络
// 调用cni设置网络 if err := c.setupPodNetwork(ctx, &sandbox); err != nil { return nil, fmt.Errorf("failed to setup network for sandbox %q: %w", id, err) }
// 创建一个沙盒,实际就是pause容器,后续可以将其他的容器加入这个沙盒 podSandboxID, msg, err = m.createPodSandbox(pod, podContainerChanges.Attempt) //
-
开始临时容器【临时容器的的使用需要k8s集群开启临时容器的功能特性】
if utilfeature.DefaultFeatureGate.Enabled(features.EphemeralContainers) { for _, idx := range podContainerChanges.EphemeralContainersToStart { start("ephemeral container", metrics.EphemeralContainer, ephemeralContainerStartSpec(&pod.Spec.EphemeralContainers[idx])) } }
-
启动初始化容器。需要等待上一个初始化容器执行结束
// 启动初始化容器 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)) }
-
启动业务容器
// 启动业务容器 for _, idx := range podContainerChanges.ContainersToStart { start("container", metrics.Container, containerStartSpec(&pod.Spec.Containers[idx])) }
更多推荐
所有评论(0)