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]))
    }
相关推荐
郝同学的测开笔记21 分钟前
一次业务投诉引发的思考:如何优雅地将K8s服务暴露给外部?
后端·kubernetes
白露与泡影1 小时前
springboot + nacos + k8s 优雅停机
spring boot·后端·kubernetes
_板栗_1 小时前
k8s 中 cpu 核数的理解
云原生·容器·kubernetes
小李飞刀李寻欢1 小时前
使用kubeadm部署Kubernetes(k8s)集群的步骤
linux·服务器·ubuntu·kubernetes·k8s
藥瓿锻2 小时前
2024 CKS题库+详尽解析| 1. kube-bench 修复不安全项
运维·安全·docker·云原生·容器·kubernetes·cks
程序员阿超的博客5 小时前
云原生核心技术 (10/12): K8s 终极实战:从零部署一个 Spring Boot + MySQL + Redis 应用
spring boot·云原生·kubernetes
互联网搬砖老肖7 小时前
Web 架构之 Kubernetes 弹性伸缩策略设计
前端·架构·kubernetes
Akamai中国8 小时前
什么是云计算的边缘原生应用?
人工智能·kubernetes·云计算·边缘计算
昌sit!10 小时前
K8S多维度问题排查
云原生·容器·kubernetes
kylin-运维10 小时前
k8s使用自建nfs做持久化无法控制磁盘使用大小问题处理
云原生·容器·kubernetes