写点什么

云原生多云应用利器 -- Karmada 控制器

作者:Daocloud 道客
  • 2022 年 3 月 01 日
  • 本文字数:5948 字

    阅读完需:约 20 分钟

在上一篇《云原生多云应用利器-- Karmada 总览篇》中已经介绍了多云的相关简介的内容和架构。接下来,在这一篇中来一起看看 Karmada 中有哪些 Controllers 来协调完成多云的控制逻辑。




Controller (控制器) 在 Kubernetes 中是逻辑能力的主要体现所在,根据资源对象的状态来完成调和工作,让资源对象逐步接近期待的状态,这个就是 Kubernetes 的申明式特性。

在 Karmada 中,同样需要对 Karmada 自己的资源对象,实现对应的申明式特性,这就需要实现对应的 Controller。在 Karmada 中目前的版本中有 11 个 Controllers,接下来就从每一个控制器所负责的资源对象,以及原理来分析一下,在 Karmada 中是怎样完成多云能力的。


Karmada Controllers 一览表及原理分析


01 Cluster Controller

cluster controller 主要就是处理 Cluster 资源对象的逻辑,负责处理 Cluster 对应需要的关联资源。

相关资源对象:Cluster

  • 创建 Cluster 的时候,需要在 Karmada 中创建对应的 execution namespace,这个 namespace 中会保存所有这个集群相关的 Work 对象。

  • 删除 Cluster 的时候,需要在 Karmada 中删除对应的 execution namespace。

  • Cluster 资源对象保存在 karmada-cluster 这个 namespace 中,这个 namespace  中保存了所有集群对应的 Cluster 资源对象。

02 Cluster status controller:

cluster status controller 主要就是处理 cluster status 资源对象的逻辑,用来收集 Cluster 的状态,保存到 Cluster 的 status 字段中,同步上报到 Karmada 的控制平面中。

相关资源对象:Cluster

  • watch Cluster 对象,然后执行 sync 方法,同步上报集群的状态给 Karmada 控制平面 (也就是 Karmada 集群中,karmada-cluster 这个 namespace 中的某一个 cluster 对象)。

  • 收集当前 agent 所在集群的状态信息,这些信息包含 Nodes 统计,Pods 相关的资源统计,Kubernetes 版本,以及 Kubernetes 集群支持的资源对象的类型的 GVR,其中包含 CRD 的支持信息等,然后同步更新到 Karmada 控制平面 Cluster 对象的 status 中。具体的状态包含哪些信息,请查看《云原生多云应用利器-- Karmada 总览篇》

03 namespace sync controller:

namespace sync controller 主要就是处理 namespace 资源对象的逻辑,负责将 Karmada 控制平面创建的 namespace 在集群中同步创建出来。

相关资源对象:namespace

  • namespace sync controller 就是为了将在 Karmada 中创建的 namespace 在所有的工作集群中也去创建出来。

  • namespace 是 “karmada-cluster”,或者是 “karmada-system”,或者是 “default”, 或者 namespace 是 “karmada-es-<xxx>”, 或者是 “kube-<xxx>” 这样 namespace 是不需要处理的。以及被包含在 SkippedPropagatingNamespaces 配置中的 namespace,也不需要处理。

04 Resourse Template controller:

detector 模块中包含了通用 controller 负责 resource template 的 Kubernetes 资源对象的调和处理逻辑,以及匹配 PropagationPolicy。主要就是处理 PropagationPolicy 资源对象的逻辑,来派生出资源对象对应的 ResourceBinding 对象。

