3.3.1 Controller-runtime框架
Controller-runtime是社区提供的用于开发 Controller的框架,包含了各种已封装的代码库。Kubebuilder与 OperatorSDK都是基于Controller-runtime框架来工作的, 使用 Controller-runtime, 开发者可以方便地开发各种 Controller、CRD、AdmissionWebHook等,如图 3-2所示。
图 3—2Controiier—runtme框架
1. 主要模块
Controller-runtime为 Controller 的开发提供了各种功能模块,每个模块中包括了一个或多个实现,通过这些模块,开发者可以灵活地构建自己的 Controller,主要包括以下内容。
(1) Client:用于读写 Kubernetes 资源对象的客户端。
(2) Cache:本地缓存,用于保存需要监听的 Kubernetes资源。缓存提供了只读客户端,用于从缓存中读取对象。缓存还可以注册处理方法(EventHandler),以响应更新的事件。
(3) Manager:用于控制多个 Controller,提供 Controller共用的依赖项,如 Client、 Cache、Schemes等。通过调用 Manager.Start方法,可以启动Controller。
(4) Controller:控制器,响应事件(Kubernetes资源对象的创建、更新、删除)并确保对象规范(Spec字段)中指定的状态与系统状态匹配,如果不匹配,则控制器需要根据事件的对象,通过协调器(Reconciler)进行同步。在实现上,Controller是用于处理 reconcile.Requests 的工作队列,reconcile.Requests 包含了需要匹配状态的资源对象。
① Controller需要提供Reconciler 来处理从工作队列中获取的请求。
② Controller 需要配置相应的资源监听,根据监听到的 Event 生成 reconcile.Requests并加入队列。
(5) Reconciler:为 Controller提供同步的功能,Controller 可以随时通过资源对象的Name和 Namespace 来调用 Reconciler,调用时,Reconciler 将确保系统状态与资源对象所表示的状态相匹配。例如,当某个 ReplicaSet 的副本数为 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(AdmissionWebHook)是扩展 KubernetesAPI的一种机制,WebHook 可以根据事件类型进行配置,比如资源对象的创建、删除、更改等事件, 当配置的事件发生时,Kubernetes的 APIServer会向 WebHook发送准入请求
(AdmissionRequests),WebHook可以对请求中的资源对象进行更改或准入验证,然后将处理结果响应给 APIServer。准入 WebHook分两种类型:变更(Mutating)准入和验证准入。变更准入用于在 APIServer进行准入验证前,更改请求中的 CRD或核心 API资源。验证准入用于验证请求中的对象是否满足某些要求。
准入 WebHook要求提供处理方法(Handler)来处理接收到的AdmissionRequests。
(7) Source:resource.Source是 Controller.Watch 的参数,提供事件,事件通常是来自Kubernetes的APIServer(如Pod创建、更新和删除)。例如,source.Kind使用指定对象(通过 GroupVersionKind指定)的 KubernetesAPIWatch 接口来提供此对象的创建、更新、删除事件。
① Source通过 WatchAPI提供 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进行过滤。