基于 FUSE 的 POSIX API
Last updated
Last updated
Alluxio POSIX API 是一种客户端协议,允许将 Alluxio 文件系统挂载为大多数 Unix 系统上的标准文件系统,使得 ls
、cat
或 mkdir
这样的标准命令也可以 访问Alluxio 管理的分布式缓存。 此外,集成POSIX API 之后,无论应用程序是用 C、C++、Python、Ruby、Perl 还是 Java 编写,都可以与 Alluxio 进行交互,而无需在现有应用程序中集成任何 Alluxio 库。
Alluxio FUSE 与 S3Fs、mountable HDFS 等项目不同,后者需要将特定的存储服务(如 S3 或 HDFS)挂载到本地文件系统。 而 Alluxio POSIX API 是一个通用的解决方案,适用于 Alluxio 所支持的多种存储系统。 对于频繁使用数据的应用,Alluxio的数据编排和缓存功能能够大幅加速I/O访问、提高读写性能。
目前,Alluxio POSIX API 广泛应用于模型训练以及将模型分发上线的业务场景。
Alluxio POSIX API 基于 FUSE 实现,它支持大多数基本文件系统操作,但考虑到 Alluxio 的固有特性(如一次写入/多次读取的文件数据模型),它挂载的文件系统不具备完整的 POSIX 语义,具体限制参考关于功能和限制的章节。
注意,Alluxio 不支持在文件路径名中包含一些特殊字符。请不要创建包含以下字符的路径,否则需在客户端进行额外处理:
问号 ('?')
带有句号的模式(./ 和 ./)
反斜杠 ('')
在按照说明进行操作之前,请确保已经正确安装 Alluxio 集群。 关于如何安装Alluxio集群,请参阅在 Kubernetes 上安装 Alluxio页面。
容器存储接口(CSI) 是 Kubernetes 定义的一个标准,用于将存储系统暴露给容器。在 Kubernetes 上使用 Alluxio FUSE 时默认使用 CSI。
集群安装完后,operator 会创建一个名为 alluxio-alluxio-csi-fuse-pvc
的 PVC。 您可以将 PVC 挂载到所需的 pod 上,operator会自动创建并绑定合适的 PV。
在上述配置中会把 FUSE 挂载到 /data
目录。下面是有关配置的一些详细说明:
所有 pod 或 replica set 都可以使用相同的 PVC。同一节点上的 pod 将共享同一个 FUSE 进程。
mountPropagation
字段对于 FUSE 进程崩溃时自动恢复是必须的。
您可以在本地目录运行 I/O 操作(如 shell 命令、训练等)。下面是一个简单的示例:
这些操作将由 Alluxio 系统进行翻译和执行,并根据配置在底层存储上执行。
Alluxio 支持大多数基本文件系统操作。 不过,由于Alluxio的固有特性,有些操作并不完全支持。
类型 | 支持的操作 | 不支持的操作 |
---|---|---|
元数据写入 | 创建文件、删除文件、创建目录、删除目录、重命名、chown, chgrp, chmod | symlink、link、utimens、chattr、sticky bit |
元数据读取 | 获取文件状态, 获取目录状态, ls目录 | |
数据写入 | 顺序写、追加写、随机写、覆盖写、截断(truncate) | 多线程/多客户端并发写入同一文件 |
数据读取 | 顺序读, 随机读, 多线程/多客户端并发读取同一文件 | |
其它组合情况 | FIFO 特殊文件类型 |
要启用追加写(append write)或随机写(random write),需要添加 alluxio.user.fuse.random.access.file.stream.enabled=true
的配置
您可以通过在 Alluxio 集群的 YAML 文件中更新 mountOptions
配置来设置FUSE的挂载选项。 如果未指定挂载选项,默认会使用 Alluxio 配置中的 alluxio.fuse.mount.options
的值(默认值为direct_io
)。 Linux 可用的挂载选项可以参考这里 。
挂载选项 | 默认值 | 调优建议 | 描述 |
---|---|---|---|
direct_io | 默认启用 | 在 Kubernetes 环境中部署 Alluxio Fuse 时设置 | 启用 `direct_io` 后,内核将不缓存数据并提前读取。它避免了系统缓冲区占用太多缓存,提高了 kubernetes 环境中 pod 的稳定性 |
kernel_cache | `kernel_cache` 利用内核系统缓存提升读取性能。 如果开启此功能,需要保证该系统中的文件数据不会从外部被修改(比如不能直接通过hdfs或者s3等底层存储对文件进行修改) | ||
auto_cache | 在非Kubernetes环境上部署 Alluxio Fuse 时设置 | `auto_cache`利用内核系统缓存提升读取性能。 如果文件的修改时间或大小自上次打开之后发生了变化,缓存数据将失效,而不会无条件地一直保留缓存数据。 更多信息请参见 [libfuse 文档](https://libfuse.github.io/doxygen/structfuse__config.html#a9db154b1f75284dd4fccc0248be71f66) | |
attr_timeout=N | 1.0 | 600 | 文件/目录属性被缓存的超时时间(秒) |
big_writes | 建议设置 | 阻止 Fuse 将 I/O 分割成小块,加快写入速度。 [libfuse3 中不支持](https://github.com/libfuse/libfuse/blob/master/ChangeLog.rst#libfuse-300-2016-12-08)。 如果使用 libfuse3,该选项将被忽略。 | |
entry_timeout=N | 1.0 | 600 | 文件名称的查找结果被缓存后的超时时间(以秒为单位) |
max_read=N | 131072 | 使用默认值 | 单次 Fuse 读请求中数据的最大大小,默认值为无限大。但读取请求的大小无论如何都会受到限制,最多为最多为 32 个 page(在 i386 上为 128KB) |
max_background=N | 12 | 256 | FUSE 内核驱动程序允许提交的最大未完成后台请求数。 |
max_idle_threads=N | 10 | 256 | 允许的空闲 FUSE daemon 线程的最大数量。 如果该值设置过小,FUSE 可能会频繁创建和销毁线程,从而产生额外的性能开销。 |
如果所使用的 Kubernetes 版本不支持 CSI,或者云厂商没有提供使用 CSI 的权限,可以尝试使用 DaemonSet 类型的 Alluxio FUSE。 在这种类型中,需要预先在所有节点上部署 FUSE Pod(可以使用 nodeSelector
来限制部署到特定节点)。
要使用 DaemonSet FUSE,需要在部署集群前更改 alluxio-cluster.yaml
配置:
这样 FUSE pod 将部署到所有带有 alluxio.com/selected-for-fuse: true
标签的节点上。
DaemonSet FUSE 会将 FUSE 挂载到 hostPathForMount
指定的宿主机路径上。 如果要在 pod 中加载 FUSE,则还需要添加 hostPath
卷:
上面的示例会挂载 fuse 挂载点的父目录并设置 mountPropagation
。 这样的话,当 FUSE 进程崩溃时,容器中的挂载点便可自动恢复。
挂载的 FUSE 设备默认会访问 Alluxio 命名空间的根目录,其中包含所有挂载点。 如果希望为其他用户提供 FUSE 并防止其访问到错误的文件或修改路径,方法如下:
挂载 PVC 的子目录,适用于可以控制用户Pod 的情况。
在示例配置中,访问容器中的 /data
路径与访问 Alluxio 命名空间中的 /s3/path/to/files
相同。
DaemonSet FUSE 也可以使用 subPath
,但 subPath
会中断新的 FUSE 挂载点对容器中挂载路径的传播,并阻止挂载点的自动恢复。请谨慎使用。
使用自定义 StorageClass 创建 PVC 可以将 PVC 绑定到子路径。这需要额外的操作,适合在无法控制用户 Pod 的情况下使用。
创建上述的 StorageClass 和 PVC,并将 PVC 挂载到容器中。 访问容器中的挂载点即等同于访问 Alluxio 命名空间中的 /s3/path/to/files
。
在Kubernetes中,PVC是 namespace 级别的资源。如果 Pod 在其他 namespace 中,为了访问CSI fuse,需要在当前 namespace 中创建独立的PVC:
将配置保存到csi-pvc.yaml
,然后执行:
请注意,CSI fuse pod仍然会在和Alluxio集群相同的namespace中启动。