相关资源对象:PropagationPolicy, Kubernetes 支持的所有的资源对象 (包括 CRD)



  • 定义处理 PropagationPolicy / ClusterPropagationPolicy 的 informer,event handler,以及对应的 reconciler 方法。

  • 定义处理 ResourceBinding / ClusterResourceBinding 的 informer,event handler,以及对应的 reconciler 方法。

  • 定义处理所有原生 Kubernetes 资源对象的 informer,event handler,以及对应的 reconciler 方法,然后为其创建对应的 ResourceBinding 对象用于调度。

  • 根据 Kubernetes 的对象定义以及 PropagationPolicy 构建 ResourceBinding 对象,同时这个 ResourceBinding 的 OwnerReferences 设置了这个 Kubernetes 的对象,这样就会在删除 Kubernetes 对象的时候删除这个 ResourceBinding,这个也是目前 ResourceBinding 会被删除的唯一逻辑了。

  • 所以虽然 ResourceBinding 是因为 PropagationPolicy 的创建而被派生出来,但是不会因为 PropagationPolicy 的删除而删除。

  • 在删除 PropagationPolicy 删除的时候,只会去除 PropagationPolicy 和 Kubernetes 对象的关系,这个关系体现在,Kubernetes object 会在匹配到 PropagationPolicy 的时候在自己的 label 上增加 PropagationPolicy 相关的 label。

  • ResourceBinding 中不会包含 Kubernetes 资源对象的详细信息,只会包含类型,namespace,name,版本,副本数,cpu/memory 请求,节点亲和性,真正详细的 Kubernetes 对象的处理是在  controller 的 syncbinding() 方法中完成,其中是通过 workload, err := helper.FetchWorkload (c.DynamicClient,c.InformerManager,c.RESTMapper, binding.Spec.Resource) 去拿到真正的 Kubernetes 资源对象的定义的。

  • 每隔 30s 去发现新的 Kubernetes 的资源对象类型,只要这些资源对象支持 list,watch,delete 方法,当然也包括 crd 类型。

05 Binding controller:

binding controller 主要就是处理 ResourceBinding 资源对象的增删改逻辑,ResourceBinding 的调和能力是派生出 work 对象,work 对象是和特定集群关联的。一个 work 只能属于一个集群,代表一个集群的资源对象的模型封装。

相关资源对象:ResourceBinding 和 ClusterResourceBinding

  • 负责 ResourceBinding 的处理,根据 binding 去创建对应的 Work 对象到集群对应的 execution space 中。

  • 在生成 Work 的时候,会处理 OverridePolicy,将需要覆盖的数据更新到 Work 对应的 manifest 中。目前支持的 override 的方式主要是 4 种,包括:PlaintextOverrider,mageOverrider,CommandOverrider,ArgsOverrider。

apiVersion: policy.karmada.io/v1alpha1 kind: OverridePolicy metadata:  name: nginx-propagation spec:  resourceselectors:   一 apiVersion: apps/v1      kind: Deployment name: nginx  targetcluster:    clusterNames:    -10-23-20-93  overriders:   plaintext:   一 path: "/spec/template/spec/containers/O/image"    operator: replace value: "nginx:test"
复制代码
  • 根据调度器计算好的每一个集群负责的副本数,如果调度器计算出来的所有集群的对应的副本数是 0,说明没有找合适的集群,就用 ReplicaSchedulingPolicy 根据权重去计算每一个集群应该负责的副本数,这个 ReplicaSchedulingPolicy 的计算副本分配的方式是用 static weight。

  • 收集每一个 binding 的状态,一个 binding 会包含多个 Work,因为同一个资源对象,在每一个集群中就需要一个 Work,所有 binding 的状态是所有工作集群中 Work 的状态的汇总,汇总之后将这个状态设置到 binding 的 status 中去。

备注: 原理图参见第 4 部分的图

06 execution controller:

execution controller 主要就是处理 Work 资源对象的增删改逻辑,用于处理 Work,将 Work 负责的 Kubernetes 资源对象在对应的集群上创建出来。

相关资源对象:Work

  • watch Karmada 控制平面的 execution namespace 中的所有 Work 对象,当有新的 Work 对象被创建了之后会在对应的工作集群中创建 Work 负责的资源对象。

  • watch Karmada 控制平面的 execution namespace 中的所有 Work 对象,当有 Work 对象被删除的时候,会在工作集群中,删除 Work 对象负责的资源对象。watch Karmada 控制平面的 execution namespace 中的所有 Work 对象,当有 Work 对象被修改了之后,会在工作集群中,修改 Work 对象负责的资源对象。


