在 Fluid 中使用 JuiceFS
Fluid 是一个 Kubernetes 原生的分布式数据集编排和加速引擎,本文介绍如何在 Fluid 中使用 JuiceFS。更多关于 Fluid 使用方式,请参考 Fluid 官方文档。
背景介绍
Fluid 使用 CRD 的方式来管理资源,分别提供了如下自定义资源:
- Dataset:用于描述一组数据集。
- JuiceFSRuntime:承载 JuiceFS 的运行时组件,为应用提供 Dataset 的访问能力。
- DataLoad:用于描述数据预热任务。
- DataMigrate:用于描述数据迁移任务。
安装
Fluid 提供 Helm Chart 的安装方式,如下:
helm repo add fluid https://fluid-cloudnative.github.io/charts
helm repo update
helm install fluid fluid/fluid
运行 JuiceFS
在 Fluid 中运行 JuiceFS 只需要 3 步,创建 Secret、Dataset 和 JuiceFSRuntime,其中 Dataset 和 JuiceFSRuntime 需要同名。
文件系统认证信息
操作之前,请先在 JuiceFS 云服务中创建文件系统。
apiVersion: v1
kind: Secret
metadata:
name: jfs-secret
type: Opaque
stringData:
token: ${JUICEFS_TOKEN}
access-key: ${ACCESS_KEY}
secret-key: ${SECRET_KEY}
创建 Dataset
apiVersion: data.fluid.io/v1alpha1
kind: Dataset
metadata:
name: jfsdemo
spec:
mounts:
- name: <vol-name> # JuiceFS Volume 名称
mountPoint: "juicefs:///"
encryptOptions:
- name: token
valueFrom:
secretKeyRef:
name: jfs-secret
key: token
- name: access-key
valueFrom:
secretKeyRef:
name: jfs-secret
key: access-key
- name: secret-key
valueFrom:
secretKeyRef:
name: jfs-secret
key: secret-key
其中:
name
:需要与在 JuiceFS 控制台创建的 volume 名一致。mountPoint
:指的是 JuiceFS 的子目录,是用户在 JuiceFS 文件系统中存储数据的目录,以juicefs://
开头;如juicefs:///demo
为 JuiceFS 文件系统的/demo
子目录;如juicefs:///
为 JuiceFS 文件系统的根目录。encryptOptions
:用于指定 JuiceFS 认证信息,需要与上一步创建的 Secret 中的 key 一致。
创建 JuiceFSRuntime
Fluid 中 Runtime 和 Dataset 是一对一的关系,一个 runtime 只能绑定一个 Dataset,且二者通过同名来绑定。JuiceFSRuntime 的创建示例如下:
apiVersion: data.fluid.io/v1alpha1
kind: JuiceFSRuntime
metadata:
name: jfsdemo # 与 Dataset 同名
spec:
replicas: 1
tieredstore:
levels:
- mediumtype: MEM
path: /dev/shm
quota: 40Gi
low: "0.1"
其中 tieredstore
代表缓存的配置,由于 JuiceFS 目前不支持多级存储,因此只需要配置一个 level
即可。level
中的配置含义如下:
path
:缓存目录,多盘缓存用:
分割多个目录;mediumtype
:用于指明缓存目录所使用的存储设备类型,取值为 "MEM"、"SSD" 或 "HDD";quota
:最大缓存容量;low
:缓存目录的最小剩余空间占比,默认 0.2;
JuiceFSRuntime 和 Dataset 创建好后,二者会自动绑定(status.phase
为 Bound
),绑定后,Fluid 会创建 JuiceFS 的 worker 组件,其个数为 replicas
指定的值,worker 组件会组成一个 JuiceFS 的分布式缓存集群,如下:
$ kubectl get po |grep jfs
jfsdemo-worker-0 1/1 Running 0 4m2s
企业版(私有部署)
JuiceFS Web 控制台负责着客户端的挂载认证、配置文件下发等工作。而在私有部署环境中,控制台的地址不再是 https://juicefs.com/console,需要在 JuiceFSRuntime 中指定控制台的地址,示例如下:
apiVersion: data.fluid.io/v1alpha1
kind: JuiceFSRuntime
metadata:
name: jfsdemo
spec:
worker:
env:
- name: "BASE_URL"
# 将 <CONSOLE_URL> 替换为私有部署控制台地址,例如 http://console.juicefs.com:8080
value: "<CONSOLE_URL>/static"
fuse:
env:
- name: "BASE_URL"
# 将 <CONSOLE_URL> 替换为私有部署控制台地址,例如 http://console.juicefs.com:8080
value: "<CONSOLE_URL>/static"
使用 Dataset
Dataset 和 JuiceFSRuntime 创建完成,且二者绑定后,Fluid 会创建一个与 Dataset 同名的 PVC,应用就可以通过 PVC 来使用 JuiceFS 了,示例如下:
apiVersion: v1
kind: Pod
metadata:
name: demo-app
spec:
containers:
- name: demo
image: nginx
volumeMounts:
- mountPath: /data
name: demo
volumes:
- name: demo
persistentVolumeClaim:
claimName: jfsdemo
Fluid 会在应用 pod 所在的节点上创建一个运行 JuiceFS 的客户端 pod,称为 FUSE pod,用以为应用提供数据读写的服务,如下:
$ kubectl get po |grep demo
demo-app 1/1 Running 0 31s
jfsdemo-fuse-fx7np 1/1 Running 0 31s
jfsdemo-worker-0 1/1 Running 0 10m
缓存配置
默认情况下,worker pod 和 FUSE pod 的缓存都在 spec.tiredstore.levels
中设置,也可以单独设置 worker 的缓存路径。
apiVersion: data.fluid.io/v1alpha1
kind: JuiceFSRuntime
metadata:
name: jfsdemo
spec:
worker:
options:
"cache-dir": "/mnt/cache1:/mnt/cache2"
"cache-size": "102400"
tieredstore:
levels:
- mediumtype: MEM
path: /dev/shm
quota: 500Mi
low: "0.1"
其中,spec.worker.options
为 worker 的挂载参数,缓存路径以 cache-dir
为 key,以 :
分隔的多个路径,也可以设置 cache-size
表示 worker 的缓存最大容量。
Dataset 的访问模式
Dataset 的默认访问模式为 ReadOnlyMany
,也支持 ReadWriteMany
,可以通过 spec.accessModes
来修改,示例如下:
apiVersion: data.fluid.io/v1alpha1
kind: Dataset
metadata:
name: demo
spec:
accessModes:
- ReadWriteMany
...
子目录配额设置
在 Dataset 中可以设置访问 JuiceFS 文件系统的子目录,同时可以为子目录设置配额。以下是一个 Dataset 的示例:
apiVersion: data.fluid.io/v1alpha1
kind: Dataset
metadata:
name: jfsdemo
spec:
mounts:
- name: minio
mountPoint: "juicefs:///demo"
options:
quota: "2Gi"
其中,spec.mounts.options.quota
指定 Dataset 子目录的配额,至少为 1Gi。
商业版 4.9.2 以上支持子目录配额设置。设置子目录配额时,需要确保 JuiceFS 的版本满足要求,在 JuiceFSRuntime 中指定 FUSE 的镜像为 juicedata/juicefs-fuse:v1.0.4-4.9.2
,具体镜像参考 JuiceFS 镜像仓库。
FUSE pod 的配置
FUSE pod 是运行在应用 pod 所在的节点上,并为其提供数据读写服务的组件。
基础配置
对于 FUSE pod 本身的配置,均在 JuiceFSRuntime 中设置;而对于 FUSE pod 中运行的 JuiceFS 客户端的挂载参数则在 Dataset 中设置。
JuiceFSRuntime 的基础配置如下:
apiVersion: data.fluid.io/v1alpha1
kind: JuiceFSRuntime
metadata:
name: jfsdemo
spec:
fuse:
image: registry.cn-hangzhou.aliyuncs.com/juicefs/juicefs-fuse
imageTag: v1.0.0-4.8.0
imagePullPolicy: IfNotPresent
podMetadata:
labels:
juicefs: "fuse"
annotations:
juicefs: "fuse"
networkMode: ContainerNetwork
env:
- name: "GOOGLE_CLOUD_PROJECT"
value: "xxx"
resources:
limits:
cpu: 2
memory: 5Gi
requests:
cpu: 1
memory: 1Gi
其中:
spec.fuse.image
:指定 FUSE pod 的镜像;spec.fuse.imageTag
:指定 FUSE pod 的镜像标签;spec.fuse.imagePullPolicy
:指定 FUSE pod 的镜像拉取策略;spec.fuse.podMetadata
:指定 FUSE pod 的元数据,包括 labels 和 annotations;spec.fuse.networkMode
:指定 FUSE pod 的网络模式,目前支持HostNetwork
和ContainerNetwork
,默认为HostNetwork
;spec.fuse.env
:指定 FUSE pod 的环境变量;spec.fuse.resources
:指定 FUSE pod 的资源限制。
挂载参数设置:
apiVersion: data.fluid.io/v1alpha1
kind: Dataset
metadata:
name: jfsdemo
spec:
mounts:
- name: minio
mountPoint: "juicefs:///demo"
options:
"max-uploads": "20"
Volume 配置
apiVersion: data.fluid.io/v1alpha1
kind: JuiceFSRuntime
metadata:
name: jfsdemo
spec:
fuse:
volumeMounts:
- name: "juicefs-cache"
mountPath: "/var/jfsCache"
volumes:
- name: "juicefs-cache"
hostPath:
path: "/var/jfsCache"
type: DirectoryOrCreate
其中:
spec.fuse.volumeMounts
:指定 FUSE pod 的 volumeMounts,可以指定多个 volumeMounts,其 name 与spec.volumes
中的对应;spec.volumes
:指定 volumes,可以指定多个 volumes。
调度策略配置
FUSE pod 的调度策略目前只支持 nodeSelector
,另外 Fluid 会默认给 FUSE pod 加上 operator: Exists
的 tolerations
,确保节点的 taint 不会影响到 FUSE pod 的调度。
nodeSelector
示例如下:
apiVersion: data.fluid.io/v1alpha1
kind: JuiceFSRuntime
metadata:
name: jfsdemo
spec:
fuse:
nodeSelector:
fluid.io/dataset: jfsdemo
worker pod 的配置
JuiceFSRuntime 会创建 JuiceFS 的缓存 worker,以 StatefulSet 的形式运行在 Kubernetes 集群中。其作用如下:
- JuiceFS 的 worker pod 组成分布式缓存集群,为 FUSE pod 提供分布式缓存;
- JuiceFS worker pod 与 FUSE pod 共享本地缓存,以加速数据访问;
- 应用被调度时,Fluid 会优先将其调度到有缓存 worker 的节点上。
基础配置
worker 的基础配置如下:
apiVersion: data.fluid.io/v1alpha1
kind: JuiceFSRuntime
metadata:
name: jfsdemo
spec:
replicas: 1
juicefsVersion:
image: registry.cn-hangzhou.aliyuncs.com/juicefs/juicefs-fuse
imageTag: v1.0.0-4.8.0
imagePullPolicy: IfNotPresent
worker:
options:
"attr-cache": "10"
podMetadata:
labels:
juicefs: "worker"
annotations:
juicefs: "worker"
networkMode: ContainerNetwork
env:
- name: "GOOGLE_CLOUD_PROJECT"
value: "xxx"
resources:
limits:
cpu: 2
memory: 5Gi
requests:
cpu: 1
memory: 1Gi
其中:
spec.replicas
:指定 worker pod 的副本数;spec.juicefsVersion
:指定 worker pod 的镜像版本;spec.worker.options
:指定 worker 的挂载参数,若此处不额外指定,worker pod 将与 FUSE pod 共用一套挂载参数。具体参数请参考 挂载参数;spec.worker.podMetadata
:指定 worker pod 的元数据,包括 labels 和 annotations;spec.worker.networkMode
:指定 worker pod 的网络模式,目前支持HostNetwork
和ContainerNetwork
,默认为HostNetwork
;spec.worker.env
:指定 worker pod 的环境变量;spec.worker.resources
:指定 worker pod 的资源限制。
Volume 配置
apiVersion: data.fluid.io/v1alpha1
kind: JuiceFSRuntime
metadata:
name: jfsdemo
spec:
worker:
networkMode: ContainerNetwork
volumeMounts:
- name: "juicefs-cache"
mountPath: "/var/jfsCache"
volumes:
- name: "juicefs-cache"
hostPath:
path: "/var/jfsCache"
type: DirectoryOrCreate
其中:
spec.worker.volumeMounts
:指定 JuiceFS worker 的 volumeMounts,可以指定多个 volumeMounts,其 name 与spec.volumes
中的对应;spec.volumes
:指定 volumes,可以指定多个 volumes。
调度策略配置
worker pod 的调度策略有很多种,其中,nodeSelector
在 JuiceFSRuntime 中配置;tolerations
和 nodeAffinity
需要在 Dataset 中配置;worker pod 之间默认已经配置了 podAntiAffinity
,确保每个 worker pod 运行在不同的节点上,不需要额外配置。
nodeSelector
示例如下:
apiVersion: data.fluid.io/v1alpha1
kind: JuiceFSRuntime
metadata:
name: jfsdemo
spec:
worker:
nodeSelector:
fluid.io/dataset: jfsdemo
tolerations
和 nodeAffinity
示例如下:
apiVersion: data.fluid.io/v1alpha1
kind: Dataset
metadata:
name: jfsdemo
spec:
tolerations:
- key: "fluid.io/dataset"
operator: "Equal"
value: "jfsdemo"
effect: "NoSchedule"
nodeAffinity:
required:
nodeSelectorTerms:
- matchExpressions:
- key: "fluid.io/dataset"
operator: "In"
values:
- "jfsdemo"