Controller-runtime框架
Controller-runtime是社区提供的用于开发Controller的框架,包含了各种已封装的代码库。Kubebuilder与Operator SDK都是基于Controller-runtime框架来工作的,使用Controller-runtime,开发者可以方便地开发各种Controller、CRD、Admission WebHook等
主要模块
Controller-runtime为Controller的开发提供了各种功能模块,每个模块中包括了一个或多个实现,通过这些模块,开发者可以灵活地构建自己的Controller,主要包括以下内容。
(1)Client:用于读写Kubernetes资源对象的客户端
(2)Cache: 本地缓存,用于保存需要监听的Kubernetes资源。缓存提供了只读客户端,用于从缓存中读取对象。缓存还可以注册处理方法(EventHandler),以响应更新的事件。
(3)Manager:用于控制多个Controller,提供Controller共用的依赖项,如Client、Cache、Schemes等。通过调用Manager.Start方法,可以启动Controller。
(4)Controller:控制器,响应事件(Kubenetes资源对象的创建、更新、删除)并确保对象规范(Spec字段)中指定的状态与系统状态匹配,如果不匹配,则控制器需要根据事件的对象,通过协调器(Reconciler)进行同步。在实现上,Controller是用于处理reconcile.Requests的工作队列,reconcile.Requests包含了需要匹配状态的资源对象。
- Controller需要提供Reconciler处理从工作队列中获取的请求。
- Controller需要配置相应的资源监听,根据监听到的Event生成reconcile.Requests并加入队列。
(5)Reconciler:为Controller提供同步的功能,Controller可以随时通过资源对象的Name和Namespace来调用Reconciler,调用时,Reconciler将确保系统状态与资源对象所表示的状态匹配。例如,当某个RelicaSet的副本数为5,但系统中只有3个Pod时,同步ReplicaSet资源的Reconciler需要新建两个Pod,并将它们的OwnerReference字段指向对应的ReplicaSet。
- Reconciler包含了Controller所有业务逻辑。
- Reconciler通常只处理单个对象类型,例如只处理ReplicaSets的Reconciler,不处理其它的对象类型。如果需要处理多种类型,需要实现多个Controller。如果你希望通过其他类型来触发Reconciler,例如,通过Pod对象的事件来触发ReplicaSet的Recon-ciler,则可以提供一个映射,通过该映射将触发Reconciler的类型映射到需要匹配的类型。
- 提供给Reconciler的参数是需要匹配的资源对象的Name和Namespace。
- Reconciler不关心触发它的事件的内容和类型。例如,对于同步ReplicaSet资源的Reconciler来说,触发它的是ReplicaSet的创建还是更新并不重要,Reconciler总会比较系统中相应的Pod数量和ReplicaSet中指定的副本数量。
(6)WebHook:准入WebHook(Admission WebHook)是扩展Kubernetes API的一种机制,WebHook可以根据事件类型进行匹配,比如资源对象的创建、删除、更改等事件,当配置的事件发生时,Kubernetes的APIServer会向WebHook发送准入请求处理结果响应给APIServer。准入WebHook分两种类型:变更(Mutaing)准入和验证准入。变更准入用于在APIServer进行准入验证前,更改请求中的CRD或核心API资源。验证准入用于验证请求中的对象是否满足某些请求。
准入WebHook要求提供处理方法(Handler)来处理接收到的AdmissionRequests。
(7)Source:resource。Source是Controller.Watch的参数,提供事件,事件通常是来自Kubernetes的APIServer(如Pod创建、更新和删除)。例如,source.Kind使用指定对象(通过GroupVersionKind指定)的Kubernetes API Watch接口来提供此对象的创建、更新、删除事件。
- Source通过Watch API提供Kubernetes指定对象的事件流。
- 建议开发者使用Controller-runtime中已有Source实现,而不是自己实现此接口。
(8)EventHandler:handler.Eventhandler是Controller.Watch参数,用于将事件对应的reconcile.Requests加入队列。例如,从Source中接收到一个Pod的创建事件,eventhandler.EnqueueHandler会根据Pod的Name与Namespace生成reconcile.Requests后,加入队列。
- EventHandlers处理事件的方式是将一个或多个reconcile.Requests加入队列。
- 在EventHandler的处理中,事件所属的对象的类型(比如Pod的创建事件属于Pod对象),可能与reconcile.Requests所加入的对象类型相同。
- 事件所属的对象的类型也可能与reconcile.Requests所加入的对象类型不同。例如将Pod的事件映射为所属的ReplicaSet的reconcile.Requests。
- EventHandler可能会将一个事件映射为多个reconcile.Requests并加入队列,多个reconcile.Requests可能属于一个对象类型,也可能设计多个对象类型。例如,由于集群扩展导致的Node事件。
- 在大多数情况下,建议开发者使用Controller-runtime中已有的EventHandler来实现,而不是自己实现此接口。
(9)Predicate: predicate.Predicate是Controller.Watch的参数,是用于过滤事件的过滤器,过滤器可以复用或者组合。
- Predicate接口以事件作为输入,以布尔值作为输出,当返回True时,表示需要将事件加入队列。
- Predicate是可选的。
- 建议开发者使用Controller-runtime中已有的Predicate实现,但可以使用其它Predicate进行过滤。
流程
Controller-runtime流程如下图
以使用Controller-runtime开发的PodController为例,Controller的整体流程如下。
(1)Source通过Kubernetes APIServer监听Pod对象,提供Pod的事件
&source.KindSource{&v1.Pod{}} -> (Pod foo/bar Create Event)
(2)EventHandler根据Pod事件,将reconcile.Request加入队列
&handler.EnqueueRequestForObject{} -> (reconcile.Request{types.NamespaceName{Name: "foo", Namespace: "bar"}})
(3)从队列中获取reconcile.Request,并调用Reconciler进行同步
Reconciler(reconcile.Request{types.NamespaceName{Name: "foo", Namespace: "bar"}})
其中,Controller的启动由Manger控制。
Manager
Manager是Controller-runtime库中最主要的结构,可以用来启动Controller、管理Controller依赖、提供集群相关资源的获取方法等。
接口
在pkg/manager/manager.go中,定义了Manager接口,部分开发者常用的方法如下:
(1)cluster.Cluster:接口类型,Manager的匿名成员,Manager继承了cluster.Cluster的所有方法。cluster.Cluster提供了一系列方法,以获取与集群相关的对象。