千家信息网

如何实现Pod的创建和管理

发表于:2025-02-05 作者:千家信息网编辑
千家信息网最后更新 2025年02月05日,这期内容当中小编将会给大家带来有关如何实现Pod的创建和管理,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。Pod同步流程是kubelet进程的核心主流程,下面将分析
千家信息网最后更新 2025年02月05日如何实现Pod的创建和管理

这期内容当中小编将会给大家带来有关如何实现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的创建和管理了,如果刚好有类似的疑惑,不妨参照上述分析进行理解。如果想知道更多相关知识,欢迎关注行业资讯频道。

0