天天看点

kube-controller-manager 启动流程controller manager启动流程

controller manager启动流程

一 Run

1.首先启动加载command

(k8s自定义了cobra的命令行参数),加载完command会执行command.Execute(),执行execute的时候会回调command的run

2.在加载command的时候首先会定义一个command

run是在执行execute回调用的 在这里的run封装了一些东西具体如下

(1)根据服务是否安全也就是判断SecureServing 和InsecureServing

相同的操作为

注册检查相关 genericcontrollermanager.NewBaseHandler

BuildHandlerChain使用基本处理程序和CompletedConfig构建处理程序链。(这里也包括认证检查)

服务运行安全的http服务器,仅当无法加载证书或初始侦听调用失败时,它才会失败,实际的服务器循环(可通过关闭stopCh来停止)在go例程中运行,即Serve不会阻塞,返回所有未劫持的活动请求都已处理后关闭的StoppedCh

不同的操作为

如果是不安全 会初始化一个server.AuthenticationInfo如果 安全我们会用方法对应结构体本身的AuthenticationInfo

(2)初始化run run是一个参数为context.Context 没有返回值的函数,在 这个函数中

第一步检测sa的认证方式

第二步创建一个上下文结构,该结构包含对控制器,例如云提供商和clientBuilder。 rootClientBuilder仅用于共享信息客户端和令牌控制器

第三步StartControllers 使用指定的ControllerContext启动一组控制器 ,启动控制器的过程中首先会对控制器init 初始化

在初始化的过程中会得倒一个 新的控制器封装 然后把他run起来 例如deployment controller 我们会调用 deployment.NewDeploymentController 获得一个初始化的deployment controller 并且在gorouting 中run起来,run起来之后他会调用informer的特性来实现资源的监听 例如deployment

