kubelet启动pod源码分析(三)
之前的blog分析了kubelet启动pod的流程,那么pod一旦启动了,谁去上报状态呢?还是回到之前代码syncLoopIteration,这个里面有四个输入源,第一次创建接受到configch add这个没有问题,然后是启动容器,此时会上报到容器正在创建的状态到apiserver,还会接收到收到configch reconcile。那么关键的来,什么时候上报成功的呢?
pkg/kubelet/pleg/generic.go里面的rslist方法
当比较新老record状态,如果不一致则更新本地缓存并且发送到channel
g.eventChannel <- events[i]
在kubelet.go里面
func (kl *Kubelet) syncLoop(updates <-chan kubetypes.PodUpdate, handler SyncHandler) {syncTicker := time.NewTicker(time.Second)defer syncTicker.Stop()housekeepingTicker := time.NewTicker(housekeepingPeriod)defer housekeepingTicker.Stop()plegCh := kl.pleg.Watch()for {if rs := kl.runtimeState.runtimeErrors(); len(rs) != 0 {glog.Infof("skipping pod synchronization - %v", rs)time.Sleep(5 * time.Second)continue}kl.syncLoopMonitor.Store(kl.clock.Now())if !kl.syncLoopIteration(updates, handler, syncTicker.C, housekeepingTicker.C, plegCh) {break}kl.syncLoopMonitor.Store(kl.clock.Now())}
}
上面的 kl.pleg.Watch()就是获取到event。这个就是syncLoopIteration的plegCh,
那么此时将进入syncLoopIteration的
case e := <-plegCh:if isSyncPodWorthy(e) {// PLEG event for a pod; sync it.if pod, ok := kl.podManager.GetPodByUID(e.ID); ok {glog.V(2).Infof("SyncLoop (PLEG): %q, event: %#v", format.Pod(pod), e)handler.HandlePodSyncs([]*v1.Pod{pod})} else {// If the pod no longer exists, ignore the event.glog.V(4).Infof("SyncLoop (PLEG): ignore irrelevant event: %#v", e)}}if e.Type == pleg.ContainerDied {if containerID, ok := e.Data.(string); ok {kl.cleanUpContainersInPod(e.ID, containerID)}}
这个方法和之前一样还是走到kubelet.go里面的syncPod这个方法
kl.statusManager.SetPodStatus(pod, apiPodStatus)
此时pod是
Status:PodStatus{Phase:Pending,Conditions:[{ {Ready False ContainersNotReady containers with unready status: [wordpress]} {PodScheduled}],Message:,Reason:,HostIP:10.39.0.45,ContainerStatuses:[{wordpress {ContainerStateWaiting{Reason:ContainerCreating,Message:,} nil nil} {nil nil nil} false 0 busybox }],QOSClass:BestEffort,InitContainerStatuses:[],},}
容器处于正在创建中的状态,但本地pleg已经感知容器已经创建成功,此时的apiPodStatus是
{Running [ [{wordpress {nil &ContainerStateRunning{StartedAt:2017-12-19 07:36:45.876193223 +0800 CST,} nil} {nil nil nil} true 0 }] BestEffort}
最终还是通过pkg/kubelet/status/status_manager.go去同步的apiserver
func (m *manager) updateStatusInternal(pod *v1.Pod, status v1.PodStatus, forceUpdate bool) bool {var oldStatus v1.PodStatuscachedStatus, 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}// 此时是oldStatus ContainerCreating新状态已经是Runningif _, readyCondition := podutil.GetPodCondition(&status, v1.PodReady); readyCondition != nil {// Need to set LastTransitionTime.lastTransitionTime := metav1.Now()_, oldReadyCondition := podutil.GetPodCondition(&oldStatus, v1.PodReady)if oldReadyCondition != nil && readyCondition.Status == oldReadyCondition.Status {lastTransitionTime = oldReadyCondition.LastTransitionTime}readyCondition.LastTransitionTime = lastTransitionTime}// Set InitializedCondition.LastTransitionTime.if _, initCondition := podutil.GetPodCondition(&status, v1.PodInitialized); initCondition != nil {// Need to set LastTransitionTime.lastTransitionTime := metav1.Now()_, oldInitCondition := podutil.GetPodCondition(&oldStatus, v1.PodInitialized)if oldInitCondition != nil && initCondition.Status == oldInitCondition.Status {lastTransitionTime = oldInitCondition.LastTransitionTime}initCondition.LastTransitionTime = lastTransitionTime}// ensure that the start time does not change across updates.if oldStatus.StartTime != nil && !oldStatus.StartTime.IsZero() {status.StartTime = oldStatus.StartTime} else if status.StartTime.IsZero() {// if the status has no start time, we need to set an initial timenow := metav1.Now()status.StartTime = &now}normalizeStatus(pod, &status)//此时判断,如果新状态和本地cache状态一致则没有必要更新到apiserverif isCached && isStatusEqual(&cachedStatus.status, &status) && !forceUpdate {glog.V(3).Infof("Ignoring same status for pod %q, status: %+v", format.Pod(pod), status)return false // No new status.}newStatus := versionedPodStatus{status: status,version: cachedStatus.version + 1,podName: pod.Name,podNamespace: pod.Namespace,}m.podStatuses[pod.UID] = newStatusselect {case m.podStatusChannel <- podStatusSyncRequest{pod.UID, newStatus}:glog.V(5).Infof("Status Manager: adding pod: %q, with status: (%q, %v) to podStatusChannel",pod.UID, newStatus.version, newStatus.status)return truedefault:// Let the periodic syncBatch handle the update if the channel is full.// We can't block, since we hold the mutex lock.glog.V(4).Infof("Skpping the status update for pod %q for now because the channel is full; status: %+v",format.Pod(pod), status)return false}
}
最终通过pkg/kubelet/status/status_manager.go的syncPod同步到apiserver
newPod, err := m.kubeClient.Core().Pods(pod.Namespace).UpdateStatus(pod)
当然处理pleg的rslist会同步,syncLoopIteration的其它两个定时时钟也可以触发,譬如 SYNC也会定时触发更新本地和apiserver直接的信息。
kubelet启动pod源码分析(三)相关推荐
- 【投屏】Scrcpy源码分析三(Client篇-投屏阶段)
Scrcpy源码分析系列 [投屏]Scrcpy源码分析一(编译篇) [投屏]Scrcpy源码分析二(Client篇-连接阶段) [投屏]Scrcpy源码分析三(Client篇-投屏阶段) [投屏]Sc ...
- storm启动nimbus源码分析-nimbus.clj
storm启动nimbus源码分析-nimbus.clj nimbus是storm集群的"控制器",是storm集群的重要组成部分.我们可以通用执行bin/storm nimbus ...
- 【Android 插件化】VirtualApp 源码分析 ( 启动应用源码分析 | HomePresenterImpl 启动应用方法 | VirtualCore 启动插件应用最终方法 )
文章目录 一.启动应用源码分析 1.HomeActivity 启动应用点击方法 2.HomePresenterImpl 启动应用方法 3.VirtualCore 启动插件应用最终方法 一.启动应用源码 ...
- Spring Boot 2.x 启动全过程源码分析(全)
上篇<Spring Boot 2.x 启动全过程源码分析(一)入口类剖析>我们分析了 Spring Boot 入口类 SpringApplication 的源码,并知道了其构造原理,这篇我 ...
- Spring Boot 2.x 启动全过程源码分析(上)入口类剖析
转载自 Spring Boot 2.x 启动全过程源码分析(上)入口类剖析 Spring Boot 的应用教程我们已经分享过很多了,今天来通过源码来分析下它的启动过程,探究下 Spring Boo ...
- Nouveau源码分析(三):NVIDIA设备初始化之nouveau_drm_probe
Nouveau源码分析(三) 向DRM注册了Nouveau驱动之后,内核中的PCI模块就会扫描所有没有对应驱动的设备,然后和nouveau_drm_pci_table对照. 对于匹配的设备,PCI模块 ...
- Spring源码分析(三)
Spring源码分析 第三章 手写Ioc和Aop 文章目录 Spring源码分析 前言 一.模拟业务场景 (一) 功能介绍 (二) 关键功能代码 (三) 问题分析 二.使用ioc和aop重构 (一) ...
- linux显示启动logo源码分析以及修改显示logo
1.linux显示启动logo整个流程分析 (1)logo图片在内核源码中是以ppm格式的文件保存,在编译内核时会把ppm格式的文件自动转换成.c文件,在c文件中会构造一个struct linux_l ...
- storm启动supervisor源码分析-supervisor.clj
storm启动supervisor源码分析-supervisor.clj supervisor是storm集群重要组成部分,supervisor主要负责管理各个"工作节点".sup ...
最新文章
- visio网络拓扑图模具_【无机纳米材料科研制图——Visio 0304】上转换NaYF4:Yb Er/Tm光子能级跃迁图...
- boost spirit的简单使用
- python实现记事本的查找功能_Python + PyQt4 实现记事本功能
- 一个类怎样引用另外一个类的成员变量或方法
- 2016全球数据新闻奖(DJA)颁布, 12个获奖作品全剖析
- IDEA打开html文件时显示错误browser error提示找不到chrome或者别的浏览器
- 数模笔记_多变量最优化计算之牛顿法
- leetcode 滑动窗口小结 (二)
- mysql自增序列nextval并发_[DB][MySql]关于取得自增字段的值、及@@IDENTITY 与并发性问题...
- 基于semisync实现MySQL的主从半同步复制
- PAIP.DW 各个版本的差别大比较。
- vmware 虚拟机安装系统成功,没有虚拟网卡的完美解决方法
- 网络空间安全未来就业前景和就业方向,看着六点
- csrf漏洞防御方案_CSRF 漏洞原理详解及防御方法
- 计算机开机键英语字母,电脑开机黑屏显示英文字母
- python 中文转带音调的拼音
- Edge兼容IE,Edge关闭弹窗阻止
- 【模式匹配】之 —— Sunday算法
- 上海宝付房价上涨?这几类人倒霉了
- input输入框设置输入值
热门文章
- 基于皮尔逊相关系数的电影智能推荐系统
- Android app调用第三方地图(百度地图,高德地图,谷歌地图)导航
- 利用Arcgis制作图像分割数据集
- VBA--LBound函数与UBound函数用法详解
- 30分钟,学会经典小游戏编程!
- 三峡学院计算机调剂,2018年重庆三峡学院考研预调剂公告
- matlab采样率为100hz,matlab自己设计一个低通滤波器,要求滤出100Hz之外的频率,采样率为10000Hz...
- 11月更新!一口气上线20+新功能,3D架构拓扑图更具趣味性~
- Arturia黑五促销,仅剩一天
- 七夕送什么蓝牙耳机,经济实惠的蓝牙耳机盘点