备注: 原理图参见第 4 部分的图

07 work status controller:

work status controller 主要就是处理 Work 资源对象的状态逻辑,负责收集 Work 的状态,也就是 Work 对应的资源对象的状态,只是这个状态是保存在 Work 的 status 字段里的。

相关资源对象:Work,以及 Work 负责的资源对象。

  • watch Work 对象为指定计算集群包含的所有的 Work 对象所负责的资源对象的类型创建对应的 informer 对象,同时调用 informer 的 WaitForCacheSync,当 WaitForCacheSync 结束了之后,也就是 list 结束了,接下来就是 watch 的任务了。这个就是 list and watch 的核心机制。

  • 在 watch 所有 Work 负责的资源对象的时候,设置了一个事件处理器,这个事情处理器会负责处理所有相关资源对象的 Add,Update,Delete 事件。这些事件存放在 queue 中。

  • 启动一个异步的 AsyncWorker, 设置一定的 WorkerNumber 数量的 goroutines 去处理 queue 里的数据,这里的数据是带有集群信息的 fedkey。 

  • 从 queue 中获取 fedkey,判断这个 fedkey 的对应的集群中的资源对象,如果这个 Work 负责的资源对象在工作集群中被非法删除了,会重新在工作集群中创建出对应的资源对象。

  • 从 queue 中获取 fedkey,判断这个 fedkey 的对应的集群中的资源对象,如果这个 Work 负责的资源对象被修改了之后是不是修改被修改回去。如果是的话,会重新 sync 回资源对象,防止直接从工作集群中直接修改资源对象。 

  • 收集 Work 对象对应的资源对象在 Worload 集群中的运行状态,然后更新到到控制平面的 Work 的 status 中。

  • watch Karmada 控制平面的 execution namespace 中的所有 Work 对象,当有新的 Work 对象被创建了之后会在对应的工作集群中创建  Work 负责的资源对象。


08 serviceexport controller:

serviceexport controller 主要就是处理 serviceexport 资源对象的状态逻辑,将需要被其它集群发现的服务暴露出来。

相关资源对象:ServiceExport



  • 当控制平面创建 ServiceExport 对象的时候,会对应的创建出 Work 对象,以及在对应的工作集群中创建出 ServiceExport 对象。 

  • 查找出 ServiceExport 对象对应的 service 对象的 EndpointSlice 对象,将这些 EndpointSlice 对象封装成 work 对象创建到控制平面中。 

  • 当在控制平面删除 ServiceExport 对象的时候,会找到对应的 work 对象,将其删除。这里删除的时候也会一起删除由 ServiceExport 关联上报上来的 EndpointSlice 对象对应的 Work 对象。因为查找要删除的 Work 的时候是根据服务名查找的,而 ServiceExport 和 Serivce 对应的 EndpointSlice 的 Work 都是用服务名来创建的,所以查找的时候会一起查找到。

  • 当工作集群的 EndpointSlice 发生变化的时候,也会同步去更新控制平面的 EndpointSlice 对象,因为 ServiceExport controller 是 watch 了每一个集群的 ServiceExport 的 add 事件以及 EndpointSlice 的 add 和 update 事件的。只要 EndpointSlice 变化,就会同步到控制平面。这样会触发 PropagationPolicy 关联的对象发生变化,就会触发更新 EndpointSlice 对应的 Work,也就会同步更新 ServiceImport 集群中由于 ServiceImport 而级联出来的 EndpointSlice 了。

09 endpointslice controller:

endpointslice controller 主要根据 serviceexport 资源对象对应到处的 Service,Service 对应的 endpointslice 上报到 Karmada 的控制面。

相关资源对象:EndpointSlice 相关的 Work

  • 负责将 work 中的 manifest 是 EndpointSlice 的 work 中的 EndpointSlice 对象,在 Karmada 控制平面中创建对应的 EndpointSlice 的对象。

  • 其中 Karmada 控制平面中的 EndpointSlice 的 namespace 就是和 work 中 manifest 中的 EndpointSlice 的 namespace 一样。但是 Karmada 控制平面中的 EndpointSlice 的 name 不一样,格式为:“imported-<cluster name>-<endpointslice name>”。

