Karmada 多集群统一编排

Posted by Poor12 Blog on July 25, 2023

在多集群的应用编排的过程中,存在上行和下行两条核心的数据流,即将应用从控制面下发到成员集群的某个节点和将状态实时同步回控制面的资源模板上。

Karmada通过内部的ResourceBinding对象和Work对象串联整个流程:

  • 下行: Template -> ResourceBinding -> Work -> Workloads in clusters
  • 上行: status of Workloads -> status of Work -> status of ResourceBinding -> status of Template

这其中最关键的挑战是在上下行的过程中如何处理联邦控制面和成员集群的冲突。以下列举几个常见的问题:

  • 如果工作负载是个CRD,如何拆分工作负载的实例到多个集群
  • 对于一个资源对象如何将多个集群的状态聚合到资源模板上
  • 对于一类CRD,如Argo Workflow,底下成员集群内有它的控制器,并且会修改资源的Spec或Metadata值,而控制面又想维持原状,如何解决两者的不一致问题
  • ….

Karmada引入了Resource Interpreter Framework来解决这个问题。Resource Interpreter Framework专为解释资源的结构,并提供了若干个接口操作:

  • InterpretReplicas:解析资源的Replicas字段
  • ReviseReplicas:拆分实例时更新资源的Replicas字段
  • InterpretStatus:将成员集群中资源的状态映射到控制面的Work
  • Retain:比较控制面和成员集群的资源对象,从而决定资源在成员集群的最终状态
  • AggregateStatus:将不同集群的状态聚合到同一个控制面的资源模板
  • InterpretHealth: 根据status解析资源的健康状态
  • InterpretDependency:根据spec解析资源的依赖

同时OverridePolicy本质上也是针对特定集群的模板渲染,是应用编排不可或缺的一个步骤。

上述的整个体系构成了Karmada的多集群应用统一编排的解决方案,基于目前的现状仍存在一些待改进点。

  • 工作负载的多集群分发目前是统一发布的,而在实际的应用发布过程中可能有时序的概念。
  • OverridePolicy目前针对的TargetClusters是静态的,且提供的字段覆盖是一种静态的值,而在真正调度前用户根本不知道应用会调度至哪个集群,并且对于某个集群的差异化配置可能不是一个固定的值,而是根据资源字段的值进行动态变化的。
  • 当用户把资源模板拆分到多个集群时,可能需要拆分的不仅仅是实例数,还有其他CRD的特定字段,在当前的框架内不能很好的解决。

对于一个完整的应用编排平台而言,仅仅依靠Karmada是不够的,借助原生API,Karmada可以轻松集成CNCF生态中的其他项目,在这个过程中也有两条路线:

  • 中心侧集成,将其他项目的控制器与Karmada控制平面组件放在一起,统一监听karmada-apiserver平面的CRD,并为控制面的控制器处理后向成员集群同步, 优势是成员集群无感知,劣势是某些项目不支持类似Karmada的这种Out-of-Cluster的部署模式,可能需要侵入式地修改代码。
  • 集群侧集成,项目的控制器和CRD安装在成员集群中,Karmada控制面只安装CRD,且只负责将CRD下发至成员集群,由成员集群的控制器来Reconcile。 优势是对第三方项目不需要侵入式修改,劣势是需要在底下的集群中安装整个项目。

随着多云多集群的应用场景的增多,越来越多的项目也在扩展对多集群场景的支持,比较典型的有GitOps。 在平台侧新增集群联邦这一层胶水层后,对原有的业务系统的改造也有两种不同的路线,例如我原先使用Argo CD来作GitOps,那么我该如何整合集群联邦层和GitOps模块。

  • 沿用项目的多集群能力,不使用集群联邦,这样可以确保项目体验的一致性。
  • 使用集群联邦的集群分发能力,项目仅作单集群内的应用编排,GitOps模块整个位于联邦层之下。