创建和使用 PV
文件系统认证信息
在 JuiceFS CSI 驱动中,挂载文件系统所需的认证信息,均存在 Kubernetes Secret 中。所谓「认证信息」,在 JuiceFS 社区版和云服务有着不同的含义:
- 对于社区版而言,「认证信息」包含元数据引擎 URL、对象存储密钥,以及
juicefs format
命令所支持的其他参数。 - 对于云服务而言,「认证信息」包含文件系统名称、Token、对象存储密钥,以及
juicefs auth
命令所支持的其他参数。
- 如果你已经在用 Helm 管理 StorageClass,那么 Kubernetes Secret 其实已经一并创建,此时我们推荐你继续直接用 Helm 管理 StorageClass 与 Secret,而不是用 kubectl 再单独创建和管理 Secret。
- 修改了文件系统认证信息后,还需要滚动升级或重启应用 Pod,CSI 驱动重新创建 Mount Pod,配置变更方能生效。
社区版
创建 Kubernetes Secret:
apiVersion: v1
kind: Secret
metadata:
name: juicefs-secret
type: Opaque
stringData:
name: <JUICEFS_NAME>
metaurl: <META_URL>
storage: s3
bucket: https://<BUCKET>.s3.<REGION>.amazonaws.com
access-key: <ACCESS_KEY>
secret-key: <SECRET_KEY>
# 设置 Mount Pod 时区,默认为 UTC。
# envs: "{TZ: Asia/Shanghai}"
# 如需在 Mount Pod 中创建文件系统,也可以将更多 juicefs format 参数填入 format-options。
# format-options: trash-days=1,block-size=4096
字段说明:
name
:JuiceFS 文件系统名称metaurl
:元数据服务的访问 URL。更多信息参考「如何设置元数据引擎」 。storage
:对象存储类型,比如s3
,gs
,oss
。更多信息参考「如何设置对象存储」 。bucket
:对象存储 Bucket URL。更多信息参考「如何设置对象存储」 。access-key
/secret-key
:对象存储的认证信息envs
:Mount Pod 的环境变量format-options
:创建文件系统的选项,详见juicefs format
。该选项仅在 v0.13.3 及以上可用。
如遇重复参数(比如 access-key
),既可以在 Kubernetes Secret 中填写,同时也可以在 format-options
下填写,此时 format-options
的参数优先级最高。
云服务
操作之前,请先在 JuiceFS 云服务中创建文件系统。
创建 Kubernetes Secret:
apiVersion: v1
kind: Secret
metadata:
name: juicefs-secret
type: Opaque
stringData:
name: ${JUICEFS_NAME}
token: ${JUICEFS_TOKEN}
access-key: ${ACCESS_KEY}
secret-key: ${SECRET_KEY}
# 设置 Mount Pod 时区,默认为 UTC。
# envs: "{TZ: Asia/Shanghai}"
# 如需指定更多认证参数,可以将 juicefs auth 命令参数填写至 format-options。
# format-options: bucket2=xxx,access-key2=xxx,secret-key2=xxx
字段说明:
name
:JuiceFS 文件系统名称token
:访问 JuiceFS 文件系统所需的 token。更多信息参考访问令牌。access-key
/secret-key
:对象存储的认证信息envs
:Mount Pod 的环境变量format-options
:云服务juicefs auth
命令所使用的的参数,作用是认证,以及生成挂载的配置文件。该选项仅在 v0.13.3 及以上可用
如遇重复参数(比如 access-key
),既可以在 Kubernetes Secret 中填写,同时也可以在 format-options
下填写,此时 format-options
的参数优先级最高。
云服务的 juicefs auth
命令作用类似于社区版的 juicefs format
命令,因此字段名依然叫做 format-options
。
企业版(私有部署)
JuiceFS Web 控制台负责着客户端的挂载认证、配置文件下发等工作。而在私有部署环境中,控制台的地址不再是 https://juicefs.com/console,因此需要在文件系统认证信息中通过 envs
字段额外指定控制台地址。
apiVersion: v1
metadata:
name: juicefs-secret
namespace: default
kind: Secret
type: Opaque
stringData:
name: ${JUICEFS_NAME}
token: ${JUICEFS_TOKEN}
access-key: ${ACCESS_KEY}
secret-key: ${SECRET_KEY}
# 不需要对 `%s` 进行任何替换更改,在执行文件系统挂载时,客户端会用实际文件系统名来替换该占位符
envs: '{"BASE_URL": "$JUICEFS_CONSOLE_URL/static", "CFG_URL": "$JUICEFS_CONSOLE_URL/volume/%s/mount"}'
# 如需指定更多认证参数,可以将 juicefs auth 命令参数填写至 format-options
# format-options: bucket2=xxx,access-key2=xxx,secret-key2=xxx
字段说明:
name
:JuiceFS 文件系统名称token
:访问 JuiceFS 文件系统所需的 token。更多信息参考访问令牌。access-key
/secret-key
:对象存储的认证信息envs
:Mount Pod 的环境变量,在私有部署中需要额外填写BASE_URL
、CFG_URL
,指向实际控制台地址format-options
:云服务juicefs auth
命令所使用的的参数,作用是认证,以及生成挂载的配置文件。该选项仅在 v0.13.3 及以上可用
为 Mount Pod 额外添加文件
部分对象存储服务(比如 Google 云存储)在访问时需要提供额外的认证文件,这就需要你用创建新的 Secret 保存这些文件(区别于前面创建的供 JuiceFS 使用的 Secret),然后在 juicefs-secret
中引用。这样一来,CSI 驱动便会将这些文件挂载进 Mount Pod,用于 JuiceFS 挂载时的认证。下方虽然以 Google 云存储为例,但对于任何需要给 Mount Pod 添加额外配置文件的场景,步骤都是一样的。
获取 Google 云存储所需要的服务帐号密钥文件,需要先了解如何进行身份验证和授权。假设你已经获取到了密钥文件 application_default_credentials.json
,用下方命令将该配置文件创建成 Kubernetes Secret:
kubectl create secret generic gc-secret \
--from-file=application_default_credentials.json=application_default_credentials.json
经过上方命令,密钥文件就被保存在 gc-secret
中了,接下来需要在 juicefs-secret
中加以引用,让 CSI 驱动将该文件挂载到 Mount Pod 中,并添加相应的环境变量:
apiVersion: v1
kind: Secret
metadata:
name: juicefs-secret
type: Opaque
stringData:
...
# 在 configs 中填写 Secret 名称和挂载目录,将该 Secret 整体挂载进指定的目录
configs: "{gc-secret: /root/.config/gcloud}"
# 定义挂载认证所需的环境变量
envs: "{GOOGLE_APPLICATION_CREDENTIALS: /root/.config/gcloud/application_default_credentials.json}"
添加完毕以后,新创建的 PV 便会使用此配置了,你可以进入 Mount Pod 里,确认配置文件挂载正确,然后用 env
命令确认环境变量也设置成功。
静态配置
静态配置是最简单直接地在 Kubernetes 中使用 JuiceFS PV 的方式,阅读「使用方式」以了解「动态配置」与「静态配置」的区别。
创建 PersistentVolume(PV)、PersistentVolumeClaim(PVC),字段含义请参考注释:
apiVersion: v1
kind: PersistentVolume
metadata:
name: juicefs-pv
labels:
juicefs-name: ten-pb-fs
spec:
# 目前 JuiceFS CSI 驱动不支持设置存储容量,填写任意有效值即可
capacity:
storage: 10Pi
volumeMode: Filesystem
accessModes:
- ReadWriteMany
persistentVolumeReclaimPolicy: Retain
csi:
# 在先前的安装步骤中,已经创建了名为 csi.juicefs.com 的 CSIDriver
driver: csi.juicefs.com
# volumeHandle 需要保证集群内唯一,因此一般直接用 PV 名即可
volumeHandle: juicefs-pv
fsType: juicefs
# 在先前的步骤中已经创建好文件系统认证信息(Secret),在这里引用
# 如果要在静态配置下使用不同的认证信息,甚至使用不同的 JuiceFS 文件系统,则需要创建不同的 Secret
nodePublishSecretRef:
name: juicefs-secret
namespace: default
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: juicefs-pvc
namespace: default
spec:
accessModes:
- ReadWriteMany
volumeMode: Filesystem
# 静态配置下必须指定 storageClassName 为空字符串
# 代表该 PV 不采用任何 StorageClass,而是直接使用 selector 所指定的 PV
storageClassName: ""
# 由于目前 JuiceFS CSI 驱动不支持设置存储容量,此处 requests.storage 填写任意小于 PV capacity 的有效值即可
resources:
requests:
storage: 10Pi
selector:
matchLabels:
juicefs-name: ten-pb-fs
创建应用 Pod,并在其中引用 PVC,示范:
apiVersion: v1
kind: Pod
metadata:
name: juicefs-app
namespace: default
spec:
containers:
- args:
- -c
- while true; do echo $(date -u) >> /data/out.txt; sleep 5; done
command:
- /bin/sh
image: centos
name: app
volumeMounts:
- mountPath: /data
name: data
resources:
requests:
cpu: 10m
volumes:
- name: data
persistentVolumeClaim:
claimName: juicefs-pvc
创建 StorageClass
如果你打算以「动态配置」或「通用临时卷」的方式使用 JuiceFS CSI 驱动,那么你需要提前创建 StorageClass。
阅读「使用方式」以了解「动态配置」与「静态配置」的区别。
通过 Helm 创建
创建 values.yaml
,复制并完善下列配置信息。当前只列举出较为基础的配置,更多 JuiceFS CSI 驱动的 Helm chart 支持的配置项可以参考 Values。
JuiceFS 社区版和云服务的配置项略有不同,下方示范面向社区版,但你可以在 Helm chart 中找到全面示范。
storageClasses:
- name: juicefs-sc
enabled: true
reclaimPolicy: Retain
# JuiceFS 文件系统认证信息
# 如果已经提前创建好文件系统,则只需填写 `name` 和 `metaurl` 这两项
backend:
name: "<name>" # JuiceFS 文件系统名
metaurl: "<meta-url>" # 元数据引擎的 URL
storage: "<storage-type>" # 对象存储类型 (例如 s3、gcs、oss、cos)
accessKey: "<access-key>" # 对象存储的 Access Key
secretKey: "<secret-key>" # 对象存储的 Secret Key
bucket: "<bucket>" # 存储数据的桶路径
# 设置 Mount Pod 时区,默认为 UTC。
# envs: "{TZ: Asia/Shanghai}"
mountPod:
resources: # Mount pod 的资源配置
requests:
cpu: "1"
memory: "1Gi"
limits:
cpu: "5"
memory: "5Gi"
如上方示范中 backend
字段所示,用 Helm 创建 StorageClass 时,文件系统认证信息也会一并创建,请在 Helm 里直接管理,无需再单独创建文件系统认证信息。
通过 kubectl 创建
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: juicefs-sc
provisioner: csi.juicefs.com
parameters:
csi.storage.k8s.io/provisioner-secret-name: juicefs-secret
csi.storage.k8s.io/provisioner-secret-namespace: default
csi.storage.k8s.io/node-publish-secret-name: juicefs-secret
csi.storage.k8s.io/node-publish-secret-namespace: default
动态配置
阅读「使用方式」以了解什么是「动态配置」。动态配置方式会自动为你创建 PV,而创建 PV 的基础配置参数在 StorageClass 中定义,因此你需要先行创建 StorageClass。
部署
创建 PersistentVolumeClaim(PVC)和示例 pod:
kubectl apply -f - <<EOF
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: juicefs-pvc
namespace: default
spec:
accessModes:
- ReadWriteMany
resources:
requests:
storage: 10Pi
storageClassName: juicefs-sc
---
apiVersion: v1
kind: Pod
metadata:
name: juicefs-app
namespace: default
spec:
containers:
- args:
- -c
- while true; do echo $(date -u) >> /data/out.txt; sleep 5; done
command:
- /bin/sh
image: centos
name: app
volumeMounts:
- mountPath: /data
name: juicefs-pv
volumes:
- name: juicefs-pv
persistentVolumeClaim:
claimName: juicefs-pvc
EOF
确认容器顺利创建运行后,可以钻进容器里确认数据正常写入 JuiceFS:
kubectl exec -ti juicefs-app -- tail -f /data/out.txt
使用通用临时卷
通用临时卷类似于 emptyDir
,为每个 Pod 单独提供临时数据存放目录。当应用容器需要大容量,并且是每个 Pod 单独的临时存储时,可以考虑这样使用 JuiceFS CSI 驱动。
JuiceFS CSI 驱动的通用临时卷用法与「动态配置」类似,因此也需要先行创建 StorageClass。不过与「动态配置」不同,临时卷使用 volumeClaimTemplate
,为每个 Pod 自动创建 PVC。
在 Pod 定义中声明使用通用临时卷:
apiVersion: v1
kind: Pod
metadata:
name: juicefs-app
namespace: default
spec:
containers:
- args:
- -c
- while true; do echo $(date -u) >> /data/out.txt; sleep 5; done
command:
- /bin/sh
image: centos
name: app
volumeMounts:
- mountPath: /data
name: juicefs-pv
volumes:
- name: juicefs-pv
ephemeral:
volumeClaimTemplate:
metadata:
labels:
type: juicefs-ephemeral-volume
spec:
accessModes: [ "ReadWriteMany" ]
storageClassName: "juicefs-sc"
resources:
requests:
storage: 1Gi
在回收策略方面,临时卷与动态配置一致,因此如果将默认 PV 回收策略设置为 Retain
,那么临时存储将不再是临时存储,PV 需要手动释放。
挂载参数
「挂载参数」,也就是 juicefs mount
命令所接受的参数,可以用于调整挂载配置。你需要通过 mountOptions
字段填写需要调整的挂载配置,在静态配置和动态配置下填写的位置不同,见下方示范。
修改了挂载参数后,还需要滚动升级或重启应用 Pod,CSI 驱动重新创建 Mount Pod,配置变更方能生效。
静态配置
apiVersion: v1
kind: PersistentVolume
metadata:
name: juicefs-pv
labels:
juicefs-name: ten-pb-fs
spec:
mountOptions:
- cache-size=204800
- subdir=/my/sub/dir
...
动态配置
在 StorageClass
定义中调整挂载参数。如果需要为不同应用使用不同挂载参数,则需要创建多个 StorageClass
,单独添加所需参数。
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: juicefs-sc
provisioner: csi.juicefs.com
mountOptions:
- cache-size=204800
- subdir=/my/sub/dir
parameters:
...
参数详解
JuiceFS 社区版与云服务的挂载参数有所区别,请参考文档:
如果要额外添加 FUSE 相关选项(也就是挂载命令的 -o
参数),请直接在 YAML 列表中追加,每行一个选项:
mountOptions:
- cache-size=204800
# 额外的 FUSE 相关选项
- writeback_cache
- debug
配置更加易读的 PV 目录名称
在「动态配置」方式下,CSI 驱动在 JuiceFS 创建的子目录名称形如 pvc-234bb954-dfa3-4251-9ebe-8727fb3ad6fd
,如果有众多应用同时使用 CSI 驱动,更会造成 JuiceFS 文件系统中创建大量此类 PV 目录,让人难以辨别:
$ ls /jfs
pvc-76d2afa7-d1c1-419a-b971-b99da0b2b89c pvc-a8c59d73-0c27-48ac-ba2c-53de34d31944 pvc-d88a5e2e-7597-467a-bf42-0ed6fa783a6b
...
在 JuiceFS CSI 驱动 0.13.3 及以上版本,支持通过 pathPattern
这个配置来定义其不同 PV 的子目录格式,让目录名称更容易阅读、查找:
$ ls /jfs
default-dummy-juicefs-pvc default-example-juicefs-pvc ...
如果你的场景需要在动态配置下,让多个应用使用同一个 JuiceFS 子目录,也可以合理配置 pathPattern
,让多个 PV 对应着 JuiceFS 文件系统中相同的子目录,实现多应用共享存储。顺带一提,「静态配置」是更为简单直接的实现多应用共享存储的方式(多个应用复用同一个 PVC 即可),如果条件允许,不妨优先采用静态配置方案。
此特性默认关闭,需要手动启用。启用的方式就是为 CSI Controller 增添 --provisioner=true
启动参数,并且删去原本的 sidecar 容器,相当于让 CSI Controller 主进程自行监听资源变更,并执行相应的初始化操作。请根据 CSI Controller 的安装方式,按照下方步骤启用。
Helm
在 values.yaml
中添加如下配置:
controller:
provisioner: true
再重新部署 JuiceFS CSI 驱动:
helm upgrade juicefs-csi-driver juicefs/juicefs-csi-driver -n kube-system -f ./values.yaml
kubectl
手动编辑 CSI Controller:
kubectl edit sts -n kube-system juicefs-csi-controller
需要修改的部分,已经在下方示范中进行高亮和注释,请参考:
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: juicefs-csi-controller
...
spec:
...
template:
...
spec:
containers:
- name: juicefs-plugin
image: juicedata/juicefs-csi-driver:v0.17.4
args:
- --endpoint=$(CSI_ENDPOINT)
- --logtostderr
- --nodeid=$(NODE_NAME)
- --v=5
+ # 令 juicefs-plugin 自行监听资源变动,执行初始化流程
+ - --provisioner=true
...
- # 删除默认的 csi-provisioner,不再通过该容器监听资源变动,执行初始化流程
- - name: csi-provisioner
- image: quay.io/k8scsi/csi-provisioner:v1.6.0
- args:
- - --csi-address=$(ADDRESS)
- - --timeout=60s
- - --v=5
- env:
- - name: ADDRESS
- value: /var/lib/csi/sockets/pluginproxy/csi.sock
- volumeMounts:
- - mountPath: /var/lib/csi/sockets/pluginproxy/
- name: socket-dir
- name: liveness-probe
image: quay.io/k8scsi/livenessprobe:v1.1.0
args:
- --csi-address=$(ADDRESS)
- --health-port=$(HEALTH_PORT)
env:
- name: ADDRESS
value: /csi/csi.sock
- name: HEALTH_PORT
value: "9909"
volumeMounts:
- mountPath: /csi
name: socket-dir
...
上述操作也可以用下方的一行命令达成,但请注意,该命令并非幂等,不能重复执行:
kubectl -n kube-system patch sts juicefs-csi-controller \
--type='json' \
-p='[{"op": "remove", "path": "/spec/template/spec/containers/1"}, {"op": "replace", "path": "/spec/template/spec/containers/0/args", "value": ["--endpoint=$(CSI_ENDPOINT)", "--logtostderr", "--nodeid=$(NODE_NAME)", "--v=5", "--provisioner=true"]}]'
使用方式
在 StorageClass
中这样使用 pathPattern
:
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: juicefs-sc
provisioner: csi.juicefs.com
parameters:
csi.storage.k8s.io/provisioner-secret-name: juicefs-secret
csi.storage.k8s.io/provisioner-secret-namespace: default
csi.storage.k8s.io/node-publish-secret-name: juicefs-secret
csi.storage.k8s.io/node-publish-secret-namespace: default
pathPattern: "${.PVC.namespace}-${.PVC.name}"
命名模板中可以引用任意 PVC 元数据,例如标签、注解、名称或命名空间,比如:
${.PVC.namespace}-${.PVC.name}
,则 PV 目录为<PVC 命名空间>-<PVC 名称>
。${.PVC.labels.foo}
,则 PV 目录为 PVC 中foo
标签的值。${.PVC.annotations.bar}
,则 PV 目录为 PVC 中bar
注解(annotation)的值。
常用 PV 设置
挂载点自动恢复
JuiceFS CSI 驱动自 v0.10.7 开始支持挂载点自动恢复:当 Mount Pod 遭遇故障,重启或重新创建 Mount Pod 以后,应用容器也能继续工作。
挂载点自动恢复后,已经打开的文件无法继续访问,请在应用程序中做好重试,重新打开文件,避免异常。
启用自动恢复,需要在应用 Pod 的 volumeMounts
中设置 mountPropagation
为 HostToContainer
或 Bidirectional
,从而将宿主机的挂载传播给 Pod。这样一来,Mount Pod 重启后,宿主机上的挂载点被重新挂载,然后 CSI 驱动将会在容器挂载路径上重新执行一次 mount bind。
apiVersion: apps/v1
kind: Deployment
metadata:
name: juicefs-app-static-deploy
spec:
...
template:
...
spec:
containers:
- name: app
# 如果设置为 Bidirectional,则需要启用 privileged
# securityContext:
# privileged: true
volumeMounts:
- mountPath: /data
name: data
mountPropagation: HostToContainer
...
volumes:
- name: data
persistentVolumeClaim:
claimName: juicefs-pvc-static
PV 容量分配
目前而言,JuiceFS CSI 驱动不支持设置存储容量。在 PersistentVolume 和 PersistentVolumeClaim 中指定的容量会被忽略,填写任意有效值即可,例如 100Gi
:
resources:
requests:
storage: 100Gi
访问模式
JuiceFS PV 支持 ReadWriteMany
和 ReadOnlyMany
两种访问方式。根据使用 CSI 驱动的方式不同,在上方 PV/PVC,(或 volumeClaimTemplate
)定义中,填写需要的 accessModes
即可。