kubelet源码阅读

版本:v1.23

别人的阅读笔记:https://github.com/gosoon/source-code-reading-notes

app.NewKubeletCommand
  app.loadConfigFile #加载配置文件
  app.Run
    app.run
      app.UnsecuredDependencies #初始化相关依赖,这些依赖是kubelet需要的,比如TLS/mount/subpath/hostutil/dockeroptions等
        app.InitializeTLS #初始化tls选项
	    mount.New #实现mount功能,可以实现不同的mount类来为mount动作提供不同的行为,默认的mount动作是linux平台的mount动作,这里就是kubelet只能运行在linux上的原因之一
	    subpath.New #对mount的封装
	    hostutil.NewHostUtil #linux平台的hostutil
        exec.New #用来运行插件的执行器,默认是linux平台
        app.ProbeVolumePlugins #探测有哪些存储插件,会返回一系列的插件对象
        app.GetDynamicPluginProber #volumn插件的探针,用来探测volumn插件是否正常
 	  nodeutil.GetHostname 
      app.getNodeName
	  #1:创建clientset和认证
      clientset.NewForConfig #通用clientset
      v1.NewForConfig #为事件准备一个单独的clientset
      clientset.NewForConfig #为healthz准备一个client
      app.BuildAuth #构建认证器(authenticator)和授权器(authorizer)
      app.runAuthenticatorCAReload
      #2:获取cgroup
      cm.NodeAllocatableRoot #获取节点可分配资源的根cgroup,确保容器可以获得足够的资源,资源指cpu、memory,下略
      cm.GetKubeletContainer #获取kubelet将要使用的cgroup,可以使用这个cgroup来确保系统繁忙的时候kubelet也能得到足够的cpu,因为kublet也是一个进程
      cm.GetRuntimeContainer #获取containerRuntime使用的cgroup ,可以用这个cgroup来调整containerRuntime进程使用的资源,因为containerRuntime也是一个进程
      #3:创建metrics服务
      cadvisor.NewImageFsInfoProvider
      cadvisor.New
      app.makeEventRecorder #事件记录器,供排查bug、审计等
      #4:创建containerManager,这是kubelet中的一个重要组件,用于管理容器的资源限制和调度
      cadvisor.cadvisorClient.MachineInfo #获取节点资源
      app.getReservedCPUs #--reserved-cpus参数不为空,表明要保留一些cpu给系统,也就是这部分cpu不能用于kubelet
      eviction.ParseThresholdConfig #解析evictionManager资源阈值,evictionManger用这些值来决定是否驱逐某些pod
      cm.ParseQOSReserved #解析-qos-reserve-requests参数
      utilfeature.DefaultFeatureGate.Enabled(features.CPUManager) #cpuManager用来管理cpu分配和调度,比如默认的是CFS调度,但是pod可能有cpu亲和性等
      cm.NewContainerManager #创建ContainerMangaer
      #5:run kubelete之前初始化containerRuntime service
      kubelet.PreInitRuntimeService
        kubelet.runDockershim #会判断是docker还是cri,如果是docker,那么kublet使用cri的时候,cri还需要通过dockershim才能管理容器
        remote.NewRemoteRuntimeService  #启动cri服务
        remote.NewRemoteImageService #启动镜像服务
        cadvisor.UsingLegacyCadvisorStats #判断是否需要启动cadvisor来监听
      #6:启动kubelet
      app.RunKubelet #运行kublet
        nodeutil.GetHostname 
        app.getNodeName
        app.makeEventRecorder
        netutils.ParseIPSloppy #解析--node-ip参数
        capabilities.Initialize #设置容器的默认权限
        credentialprovider.SetPreferredDockercfgPath #设置docker配置文件的路径
        app.createAndInitKubelet 
          kubelet.NewMainKubelet #创建kubelet
            kubelet.makePodSourceConfig #创建podconfig,会创建一个chan,这个chan是syncLoop中syncLoopIteration监听的数据源之一
              config.NewPodConfig #创建podConfig,内部有一个podStorage,podStorage对象含有一个chan和map,这个chan会收到来自多个源发来的podupdate对象,map保存chan收到的对象
                                  #podUpdate{op,pods,source},op记录操作(增删改),pods记录变动的pod信息,source记录来源(file/http/apiserver)
                                  #file:即static-pod所在目录
              config.PodConfig.Channel #创建一个channel,这个channel内含有一个chan,channel负责接收发送到这个chan的信息并把处理后的结果发往内部保存的一个updatesChan
                                       #这个updatesChan就是syncLoop中监听的configChan,因为这个对象叫podConfig,所以对应的chan在syncLoop里就叫configChan
                                       #一个channel对应一个chan,所有channel收到的对象经过处理后最终都会统一发往configChan,就是上面podConfig里的那个chan
                sets.String.Insert #保存source名字到podConfig内部的数组
                config.Mux.Channel #创建一个新的chan,然后开一个线程监听这个新的chan,然后对收到的事件进行处理和包装后发往内部保存的updatesChan(即syncLoop里的configChan)
                  go config.Mux.listen  一个死循环:监听新chan->阻塞->收到事件->处理和包装->发送事件到updatesChan->继续监听新chan......如此循环
                    config.podStorage.Merge 
                      config.podStorage.merge #监听新创建的chan并把事件拆分成adds/updates/deletes/removes/reconciles podUpdate对象集合
                    updatesChan <- adds/updates/deletes/removes/reconciles 把上面解析出的podUpdate对象发送到updatesChan
              config.NewSourceFile #创建一个监听static-pod文件所在目录的监听器,然后把收到的事件发往我们刚才通过channel函数创建的chan
                config.newSourceFile #把刚创建的chan和一个文件路径保存到一个sourceFile对象内部,路径由--pod-manifest-path参数指定,默认为/etc/kubernetes/manifests
                cofig.sourceFile.Run #开一个线程去监听目录变化事件,然后把事件发往新创建的chan。除了监听事件外还会定时去刷新一遍目录看是否有变更
              config.PodConfig.Channel    #创建一个新chan   
              config.NewSourceURL         #创建一个http服务器,定时去请求指定url来获取pod变动信息并发送到刚创建的chan
              config.PodConfig.Channel    #创建一个新chan
              config.NewSourceApiserver   #通过listAndWatch来监听来自apiserver的pods变化并发送到updatesChan
            SharedInformerFactory.Core().V1().Nodes() #监听node
            kubecontainer.GCPolicy{} #这是一个对象,包含了容器gc设置
            v1.DaemonEndpoint{Port: kubeCfg.Port} #这是一个对象,包含了kubelet端口,kubelet是以守护进程的形式运行
            images.ImageGCPolicy{} #这是一个对象,包含了镜像gc设置
            eviction.ParseThresholdConfig #解析eviction配置参数
            eviction.Config{} #这是一个eviction配置对象
            SharedInformerFactory.Core().V1().Services() #监听service
            oomwatcher.NewWatcher #创建一个oom事件监听器
              oomparser.New
                kmsgparser.NewParser #解析/dev/kmsg文件,这个文件对应的是内核日志
            netutils.ParseIPSloppy #从配置文件获取集群dnsip地址
            kubelet.Kubelet{} #这是一个kubelet对象
            cloudresource.NewSyncManager  #如果是云厂商提供服务,那么SyncManager负责定时收集云厂商的资源信息(这里仅仅是同步云节点地址信息)
			flowcontrol.NewBackOff #创建一个指数退避对象,用来处理image拉取失败时再次拉取的间隔
            results.NewManager #创建livenessProbMangaer
            results.NewManager #创建readinessProbMangaer
            results.NewManager #创建startupProbMangaer
            container.NewCache #创建podcache
            pod.NewBasicMirrorClient #创建mirrorClient用来同步mirrorpod和internalpod
            pod.NewBasicPodManager #创建podManager
            status.NewManager      #创建statusMangaer,用来更新apiserver上中pod的status字段
            status.NewResourceAnalyzer #创建资源分析器,统计资源使用情况
              status.newFsResourceAnalyzer #这里仅统计文件系统资源使用情况
              status.NewSummaryProvider #提供kubelet的统计信息
            runtimeclass.NewManager #创建runtimeclassManager,内部会启动一个informer监听apiserver的runtimeclass资源
                                    #原理:可以在pod.spec.runtimeClassName指定pod的runtimeClass,当kubelet收到一个pod时,在syncPod函数内会检查该pod的runtimeClass字段
                                    #对应的资源是否已经在集群中声明了,如果没有,则拒绝,然后会把runtimeClassName发给cri(当然,会有一个准入控制插件来判断该node是否支持该runtimeClass,
                                    #如果不支持,那么准入插件就会拒绝该pod)
            logs.NewContainerLogManager #创建日志管理器
            kubelet.NewReasonCache      #创建cache,缓存container failed原因
            queue.NewBasicWorkQueue     #创建工作队列
            kubelet.newPodWorkers       #创建podworker,处理pod的生命周期比如创建删除
            kuberuntime.NewKubeGenericRuntimeManager #创建containerRuntimeManager,负责管理容器
              credentialprovider.NewDockerKeyring #创建image拉取凭证
              images.NewImageManager #用来拉取image,如果设置了qps,那么会限制拉取速率,根据配置决定是并发拉取还是串行拉取
              lifecycle.NewHandlerRunner #容器lifecycle hook,支持exec钩子/httpGet钩子
              kuberuntime.newContainerGC #容器gc
            kubecontainer.NewRuntimeCache #创建了一个pod cache,对于每一个pod信息,都会用一个时间戳来表示pod最近一次更新的时间
            stats.NewHostStatsProvider #用来查看pod在主机上的文件系统使用情况
            stats.NewCadvisorStatsProvider #创建一个provider,来提供node和container的信息
            pleg.NewGenericPLEG #创建pleg
            kubelet.newRuntimeState #创建一个state记录kublet状态
            runtimeState.addHealthCheck #添加pleg健康检查
            kubelet.updatePodCIDR #更新pod cidr
            kubecontainer.NewContainerGC #创建containerGC,实际就是前面创建runtimeManager时创建的哪个containergc
            kubelet.newPodContainerDeletor #创建container删除器,就是一个线程不断从一个chan读取要删除的pod,然后删除,另一个线程把要删除的pod信息写入这个chan
            images.NewImageGCManager       #创建imageGC
            kubeletcertificate.NewKubeletServerCertificateManage #创建一个用于 kubelet 的证书管理器,用于检索服务器证书,或者返回一个错误
            prober.NewManager #创建一个探针管理器,用来管理前面创建的liveness/rediness/startup探针
            token.NewManager  #创建一个管理pod serviceAccount的token管理器
            kubelet.NewInitializedVolumePluginMgr #创建一个volumn插件管理器,可以用来管理多种volumn插件,如emptydir/hostpath/nfs/glusterfs/aws/gce等
              SharedInformerFactory.Storage().V1().CSIDrivers() #监听api的csidrivers资源,同runtimeclassManager,都是判断pod的csi字段是不是有效地,如果有效,就接受,否则就拒绝
              volumn.VolumePluginMgr.InitPlugins #初始化所有存储插件
                flexvolumn.flexVolumeProber.Init #创建plugin对应的目录,并创建一个watcher监视这个目录的增删改
                  flexvolumn.flexVolumeProber.createPluginDir #如果不存在则创建volumnplugin可执行文件存放的目录,默认路径为/usr/lib/kubernetes/kubelet-plugins/volumn/exec
                  flexvolumn.flexVolumeProber.initWatcher #初始化watcher
                volume.VolumePlugin.Init #调用对应插件对应的init函数来初始化volume插件,比如ceph插件就是简单的把init函数参数保存到自己内部,插件实现类似调度器,实现指定接口即可
            kubelet.Kubectl.getPluginsRegistrationDir #获取插件根目录,插件根目录默认为/var/lib/kubelet/plugin_registry
            pluginmanager.NewPluginManager #创建一个插件管理器,管理所有类型的插件(校验插件、注册插件、删除插件),比如csi
            volumemanager.NewVolumeManager   #用来管理volumn的,前面的volumnPluginMgr是用来管理volume插件的,这个地方还不太懂
              reconciler.NewReconciler #创建一个reconclier,用来驱使volume的实际状态和volume的期望状态一致
            flowcontrol.NewBackOff #创建一个backoff定时器,用于控制容器失败以后的重启间隔
            eviction.NewManager #创建evictionMangaer,定时驱逐pod
            lifecycle.PodAdmitHandlers.AddPodAdmitHandler(evictionManager) #添加准入处理器,如果一个pod加入以后会超过阈值,那么就拒绝该pod
            lifecycle.PodAdmitHandlers.AddPodAdmitHandler(sysctlsAllowlist) #添加准入控制器,sysctl表示系统调用白名单,如果一个pod的某些系统调用不在允许的名单内就拒绝该pod
	        kubelet.newActiveDeadlineHandler #添加handler,用来处理一个pod是否超过了他的截止期(超过截止期的pod可以算作死亡)
	        kubelet.Kubelet.AddPodSyncLoopHandler #把activeDeadlineHandler添加到sync loop中,调用ShouldSync来判断pod是否需要同步
	        kubelet.Kubelet.AddPodSyncHandler #把activeDeadlineHandler添加到sync loop中,调用shouldEvict来判断pod是否需要驱逐
            cm.containerManager.GetAllocateResourcesPodAdmitHandler #获取资源准入插件,在批准pod之前预分配资源,如果分配失败(比如资源不足)就拒绝该pod
            lifecycle.PodAdmitHandlers.AddPodAdmitHandler #添加刚才的资源准入handler
            preemption.NewCriticalPodAdmissionHandler #创建抢占准入handler,如果一个pod是因为资源不足而被拒绝,那么这个抢占handler尝试抢占一批pod来释放资源
			lifecycle.NewPredicateAdmitHandler #创建谓词准入控制。不大懂
			lifecycle.NewAppArmorAdmitHandler  #创建准入控制,判断一个具有armor配置文件(linux的一种安全配置文件)的pod是否允许运行
            lifecycle.NewNoNewPrivsAdmitHandler #创建准入控制,检查Pod中的容器是否需要在没有新权限的情况下运行。如果不需要,那么该 Pod 将被接受
	        lifecycle.NewProcMountAdmitHandler  #创建准入控制,执行ProcMount的验证。ProcMount是Linux 中的一种安全特性,用于指定挂载进程的挂载选项
            lease.NewController                 #创建node lease资源,通过heartbeat来定时更新leases资源,来告知apiserver本node还是ready的
            nodeshutdown.NewManager #创建manager,在节点关闭的时候正确停止所有container
            kubelet.Kubelet.defaultNodeStatusFuncs #获取一系列设置节点状态的函数
          kubelet.Kubelet.BirthCry #发送kubelet正在启动事件到一个chan
          kubelet.Kubelet.StartGarbageCollection #启动垃圾收集
            go container.realContainerGC.GarbageCollect #开一个go route,定时启动GarbageCollect来移除所有死亡的容器
              kuberuntime.containerGC.GarbageCollect
                kuberuntime.containerGC.evictContainers #移除可驱逐的容器,一组具有相同垃圾回收条件的容器会被组织成一个evictUnit
                  kuberuntime.containerGC.evictableContainers #如果一个容器状态不为running且该容器存在时间超过了一个阈值,那么该容器就是可删除的,是可删除,不一定能够删除,因为还要看pod
                  kubelet.podWorkers.ShouldPodContentBeRemoved #如果一个容器对应的pod的状态为evicted/deleted/terminated,那么该容器就可以删除,反之该容器就不能删除
                  kuberuntime.containerGC.removeOldestN        #移除最老的n个容器
                    kuberuntime.kubeGenericRuntimeManager.killContainer #如果容器状态为未知,那么就先尝试kill该容器
                      cm.internalContainerLifecycleImpl.PreStopContainer
                      kuberuntime.kubeGenericRuntimeManager.executePreStopHook #调用用户自定义的钩子函数,kubelet支持preStop和postStart两种用户可自定义的钩子
                      cri.ContainerManager.StopContainer #调用cri停止该容器
                    kuberuntime.kubeGenericRuntimeManager.removeContainer
                      cm.internalContainerLifecycleImpl.PostStopContainer #调用相应的容器钩子函数,目前是topologyManager.RemoveContainer即成功topology的podmap中移除该pod
                      kuberuntime.kubeGenericRuntimeManager.removeContainerLog #删除容器日志
                      cri.ContainerManager.RemoveContainer #调用容器运行时删除容器
                kuberuntime.containerGC.evictSandboxes  #移除没有容器的沙箱
                  kubelet.podWorkers.ShouldPodContentBeRemoved
                  kuberuntime.containerGC.removeOldestNSandboxes 
                    kuberuntime.containerGC.removeSandbox #移除n个不活跃的沙箱
                      cri.PodManager.StopPodSandbox #先停止沙箱
                      cri.PodManager.RemovePodSandbox #再删除沙箱
                kuberuntime.containerGC.evictPodLogsDirectories #移除沙箱日志目录
              images.realImageGCManager.GarbageCollect #镜像回收线程
        rlimit.SetNumFiles #设置允许打开的最大文件数
        app.startKubelet #运行kubelet
          go kubelet.Kubelet.Run
            http.FileServer #启动日志服务,开启一个http日志服务,以便可以通过http查看日志
			kubelet.Kubelet.SyncManager.Run #cloudResourceSyncManager.Run,就是来同步云厂商资源状态的(这里仅仅是同步云厂商节点地址)
              kubelet.Kubelet.SyncManager.syncNodeAddresses
			kubelet.Kubelet.initializeModules
              kubelet.Kubelet.setupDataDirs #设置rootdir/podsdir/plugindir/podsresourcedir,其中默认的root路径为/var/lib/kubelet
              image.realImageGCManager.Start #启动image gc ,两个操作:1:定时更新image时间戳;2:定时更新image缓存(因为image可能被其他人删了,所以需要定时同步)
				go image.realImageGCManager.detectImages #死循环,定时更新时间戳并返回正在使用的image
                go {
                   kuberuntime.kubeGenericRuntimeManager.ListImages #从runtimeContainer重新获取最新的image信息快照
                   image.imageCache.set #更新image缓存
                }
              certificate.manager.Start #启动证书管理器,就是轮换证书,当证书过期时,可以自动生成新的密钥,并从 Kubernetes API 申请新的证书。
              oom.realWatcher.Start #启动oom监视器
                go oomparser.OomParser.StreamOoms #启动一个线程去
                  kmsgparser.parser.Parse #从/dev/kmsg获取日志并写到一个chan中
                  oomparser.checkIfStartOfOomMessages #检查一行日志是不是包含"invoked oom-killer:",如果是的,那么就认为是触发了oom,然后封装成一个对象发往指定chan
                event.recorderImpl.Eventf #发送oom 事件到指定chan
              stats.resourceAnalyzer.Start #启动文件系统资源分析器
                stats.fsResourceAnalyzer.Start 
                  stats.fsResourceAnalyzer.updateCachedPodVolumeStats #统计pod volume的信息
                  stats.volumeStatCalculator.calcAndStoreStats #计算volume的最新信息
			volumeManager.volumeManager.Run #启动volumn管理器
              go volume.VolumePluginMgr.Run #监听apiserver csi资源,当处理一个pod的时候会检查volume字段指定的csi类型apiserver是否支持
              desiredStateOfWorldPopulator.Run  #desiredStateWorld(dsw)存放pod的卷的期望状态,actualStateWorld(asw)表示pod的卷的实际状态,
												#是否同步就是检测dsw中的状态是否等于asw的状态
											    #volumeManager会不断从podManager中获取pod信息然后从中提取volume的期望状态并更新到dsw中
                                                #在syncLoop中podworker只是不断检测pod的卷状态是否同步,即podWorkder不处理卷的增删,卷由volumeManager负责管理和操作
				desiredStateOfWorldPopulator.findAndAddNewPods        #遍历podManager,更新获取所有非terminated状态的pod的volume信息到dsw
				desiredStateOfWorldPopulator.findAndRemoveDeletedPods #同上,从dws中删除不存在的pod的volume信息
              reconciler.reconciler.Run  #同步卷使得pod的dsw=asw,比如一个卷没有挂载,那么就重新挂载;如果一个卷大小有调整,那么就调整卷大小(这一块不大清楚)
                go reconciler.reconciler.reconciliationLoopFunc 
                  reconciler.reconciler.reconcile                      #这里完成卷同步操作,这里是直接读取asw
                    reconciler.reconciler.unmountVolumes               #从pod上unmount卷
                    reconciler.reconciler.mountAttachVolumes           #mount卷到pod上
                    reconciler.reconciler.unmountDetachDevices         #对应的设备unmount或者detach
                    reconciler.reconciler.processReconstructedVolumes  #处理重建的卷
                  reconciler.reconciler.sync #通过扫描所有pod更新asw到最新状态即reconcile操作中只是读取asw,这里更新asw
            go kubelet.Kubelet.syncNodeStatus #同步node状态到master上
              kubelet.Kubelet.updateNodeStatus
                kubelet.Kubelet.tryUpdateNodeStatus #通过clientgo更新apiserver上node的状态
                  kubelet.Kubelet.defaultNodeStatusFuncs #根据实际情况设置节点状态
                  volumeManager) MarkVolumesAsReportedInUse
                  nodeutil.PatchNodeStatus #更新master节点上的节点状态
            go leases.Controller.Run #定时更新node对应的lease信息以表明node还是正常的
            go kubelet.Kubelet.updateRuntimeUp #一个死循环,每隔5s检查一次containerRuntime的状态,如果有错则设置runtimeErrors字段
              kubeRuntime.kubeGenericRuntimeManager.Status #检查容器运行时状态
              kubelet.Kubelet.initializeRuntimeDependentModules #当containerRuntime启动以后,初始化相关模块,这个初始化操作只会进行一次
                cadvisor.cadvisorClient.Start #启动cadvisor,就是监视容器
                cm.containerManagerImpl.Start #启动containerMangaer,这个主要是资源分配,即cpu/memory/磁盘/cgroup的设置
                  cm.buildContainerMapFromRuntime #构建map[containerId]struct{sandBoxId,podId}
                  cpumanager.manager.Start #cpumangaer就是根据pod的resource字段来分配多少个cpu给这个pod
                    state.NewCheckpointState #从文件读取cpu的分配状态即checkpoint,默认文件为:/var/lib/kubelet/cpu_manager_state
                    cpumanager.Policy.Start #这是一个接口函数,policy有none和static,node表示默认策略,start什么也不做,而static的start则会校验读取的checkpoint的cpu分配状态是否有效
                    cpumanager.Policy.GetAllocatableCPUs #返回可用的cpuset,none策略则是默认返回所有cpu,static策略则是返回部分cpu集合(因为要除去保留的)
                    go cpumanager.manager.reconcileState #检查容器的状态,并根据状态来分配cpu确保实际cpu分配和预期相同
                      state.Reader.GetCPUSetOrDefault #获取容器默认的cpu集合
                      if !cpuset.CpuSet.Equals #如果默认的和预期的不相同就更新
                        cpumanager.manager.updateContainerCPUSet #更新容器对应的cpuset
                          cpumanager.runtimerServer.UpdateContainerResources #调用runtimeService来更新container的配置文件即通过修改配置文件即可修改container的cpu配置
                        state.Reader.SetCPUSet #更新状态
                  memorymanager.manager.Start #和cpumanager差不多的操作,只不过对应的文件为/var/lib/kubelet/memory_manager_state以及没有reconcile操作
                    state.NewCheckpointState 
                    memorymanager.Policy.Start 
                    memorymanager.manager.GetAllocatableMemory
                  cadvisor.cadvisorClient.RootFsInfo #获取根文件系统
                  cadvisor.EphemeralStorageCapacityFromFsInfo #获取根文件系统对应的磁盘存储容量
                  cm.containerManagerImpl.validateNodeAllocatable #校验配置文件和node实际可分配的资源数是否有冲突(因为node可能保留了许多资源导致实际的不够)
                  cm.containerManagerImpl.setupNode #主要是设置节点对应的cgroup(可以通过参数--cgroup-root配置)以及oom_score(分数越低,容器越容易oom)
                  devicemanager.ManagerImpl.Start #开一个server监听/var/lib/kubelet/device-plugins/kubelet.sock unix套接字
                                                  #device-plugins是k8s提供的资源设备插件框架,在这个目录下注册了某个资源设备插件,那么就可以在pod的resouce字段里设置该资源
                eviction.managerImpl.Start #启动evictionManager
                  go eviction.managerImpl.synchronize #就是一个死循环,1:定时更新某些指标到chan;2:如果超过了阈值,达到了驱逐条件,就开启驱逐,阈值是通过signal传过来的即事件触发
					eviction.thresholdsMet #确定哪些指标达到了阈值,硬阈值(达到阈值即触发驱逐)
					eviction.thresholdsMetGracePeriod #确定哪些指标达到了软阈值(即达到阈值且持续了一段时间才触发驱逐)
                    eviction.managerImpl.localStorageEviction #先尝试驱逐因本地容量超过阈值导致的驱逐
                      eviction.managerImpl.emptyDirLimitEviction #驱逐emptydir超阈值的pod
                        eviction.managerImpl.evictPod #驱逐一个pod
                          kubelet.killPodNow #封装一个killpod操作,然后调用podworker去执行对应的操作
                            kubelet.PodWorker.UpdatePod #内部会异步调用runtimeservice去异步驱逐
                      eviction.managerImpl.podEphemeralStorageLimitEviction #驱逐超过临时存储容量限制的pod
                        eviction.managerImpl.evictPod
                      eviction.managerImpl.containerEphemeralStorageLimitEviction #驱逐pod内有某些容器超过临时存储容量限制的pod
                        eviction.managerImpl.evictPod
                    eviction.managerImpl.reclaimNodeLevelResources #尝试回收节点级别的资源
                    rank #evictionapi.Signalxxx系列函数,用来给pod排序
                    eviction.managerImpl.evictPod #按前面排好的顺序驱逐pod,如果是关键pod就跳过,直到成功驱逐一个pod即这个地方每次只驱逐一个pod
                  eviction.waitForPodsCleanup #等待本次驱逐的pod完成最后的清理工作即检测pod节点级资源是否已经回收了下一次
                pluginManager.pluginManager.Run #启动pluginManger管理插件的增删改,就是开一个watcher监视文件目录的改动,当目录内容变化的时候及时register和unregister插件
                  pluginwatcher.Watcher.Start #启动一个fswatcher,监视目录的改动,目录:/var/lib/kubelet/plugin_registry
                  reconciler.reconciler.Run #同步状态,就是register和unregister插件,默认有csiplugin和deviceplugin,而cpu/memory则是由cpumanager/memorymanager去管理
                logs.containerLogManager.Run  #启动日志管理器
                nodeshutdown.managerImpl.Start #启动节点关闭管理器
            kubelet.Kubelet.initNetworkUtil #初始化iptables
            status.manager.Start #启动statusManager,就是一个死循环,然后死循环里一个select,不断从指定chan接收podstatus,然后不断更新apiserver上的pod信息
		      status.manager.syncPod #更新单个pod信息
  		        status.manager.needsUpdate #判断收到的podstatus是不是最新的,是否需要更新
                kubeClient.CoreV1().Pods().Get #获取apiserver上pod的信息
                status.manager.mergePodStatus #合并收到的podstatus和查到的podstatus
                statusutil.PatchPodStatus #更新apiserver上的podstatus
                status.manager.canBeDeleted #看pod能否删除
                kubeClient.CoreV1().Pods().Delete #删除pod,不过会设置一个graceperiod,并不是立即删除
  		        status.manager.deletePodStatus #从本地缓存podstatus
              status.mangaer.syncBatch #更新一批pod的信息
            runtimeClass.Manager.Start #启动runtimeClass,实际就是启动informer监听apiserver runtimeclass的变化
            pleg.GenericPLEG.Start #启动pleg
              go pleg.GenericPLEG.relist #从apiserver获取podlist,从containerRuntime获取podlist,比对,然后发送事件,默认两次relist操作之前间隔1s
                pleg.GenericPLEG.getRelistTime #获取上一次relist开始的时间
                kuberuntime.kubeGenericRuntimeManager.GetPods #调用runtimeservice获取所有pod信息
                pleg.GenericPLEG.updateRelistTime #reslist设置为本次更新开始的时间
                pleg.podRecords.setCurrent #更新pleg缓存的pod的信息
                pleg.getContainersFromPods #获取所有container
                pleg.computeEvents #根据container的状态生成事件对象,pleg状态有created/running/exited/unknow/non existed(如果获取不到pod内container的信息,那么状态就是nonexisted)
                pleg.updateEvents #把event事件对象追加到一个临时的map里
                pleg.GenericPLEG.updateCache #更新缓存,pleg的cache对象是外部kubelet对象的podcache的一个引用,所以这里实际就是更新kubelet的缓存,本次更新会保存更新失败的pod的信息
                  kuberuntime.kubeGenericRuntimeManager.GetPodStatus #通过runtimeserver实时获取pod最新状态,这里不是使用前面已经获取的pod信息
                  container.cache.Set #更新kubelet pod信息缓存
                pleg.podRecords.update #podRecord是pleg自身的缓存,不是外部传进来的
                  pleg.podRecords.updateInternal #一个podRecored包含两个对象{oldPodInfo,currentPodInfo},update操作就是oldPodInfo=currentPodInfo,currentPodInfo=nil
                eventChannel <- events #发送事件到syncloop,在syncloop调用的syncloopIteration函数中会有一个select,pleg的eventChannel是该select监听的事件源之一
                pleg.GenericPLEG.updateCache #更新上一次更新过程中更新失败的pod信息,即再次尝试通过runtimeservice获取pod信息,再次失败的则会继续留到下一次relist操作再次进新尝试
                container.cache.UpdateTime #当执行完本次所有更新操作之后,记录本次cache更新完成的时间
            kubelet.Kubelet.syncLoop #一个死循环,死循环内一个select,这个select有多个数据源,每次迭代就是监听是否有事件到来,如果有则运行,否则阻塞
              kubelet.runtimeState.runtimeErrors   #一方面是前面有一个updateRuntimeUp会定时检查是否有runtimeError,一方面是会调用pleg.healthy,健康检查函数有且只有一个plegcheck
                                                   #如果报错,则睡眠一段随机时间然后再尝试
              pleg.GenericPLEG.Watch #获取pleg的chan
              atomic.Value.Store #记录本次同步操作开始的时间,后面还会记录一个检查完成的时间,这个时间在/healthz服务中会用到
              kubelet.Kubelet.syncLoopIteration  #就是一个大的select,监听多个chan,然后哪个chan有数据就读取哪个chan并进行对应处理,
                                                 #configChan: 来自于file/http/apiserver的事件
                                                 #syncTicker: 定时器,默认每1s触发一次同步操作(如果指定时间内其他数据源没有事件到来就会触发此事件)
                                                 #housekeepingTicker: 定时器,默认每2s触发一次清理工作
                                                 #pleg: pleg发来的事件(即relist操作中发送的事件)
												 #readinessManager.Updates: 就绪探针触发的事件
												 #startupManager.Updates: 启动探针触发的事件
												 #livenessManager.Updates: 存活探针触发的事件
			    case <-configChan: #来自file/http/apiserver的事件,case下还有一个case来分别处理Update/Remove/Reconcile/Delete等事件,这里仅以add为例,略去了case
							        #remove是立即删除,delete不是即有一个graceperiod
				  kubelet.Kubelet.HandlePodAddition   #处理来pod添加事件,不同事件对应的函数名为HandlePodXXXX
                    sort.Sort                         #每个add事件可能包含多个新增的pod,所以先按时间顺序排个序
                    pod.PodManager.Add                #把pod对象添加到podManager中
                    if types.IsMirrorPod              #检查pod的annotation中是否有kubernetes.io/config.mirror这个字段,如果有,就说明是mirrorpod,反之是普通pod
                      kubelet.Kubelet.handleMirrorPod #mirror pod和普通pod的处理不同,apiserver上只有mirrorpod,没有staticpod,所以为了方便管理,
													  #kubelet会在apiserver上创建一个和staticpod一一对应的mirror pod,我们通过kubectl操作mirror pod就是操作static pod
													  #只不过mirror pod的处理不同,mirrorpod的add/delete/remove/update事件都会当做一个update事件来处理
													  #所以我们是无法通过apiserver来删除静态pod的,因为删除操作会被当做update操作,顶多会被转换成重启操作
													  #如果一个pod的annotation字段含有 kubernetes.io/config.mirror字段,那么该pod就是一个mirror pod
                    else
                      kubelet.podWorkers.IsPodTerminationRequested #检查pod是否被kubelet的其他部分请求终止(即可能存在其他进程同时在申请终止该pod)
                      kubelet.Kubelet.filterOutInactivePods #如果否,则返回目前所有处于actived状态的pod
                      kubelet.Kubelet.canAdmitPod #调用前面添加的准入插件来判断是否接受该pod,如果否就拒绝该pod
                      pod.basicManager.GetMirrorPodByPod #获取pod对应的mirrorpod?mirrorpod不太懂
                      kubelet.Kubelet.dispatchWork ##把事件对象包装以后丢给podWork异步处理,dispatchWork就是把接收到的参数封装成UpdatePodOptions,调用 UpdatePod 方法.
                        kubelet.podWorkers.UpdatePod #update函数主要是进行检测和设置选项,实际操作由syncPod函数执行
                          go kubelet.podWorkers.managePodLoop #update事件 一共三种状态:sync/terminating/terminated,三种状态对应三个不同的函数
							case: TerminatedPodWork
							  syncTerminatedPodFn
								kubelet.Kubectl.generateAPIPodStatus #生成pod的状态
                                status.Manager.SetPodStatus #更新apiserver上的podstatus
                                volumemanager.volumeManager.WaitForUnmount #等待volume unmount完成(unmount操作由volumeManager进行,这里只是检测)
                                status.Manager.TerminatePod #主要把pod的.status.containerStatuses 和.status.initContainerStatuses中container的state置为Terminated
                                  status.Manager.updateStatusInternal #更新状态到apiserver
									podStatusChannel<-xx #发送pod状态到一个chan,statusManager在监听这个chan,并把信息更新到apiserver中
							case: TerminatingPodWork
                              kubelet.Kubelet.syncTerminatingPod #处理正在终止状态的事件
							defaulte: 
                              kubelet.Kubelet.syncPod #负责创建pod,代码很长,跳过
 
			    case <-plegChan:
                  kubelet.Kubelet.HandlePodSyncs
                    pod.basicManager.GetMirrorPodByPod 
                    kubelet.Kubelet.dispatchWork #把事件对象包装以后丢给podWork异步处理
			    case <-syncChan: #当一个pod在deadline之后仍然是active状态,那么就需要重新同步这个pod的信息
				  kubectl.kubectl.getPodsToSync #获取需要进行同步的pod列表
                    kubelet.Kubelet.dispatchWork #把事件对象包装以后丢给podWork异步处理,事件对象有一个type字段,然后podworker就根据事件类型来调用对应的处理函数
                case <-resultes.Updates: #存活探针触发的事件
				  kubelet.handleProbeSync #直接丢给podWorker
				    kubelet.Kubelet.HandlePodSyncs 
					  kubelet.Kubelet.dispatchWork #把事件对象包装以后丢给podWork异步处理
                case <-resultes.Updates: #就绪探针触发的事件,同上
                case <-resultes.Updates: #启动探针触发的事件,同上
              atomic.Value.Store #记录本次同步操作结束的时间,这个时间在/healthz服务中会用到
          go kubelet.Kubelet.ListenAndServe #开启kubelet对外服务
			server.ListenAndServeKubeletServer
			  server.NewServer #创建kubectlServer对象并进行配置和设置默认值
			    server.Server.InstallAuthFilter #验证相关
			    server.Server.InstallDefaultHandlers #设置url和对应的处理方法
      http.ListenAndServe #运行healthz服务,路径为healthz
      daemon.SdNotify #如果使用的是systemd,那么通知systemd
	  <-done #一直阻塞在这里,直到程序结束

  
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值