之前的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源码分析(三)相关推荐

  1. 【投屏】Scrcpy源码分析三(Client篇-投屏阶段)

    Scrcpy源码分析系列 [投屏]Scrcpy源码分析一(编译篇) [投屏]Scrcpy源码分析二(Client篇-连接阶段) [投屏]Scrcpy源码分析三(Client篇-投屏阶段) [投屏]Sc ...

  2. storm启动nimbus源码分析-nimbus.clj

    storm启动nimbus源码分析-nimbus.clj nimbus是storm集群的"控制器",是storm集群的重要组成部分.我们可以通用执行bin/storm nimbus ...

  3. 【Android 插件化】VirtualApp 源码分析 ( 启动应用源码分析 | HomePresenterImpl 启动应用方法 | VirtualCore 启动插件应用最终方法 )

    文章目录 一.启动应用源码分析 1.HomeActivity 启动应用点击方法 2.HomePresenterImpl 启动应用方法 3.VirtualCore 启动插件应用最终方法 一.启动应用源码 ...

  4. Spring Boot 2.x 启动全过程源码分析(全)

    上篇<Spring Boot 2.x 启动全过程源码分析(一)入口类剖析>我们分析了 Spring Boot 入口类 SpringApplication 的源码,并知道了其构造原理,这篇我 ...

  5. Spring Boot 2.x 启动全过程源码分析(上)入口类剖析

    转载自   Spring Boot 2.x 启动全过程源码分析(上)入口类剖析 Spring Boot 的应用教程我们已经分享过很多了,今天来通过源码来分析下它的启动过程,探究下 Spring Boo ...

  6. Nouveau源码分析(三):NVIDIA设备初始化之nouveau_drm_probe

    Nouveau源码分析(三) 向DRM注册了Nouveau驱动之后,内核中的PCI模块就会扫描所有没有对应驱动的设备,然后和nouveau_drm_pci_table对照. 对于匹配的设备,PCI模块 ...

  7. Spring源码分析(三)

    Spring源码分析 第三章 手写Ioc和Aop 文章目录 Spring源码分析 前言 一.模拟业务场景 (一) 功能介绍 (二) 关键功能代码 (三) 问题分析 二.使用ioc和aop重构 (一) ...

  8. linux显示启动logo源码分析以及修改显示logo

    1.linux显示启动logo整个流程分析 (1)logo图片在内核源码中是以ppm格式的文件保存,在编译内核时会把ppm格式的文件自动转换成.c文件,在c文件中会构造一个struct linux_l ...

  9. storm启动supervisor源码分析-supervisor.clj

    storm启动supervisor源码分析-supervisor.clj supervisor是storm集群重要组成部分,supervisor主要负责管理各个"工作节点".sup ...

最新文章

  1. visio网络拓扑图模具_【无机纳米材料科研制图——Visio 0304】上转换NaYF4:Yb Er/Tm光子能级跃迁图...
  2. boost spirit的简单使用
  3. python实现记事本的查找功能_Python + PyQt4 实现记事本功能
  4. 一个类怎样引用另外一个类的成员变量或方法
  5. 2016全球数据新闻奖(DJA)颁布, 12个获奖作品全剖析
  6. IDEA打开html文件时显示错误browser error提示找不到chrome或者别的浏览器
  7. 数模笔记_多变量最优化计算之牛顿法
  8. leetcode 滑动窗口小结 (二)
  9. mysql自增序列nextval并发_[DB][MySql]关于取得自增字段的值、及@@IDENTITY 与并发性问题...
  10. 基于semisync实现MySQL的主从半同步复制
  11. PAIP.DW 各个版本的差别大比较。
  12. vmware 虚拟机安装系统成功,没有虚拟网卡的完美解决方法
  13. 网络空间安全未来就业前景和就业方向,看着六点
  14. csrf漏洞防御方案_CSRF 漏洞原理详解及防御方法
  15. 计算机开机键英语字母,电脑开机黑屏显示英文字母
  16. python 中文转带音调的拼音
  17. Edge兼容IE,Edge关闭弹窗阻止
  18. 【模式匹配】之 —— Sunday算法
  19. 上海宝付房价上涨?这几类人倒霉了
  20. input输入框设置输入值

热门文章

  1. 基于皮尔逊相关系数的电影智能推荐系统
  2. Android app调用第三方地图(百度地图,高德地图,谷歌地图)导航
  3. 利用Arcgis制作图像分割数据集
  4. VBA--LBound函数与UBound函数用法详解
  5. 30分钟,学会经典小游戏编程!
  6. 三峡学院计算机调剂,2018年重庆三峡学院考研预调剂公告
  7. matlab采样率为100hz,matlab自己设计一个低通滤波器,要求滤出100Hz之外的频率,采样率为10000Hz...
  8. 11月更新!一口气上线20+新功能,3D架构拓扑图更具趣味性~
  9. Arturia黑五促销,仅剩一天
  10. 七夕送什么蓝牙耳机,经济实惠的蓝牙耳机盘点