kubelet源码分析——启动Pod (3)

1 拉sandbox镜像
2 创建sandbox 容器
3 创建sandbox的checkpoint
4 启动sandbox容器,如果失败交由kubelet GC
5 hostNetwork就可以返回,否则让CNI编织网络
这个过程会涉及到几层的调用链,才会找到最终创建sandbox的代码,从kubeGenericRuntimeManager.SyncPod起

m.createPodSandbox /pkg/kubelet/kuberuntime/kuberuntime_manager.go |--m.runtimeService.RunPodSandbox /pkg/kubelet/kuberuntime/kuberuntime_sandbox.go |--r.runtimeClient.RunPodSandbox runtimeService.RunPodSandbox的实现类是remoteRuntimeService /pkg/kubelet/cri/remote/remote_runtime.go |--dockerService.RunPodSandbox /pkg/kubelet/dockershim/docker_sandbox/go

dockerService.RunPodSandbox方法的简略如下

func (ds *dockerService) RunPodSandbox(ctx context.Context, r *runtimeapi.RunPodSandboxRequest) (*runtimeapi.RunPodSandboxResponse, error) { // Step 1: Pull the image for the sandbox. if err := ensureSandboxImageExists(ds.client, image); err != nil { return nil, err } // Step 2: Create the sandbox container. createConfig, err := ds.makeSandboxDockerConfig(config, image) createResp, err := ds.client.CreateContainer(*createConfig) // Step 3: Create Sandbox Checkpoint. if err = ds.checkpointManager.CreateCheckpoint(createResp.ID, constructPodSandboxCheckpoint(config)); err != nil { return nil, err } // Step 4: Start the sandbox container. err = ds.client.StartContainer(createResp.ID) // Step 5: Setup networking for the sandbox. if config.GetLinux().GetSecurityContext().GetNamespaceOptions().GetNetwork() == runtimeapi.NamespaceMode_NODE { return resp, nil } err = ds.network.SetUpPod(config.GetMetadata().Namespace, config.GetMetadata().Name, cID, config.Annotations, networkOptions) } CNI编织网路

kubelet使用 /etc/cni/net.d的配置文件启动 /opt/cni/bin 二进制的CNI 插件
CNI 插件创建veth,master到指定设备,必要是通过unix socket与daemonset里面的CNI容器获取目标pod的信息

创建临时容器、 init 容器及业务容器

1 拉镜像
2 创建容器
3 启动容器
4 执行post start hook
三种容器都是调用了kubeGenericRuntimeManager.SyncPod内定义的局部函数,只是因为容器类型不一样而入参不一样而已

在局部函数调用kubeGenericRuntimeManager.startContainer方法简略如下,代码路径/pkg/kubelet/kuberuntime/kuberuntime_container.go

func (m *kubeGenericRuntimeManager) startContainer(podSandboxID string, podSandboxConfig *runtimeapi.PodSandboxConfig, spec *startSpec, pod *v1.Pod, podStatus *kubecontainer.PodStatus, pullSecrets []v1.Secret, podIP string, podIPs []string) (string, error) { // Step 1: pull the image. imageRef, msg, err := m.imagePuller.EnsureImageExists(pod, container, pullSecrets, podSandboxConfig) // Step 2: create the container. containerID, err := m.runtimeService.CreateContainer(podSandboxID, containerConfig, podSandboxConfig) // Step 3: start the container. err = m.runtimeService.StartContainer(containerID) // Step 4: execute the post start hook. if container.Lifecycle != nil && container.Lifecycle.PostStart != nil { msg, handlerErr := m.runner.Run(kubeContainerID, pod, container, container.Lifecycle.PostStart) } } 小结

本篇从kubelet的主循环开始,讲述了pod的启动过程,包括状态更新,分配cgroup,创建容器目录,等待volume挂载,注入imagepull secret,创建sandbox,调用cni编织网络,启动临时容器,init容器,业务容器,执行postStart生命周期钩子。

参考文章

万字长文:K8s 创建 pod 时,背后到底发生了什么?
kubelet 创建 pod 的流程
Pod 的创建
kubernetes/k8s CRI分析-kubelet创建pod分析

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zzyyjf.html