k8s深入:源码分析pod调度完成后kubelet都干了什么?,包含k8s1.24之前和之后的逻辑区别

  1. 判断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)
    }
  2. 将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)
    }
    }
  3. 更新或者创建cgroup

    go 复制代码
    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)
    }
  4. 为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
    }
  5. 判断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
    }
  6. 调用 cri接口创建沙箱

    这里区分k8s版本: 如果是1.24之前

    cri由docker-shim实现,docker-shim会调用docker

    1、拉取pause镜像

    go 复制代码
    image := defaultSandboxImage
    podSandboxImage := ds.podSandboxImage
    if len(podSandboxImage) != 0 {
       image = podSandboxImage
    }
    // 检查镜像是否存在,不存在则拉取
    if err := ensureSandboxImageExists(ds.client, image); err != nil {
       return nil, err
    }

    2、创建沙箱【就是容器pause】

    css 复制代码
    createResp, err := ds.client.CreateContainer(*createConfig)

    3、创建沙箱检查点

    ini 复制代码
    if err = ds.checkpointManager.CreateCheckpoint(createResp.ID, constructPodSandboxCheckpoint(config)); 

    4、开始沙箱【pause这个容器】

    ini 复制代码
    err = ds.client.StartContainer(createResp.ID)

    5、设置网络: 调用cni接口设置沙箱网络

    arduino 复制代码
    err = ds.network.SetUpPod(config.GetMetadata().Namespace, config.GetMetadata().Name, cID, config.Annotations, networkOptions)

    1.24及之后

    【假设是containerd】,则在containerd端实现的cri接口内部还会调用 cni接口配置网络

    1、拉取镜像

    arduino 复制代码
    image, err := c.ensureImageExists(ctx, c.config.SandboxImage, config)

    2、创建容器

    go 复制代码
    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接口设置网络

    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)
    ​
    // 
  7. 开始临时容器【临时容器的的使用需要k8s集群开启临时容器的功能特性】

    go 复制代码
    if utilfeature.DefaultFeatureGate.Enabled(features.EphemeralContainers) {
       for _, idx := range podContainerChanges.EphemeralContainersToStart {
          start("ephemeral container", metrics.EphemeralContainer, ephemeralContainerStartSpec(&pod.Spec.EphemeralContainers[idx]))
       }
    }
  8. 启动初始化容器。需要等待上一个初始化容器执行结束

    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))
    }
  9. 启动业务容器

    go 复制代码
    // 启动业务容器
    for _, idx := range podContainerChanges.ContainersToStart {
       start("container", metrics.Container, containerStartSpec(&pod.Spec.Containers[idx]))
    }
相关推荐
荣光波比17 小时前
K8S(一)—— 云原生与Kubernetes(K8S)从入门到实践:基础概念与操作全解析
云原生·容器·kubernetes
伞啊伞17 小时前
K8s概念基础(一)
云原生·容器·kubernetes
hello_25018 小时前
k8s基础监控promql
云原生·容器·kubernetes
静谧之心20 小时前
在 K8s 上可靠运行 PD 分离推理:RBG 的设计与实现
云原生·容器·golang·kubernetes·开源·pd分离
1024find1 天前
Spark on k8s部署
大数据·运维·容器·spark·kubernetes
能不能别报错2 天前
K8s学习笔记(十六) 探针(Probe)
笔记·学习·kubernetes
能不能别报错2 天前
K8s学习笔记(十四) DaemonSet
笔记·学习·kubernetes
火星MARK2 天前
k8s面试题
容器·面试·kubernetes
赵渝强老师2 天前
【赵渝强老师】Docker容器的资源管理机制
linux·docker·容器·kubernetes
能不能别报错2 天前
K8s学习笔记(十五) pause容器与init容器
笔记·学习·kubernetes