当前位置:首页 > Web开发 > 正文

v1.PodInitialized)// Set PodScheduledCondition.LastTransiti

2024-03-31 Web开发

标签:

在K8s中将Pod调理到某一台Node节点之后,后续的状态维护信息则是由对应机器上的kubelet进行维护,如何实时反馈本地运行状态,并通知apiserver则是设计的难点, 本节主要是通过感知Pod状态变革和探测状态转变两个流程来实际分析其核心数据布局,来了解内部设计

1. 状态打点 1.1 静态Pod


静态Pod主要是指的那些不是通过感知apiserver创建的pod, 因为apiserver上并不包罗,但是同时也需要维护和获取这类Pod的状态, k8s中就设计了一个镜像Pod的观点,其实就是为静态Pod镜像出来一个Pod该Pod的主要信息与静态Pod一致,并且在apiserver中进行创建,通过apiserver可以感知的这个镜像Pod来反应真实的静态Pod的状态,?

1.2 状态数据源


statusManager是进行状态同步的关键组件其需要综合当前Pod运行中的数据和apiserver存储的数据,从而决定最终的状态转换, 这里先存眷图上画出来的,更多的状态等后续会一一介绍

2. 版本一致性 type versionedPodStatus struct { status v1.PodStatus // 单调递增的版本号(每个pod) version uint64 // Pod name & namespace, for sending updates to API server. podName string podNamespace string }

在Kubelet中为保证与apiserver端信息的同步,在本地生存了一个Pod状态版本信息,其里面除了生存当前Pod的状态数据还有一个版本版本号,通过单调递增的版本号的对最近确定是否进行状态的同步

3. 核心源码实现

statusManager的流程其实还是蛮庞大的,今天我们就只讲一个场景,即kubelet通过apiserver感知到一个Pod更新,然后顺着该成果的数据流来进行梳理statusMangaer里面的数据流转

3.1 核心数据布局

manager中的核心状态相关的数据布局可以主要分为两大类:映射数据维护(podManager、podStatuses、apiStatusVersions)数据通信管道(podStatusChannel), 残剩的则是对与apiserver通信的kublet和进行pod删除查抄的?podDeletionSafety

type manager struct { kubeClient clientset.Interface // 打点缓存Pod,包罗镜像pod和静态pod的映射 podManager kubepod.Manager // 从pod UID映射到相应pod的版本状态信息 。 podStatuses map[types.UID]versionedPodStatus podStatusesLock sync.RWMutex podStatusChannel chan podStatusSyncRequest // 存储镜像pod的版本 apiStatusVersions map[kubetypes.MirrorPodUID]uint64 podDeletionSafety PodDeletionSafetyProvider } 3.2 设置Pod状态

设置Pod状态主要是位于kubelet中的syncPod中,在接收到pod事件变换之后,会与apiserver进行 Pod最新数据的同步从而获取当前pod在apiserver真个最新状态

func (m *manager) SetPodStatus(pod *v1.Pod, status v1.PodStatus) { m.podStatusesLock.Lock() defer m.podStatusesLock.Unlock() for _, c := range pod.Status.Conditions { if !kubetypes.PodConditionByKubelet(c.Type) { klog.Errorf("Kubelet is trying to update pod condition %q for pod %q. "+ "But it is not owned by kubelet.", string(c.Type), format.Pod(pod)) } } // Make sure we‘re caching a deep copy. status = *status.DeepCopy() // 如果Pod被删除了则需要强制与apiserver进行信息的同步 m.updateStatusInternal(pod, status, pod.DeletionTimestamp != nil) } 3.3 更新内部缓存状态孕育产生同步事件

3.3.1 获取缓存状态 var oldStatus v1.PodStatus // 检测之前的本地缓存数据 cachedStatus, isCached := m.podStatuses[pod.UID] if isCached { oldStatus = cachedStatus.status } else if mirrorPod, ok := m.podManager.GetMirrorPodByPod(pod); ok { oldStatus = mirrorPod.Status } else { oldStatus = pod.Status } 3.3.2 检测容器状态

检测容器状态主要是针对容器终止状态转发的合法性进行检测,其实就是按照设定的Pod的RestartPolicy来检测针对一个终止的容器是否可以进行重启

if err := checkContainerStateTransition(oldStatus.ContainerStatuses, status.ContainerStatuses, pod.Spec.RestartPolicy); err != nil { klog.Errorf("Status update on pod %v/%v aborted: %v", pod.Namespace, pod.Name, err) return false } if err := checkContainerStateTransition(oldStatus.InitContainerStatuses, status.InitContainerStatuses, pod.Spec.RestartPolicy); err != nil { klog.Errorf("Status update on pod %v/%v aborted: %v", pod.Namespace, pod.Name, err) return false } 3.3.3 更新PodCondition最后转换时间

通过最新的status里面的condition设定对应PodCondition的LastTransitionTime更新时间未当前时间

// Set ContainersReadyCondition.LastTransitionTime. updateLastTransitionTime(&status, &oldStatus, v1.ContainersReady) // Set ReadyCondition.LastTransitionTime. updateLastTransitionTime(&status, &oldStatus, v1.PodReady) // Set InitializedCondition.LastTransitionTime. updateLastTransitionTime(&status, &oldStatus, v1.PodInitialized) // Set PodScheduledCondition.LastTransitionTime. updateLastTransitionTime(&status, &oldStatus, v1.PodScheduled) 3.3.4 校对时间截断过长信息

温馨提示: 本文由Jm博客推荐,转载请保留链接: https://www.jmwww.net/file/web/30203.html