(deployment controller 利用了 informer 的工作能力,实现了资源的监听,同时与其他 controller 协同工作。主要使用了三个 shared informer —— deployment informer、rs informer、pod informer,首先 deployment controller 会向三个 shared informer 中注册钩子函数,三个钩子函数会在相应事件到来时,将相关的 deployment 推进 workqueue 中。deployment controller 启动时会有一个 worker 来控制 syncHandler 函数,实时地将 workqueue 中的 item 推出,根据 item 来执行任务。主要包括:领养和弃养 rs、向 eventRecorder 分发事件、根据升级策略决定如何处理下级资源)[这里引用了https://mp.weixin.qq.com/s/J97lvKzix2fX4536_iWnXw]

(3)informerfactory start 允许访问控制器的通知程序 ,这里调用了sharedInformerFactory start

(4)objectormetadatainformerfactory start

// ObjectOrMetadataInformerFactory 允许访问类型资源的通知者

// 和动态资源的元数据。 当前使用的所有通用控制器

// 对象元数据-如果将来的控制器需要访问完整的对象,则此

// 将成为GenericInformerFactory并接受一个动态客户端。

这里会调用sharedInformerFactory start以及i.metadataInformerFactory.Start

(5)close(controllerContext.InformersStarted)

// 所有控制器初始化并运行后, InformersStarted 关闭。 在此之后,这是安全的, 由单个控制器启动共享通知者。 在关闭之前,他们不应该这样做。

注*sharedInformerFactory启动过程,这里他内部informers

map[reflect.Type]cache.SharedIndexInformer 根据type 区分不同的informer会遍历所有的informer 如果状态标记为true 表示已启动 如果标记 false 启动并且标记为true,informer的run调用了sharedIndexInformer的run,其中会创建一个fifo队列并且会调用controller的run,而controller的run,会调用reflector的run,refector的run会调用listandwatch,listandwatch启动的时候会刷新缓存,并且watchhandler也就是watch一个event,并且插入fifo队列,所以说这里根据reflect.type 会挨个启动

metadataSharedInformerFactory Start与informers,类似不过他的结构是map[schema.GroupVersionResource]informers.GenericInformer根据不同的groupversionresource基于,sharedInformers 不过多了一个lister一个通用的索引器 启动流程与sharedInformerFactory类似
kube-controller-manager 启动流程controller manager启动流程
func (f *sharedInformerFactory) Start(stopCh <-chan struct{}) {
	f.lock.Lock()
	defer f.lock.Unlock()

	for informerType, informer := range f.informers {
		//如果informer是 false  也就是未启动状态 那么!false=true
		if !f.startedInformers[informerType] {
			//启动这个informer
			go informer.Run(stopCh)
			//启动之后做标记
			f.startedInformers[informerType] = true
		}
	}
}
           

(3)resourcelock.New

根据给定的类型 给锁

(4)leaderelection.RunOrDie

RunOrDie 使用提供的配置启动客户端,如果配置失败,验证失败

参数

ctx context.Context

在这里传入的是context.TODO()

/ /TODO 返回一个非空的Context。 代码何时应使用context.TODO

使用场景为:

// 尚不清楚要使用哪个上下文,或者尚不可用(因为

// 周围函数尚未扩展为接受上下文参数)。

lec LeaderElectionConfig

总结一下这个主要是做 主从抢占 也就是阻塞机制 当集群模式部署controller manager 那么一个master 多个slave 通过锁的租期以及续租 以及状态的锁的解除来做抢占
type LeaderElectionConfig struct { 
     // 用于锁定的资源 
     Lock rl . Interface 
// 等待强迫获得领导。 这是针对时间最后观察到的确认。 
// 客户需要等待完整的 LeaseDuration ,而无需观察到对可以尝试接管的记录。 当所有客户都关闭,然后以不同的名称启动一组新的客户端相同的领导者记录,他们必须等待完整的 LeaseDuration 之后尝试获取租约。 因此 LeaseDuration 应该尽可能短 
// 可能(在时钟偏斜率的公差范围内)以避免可能在方案中长时间等待。 
// 核心客户端的默认值是 15 秒。 
//简单描述就是这个是一个租约 到时间了需要取续租约 (租期) 
     LeaseDuration time . Duration 
// RenewDeadline是代理主控重试的持续时间 
//在放弃之前刷新领导。 
//核心客户端的默认值是10秒。 
//续约期限 
     RenewDeadline time . Duration 
// RetryPeriod是LeaderElector客户应等待的持续时间 
//在两次尝试之间。核心客户端将此值默认为2秒。 
//重试时间 
     RetryPeriod time . Duration 
//回调是在特定生命周期内触发的回调 
// LeaderElector的事件 
     Callbacks LeaderCallbacks 
     //这里初始化了一个lec将run传递进去
// 关联的健康检查器 
     WatchDog * HealthzAdaptor 
//如果应释放锁,则应将ReleaseOnCancel设置为true 
//取消运行上下文时。 如果将其设置为true,则必须 
//确保此租约保护的所有代码均已成功完成 
//在取消上下文之前,否则您可能有两个过程 
//同时作用于关键路径。 
     ReleaseOnCancel bool 
// Name是用于调试的资源锁的名称 
     Name string 
} 
           
// LeaderCallbacks是在特定时间段内触发的回调 
// LeaderElector的生命周期事件。 这些是异步调用的。 
// 
//将来可能的回调: 
// * OnChallenge() 
type LeaderCallbacks struct { 
//当LeaderElector客户端开始领导时调用OnStartedLeading 
     // OnStartedLeading is called when a LeaderElector client starts leading 
     OnStartedLeading func ( context . Context ) 
     // OnStoppedLeading is called when a LeaderElector client stops leading 
//当LeaderElector客户端停止引导时调用OnStoppedLeading 
     OnStoppedLeading func () 
     // OnNewLeader is called when the client observes a leader that is 
    // not the previously observed leader. This includes the first observed 
    // leader when the client starts. 
//当客户端观察到领导者时,将调用OnNewLeader 
//不是先前观察到的领导者。 这包括第一次观察到的 
//客户端启动时的领导者。 
     OnNewLeader func ( identity string ) 
} 
           

二 .在加载command的时候进行参数解析

参数解析分为以下几个过程

(1)Flags 通过传入 controllers 以及默认的controllers 来做各个controller的命令行参数解析

(2)注册global全局参数

(3)将flags 解析的参数 转移到我们定义的command的flags上

(4)定义usage的使用方法

(5)定义help的使用方法

继续阅读