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]))
    }
相关推荐
木鱼时刻1 天前
容器与 Kubernetes 基本概念与架构
容器·架构·kubernetes
chuanauc1 天前
Kubernets K8s 学习
java·学习·kubernetes
庸子2 天前
基于Jenkins和Kubernetes构建DevOps自动化运维管理平台
运维·kubernetes·jenkins
李白你好2 天前
高级运维!Kubernetes(K8S)常用命令的整理集合
运维·容器·kubernetes
Connie14512 天前
k8s多集群管理中的联邦和舰队如何理解?
云原生·容器·kubernetes
伤不起bb2 天前
Kubernetes 服务发布基础
云原生·容器·kubernetes
别骂我h2 天前
Kubernetes服务发布基础
云原生·容器·kubernetes
weixin_399380692 天前
k8s一键部署tongweb企业版7049m6(by why+lqw)
java·linux·运维·服务器·云原生·容器·kubernetes
斯普信专业组3 天前
K8s环境下基于Nginx WebDAV与TLS/SSL的文件上传下载部署指南
nginx·kubernetes·ssl
&如歌的行板&3 天前
如何在postman中动态请求k8s中的pod ip(基于nacos)
云原生·容器·kubernetes