Fluid 架构

Fluid 系统架构
Fluid 是构建在 K8s 上的系统,对原生 K8s 具备良好的兼容性,无需修改任意代码。如上图所示,用户需要定义两个 CRD,分别是 Dataset 和 Runtime。Dataset 是数据集的通用定义,这是我们提供的 K8s 资源对象,需要写 YAML 文件来定义数据集从哪儿来,以及想要放到哪儿去;Runtime 是存储这些数据集的缓存引擎,目前使用的是开源的分布式缓存系统 Alluxio。这里要注意的是 Dataset 和 Runtime 定义的时候,它通常是要具有相同 Namespace,从而实现很好的绑定。

- Fluid Operator 是 Fluid 项目的核心,它分为两部分。第一部分是 Fluid-controller-manager,包含很多 Controller;另一部分为 Fluid-Scheduler。这两个组件完成了编排调度的操作。Fluid-controller-manager 做的工作就是对数据进行编排,包括三个 Controller。这三个 Controller 从逻辑上它们是独立的,可以去做单进程。但为了降低复杂性,很多 Controller 的功能编译时被合并成一个和多个可执行文件,所以在真正运行起来时,也是一个进程。
    - 数据集的 Dataset Controller 负责整个数据集的生命周期管理,包括数据集的创建,以及要和哪个 Runtime 进行绑定。
    - Runtime Controller 负责数据集如何在云原生平台上被调度与缓存,应该放在哪些节点上,要有多少副本。
    - Volume Controller:由于 Fluid 是基于 K8s 运行,因此需要和 K8s 进行对接,这里我们使用的是 PVC(数据持久卷)协议,这是 K8s 本地存储栈的协议,使用非常广泛,Fluid 与 PVC 的对接非常流畅。
    - 最下面为 Cache Runtime Engine,是真正完成缓存数据具体工作的地方。
- 图中右边部分的 Fluid-Scheduler 主要是基于定义好的 dataset、runtime controller 等具体信息,对 K8s 的调度器做一些扩展。这里面包含两个 Plugin:
    - Cache co-locality Plugin:Cache co-locality Plugin 做的事就是结合前面数据编排的信息,把应用调度到最合适的节点上,然后尽量能够让用户去读到缓存节点里面的信息。
    - Prefetch Plugin:当用户集群还没有缓存流入数据情况之下,且知道应用肯定是要读哪一类数据时,尤其在应用调度和编排运行之前,可以做 Prefetch 的调度,将这个数据从最底下的存储卷当中缓存到数据缓存里面,可以手动触发。
- 再往下就是标准 K8s。通过 K8s 可以对接底层不同的存储,具体的对接方式可通过 K8s 的 PVC 完成。由于通过 Alluxio 进行了抽象,可以直接支持 Alluxio 本身支持的存储类型。
根据数据集本地性调度作业

- 对于使用数据集应用的编排也很容易,只需要使用 PVC 模式把 Fluid 数据集挂载到应用当中,然后 K8s 调度器就会和 Fluid 调度器进行交互。
- 如上图例子所示,挂载之后进行交互,根据调度策略安排 Pod 在对应的节点上运行。K8s 调度器和 Fluid 调度器交互时会看见三个节点,其中有两个有 Alluxio 缓存节点。我们知道经典的 K8s 调度包括两个很重要的阶段,一个是过滤阶段,另一个是优选阶段。在过滤阶段就会将第三个节点直接过滤掉,而在优选阶段可以利用一些内置优选的策略来选择更合适的节点,例如缓存空间量大小,这里面有很多未来可以拓展优化实现的空间。

实现
Fluid 工作原理解析Fluid 的整个架构主要分为两个部分。
Controller,包括 RuntimeController 及 DatasetController,分别管理 Runtime 和 Dataset 的生命周期,二者共同作用,以 helm chart 为基础,快速搭建出一套完整的分布式缓存系统,通常是 master + worker + fuse 的形式,向上提供服务。master 是缓存系统的核心组件,通常是一个 pod;worker 是组成缓存集群的组件,可以是多个 pod,可以设置个数;fuse 是提供 POSIX 接口服务的组件;
调度器,在有缓存的情况下,调度器会根据 worker 的节点信息,使得上层应用 pod 尽可能调度到有缓存的节点。
整个过程如下,Dataset Controller 监听 Dataset,Runtime Controller 监听对应的 Runtime,当二者一致时,RuntimeController 会启动 Engine,Engine 创建出对应的 Chart(Runtime Controller 启动 JuiceFS 的环境的方法是启动一个 helm chart,其渲染的 values.yaml 以 ConfigMap 的形式保存在集群中),里面包含 Master、Worker、FUSE 组件。同时,Runtime Controller 会定期同步数据(如总数据量、当前使用数据量等)状态更新 Dataset 和 Runtime 的状态信息。

各个组件的作用:
- dataset-controller:管理 Dataset 的生命周期
- juicefsruntime-controller:管理 JuiceFSRuntime 生命周期,并快速搭建 JuiceFS 环境;
- fluid-webhook:实现 Fluid 应用的缓存调度工作;
- csi-nodeplugin:实现各引擎的挂载路径与应用之间的连接工作;
大致理解:Dataset 表述了要访问哪些数据源文件,对pod 提供了pv和pvc ,对下封装了缓存、数据集调度等能力。
- fluid 开发了对应的csi ,Dataset 和 Runtime Bound 之后,fluid 会自动创建与 Dataset 同名的pvc 和 pvc
- pod 调度到一个node 上之后,因为pod 声明了和dataset 同名的pvc,fluid csi 在node 上准备一个目录(pv),走csi 流程挂到pod 里。
- 此外 在node上启动一个fuse pod(或者说,fuse pod 将挂载点暴露在宿主机上,然后 csi 将挂载点 bind 到应用 pod 里)。pod 里程序对这个目录的读写请求 都转给了fuse pod,fuse 将文件io 转为网络io 访问真实的runtime。PS:
在 Fluid 中,数据加速对应的是 DataLoad,也是一个 CRD,DatasetController 负责监听该资源,根据对应的 DataSet 启动 Job,执行数据预热操作。同时 Runtime Controller 向 Worker 同步缓存的数据信息,并更新 Dataset 的状态。
posted @ 2024-02-25 09:07  muzinan110  阅读(111)  评论(0编辑  收藏  举报