如何实现Pod的创建和管理
更新:HHH   时间:2023-1-7


这期内容当中小编将会给大家带来有关如何实现Pod的创建和管理,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。

Pod同步流程是kubelet进程的核心主流程,下面将分析该主流程中最关键的部分--Pod的创建和管理。这部分逻辑封装在kubeGenericRuntimeManager.SyncPod(kuberuntime_manager.go)方法中,主要执行以下步骤:

  1. 根据从API Server获得的Pod Spec以及当前Pod的Status计算所需要执行的Actions

  2. 在需要情况下Kill掉当前Pod

  3. 根据需要(如重启)kill掉pod内的containers

  4. 根据需要创建Pod的sandbox container

  5. 启动下一个init container

  6. 启动Pod内的containers

其中比较复杂的步骤解释如下:

1.computePodActions

对比spec和status,计算出要达到预期状态所需的actions:

// computePodActions checks whether the pod spec has changed and returns the changes if true.

func (m *kubeGenericRuntimeManager) computePodActions(pod *v1.Pod, podStatus *kubecontainer.PodStatus) podActions {

   // 1. 对比sandbox状态,计算是否需要创建sandbox,以及当前sandbox id

   createPodSandbox, attempt, sandboxID := m.podSandboxChanged(pod, podStatus)

   changes := podActions{

      KillPod:           createPodSandbox,

      CreateSandbox:     createPodSandbox,

      SandboxID:         sandboxID,

      Attempt:           attempt,

      ContainersToStart: []int{},

      ContainersToKill:  make(map[kubecontainer.ContainerID]containerToKillInfo),

   }

 

   // 2. 需要新建sandbox,一旦进入该分支就必定return,之后代码不再执行

   if createPodSandbox {

      ....

      // 在新建sandbox分支中,若存在init容器,则取第一个,返回

     if len(pod.Spec.InitContainers) != 0 {

         // Pod has init containers, return the first one.

         changes.NextInitContainerToStart = &pod.Spec.InitContainers[0]

         return changes

      }

       

      // 不存在init容器,直接跑工作containers

      for idx, c := range pod.Spec.Containers {

         if containerSucceeded(&c, podStatus) && pod.Spec.RestartPolicy == v1.RestartPolicyOnFailure {

            continue

         }

         changes.ContainersToStart = append(changes.ContainersToStart, idx)

      }

      return changes

   }

 

   // 3. sandbox已运行,启动init容器。寻找下一个需要执行的init容器

   initLastStatus, next, done := findNextInitContainerToRun(pod, podStatus)

   if !done {

      if next != nil {

         initFailed := initLastStatus != nil && isContainerFailed(initLastStatus)

         if initFailed && !shouldRestartOnFailure(pod) {

            changes.KillPod = true

         else {

            changes.NextInitContainerToStart = next

         }

      }

      // 若init未完成,直接返回

      return changes

   }

 

   // 4. init已完成,计算需要kill&start的工作container

   keepCount := 0

   for idx, container := range pod.Spec.Containers {

   .....

   }

 

   // 5. 是否需要kill pod

   if keepCount == 0 && len(changes.ContainersToStart) == 0 {

      changes.KillPod = true

   }

 

   return changes

}

2. SyncPod

该方法是pod管理的关键,实现了本文开头讲的六个步骤:

func (m *kubeGenericRuntimeManager) SyncPod(pod *v1.Pod, _ v1.PodStatus, podStatus *kubecontainer.PodStatus, pullSecrets []v1.Secret, backOff *flowcontrol.Backoff) (result kubecontainer.PodSyncResult) {

   // 1. 计算pod actions,见上文

   podContainerChanges := m.computePodActions(pod, podStatus)

   .....

 

   // 2. 需要情况下执行kill pod

   if podContainerChanges.KillPod {

      ....

      killResult := m.killPodWithSyncResult(pod, kubecontainer.ConvertPodStatusToRunningPod(m.runtimeName, podStatus), nil)

      ....

   else {

      // 3. 不需要kill pod,但需要kill工作container

      for containerID, containerInfo := range podContainerChanges.ContainersToKill {

         ....

         if err := m.killContainer(pod, containerID, containerInfo.name, containerInfo.message, nil); err != nil {

            ...

            return

         }

      }

   }

 

   .....

 

   // 4. 按需创建sandbox

   podSandboxID := podContainerChanges.SandboxID

   if podContainerChanges.CreateSandbox {

      .....

      podSandboxID, msg, err = m.createPodSandbox(pod, podContainerChanges.Attempt)

      ....

   }

 

   ....

 

   // 5. 运行next init container

   if container := podContainerChanges.NextInitContainerToStart; container != nil {

      ....

      if msg, err := m.startContainer(podSandboxID, podSandboxConfig, container, pod, podStatus, pullSecrets, podIP); err != nil {

         startContainerResult.Fail(err, msg)

         utilruntime.HandleError(fmt.Errorf("init container start failed: %v: %s", err, msg))

         return

      }

      ....

   }

 

   // 6. 运行工作containers。注意,根据computePodActions,若NextInitContainerToStart不为空,则不存在ContainersToStart ,即这个循环在当前这个SyncPod中不会被执行

   for _, idx := range podContainerChanges.ContainersToStart {

      ....

      if msg, err := m.startContainer(podSandboxID, podSandboxConfig, container, pod, podStatus, pullSecrets, podIP); err != nil {

         startContainerResult.Fail(err, msg)

         // known errors that are logged in other places are logged at higher levels here to avoid

         // repetitive log spam

         switch {

         case err == images.ErrImagePullBackOff:

            glog.V(3).Infof("container start failed: %v: %s", err, msg)

         default:

            utilruntime.HandleError(fmt.Errorf("container start failed: %v: %s", err, msg))

         }

         continue

      }

   }

 

   return

}

SyncPod中需要特别注意的是:在init containers启动过程中,SyncPod每次只会运行一个init container(next),之后就返回了。

上述就是小编为大家分享的如何实现Pod的创建和管理了,如果刚好有类似的疑惑,不妨参照上述分析进行理解。如果想知道更多相关知识,欢迎关注天达云行业资讯频道。

返回云计算教程...