备注: 原理图参见第 8 部分的图

10 serviceimport controller:

serviceimport controller 主要负责根据 ServiceExport 暴露出来的 Service,在自己负责的集群中创建对应的 service,注意 service 的名称不是完全一样的,同时在自己负责的集群中也创建对应的 EndpointSlice,这个 EndpointSlice 的数据就是来源于 EndpointSlice controller 中上报到 karmada 控制平面的 EndpointSlice 对象,具体是通过在 karmada-webhook 中给 ServiceImport 的 PropagationPolicy 中增加了 EndpointSlice 的下发能力。

相关资源对象:ServiceImport

  • 根据在 karmada 控制平面中创建的 ServiceImport ,去创建对应的 Service,这个 Service 是创建在 Karmada 控制平面的。

  • 如果控制平面中的 ServiceImport,也会删除控制平面中的由这个 ServiceImport 派生出来的 Service。

  • 由于 ServiceImport 的 controller 中会在控制平面中创建 Service,同时由于 ServiceExport 的 controller 中,会创建一个被 export 的 Service 的 EndpointSlice 的 work 在控制平面中,这个 work 会被 EndpointSlice controller 控制,同时 EndpointSlice controller 在控制平面中创建对应的 EndpointSlice 对象,EndpointSlice 中的每一个 Endpoint 的 IP 都是 Pod 的 IP 地址。

  • 在创建 ServiceImport 需要的 PropagationPolicy 的时候会在 karmada-webhook 中修改 PropagationPolicy 的 resource selector,在其中增加 Service 和 EndpointSlice 的部分,helper.GetFollowedResourceSelectorsWhenMatchServiceImport(policy.Spec.ResourceSelectors)。 最后会随着 detector 和 binding controller 中的逻辑,在对应的集群的 execution 的 space 中创建对应 Service 和 EndpointSlice 的 work,然后由 execution controller 去对应的工作集群去创建真正的资源对象。这样在 ServiceImport 的集群中,就可以通过派生出来的 Service,进行访问远程被 export 出来的服务。前提是两个集群之间的 Pod 网络是互通的。  

  • 由 ServiceImport 派生出来的 service 的 name 为 :“derived-<service name>”。

备注: 原理图参见第 8 部分的图

11 hpa controller:

hpa controller 主要负责将 Karmada 控制面中创建的 HPA 对象通过创建 Work 的方式下发到对应的集群中。

   相关资源对象:HPA

  • 首先根据 HPA 的定义,获取需要被 HPA 控制的资源对象对象,这里主要就是指的像 Deployment 这种需要计算资源的对象。

  • 根据 HPA 控制的资源对象,去查找这些资源对象对应的 ResourceBinding 的 cr 对象,因为 ResourceBinding 是最终反应 Deployment 被调度到哪些集群的实时的,最终的状态。

  • 根据找到的集群,在这些集群中创建每个集群对应的 Work 对象,这个 Work 对象负责的资源对象就是 HPA 对象。

  • 通过这样的实现,保证了 HPA 被创建的集群一定是和真正的工作负载是在一个集群中的,保证了 HPA 的正确的调度。

12「DaoCloud 道客」贡献参与

目前「DaoCloud 道客」在 Karmada 项目中,主要参与调度模块和部署模块的设计开发,也参与相关 bug 的修复,完成了非 root 权限快速安装 karmada 的功能开发,对优先级调度和抢占特性、插件管理特性等方面,也在持续的关注和跟进。

图注:已提交的 PR 

图注:跟进的项目




本文作者 


熊中祥

「DaoCloud 道客」技术合伙人,云原生技术专家

发布于: 刚刚阅读数: 4
用户头像

驾驭数字方程式 2022.02.11 加入

遨游云原生,驾驭数字方程式,打造开放的云操作系统为企业数字化转型赋能

评论

发布
暂无评论
云原生多云应用利器 -- Karmada 控制器_Kubernetes_Daocloud 道客_InfoQ写作平台