因语雀与csdn markdown 格式有区别,请查看原文:
https://www.yuque.com/dycloud/pss8ys
一、JuiceFS 介绍
1.1 JuiceFS 是什么
JuiceFS 是一款面向云环境设计的高性能 POSIX 文件系统,核心能力是将对象存储转化为全功能文件系统。它采用独特的数据-元数据分离架构,解决了海量文件存储的扩展性难题,特别适合 AI 训练、大数据分析、容器存储等场景。
🔑 核心价值:让对象存储获得近似本地文件系统的性能与功能,同时保持云存储的无限扩展性和成本优势。
JuiceFS 采用 「数据」与「元数据」分离存储 的架构,从而实现文件系统的分布式设计。文件数据本身会被切分保存在对象存储(例如 Amazon S3),而元数据则可以保存在 Redis、MySQL、TiKV、SQLite 等多种数据库中,你可以根据场景与性能要求进行选择。
JuiceFS 提供了丰富的 API,适用于各种形式数据的管理、分析、归档、备份,可以在不修改代码的前提下无缝对接大数据、机器学习、人工智能等应用平台,为其提供海量、弹性、低价的高性能存储。运维人员不用再为可用性、灾难恢复、监控、扩容等工作烦恼,专注于业务开发,提升研发效率。同时运维细节的简化,对 DevOps 极其友好。
1.2 核心特性
- POSIX 兼容:像本地文件系统一样使用,无缝对接已有应用,无业务侵入性;
- HDFS 兼容:完整兼容 HDFS API,提供更强的元数据性能;
- S3 兼容:提供 S3 网关 实现 S3 协议兼容的访问接口;
- 云原生:通过 Kubernetes CSI 驱动 轻松地在 Kubernetes 中使用 JuiceFS;
- 分布式设计:同一文件系统可在上千台服务器同时挂载,高性能并发读写,共享数据;
- 强一致性:确认的文件修改会在所有服务器上立即可见,保证强一致性;
- 强悍性能:毫秒级延迟,近乎无限的吞吐量(取决于对象存储规模),查看性能测试结果;
- 数据安全:支持传输中加密(encryption in transit)和静态加密(encryption at rest),查看详情;
- 文件锁:支持 BSD 锁(flock)和 POSIX 锁(fcntl);
- 数据压缩:支持 LZ4 和 Zstandard 压缩算法,节省存储空间。
1.3 应用场景
JuiceFS 为海量数据存储设计,可以作为很多分布式文件系统和网络文件系统的替代,特别是以下场景:
- 大数据分析:HDFS 兼容;与主流计算引擎(Spark、Presto、Hive 等)无缝衔接;无限扩展的存储空间;运维成本几乎为 0;性能远好于直接对接对象存储。
- 机器学习:POSIX 兼容,可以支持所有机器学习、深度学习框架;方便的文件共享还能提升团队管理、使用数据效率。
- Kubernetes:JuiceFS 支持 Kubernetes CSI;为容器提供解耦的文件存储,令应用服务可以无状态化;方便地在容器间共享数据。
- 共享工作区:可以在任意主机挂载;没有客户端并发读写限制;POSIX 兼容已有的数据流和脚本操作。
- 数据备份:在无限平滑扩展的存储空间备份各种数据,结合共享挂载功能,可以将多主机数据汇总至一处,做统一备份。
1.4 架构设计
JuiceFS 整体上主要由三个部分组成。
- ** 客户端(Client)**:所有文件读写,乃至于碎片合并、回收站文件过期删除等后台任务,均在客户端中发生。所以客户端需要同时与对象存储和元数据引擎打交道。客户端支持众多接入方式:
- 通过 FUSE,JuiceFS 文件系统能够以 POSIX 兼容的方式挂载到服务器,将海量云端存储直接当做本地存储来使用。
- 通过 Hadoop Java SDK,JuiceFS 文件系统能够直接替代 HDFS,为 Hadoop 提供低成本的海量存储。
- 通过 Kubernetes CSI 驱动,JuiceFS 文件系统能够直接为 Kubernetes 提供海量存储。
- 通过 S3 网关,使用 S3 作为存储层的应用可直接接入,同时可使用 AWS CLI、s3cmd、MinIO client 等工具访问 JuiceFS 文件系统。
- 通过 WebDAV 服务,以 HTTP 协议,以类似 RESTful API 的方式接入 JuiceFS 并直接操作其中的文件。
- 数据存储(Data Storage):文件将会切分上传保存在对象存储服务,既可以使用公有云的对象存储,也可以接入私有部署的自建对象存储。JuiceFS 支持几乎所有的公有云对象存储,同时也支持 OpenStack Swift、Ceph、MinIO 等私有化的对象存储。
- 元数据引擎(Metadata Engine):用于存储文件元数据(metadata),包含以下内容:
- 常规文件系统的元数据:文件名、文件大小、权限信息、创建修改时间、目录结构、文件属性、符号链接、文件锁等。
- JuiceFS 独有的元数据:文件的 chunk 及 slice 映射关系、客户端 session 等。
JuiceFS 采用多引擎设计,目前已支持 Redis、TiKV、MySQL/MariaDB、PostgreSQL、SQLite 等作为元数据服务引擎,也将陆续实现更多元数据存储引擎。
1.5 读写流程
1.5.1 写流程
与传统文件系统只能使用本地磁盘存储数据和对应的元数据的模式不同,JuiceFS 会将数据格式化以后存储在对象存储,同时会将文件的元数据存储在专门的元数据服务中,这样的架构让 JuiceFS 成为一个强一致性的高性能分布式文件系统。
任何存入 JuiceFS 的文件都会被拆分成一个或多个 「Chunk
」(最大 64 MiB)。而每个 Chunk 又由一个或多个 「Slice
」 组成。Chunk 的存在是为了对文件做切分,优化大文件性能,而 Slice 则是为了进一步优化各类文件写操作,二者同为文件系统内部的逻辑概念。Slice 的长度不固定,取决于文件写入的方式。每个 Slice 又会被进一步拆分成 「Block」(默认大小上限为 4 MiB),成为最终上传至对象存储的最小存储单元。
所以我们在对象存储平台的文件浏览器中找不到存入 JuiceFS 的源文件,存储桶中只有一个 chunks 目录和一堆数字编号的目录和文件,这正是经过 JuiceFS 拆分存储的数据块。与此同时,文件与 Chunks、Slices、Blocks 的对应关系等元数据信息存储在元数据引擎中。正是这样的分离设计,让 JuiceFS 文件系统得以高性能运作。
JuiceFS 的存储设计,还有着以下技术特点:
- 对于任意大小的文件,JuiceFS 都不进行合并存储,这也是为了性能考虑,避免读放大。
- 提供强一致性保证,但也可以根据场景需要与缓存功能一起调优,比如通过设置出更激进的元数据缓存,牺牲一部分一致性,换取更好的性能。。
- 支持并默认开启「回收站」功能,删除文件后保留一段时间才彻底清理,最大程度避免误删文件导致事故。
1.5.2 读流程
应用程序 调用 JuiceFS 文件系统接口发起读请求
- 1. 应用请求发起
应用程序 调用 JuiceFS 文件系统接口发起读请求:
read(file, offset, len)
表示要从文件的某个位置(offset)读取一定长度(len)的数据。
- 2. JuiceFS Client 查询元数据
JuiceFS Client 收到读请求,先向元数据服务查询这个文件内容的分块(chunk)分布位置。
比如:查 inode=123 的分块位置
- 3. 元数据服务返回块列表
元数据服务根据 inode,把块(chunk)的位置和对应对象存储的对象名返回,比如
[chunk1@obj1, chunk2@obj2]
意思是:这次读请求命中了 obj1、obj2 两个对象中的数据块。
- 4. 检查本地缓存
JuiceFS Client 根据块信息,先向本地缓存查询所需 chunk 是否存在:
如果命中缓存:直接从本地读取该 chunk 的数据
如果未命中缓存:则需要访问底层对象存储去拉取数据
- 5. 命中缓存的处理流程
本地缓存命中
- <font style="color:rgb(51, 54, 57);">本地缓存系统直接返回所需数据块</font>
- <font style="color:rgb(51, 54, 57);">JuiceFS Client 将数据返回给应用程序</font>
- <font style="color:rgb(51, 54, 57);">整个流程结束,效率很高</font>
- 6. 未命中缓存的处理流程
本地缓存未命中
1. <font style="color:rgb(51, 54, 57);">本地缓存返回未命中标记,JuiceFS Client 转而向</font>**<font style="color:rgb(51, 54, 57);">对象存储</font>**<font style="color:rgb(51, 54, 57);">请求 chunk1</font>
2. <font style="color:rgb(51, 54, 57);">对象存储把 chunk1 数据返回给 JuiceFS Client</font>
3. <font style="color:rgb(51, 54, 57);">JuiceFS Client 读取数据后,</font>**<font style="color:rgb(51, 54, 57);">将数据块缓存到本地(写到本地缓存)</font>**<font style="color:rgb(51, 54, 57);">,以备下次快速访问</font>
4. <font style="color:rgb(51, 54, 57);">JuiceFS Client 再把数据返回给应用程序</font>
总结:
- 应用发起读请求到 JuiceFS Client
- Client 查元数据服务,获得数据块与对象存储位置的对应关系
- Client 先查本地缓存,若缓存有直接取出
- 若本地未命中,则去对象存储拉取
- 拉取到的数据写入本地缓存
- 最终数据返回给应用程序
二、JuiceFS 安装配置
2.1 安装
JuiceFS 是采用 Go 语言开发的,所以具有良好的跨平台能力,支持在几乎所有主流架构的各类操作系统上运行,包括且不限于 Linux、macOS、Windows 等。
JuiceFS 客户端只有一个二进制文件,可以下载预编译的版本直接解压使用,也可以用源代码手动编译,也可以直接使用一键安装脚本 <font style="color:#DF2A3F;">curl -sSL https://d.juicefs.com/install | sh -</font>
自动下载安装最新版 JuiceFS 客户端。
如果在 Mac 下面使用,需要先安装 FUSE for macOS,这是因为 macOS 默认不支持 FUSE 接口。
[root@k8s-master01 ~]# juicefs version
juicefs version 1.3.0+2025-07-03.30190ca
2.2 单机模式
JuiceFS 文件系统由「对象存储」和「数据库」共同驱动,除了对象存储,还支持使用本地磁盘、WebDAV 和 HDFS 等作为底层存储。这里我们首先使用本地磁盘和 SQLite 数据库快速创建一个单机文件系统用以了解和体验 JuiceFS。
当然首先需要安装 JuiceFS 的客户端,然后接下来我们就可以使用 juicefs format
命令来创建一个 JuiceFS 文件系统了,该命令的格式为:
juicefs format [command options] META-URL NAME
从命令可以看出格式化文件系统需要提供 3 种信息:
<font style="color:#DF2A3F;">[command options]</font>
:设定文件系统的存储介质,留空则默认使用本地磁盘作为存储介质,路径为$HOME/.juicefs/local
、/var/jfs
或C:/jfs/local
<font style="color:#DF2A3F;">META-URL</font>
:用来设置元数据存储,即数据库相关的信息,通常是数据库的 URL 或文件路径<font style="color:#DF2A3F;">NAME</font>
:是文件系统的名称
比如我们这里创建一个名为 dujiefs
的文件系统,则可以使用如下所示的命令:
[root@k8s-master01 ~]# juicefs format sqlite3://dujiefs.db dujiefs
2025/07/16 21:13:56.388967 juicefs[84626] <INFO>: Meta address: sqlite3://dujiefs.db [NewClient@interface.go:578]
2025/07/16 21:13:56.394557 juicefs[84626] <INFO>: Data use file:///var/jfs/dujiefs/ [format@format.go:527]
2025/07/16 21:13:56.405053 juicefs[84626] <INFO>: Volume is formatted as {"Name": "dujiefs","UUID": "c4e99180-6ccc-4353-ba4e-230adc805992","Storage": "file","Bucket": "/var/jfs/","BlockSize": 4096,"Compression": "none","EncryptAlgo": "aes256gcm-rsa","TrashDays": 1,"MetaVersion": 1,"MinClientVersion": "1.1.0-A","DirStats": true,"EnableACL": false
} [format@format.go:564]
从返回的信息中可以看到,该文件系统使用 SQLite 作为元数据存储引擎,数据库文件位于当前目录,文件名为 dujiefs.db
,保存了 dujiefs 文件系统的所有信息,它构建了完善的表结构,将用作所有数据的元信息的存储。
由于没有指定任何存储相关的选项,客户端默认使用本地磁盘作为存储介质,根据返回的信息, dujiefs 的存储路径为 file:///var/jfs/dujiefs/
。
[root@k8s-master01 ~]# ll /var/jfs/dujiefs/juicefs_uuid
-rw-r--r-- 1 root root 36 7月 16 21:13 /var/jfs/dujiefs/juicefs_uuid
这样我们就成功创建了一个文件系统了,接下来我们就可以使用 juicefs mount
命令来挂载文件系统了,该命令的一般格式为:
juicefs mount [command options] META-URL MOUNTPOINT
与创建文件系统的命令类似,挂载文件系统需要提供以下信息:
[command options]
:用来指定文件系统相关的选项,例如:-d
可以实现后台挂载;META-URL
:用来设置元数据存储,即数据库相关的信息,通常是数据库的 URL 或文件路径;MOUNTPOINT
:指定文件系统的挂载点。
由于 SQLite 是单文件数据库,挂载时要注意数据库文件的的路径,JuiceFS 同时支持相对路径和绝对路径。比如我们这里可以使用以下命令将 dujiefs 文件系统挂载到 ./jfs
文件夹:
[root@k8s-master01 ~]# juicefs mount sqlite3://dujiefs.db ./jfs
2025/07/16 21:16:36.011783 juicefs[86277] <INFO>: Meta address: sqlite3://dujiefs.db [NewClient@interface.go:578]
2025/07/16 21:16:36.019412 juicefs[86277] <INFO>: Data use file:///var/jfs/dujiefs/ [mount@mount.go:588]
2025/07/16 21:16:36.113630 juicefs[86286] <INFO>: Meta address: sqlite3://dujiefs.db [NewClient@interface.go:578]
2025/07/16 21:16:36.118450 juicefs[86286] <INFO>: Data use file:///var/jfs/dujiefs/ [mount@mount.go:588]
2025/07/16 21:16:36.118570 juicefs[86286] <INFO>: JuiceFS version 1.3.0+2025-07-03.30190ca [mount@mount.go:631]
2025/07/16 21:16:36.119972 juicefs[86286] <INFO>: Disk cache (/var/jfsCache/c4e99180-6ccc-4353-ba4e-230adc805992/): used ratio - [space 44.3%, inode 1.2%] [newCacheStore@disk_cache.go:147]
2025/07/16 21:16:36.120107 juicefs[86286] <INFO>: Adjusted cache capacity based on freeratio: from 107374182400 to 67612702976 bytes [setlimitByFreeRatio@disk_cache.go:171]
2025/07/16 21:16:36.120226 juicefs[86286] <INFO>: Adjusted max items based on freeratio: from 0 to 33030143 items [setlimitByFreeRatio@disk_cache.go:176]
2025/07/16 21:16:36.126068 juicefs[86286] <INFO>: Create session 1 OK with version: 1.3.0+2025-07-03.30190ca [NewSession@base.go:535]
2025/07/16 21:16:36.127250 juicefs[86286] <INFO>: Prometheus metrics listening on 127.0.0.1:9567 [exposeMetrics@mount.go:134]
2025/07/16 21:16:36.129981 juicefs[86286] <INFO>: Add fuse.juicefs into PRUNEFS of /etc/updatedb.conf [disableUpdatedb@mount_unix.go:448]
2025/07/16 21:16:36.130117 juicefs[86286] <INFO>: Mounting volume dujiefs at ./jfs ... [mountMain@mount_unix.go:1027]
2025/07/16 21:16:36.523383 juicefs[86277] <INFO>: OK, dujiefs is ready at /root/jfs [checkMountpoint@mount_unix.go:235]
2025-07-16 21:16:41.128019 I | Unimplemented opcode POLL
2025/07/16 21:16:41.129289 juicefs[86277] <INFO>: watching /root/jfs, pid 86286 [watchdog@mount_unix.go:162]
默认情况下,客户端会在前台挂载文件系统,程序会一直运行在当前终端进程中,使用 Ctrl + C 组合键或关闭终端窗口,文件系统会被卸载。
为了让文件系统可以在后台保持挂载,可以在挂载时指定 -d
或 --background
选项,即让客户端在守护进程中挂载文件系统:
[root@k8s-master01 ~]# juicefs mount -d sqlite3://dujiefs.db ./jfs
2025/07/16 21:17:10.783120 juicefs[86631] <INFO>: Meta address: sqlite3://dujiefs.db [NewClient@interface.go:578]
2025/07/16 21:17:10.789139 juicefs[86631] <INFO>: Data use file:///var/jfs/dujiefs/ [mount@mount.go:588]
2025/07/16 21:17:11.296754 juicefs[86631] <INFO>: OK, dujiefs is ready at /root/jfs [checkMountpoint@mount_unix.go:235]
接下来,任何存入挂载点 ~/jfs
的文件,都会按照 JuiceFS 的文件存储格式被拆分成特定的「数据块」并存入 file:///var/jfs/dujiefs/
目录中,相对应的「元数据」会全部存储在 ydzsfs.db
数据库中。
最后执行以下命令可以将挂载点 ~/jfs
卸载:
[root@k8s-master01 ~]# juicefs umount ~/jfs
2.3 使用对象存储
几乎所有主流的云计算平台都有提供对象存储服务,如亚马逊 S3、阿里云 OSS 等,JuiceFS 支持几乎所有的对象存储服务。一般来说,创建对象存储通常只需要 2 个环节:
- 创建 Bucket 存储桶,拿到 Endpoint 地址;
- 创建 Access Key ID 和 Access Key Secret,即对象存储 API 的访问密钥。
以阿里云 oss 为例,创建好的资源大概像下面这样:
**Bucket Endpoint:**k8s-test-files.oss-cn-beijing.aliyuncs.com
AccessKeyID:xxxxx
AccessKey Secret:xxxxxx
我们这里以阿里云 OSS 服务为例来进行演示,首先创建一个 Bucket 存储桶,命名为 k8s-test-files
,然后创建 获取账号的密钥对
[root@k8s-master01 ~]# juicefs format --storage oss \
> --bucket https://k8s-test-files.oss-cn-beijing.aliyuncs.com \
> --access-key xxxxxx \
> --secret-key xxxxxx \
> sqlite3://k8s-test-files.db k8s-test-files2025/07/16 21:26:25.458490 juicefs[92527] <INFO>: Meta address: sqlite3://k8s-test-files.db [NewClient@interface.go:578]
2025/07/16 21:26:25.465257 juicefs[92527] <WARNING>: The latency to database is too high: 6.505436ms [newSQLMeta@sql.go:506]
2025/07/16 21:26:25.468105 juicefs[92527] <INFO>: Data use oss://k8s-test-files/k8s-test-files/ [format@format.go:527]
2025/07/16 21:26:25.778414 juicefs[92527] <INFO>: Volume is formatted as {"Name": "k8s-test-files","UUID": "a4531ea8-31c9-42a5-8953-bdb20af94bf3","Storage": "oss","Bucket": "https://k8s-test-files.oss-cn-beijing.aliyuncs.com","AccessKey": "xxxxxxxx","SecretKey": "removed","BlockSize": 4096,"Compression": "none","EncryptAlgo": "aes256gcm-rsa","KeyEncrypted": true,"TrashDays": 1,"MetaVersion": 1,"MinClientVersion": "1.1.0-A","DirStats": true,"EnableACL": false
} [format@format.go:564]
在上述命令中,我们指定了对象存储的相关配置信息:
<font style="color:#DF2A3F;">--storage</font>
:设置存储类型,比如 cos、oss、s3 等;<font style="color:#DF2A3F;">--bucket</font>
:设置对象存储的 Endpoint 地址;<font style="color:#DF2A3F;">--access-key</font>
:设置对象存储 API 访问密钥 Access Key ID;<font style="color:#DF2A3F;">--secret-key</font>
:设置对象存储 API 访问密钥 Access Key Secret。
创建完成即可进行挂载:
[root@k8s-master01 ~]# juicefs mount sqlite3://k8s-test-files.db ~/jfs -d
2025/07/16 21:29:09.579626 juicefs[94136] <INFO>: Meta address: sqlite3://k8s-test-files.db [NewClient@interface.go:578]
2025/07/16 21:29:09.585531 juicefs[94136] <INFO>: Data use oss://k8s-test-files/k8s-test-files/ [mount@mount.go:588]
2025/07/16 21:29:10.091791 juicefs[94136] <INFO>: OK, k8s-test-files is ready at /root/jfs [checkMountpoint@mount_unix.go:235]
挂载命令与使用本地存储时完全一样,这是因为创建文件系统时,对象存储相关的信息已经写入了 myjfs.db
数据库,因此客户端不需要额外提供对象存储认证信息,也没有本地配置文件。
相比使用本地磁盘,SQLite 和对象存储的组合实用价值更高。从应用的角度看,这种形式等同于将容量几乎无限的对象存储接入到了本地计算机,让你可以像使用本地磁盘那样使用云存储。
进一步的,该文件系统的所有数据都存储在云端的对象存储,因此可以把 k8s-test-files.db
数据库复制到其他安装了 JuiceFS 客户端的计算机上进行挂载和读写。也就是说,任何一台计算机只要能够读取到存储了元数据的数据库,那么它就能够挂载读写该文件系统。
比如现在我们在 ~/jfs
目录下面任意创建一些文件:
[root@k8s-master01 ~]# echo testsss > ~/jfs/dujie.txt
[root@k8s-master01 ~]#
[root@k8s-master01 ~]# cat ~/jfs/dujie.txt
testsss
正常创建完成后该文件会按照 JuiceFS 的文件存储格式被拆分成特定的「数据块」并上传到对象存储中去,相对应的「元数据」会全部存储在 k8s-test-files.db
数据库中。
很显然,SQLite 这种单文件数据库很难实现被多台计算机同时访问。如果把 SQLite 改为 Redis、PostgreSQL、MySQL 等能够通过网络被多台计算机同时读写访问的数据库,那么就可以实现 JuiceFS 文件系统的分布式挂载读写。
2.4 分布式模式
前面通过采用「对象存储」和「SQLite」数据库的组合,实现了一个可以在任意主机上挂载的文件系统。得益于对象存储可以被网络上任何有权限的计算机访问的特点,我们只需要把 SQLite 数据库文件复制到任何想要访问该存储的计算机,就可以实现在不同计算机上访问同一个 JuiceFS 文件系统。
很显然,想要依靠在计算机之间复制 SQLite 数据库的方式进行文件系统共享,虽然可行,但文件的实时性是得不到保证的。受限于 SQLite 这种单文件数据库无法被多个计算机同时读写访问的情况,为了能够让一个文件系统可以在分布式环境中被多个计算机同时挂载读写,我们需要采用支持通过网络访问的数据库,比如 Redis、PostgreSQL、MySQL 等。
接下来我们将 SQLite 数据库替换成基于网络的数据库,从而实现 JuiceFS 文件系统的分布式挂载读写。JuiceFS 目前支持的基于网络的数据库有:
- 键值数据库:Redis、TiKV
- 关系型数据库:PostgreSQL、MySQL、MariaDB
不同的数据库性能和稳定性表现也各不相同,比如 Redis 是内存型键值数据库,性能极为出色,但可靠性相对较弱。PostgreSQL 是关系型数据库,相比之下性能没有内存型强悍,但它的可靠性要更强。我们这里以 Redis 为例来演示分布式模式的使用,我们就直接在 K8s 集群中部署一个简单的 Redis 服务来进行说明:
apiVersion: apps/v1
kind: Deployment
metadata:name: redis
spec:selector:matchLabels:app: redistemplate:metadata:labels:app: redisspec:containers:image: redis/redis-stack-server:6.2.6-v6imagePullPolicy: IfNotPresentname: redisports:- containerPort: 6379protocol: TCP
---
apiVersion: v1
kind: Service
metadata:name: redis
spec:ports:- name: redis-portport: 6379targetPort: 6379selector:app: redistype: NodePort
[root@k8s-master01 ~]# kubectl get pods,svc
NAME READY STATUS RESTARTS AGE
pod/redis-6ddf6cf85d-jxpd7 1/1 Running 0 60sNAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/redis NodePort 10.96.171.175 <none> 6379:32470/TCP 109s
然后接下来我们就可以利用前面的对象存储和这里的 Redis 来创建一个分布式的 JuiceFS 文件系统了,使用如下所示命令:
[root@k8s-master01 ~]# juicefs format --storage oss \
> --bucket https://k8s-test-files.oss-cn-beijing.aliyuncs.com \
> --access-key xxxxx \
> --secret-key xxxxxx \
> redis://192.168.1.20:32470/1 dujiefs2025/07/16 21:41:41.756585 juicefs[102250] <INFO>: Meta address: redis://192.168.1.20:32470/1 [NewClient@interface.go:578]
2025/07/16 21:41:41.763414 juicefs[102250] <WARNING>: AOF is not enabled, you may lose data if Redis is not shutdown properly. [checkRedisInfo@info.go:84]
2025/07/16 21:41:41.764574 juicefs[102250] <INFO>: Ping redis latency: 1.056191ms [checkServerConfig@redis.go:3692]
2025/07/16 21:41:41.766299 juicefs[102250] <INFO>: Data use oss://k8s-test-files/dujiefs/ [format@format.go:527]
2025/07/16 21:41:42.047836 juicefs[102250] <INFO>: Volume is formatted as {"Name": "dujiefs","UUID": "c334b68c-b303-4fdd-9478-4ed101e51d5f","Storage": "oss","Bucket": "https://k8s-test-files.oss-cn-beijing.aliyuncs.com","AccessKey": "xxxxxx","SecretKey": "removed","BlockSize": 4096,"Compression": "none","EncryptAlgo": "aes256gcm-rsa","KeyEncrypted": true,"TrashDays": 1,"MetaVersion": 1,"MinClientVersion": "1.1.0-A","DirStats": true,"EnableACL": false
} [format@format.go:564]
文件系统创建完毕以后,包含对象存储密钥等信息会完整的记录到数据库中,JuiceFS 客户端只要拥有数据库地址、用户名和密码信息,就可以挂载读写该文件系统,所以 JuiceFS 客户端不需要本地配置文件。
由于这个文件系统的「数据」和「元数据」都存储在基于网络的服务中,因此在任何安装了 JuiceFS 客户端的计算机上都可以同时挂载该文件系统进行共享读写,例如:
[root@k8s-master01 ~]# juicefs mount redis://192.168.1.20:32470/1 ~/test -d
2025/07/16 21:42:26.584250 juicefs[102790] <INFO>: Meta address: redis://192.168.1.20:32470/1 [NewClient@interface.go:578]
2025/07/16 21:42:26.589964 juicefs[102790] <WARNING>: AOF is not enabled, you may lose data if Redis is not shutdown properly. [checkRedisInfo@info.go:84]
2025/07/16 21:42:26.590998 juicefs[102790] <INFO>: Ping redis latency: 883.641µs [checkServerConfig@redis.go:3692]
2025/07/16 21:42:26.595887 juicefs[102790] <INFO>: Data use oss://k8s-test-files/dujiefs/ [mount@mount.go:588]
2025/07/16 21:42:27.101479 juicefs[102790] <INFO>: OK, dujiefs is ready at /root/test [checkMountpoint@mount_unix.go:235]
2.5 调大缓存提升性能
由于「对象存储」是基于网络的存储服务,不可避免会产生访问延时。为了解决这个问题,JuiceFS 提供并默认启用了缓存机制,即划拨一部分本地存储作为数据与对象存储之间的一个缓冲层,读取文件时会异步地将数据缓存到本地存储。
缓存机制让 JuiceFS 可以高效处理海量数据的读写任务,默认情况下,JuiceFS 会在 $HOME/.juicefs/cache 或 /var/jfsCache 目录设置 100GiB 的缓存。在速度更快的 SSD 上设置更大的缓存空间可以有效提升 JuiceFS 的读写性能。你可以使用 –cache-dir 调整缓存目录的位置,使用 –cache-size 调整缓存空间的大小,例如:
[root@k8s-master01 ~]# juicefs mount --background \
> --cache-dir /mycache \
> --cache-size 512000 \
> redis://192.168.1.20:32470/1 \
> ~/jfs2025/07/16 21:50:15.839157 juicefs[107654] <INFO>: Meta address: redis://192.168.1.20:32470/1 [NewClient@interface.go:578]
2025/07/16 21:50:15.847879 juicefs[107654] <WARNING>: AOF is not enabled, you may lose data if Redis is not shutdown properly. [checkRedisInfo@info.go:84]
2025/07/16 21:50:15.848719 juicefs[107654] <INFO>: Ping redis latency: 692.301µs [checkServerConfig@redis.go:3692]
2025/07/16 21:50:15.851939 juicefs[107654] <INFO>: Data use oss://k8s-test-files/dujiefs/ [mount@mount.go:588]
2025/07/16 21:50:16.361984 juicefs[107654] <INFO>: OK, dujiefs is ready at /root/jfs [checkMountpoint@mount_unix.go:235]
注意:JuiceFS 进程需要具有读写
<font style="color:rgb(38, 38, 38);">--cache-dir</font>
目录的权限。
上述命令将缓存目录设置在了 <font style="color:rgb(38, 38, 38);">/mycache</font>
目录,并指定缓存空间为 <font style="color:rgb(38, 38, 38);">500GiB</font>
。
当挂载好文件系统以后可以通过 <font style="color:#DF2A3F;">juicefs bench</font>
命令对文件系统进行基础的性能测试和功能验证,确保 JuiceFS 文件系统能够正常访问且性能符合预期。
运行 juicefs bench
命令以后会根据指定的并发度(默认为 1)往 JuiceFS 文件系统中写入及读取 N 个大文件(默认为 1)及 N 个小文件(默认为 100),并统计读写的吞吐和单次操作的延迟,以及访问元数据引擎的延迟。测试后可以去对象存储中查看多了很多数据了。
2.6 生产环境部署
为了保证 JuiceFS 文件系统能符合生产环境的要求,这里给出了如下一些生产环境部署的建议。
2.6.1 监控指标收集与可视化
务必收集 JuiceFS 客户端的监控指标并通过 Grafana 可视化。
2.6.2 元数据自动备份
元数据自动备份是自 JuiceFS v1.0.0 版本开始加入的特性
元数据对 JuiceFS 文件系统非常关键,一旦丢失或损坏将可能影响大批文件甚至整个文件系统。因此必须对元数据进行定期备份。
元数据自动备份特性默认开启,备份间隔为 1 小时,备份的元数据会经过压缩后存储至对应的对象存储中(与文件系统的数据隔离)。备份由 JuiceFS 客户端执行,备份期间会导致其 CPU 和内存使用量上升,默认情况下可认为会在所有客户端中随机选择一个执行备份操作。
特别注意默认情况下当文件系统的文件数达到一百万时,元数据自动备份功能将会关闭,需要配置一个更大的备份间隔(--backup-meta
选项)才会再次开启。备份间隔每个客户端独立配置,设置 --backup-meta 0
则表示关闭元数据自动备份特性。
注意:备份元数据所需的时间取决于具体的元数据引擎,不同元数据引擎会有不同的性能表现。
2.6.3 回收站
回收站是自 JuiceFS v1.0.0 版本开始加入的特性
回收站默认开启,文件被删除后的保留时间默认配置为 1 天,可以有效防止数据被误删除时造成的数据丢失风险。
不过回收站开启以后也可能带来一些副作用,如果应用需要经常删除文件或者频繁覆盖写文件,会导致对象存储使用量远大于文件系统用量。这本质上是因为 JuiceFS 客户端会将对象存储上被删除的文件或者覆盖写时产生的需要垃圾回收的数据块持续保留一段时间。因此,在部署 JuiceFS 至生产环境时就应该考虑好合适的回收站配置,回收站保留时间可以通过以下方式配置(如果将 --trash-days
设置为 0 则表示关闭回收站特性):
- 新建文件系统:通过
juicefs format
的--trash-days <value>
选项设置 - 已有文件系统:通过
juicefs config
的--trash-days <value>
选项修改
2.6.4 客户端后台任务
同一个 JuiceFS 文件系统的所有客户端在运行过程中共享一个后台任务集,每个任务定时执行,且具体执行的客户端随机选择。具体的后台任务包括:
- 清理待删除的文件和对象
- 清理回收站中的过期文件和碎片
- 清理长时间未响应的客户端会话
- 自动备份元数据
由于这些任务执行时会占用一定资源,因此可以为业务较繁重的客户端配置 --no-bgjob
选项来禁止其参与后台任务。
注意:请保证至少有一个 JuiceFS 客户端可以执行后台任务
2.6.5 客户端日志滚动
当后台运行 JuiceFS 挂载点时,客户端默认会将日志输出到本地文件中。取决于挂载文件系统时的运行用户,本地日志文件的路径稍有区别。root 用户对应的日志文件路径是 /var/log/juicefs.log
,非 root 用户的日志文件路径是 $HOME/.juicefs/juicefs.log
。
本地日志文件默认不会滚动,生产环境中为了确保日志文件不占用过多磁盘空间需要手动配置。以下是一个日志滚动的示例配置:
# /etc/logrotate.d/juicefs
/var/log/juicefs.log {dailyrotate 7compressdelaycompressmissingoknotifemptycopytruncate
}
通过 logrotate -d /etc/logrotate.d/juicefs
命令可以验证配置文件的正确性。
三、K8S 中部署
3.1 以 hostPath 方式挂载 JuiceFS
如果你仅仅需要在 Kubernetes 容器中简单使用 JuiceFS,没有其他任何复杂要求(比如隔离性、权限控制),那么完全可以以 hostPath 卷的方式使用 JuiceFS,搭建起来也十分简单。
首先安装前文的方式在 Kubernetes 节点上统一安装、挂载 JuiceFS。
然后在 Pod 的资源清单文件定义中使用 hostPath 卷,直接将宿主机上的 JuiceFS 子目录挂载到容器中即可:
apiVersion: v1
kind: Pod
metadata:name: juicefs-app
spec:containers:- ...volumeMounts:- name: jfs-datamountPath: /opt/app-datavolumes:- name: jfs-datahostPath:path: /jfs/myapp/ # 假设挂载点为 /jfstype: Directory
相比以 CSI 驱动的方式来使用 JuiceFS,hostPath 更为简单直接,出问题也更易排查,但也要注意:
- 为管理方便,一般所有容器都在使用同一个宿主机挂载点,缺乏隔离可能导致数据安全问题,未来也无法在不同应用中单独调整 JuiceFS 挂载参数。请谨慎评估。
- 所有节点都需要提前挂载 JuiceFS,因此集群加入新节点,需要在初始化流程里进行安装和挂载,否则新节点没有 JuiceFS 挂载点,容器将无法创建。
- 宿主机上的 JuiceFS 挂载进程所占用的系统资源(如 CPU、内存等)不受 Kubernetes 控制,有可能占用较多宿主机资源。可以考虑用
system-reserved
来适当调整 Kubernetes 的系统资源预留值,为 JuiceFS 挂载进程预留更多资源。 - 如果宿主机上的 JuiceFS 挂载进程意外退出,将会导致应用 Pod 无法正常访问挂载点,此时需要重新挂载 JuiceFS 文件系统并重建应用 Pod。作为对比,JuiceFS CSI 驱动提供 **「挂载点自动恢复」**功能来解决这个问题。
如果你使用 Docker 作为 Kubernetes 容器运行环境,最好令 JuiceFS 先于 Docker 启动,否则在节点重启的时候,偶尔可能出现容器启动时,JuiceFS 尚未挂载好的情况,此时便会因该依赖问题启动失败。以 systemd 为例,可以用下方 unit file 来配置启动顺序:
# /etc/systemd/system/docker.service.d/override.conf
[Unit]
# 请使用下方命令确定 JuiceFS 挂载服务的名称(例如 jfs.mount):
# systemctl list-units | grep "\.mount"
After=network-online.target firewalld.service containerd.service jfs.mount
3.2 以 CSI 驱动方式挂载 JuiceFS
JuiceFS CSI 驱动遵循 CSI 规范,实现了容器编排系统与 JuiceFS 文件系统之间的接口。在 Kubernetes 下,JuiceFS 可以用 PersistentVolume 的形式提供给 Pod 使用。
3.2.1 CSI 驱动运行模式
整体上 JuiceFS CSI 驱动包含以下组件:<font style="color:#DF2A3F;">JuiceFS CSI Controller(StatefulSet)</font>
以及 <font style="color:#DF2A3F;">JuiceFS CSI Node Service(DaemonSet)</font>
。
3.2.2 容器挂载模式
CSI 默认采用容器挂载(Mount Pod)模式,也就是让 JuiceFS 客户端运行在独立的 Pod 中,其架构如下:
采用独立 Mount Pod 来运行 JuiceFS 客户端,并由 CSI Node Service 来管理 Mount Pod 的生命周期。这样的架构提供如下好处:
- 多个 Pod 共用 PV 时,不会新建 Mount Pod,而是对已有的 Mount Pod 做引用计数,计数归零时删除 Mount Pod。
- CSI 驱动组件与客户端解耦,方便 CSI 驱动自身的升级。
在同一个节点上,一个 PVC 会对应一个 Mount Pod,而使用了相同 PV 的容器,则可以共享一个 Mount Pod。PVC、PV、Mount Pod 之间的关系如下图所示:
CSI 驱动默认以容器挂载模式运行,但特定场景下该模式不一定适用,因此 CSI 驱动还提供 Sidecar 模式以及进程挂载模式。
3.2.3 Sidecar 模式
Mount Pod 需要由 CSI Node 创建,考虑到 CSI Node 是一个 DaemonSet 组件,如果你的 Kubernetes 集群不支持部署 DaemonSet(比如一些云服务商提供的 Serverless Kubernetes 服务),那么 CSI Node 将无法部署,也就无法正常使用 CSI 驱动。对于这种情况,可以选择使用 CSI 驱动的 Sidecar 模式,让 JuiceFS 客户端运行在 Sidecar 容器中。
以 Sidecar 模式安装 CSI 驱动,所部署的组件只有 CSI Controller,不再需要 CSI Node。对于需要使用 CSI 驱动的 Kubernetes 命名空间,CSI Controller 会监听容器变动,检查是否使用了 JuiceFS PVC,并根据情况为其注入 Sidecar 容器。
创建和使用的流程大致如下:
- CSI Controller 启动时,向 API Server 注册 Webhook;
- 应用 Pod 指定使用 JuiceFS PVC;
- API Server 在创建应用 Pod 前调用 CSI Controller 的 Webhook 接口;
- CSI Controller 向应用 Pod 中注入 Sidecar 容器,容器中运行着 JuiceFS 客户端;
- API Server 创建应用 Pod,Sidecar 容器启动后运行 JuiceFS 客户端执行挂载,应用容器启动后可直接访问文件系统。
使用 Sidecar 模式需要注意:
- 运行环境需要支持
FUSE
,也就是支持以特权容器(Privileged)运行; - 不同于 Mount Pod 的容器挂载方式,Sidecar 容器注入进了应用 Pod,因此将无法进行任何复用,大规模场景下,请尤其注意资源规划和分配;
- Sidecar 容器和应用容器的挂载点共享是通过
<font style="color:#DF2A3F;">hostPath</font>
实现的,是一个有状态服务,如果 Sidecar 容器发生意外重启,应用容器中的挂载点不会自行恢复,需要整个 Pod 重新创建(相较下,Mount Pod 模式则支持挂载点自动恢复); - 不要直接从 Mount Pod 模式升级成 Sidecar 模式。已有的 Mount Pod 在 Sidecar 模式下将无法回收。并且一般而言,考虑到 Sidecar 不支持复用,不推荐从 Mount Pod 模式迁移为 Sidecar 模式;
- 对于启用了 Sidecar 注入的命名空间,CSI Controller 会监听该命名空间下创建的所有容器,检查 PVC 的使用并查询获取相关信息。如果希望最大程度地减小开销,可以在该命名空间下,对不使用 JuiceFS PV 的应用 Pod 打上
<font style="color:#DF2A3F;">disable.sidecar.juicefs.com/inject: true</font>
标签,让 CSI Controller 忽略这些不相关的容器。
3.2.4 进程挂载模式
相较于采用独立 Mount Pod 的容器挂载方式或 Sidecar 模式,CSI 驱动还提供无需独立 Pod 的进程挂载模式,在这种模式下,CSI Node Service 容器中将会负责运行一个或多个 JuiceFS 客户端,该节点上所有需要挂载的 JuiceFS PV,均在 CSI Node Service 容器中以进程模式执行挂载。
由于所有 JuiceFS 客户端均在 CSI Node Service 容器中运行,CSI Node Service 将需要更大的资源声明,推荐将其资源请求调大到至少 1 CPU 和 1GiB 内存,资源约束调大到至少 2 CPU 和 5GiB 内存,或者根据实际场景资源占用进行调整。
在 Kubernetes 中,容器挂载模式无疑是更加推荐的 CSI 驱动用法,但脱离 Kubernetes 的某些场景,则可能需要选用进程挂载模式。在 v0.10 之前,JuiceFS CSI 驱动仅支持进程挂载模式。而 v0.10 及之后版本则默认为容器挂载模式。
3.3 CSI 驱动安装
3.3.1 安装
https://juicefs.com/docs/zh/csi/guide/custom-image
[root@k8s-master01 ~]# helm repo add juicefs https://juicedata.github.io/charts/
"juicefs" has been added to your repositories
[root@k8s-master01 ~]# helm repo update
[root@k8s-master01 ~]# helm fetch --untar juicefs/juicefs-csi-driver
[root@k8s-master01 ~]# cd juicefs-csi-driver
# 查看redis
[root@k8s-master01 ~]# kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 4d1h
redis NodePort 10.96.171.175 <none> 6379:32470/TCP 48m[root@k8s-master01 juicefs-csi-driver]# vim values.yaml
image:repository: harbor.home.com/library/juicefs-csi-drivertag: "v0.29.0"pullPolicy: ""dashboardImage:repository: harbor.home.com/library/csi-dashboardtag: "v0.29.0"pullPolicy: ""sidecars:livenessProbeImage:repository: harbor.home.com/library/livenessprobetag: "v2.12.0"pullPolicy: ""nodeDriverRegistrarImage:repository: harbor.home.com/library/csi-node-driver-registrartag: "v2.9.0"pullPolicy: ""csiProvisionerImage:repository: harbor.home.com/library/csi-provisionertag: "v2.2.2"pullPolicy: ""csiResizerImage:repository: harbor.home.com/library/csi-resizertag: "v1.9.0"pullPolicy: ""...- pvcSelector:matchLabels:custom-image: "true"# eeMountImage: "juicedata/mount:ee-5.0.17-0c63dc5"ceMountImage: "harbor.home.com/library/mount:ce-v1.3.0"
...
storageClasses:
- name: "juicefs-sc"# Set to true to actually create this StorageClassenabled: false# Set existingSecret to indicate whether to use an existing secret. If it is empty, a corresponding secret will be created according to the plain text configuration.existingSecret: ""# Either Retain or Delete, ref: https://juicefs.com/docs/csi/guide/resource-optimization#reclaim-policyreclaimPolicy: Retain# Set to true to allow PVC expansionallowVolumeExpansion: true# Additional annotations for this StorageClass, e.g. make it default# annotations:# storageclass.kubernetes.io/is-default-class: "true"backend:# The JuiceFS file system namename: "juicefs"# Connection URL for metadata engine (e.g. Redis), for community edition use only, ref: https://juicefs.com/docs/community/databases_for_metadatametaurl: "redis://192.168.1.20:32470/1"# Object storage type, such as s3, gs, oss, for community edition use only, ref: https://juicefs.com/docs/community/how_to_setup_object_storagestorage: "oss"# Bucket URL, for community edition use only, ref: https://juicefs.com/docs/community/how_to_setup_object_storagebucket: "https://k8s-test-files.oss-cn-beijing.aliyuncs.com"# Token for JuiceFS Enterprise Edition token, ref: https://juicefs.com/docs/cloud/acltoken: ""# Access key for object storageaccessKey: "xxxxx"# Secret key for object storagesecretKey: "xxxxx"pathPattern: "${.PVC.namespace}-${.PVC.name}"mountPod:# Mount pod resource requests & limitsresources:limits:cpu: 5000mmemory: 5Girequests:cpu: 1000mmemory: 1Gi# Override mount pod image, ref: https://juicefs.com/docs/csi/guide/custom-imageimage: "harbor.home.com/library/mount:ce-v1.3.0"# Set annotations for the mount podannotations: {}
安装
[root@k8s-master01 juicefs-csi-driver]# helm upgrade --install juicefs-csi-driver juicefs/juicefs-csi-driver -n kube-system -f ./values.yaml
3.3.2 创建 secret
apiVersion: v1
kind: Secret
metadata:name: juicefs-secretnamespace: kube-system
type: Opaque
stringData:name: juicefs-vol access-key: xxxx secret-key: xxxxx# follows are for JuiceFS enterprise# follows are for JuiceFS communitymetaurl: redis://192.168.1.20:32470storage: ossbucket: https://k8s-test-files.oss-cn-beijing.aliyuncs.com
3.3.3 创建 storageclass
StorageClass(存储类)里指定了创建 PV 所需的各类配置,你可以将其理解为动态配置下的「Profile」:不同的 StorageClass 就是不同的 Profile,可以在其中指定不同的文件系统认证信息、挂载配置,让动态配置下可以同时使用不同的文件系统,或者指定不同的挂载。因此如果你打算以「动态配置」或「通用临时卷」的方式使用 JuiceFS CSI 驱动,那么你需要提前创建 StorageClass。
注意,StorageClass 仅仅是动态配置下用于创建 PV 的「模板」,也正因此,使用的时候必须注意:
- 在 StorageClass 中修改挂载配置,不影响已经创建的 PV。 对于已有的 PV,需要直接在 PV 级别调整挂载配置,或者干脆删除 PVC 重建;
- 自 v0.24.3 开始,可以在 ConfigMap 中使用
<font style="color:rgb(28, 30, 33);background-color:rgb(246, 247, 248);">matchStorageClassName</font>
来方便地选择已有 PVC,更推荐用这种方式来修改 StorageClass 相关配置。
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:name: juicefs-sc
provisioner: csi.juicefs.com
parameters:csi.storage.k8s.io/provisioner-secret-name: juicefs-secretcsi.storage.k8s.io/provisioner-secret-namespace: kube-systemcsi.storage.k8s.io/node-publish-secret-name: juicefs-secretcsi.storage.k8s.io/node-publish-secret-namespace: kube-systemjuicefs/mount-image: harbor.home.com/library/mount:ce-v1.3.0
3.4 测试
部署完成后我们可以安装上面的提示来创建一个 PVC 和 Pod 进行测试下:
apiVersion: v1
kind: PersistentVolumeClaim
metadata:name: juicefs-pvcnamespace: test
spec:accessModes:- ReadWriteManyresources:requests:storage: 200GstorageClassName: juicefs-sc
---
apiVersion: v1
kind: Pod
metadata:name: juicefs-app
spec:containers:- args:- -c- while true; do echo $(date -u) >> /data/out.txt; sleep 5; donecommand:- /bin/shimage: busyboxname: appvolumeMounts:- mountPath: /dataname: juicefs-pvvolumes:- name: juicefs-pvpersistentVolumeClaim:claimName: juicefs-pvc
[root@k8s-master01 jfs]# kubectl get pvc
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS VOLUMEATTRIBUTESCLASS AGE
juicefs-pvc Bound pvc-cf9cac89-96a8-4bb6-a97b-327c67a2c183 200G RWX juicefs-sc <unset> 2m11s
默认情况下 JuiceFS CSI 采用容器挂载(Mount Pod)模式,会让 JuiceFS 客户端运行在独立的 Pod 中,所以当我们创建上面的 Pod 后,会先创建一个独立的 Mount Pod:
[root@k8s-master01 jfs]# kubectl get pods -n kube-system -l app.kubernetes.io/name=juicefs-mount
NAME READY STATUS RESTARTS AGE
juicefs-k8s-node03-pvc-61b5439f-ab85-4ec8-824e-918f1c445143-ogcbtn 1/1 Running 0 69s[root@k8s-master01 juicefs-csi-driver]# kubectl logs -f -n kube-system juicefs-k8s-node03-pvc-61b5439f-ab85-4ec8-824e-918f1c445143-ogcbtn
2025/07/17 03:43:51.354741 juicefs[7] <INFO>: Meta address: redis://192.168.1.20:32470 [NewClient@interface.go:578]
2025/07/17 03:43:51.361287 juicefs[7] <WARNING>: AOF is not enabled, you may lose data if Redis is not shutdown properly. [checkRedisInfo@info.go:84]
2025/07/17 03:43:51.362623 juicefs[7] <INFO>: Ping redis latency: 1.228855ms [checkServerConfig@redis.go:3692]
2025/07/17 03:43:51.364295 juicefs[7] <INFO>: Data use oss://k8s-test-files/juicefs-vol/ [format@format.go:527]
2025/07/17 03:43:51.648929 juicefs[7] <INFO>: Volume is formatted as {"Name": "juicefs-vol","UUID": "82ef5f79-f254-4bdf-9aae-7954d0354fc8","Storage": "oss","Bucket": "https://k8s-test-files.oss-cn-beijing.aliyuncs.com","AccessKey": "xxxxx","SecretKey": "removed","BlockSize": 4096,"Compression": "none","EncryptAlgo": "aes256gcm-rsa","KeyEncrypted": true,"TrashDays": 1,"MetaVersion": 1,"MinClientVersion": "1.1.0-A","DirStats": true,"EnableACL": false
} [format@format.go:564]
2025/07/17 03:43:52.504044 juicefs[1] <INFO>: Meta address: redis://192.168.1.20:32470 [NewClient@interface.go:578]
2025/07/17 03:43:52.516657 juicefs[1] <WARNING>: AOF is not enabled, you may lose data if Redis is not shutdown properly. [checkRedisInfo@info.go:84]
2025/07/17 03:43:52.517924 juicefs[1] <INFO>: Ping redis latency: 1.155465ms [checkServerConfig@redis.go:3692]
2025/07/17 03:43:52.529824 juicefs[1] <INFO>: Data use oss://k8s-test-files/juicefs-vol/ [mount@mount.go:588]
2025/07/17 03:43:53.760643 juicefs[24] <INFO>: Meta address: redis://192.168.1.20:32470 [NewClient@interface.go:578]
2025/07/17 03:43:53.852370 juicefs[24] <WARNING>: AOF is not enabled, you may lose data if Redis is not shutdown properly. [checkRedisInfo@info.go:84]
2025/07/17 03:43:53.886953 juicefs[24] <INFO>: Ping redis latency: 34.404648ms [checkServerConfig@redis.go:3692]
2025/07/17 03:43:54.032569 juicefs[24] <INFO>: Data use oss://k8s-test-files/juicefs-vol/ [mount@mount.go:588]
2025/07/17 03:43:54.032693 juicefs[24] <INFO>: JuiceFS version 1.3.0+2025-07-03.30190ca1 [mount@mount.go:631]
2025/07/17 03:43:54.081067 juicefs[24] <INFO>: Disk cache (/var/jfsCache/82ef5f79-f254-4bdf-9aae-7954d0354fc8/): used ratio - [space 45.5%, inode 1.1%] [newCacheStore@disk_cache.go:147]
2025/07/17 03:43:54.081198 juicefs[24] <INFO>: Adjusted cache capacity based on freeratio: from 107374182400 to 67612702976 bytes [setlimitByFreeRatio@disk_cache.go:171]
2025/07/17 03:43:54.081223 juicefs[24] <INFO>: Adjusted max items based on freeratio: from 0 to 33030143 items [setlimitByFreeRatio@disk_cache.go:176]
2025/07/17 03:43:54.092159 juicefs[24] <INFO>: Create session 2 OK with version: 1.3.0+2025-07-03.30190ca1 [NewSession@base.go:535]
2025/07/17 03:43:54.097453 juicefs[24] <INFO>: Prometheus metrics listening on [::]:9567 [exposeMetrics@mount.go:134]
2025/07/17 03:43:54.106918 juicefs[24] <INFO>: Add fuse.juicefs into PRUNEFS of /etc/updatedb.conf [disableUpdatedb@mount_unix.go:448]
2025/07/17 03:43:54.107215 juicefs[24] <INFO>: Mounting volume juicefs-vol at /jfs/pvc-61b5439f-ab85-4ec8-824e-918f1c445143-ogcbtn ... [mountMain@mount_unix.go:1027]
2025/07/17 03:43:54.548096 juicefs[1] <INFO>: OK, juicefs-vol is ready at /jfs/pvc-61b5439f-ab85-4ec8-824e-918f1c445143-ogcbtn [checkMountpoint@mount_unix.go:235]
2025-07-17 03:43:57.640297 I | Unimplemented opcode POLL
2025/07/17 03:43:57.642404 juicefs[1] <INFO>: watching /jfs/pvc-61b5439f-ab85-4ec8-824e-918f1c445143-ogcbtn, pid 24 [watchdog@mount_unix.go:162]
可以看到 Mount Pod 已经成功挂载了 JuiceFS 文件系统,接下来我们再看下我们创建的 Pod:
[root@k8s-master01 juicefs-csi-driver]# kubectl get pods -n test
NAME READY STATUS RESTARTS AGE
juicefs-app 1/1 Running 0 2m28s
[root@k8s-master01 juicefs-csi-driver]#
[root@k8s-master01 juicefs-csi-driver]# kubectl get pvc -n test
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS VOLUMEATTRIBUTESCLASS AGE
juicefs-pvc Bound pvc-61b5439f-ab85-4ec8-824e-918f1c445143 200G RWX juicefs-sc <unset> 2m28s
[root@k8s-master01 juicefs-csi-driver]# kubectl exec -it -n test juicefs-app sh
kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl exec [POD] -- [COMMAND] instead.
/ #
/ # ls /data
out.txt
/ #
/ # cat /data/out.txt
Thu Jul 17 03:43:56 UTC 2025
Thu Jul 17 03:44:01 UTC 2025
Thu Jul 17 03:44:06 UTC 2025
Thu Jul 17 03:44:11 UTC 2025
Thu Jul 17 03:44:16 UTC 2025
Thu Jul 17 03:44:21 UTC 2025
Thu Jul 17 03:44:26 UTC 2025
这个时候 Pod 中的 /data
目录已经成功挂载了 JuiceFS 文件系统,我们可以前往 Mount Pod 中查看下:
[root@k8s-master01 jfs]# kubectl exec -it -n kube-system juicefs-k8s-node03-pvc-61b5439f-ab85-4ec8-824e-918f1c445143-ogcbtn sh
kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl exec [POD] -- [COMMAND] instead.
#
# ls /jfs
pvc-61b5439f-ab85-4ec8-824e-918f1c445143-ogcbtn
# ls /jfs/pvc-61b5439f-ab85-4ec8-824e-918f1c445143-ogcbtn
out.txt
# head -n 5 /jfs/pvc-61b5439f-ab85-4ec8-824e-918f1c445143-ogcbtn/out.txt
Thu Jul 17 03:43:56 UTC 2025
Thu Jul 17 03:44:01 UTC 2025
Thu Jul 17 03:44:06 UTC 2025
Thu Jul 17 03:44:11 UTC 2025
Thu Jul 17 03:44:16 UTC 2025
3.5 静态 PV
上面安装 JuiceFS CSI Driver 后手动创建了一个 StorageClass,所以我们可以直接使用这个 StorageClass 来创建 PVC,但是如果我们想要使用静态 PV 的话,我们就需要手动创建 PV 和 PVC,下面我们就来看下如何创建静态 PV。首先手动创建一个 PV,创建所需的资源定义示范如下:
apiVersion: v1
kind: PersistentVolume
metadata:name: juicefs-static-pvlabels:juicefs-name: ten-gb-fs
spec:capacity:storage: 10GivolumeMode: FilesystemaccessModes:- ReadWriteManypersistentVolumeReclaimPolicy: Retaincsi:# 在先前的安装步骤中,已经创建了名为 csi.juicefs.com 的 CSIDriver# 可以使用 kubectl get csidriver csi.juicefs.com 查看driver: csi.juicefs.com# volumeHandle 需要保证集群内唯一,因此一般直接用 PV 名即可volumeHandle: juicefs-pvfsType: juicefs# 在先前的步骤中已经创建好文件系统认证信息(Secret),在这里引用# 如果要在静态配置下使用不同的认证信息,甚至使用不同的 JuiceFS 文件系统,则需要创建不同的 SecretnodePublishSecretRef:name: juicefs-secret namespace: kube-system
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:name: juicefs-static-pvcnamespace: default
spec:accessModes:- ReadWriteManyvolumeMode: Filesystem# 静态配置下必须指定 storageClassName 为空字符串# 代表该 PV 不采用任何 StorageClass,而是直接使用 selector 所指定的 PVstorageClassName: ""# 由于目前 JuiceFS CSI 驱动不支持设置存储容量,此处 requests.storage 填写任意小于等于 PV capacity 的有效值即可resources:requests:storage: 10Giselector:matchLabels:juicefs-name: ten-gb-fs
然后再创建一个应用 Pod,并在其中引用上面的 PVC:
apiVersion: v1
kind: Pod
metadata:name: juicefs-appnamespace: default
spec:containers:- args:- -c- while true; do echo $(date -u) >> /data/out.txt; sleep 5; donecommand:- /bin/shimage: busyboxname: appvolumeMounts:- mountPath: /dataname: dataresources:requests:cpu: 10mvolumes:- name: datapersistentVolumeClaim:claimName: juicefs-static-pvc
➜ kubectl get pv juicefs-static-pv
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
juicefs-static-pv 10Gi RWX Retain Bound default/juicefs-static-pvc 9s
➜ kubectl get pvc juicefs-static-pvc
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
juicefs-static-pvc Bound juicefs-static-pv 10Gi RWX 15s
➜ kubectl get pods
NAME READY STATUS RESTARTS AGE
juicefs-app 1/1 Running 0 58s
此外如果想要在不同命名空间中共享同一个文件系统,只需要让不同 PV 使用相同的文件系统认证信息(Secret)即可:
apiVersion: v1
kind: PersistentVolume
metadata:name: mypv1namespace: ns1labels:pv-name: mypv1
spec:csi:nodePublishSecretRef:name: juicefs-sc-secretnamespace: kube-system...
---
apiVersion: v1
kind: PersistentVolume
metadata:name: mypv2namespace: ns2labels:pv-name: mypv2
spec:csi:nodePublishSecretRef:name: juicefs-sc-secretnamespace: kube-system...
这样也就不会重复创建 Mount Pod 了。默认情况下,仅在多个应用 Pod 使用相同 PV 时,Mount Pod 才会被复用。如果你希望进一步降低开销,可以更加激进地复用 Mount Pod,让使用相同 StorageClass 创建出来的所有 PV,都复用同一个 Mount Pod(当然复用只能发生在同一个节点)。不同的应用 Pod,将会绑定挂载点下不同的路径,实现一个挂载点为多个应用容器提供服务。
为相同 StorageClass PV 复用 Mount Pod,需要为 CSI Node Service 添加 <font style="color:rgb(38, 38, 38);">STORAGE_CLASS_SHARE_MOUNT</font>
这个环境变量:
➜ kubectl -n kube-system set env -c juicefs-plugin daemonset/juicefs-csi-node STORAGE_CLASS_SHARE_MOUNT=true
但是高度复用意味着更低的隔离程度,如果 Mount Pod 发生意外,挂载点异常,影响面也会更大,因此如果你决定启用该复用策略,请务必同时启用「挂载点自动恢复」(JuiceFS CSI 驱动自 v0.10.7 开始支持挂载点自动恢复:当 Mount Pod 遭遇故障,重启或重新创建 Mount Pod 以后,应用容器也能继续工作。),以及合理增加 「Mount Pod 的资源请求」。
四、高级功能与配置
4.1 ConfigMap 配置
从 v0.24 开始,CSI 驱动支持在名为 <font style="color:#DF2A3F;background-color:rgb(246, 247, 248);">juicefs-csi-driver-config</font>
的 ConfigMap 中书写配置,支持多种多样的配置项,既可以用来配置 Mount Pod 或 sidecar,也包含 CSI 驱动自身的配置,并且支持动态更新:修改 Mount Pod 配置时不需要重建 PV,修改 CSI 自身配置时,也不需要重启 CSI Node 或者 Controller。
由于 ConfigMap 功能强大、更加灵活,它将会或已经取代从前在 CSI 驱动中各种修改配置的方式,例如下方标有「不推荐」的小节,均为旧版中灵活性欠佳的实践,请及时弃用。简而言之,如果一项配置已经在 ConfigMap 中得到支持,则在 ConfigMap 中具有最高优先级,因此请优先在 ConfigMap 中对其进行配置,弃用旧版本中的实践。
修改 ConfigMap 以后,相关改动并不会立刻生效,这是由于挂载进容器的 ConfigMap 并非实时更新,而是定期同步(详见 Kubernetes 官方文档)。
如果希望立即生效,可以给 CSI 组件临时添加 Annotation 来触发更新:
kubectl -n kube-system annotate pods -l app.kubernetes.io/name=juicefs-csi-driver useless-annotation=true
ConfigMap 生效后,后续创建的 Mount Pod 都会应用新的配置,但已有的 Mount Pod 并不会自动更新! 根据所修改的项目不同,可能需要重建应用 Pod 或者 Mount Pod,方可令修改生效。请继续阅读下方相关章节了解各自项目具体的生效条件。
ConfigMap 中支持的所有配置项,都可以在这里找到示范
globalConfig:# 支持模板变量,比如 ${MOUNT_POINT}、${SUB_PATH}、${VOLUME_ID}mountPodPatch:# 未定义 pvcSelector,则为全局配置- lifecycle:preStop:exec:command:- sh- -c- +e- umount -l ${MOUNT_POINT}; rmdir ${MOUNT_POINT}; exit 0# 如果多个 pvcSelector 匹配的是相同的 PVC,则后定义的配置会覆盖更早定义的配置- pvcSelector:matchLabels:mylabel1: "value1"# 启用 host networkhostNetwork: true- pvcSelector:matchLabels:mylabel2: "value2"# 增加 labelslabels:custom-labels: "mylabels"- pvcSelector:matchLabels:...# 修改资源定义resources:requests:cpu: 100mmemory: 512Mi- pvcSelector:matchLabels:...readinessProbe:exec:command:- stat- ${MOUNT_POINT}/${SUB_PATH}failureThreshold: 3initialDelaySeconds: 10periodSeconds: 5successThreshold: 1- pvcSelector:matchLabels:...# 目前暂不推荐使用 liveness probe,请优先使用 readiness probe# JuiceFS 客户端自身也会进行检活和重启,因此避免额外设置 liveness probe,从外部重启livenessProbe:exec:command:- stat- ${MOUNT_POINT}/${SUB_PATH}failureThreshold: 3initialDelaySeconds: 10periodSeconds: 5successThreshold: 1- pvcSelector:matchLabels:...annotations:# 延迟删除juicefs-delete-delay: 5m# 退出时清理 cachejuicefs-clean-cache: "true"# 为 Mount Pod 注入环境变量- pvcSelector:matchLabels:...env:- name: DEMO_GREETINGvalue: "Hello from the environment"- name: DEMO_FAREWELLvalue: "Such a sweet sorrow"# 挂载 volumes 到 Mount Pod- pvcSelector:matchLabels:...volumeDevices:- name: block-devicesdevicePath: /dev/sda1volumes:- name: block-devicespersistentVolumeClaim:claimName: block-pv# 选择特定的 StorageClass- pvcSelector:matchStorageClassName: juicefs-scterminationGracePeriodSeconds: 60# 选择特定的 PVC- pvcSelector:matchName: pvc-nameterminationGracePeriodSeconds: 60
4.2 定制 MountPod 容器或 Sidecar 容器
通过 ConfigMap 修改配置后,推荐使用「平滑升级 Mount Pod」特性来在不重建应用 Pod 的情况下使修改生效,但是需要注意,请升级到 v0.25.2 或更新版本,v0.25.0(该功能首次发布)尚不支持某些配置平滑升级,如果希望充分利用平滑升级的能力,务必升级到最新版再操作。
如果仍在使用旧版、无法享受到平滑升级,则需要根据情况来重建应用 Pod 或 Mount Pod,具体操作在下方,请务必提前配置好「挂载点自动恢复」,避免重建 Mount Pod 后,应用 Pod 中的挂载点永久丢失。
4.2.1 环境变量
4.2.1.1 使用 ConfigMap
该功能最低需要 CSI 驱动版本 v0.24.5,修改后需要重建业务 Pod 生效。
mountPodPatch:- env:- name: DEMO_GREETINGvalue: "Hello from the environment"- name: DEMO_FAREWELLvalue: "Such a sweet sorrow"
4.2.1.2 使用 Secret
apiVersion: v1
kind: Secret
metadata:name: juicefs-secretnamespace: defaultlabels:# 增加该标签以启用认证信息校验juicefs.com/validate-secret: "true"
type: Opaque
stringData:envs: '{"BASE_URL": "http://10.0.0.1:8080/static"}'
4.2.2 资源限制
该特性需要的 CSI 驱动最低版本为 0.24.0,示例如下:
mountPodPatch:- resources:requests:cpu: 100mmemory: 512Mi
4.2.3 挂载参数
https://juicefs.com/docs/zh/community/command_reference/#mount
每一个 JuiceFS 挂载点都是 <font style="color:#DF2A3F;background-color:rgb(246, 247, 248);">juicefs mount</font>
命令创建的,在 CSI 驱动体系中,需要通过 <font style="color:#DF2A3F;background-color:rgb(246, 247, 248);">mountOptions</font>
字段填写需要调整的挂载配置。
<font style="color:#DF2A3F;background-color:rgb(246, 247, 248);">mountOptions</font>
同时支持 JuiceFS 本身的挂载参数和 FUSE 相关选项。但要注意,虽然 FUSE 参数在命令行使用时会用 <font style="color:#DF2A3F;background-color:rgb(246, 247, 248);">-o</font>
传入,但在 <font style="color:#DF2A3F;background-color:rgb(246, 247, 248);">mountOptions</font>
中需要省略 <font style="color:#DF2A3F;background-color:rgb(246, 247, 248);">-o</font>
,直接在列表中追加参数即可。以下方挂载命令为例:
juicefs mount ... --cache-size=204800 -o writeback_cache,debug
翻译成 CSI 中的 <font style="color:rgb(28, 30, 33);background-color:rgb(246, 247, 248);">mountOptions</font>
,格式如下:
mountOptions:# JuiceFS mount options- cache-size=204800# 额外的 FUSE 相关选项- writeback_cache- debug
4.2.4 使用 ConfigMap
该功能最小需要 CSI 驱动 v0.24.7。修改 ConfigMap 相关配置后,需重建业务 Pod 生效。
ConfigMap 中的配置具备最高优先级,他会递归合并覆盖 PV 中的 <font style="color:#DF2A3F;background-color:rgb(246, 247, 248);">mountOptions</font>
,因此为了避免出现“修改了却不生效”的误用情况,建议将所有配置迁移到 ConfigMap,不再继续使用 PV 级别的 <font style="color:#DF2A3F;background-color:rgb(246, 247, 248);">mountOptions</font>
。
灵活使用 <font style="color:#DF2A3F;background-color:rgb(246, 247, 248);">pvcSelector</font>
可实现批量修改 <font style="color:#DF2A3F;background-color:rgb(246, 247, 248);">mountOptions</font>
的目的。
mountPodPatch:- pvcSelector:matchLabels:# 所有含有此 label 的 PVC 都将应用此配置need-update-options: "true"mountOptions:- writeback- cache-size=204800
4.2.5 健康检查&容器回调
该特性需要的 CSI 驱动最低版本为 0.24.0,使用场景:
- 配合
<font style="color:rgb(28, 30, 33);background-color:rgb(246, 247, 248);">readinessProbe</font>
配合监控体系,建立告警机制; - 定制
<font style="color:rgb(28, 30, 33);background-color:rgb(246, 247, 248);">preStopHook</font>
,避免 sidecar 场景中,挂载容器早于业务容器退出,造成业务波动。详见 Sidecar 模式推荐设置。
- pvcSelector:matchLabels:custom-probe: "true"readinessProbe:exec:command:- stat- ${MOUNT_POINT}/${SUB_PATH}failureThreshold: 3initialDelaySeconds: 10periodSeconds: 5successThreshold: 1
4.2.6 挂载额外的 Volume
使用场景:
- 部分对象存储服务(比如 Google 云存储)在访问时需要提供额外的认证文件,这就需要你用创建单独的 Secret 保存这些文件,然后在认证信息中引用。这样一来,CSI 驱动便会将这些文件挂载进 Mount Pod,然后在 Mount Pod 中添加对应的环境变量,令 JuiceFS 挂载时使用该文件进行对象存储的认证。
- JuiceFS 企业版支持挂载共享块设备,既可以作为缓存存储,也可以配置成数据块的永久存储。
4.2.6.1 使用 ConfigMap
该功能最低需要 CSI 驱动版本 v0.24.7,修改后需重建业务 Pod 生效。
# mount some volumes to the Mount Pod- pvcSelector:matchLabels:need-block-device: "true"volumeDevices:- name: block-devicesdevicePath: /dev/sda1volumes:- name: block-devicespersistentVolumeClaim:claimName: block-pv- pvcSelector:matchLabels:need-mount-secret: "true"volumeMounts:- name: config-1mountPath: /root/.config/gcloudvolumes:- name: gc-secretsecret:secretName: gc-secretdefaultMode: 420
4.2.6.2 使用 secret
在 JuiceFS Secret 的 <font style="color:#DF2A3F;background-color:rgb(246, 247, 248);">configs</font>
字段中,只能挂载额外的 Secret,无法配置共享块设备的挂载。
apiVersion: v1
kind: Secret
metadata:name: juicefs-secret
type: Opaque
stringData:...# 在 configs 中填写 Secret 名称和挂载目录,将该 Secret 整体挂载进指定的目录configs: "{gc-secret: /root/.config/gcloud}"
4.3 应用间共享存储
如果你在 JuiceFS 文件系统已经存储了大量数据,希望挂载进容器使用,或者希望让多个应用共享同一个 JuiceFS 目录,有以下做法:
4.3.1 挂载子目录
挂载子目录有两种方式,一种是通过 <font style="color:rgb(28, 30, 33);background-color:rgb(246, 247, 248);">--subdir</font>
挂载选项,另一种是通过 volumeMounts.subPath属性,下面分别介绍。
- 使用****
**<font style="color:rgb(28, 30, 33);background-color:rgb(246, 247, 248);">--subdir</font>**
****挂载选项
修改「挂载参数」,用 <font style="color:rgb(28, 30, 33);background-color:rgb(246, 247, 248);">subdir</font>
参数挂载子目录。如果子目录尚不存在,CSI Controller 会在挂载前自动创建。
apiVersion: v1
kind: PersistentVolume
metadata:name: juicefs-pvlabels:juicefs-name: ten-pb-fs
spec:mountOptions:- subdir=/my/sub/dir...
- 使用
**<font style="color:rgb(28, 30, 33);background-color:rgb(246, 247, 248);">volumeMounts.subPath</font>**
属性
apiVersion: v1
kind: Pod
metadata:name: juicefs-appnamespace: default
spec:containers:- volumeMounts:- name: datamountPath: /data# 注意 subPath 只能用相对路径,不能用绝对路径。subPath: my/sub/dir...volumes:- name: datapersistentVolumeClaim:claimName: juicefs-pvc
如果在同一台宿主机上可能会运行多个应用 Pod,并且这些应用 Pod 需要挂载同一个文件系统的不同子目录,那么建议使用 <font style="color:rgb(28, 30, 33);background-color:rgb(246, 247, 248);">volumeMounts.subPath</font>
属性来挂载,因为这种方式只会创建 1 个 Mount Pod,可以大大节省宿主机的资源。
4.3.2 跨命名空间共享同一个文件系统
如果想要在不同命名空间中共享同一个文件系统,只需要让不同 PV 使用相同的文件系统认证信息(Secret)即可:
apiVersion: v1
kind: PersistentVolume
metadata:name: mypv1labels:pv-name: mypv1
spec:csi:nodePublishSecretRef:name: juicefs-secretnamespace: default...
---
apiVersion: v1
kind: PersistentVolume
metadata:name: mypv2labels:pv-name: mypv2
spec:csi:nodePublishSecretRef:name: juicefs-secretnamespace: default...
4.4 常用 PV 设置
4.4.1 PV 容量分配
从 v0.19.3 开始,JuiceFS CSI 驱动支持在动态配置设置存储容量(要注意,仅支持动态配置)。
在静态配置中,PVC 中指定的容量会被忽略,填写任意有效值即可,建议填写一个较大的数值,避免未来版本如果带来该功能支持时,因为容量超限导致问题。
...
storageClassName: ""
resources:requests:storage: 10Ti
而在动态配置中,可以在 PVC 中指定存储容量,这个容量限制将会被翻译成 <font style="color:rgb(28, 30, 33);background-color:rgb(246, 247, 248);">juicefs quota</font>
命令,在 CSI Controller 中执行,为该 PV 所对应的子目录添加容量限制。关于 <font style="color:rgb(28, 30, 33);background-color:rgb(246, 247, 248);">juicefs quota</font>
命令,可以参考社区版文档
...
storageClassName: juicefs-sc
resources:requests:storage: 100Gi
创建并挂载好 PV 后,可以进入容器用 <font style="color:rgb(28, 30, 33);background-color:rgb(246, 247, 248);">df -h</font>
验证容量生效:
$ df -h
Filesystem Size Used Avail Use% Mounted on
overlay 84G 66G 18G 80% /
tmpfs 64M 0 64M 0% /dev
JuiceFS:myjfs 100G 0 100G 0% /data-0
4.4.2 PV 扩容
在 JuiceFS CSI 驱动 0.21.0 及以上版本,支持动态扩展 PersistentVolume 的容量(仅支持动态配置)。需要在 StorageClass 中指定 <font style="color:rgb(28, 30, 33);background-color:rgb(246, 247, 248);">allowVolumeExpansion: true</font>
,同时指定扩容时所需使用的 Secret,主要提供文件系统的认证信息,例如:
apiVersion: storage.k8s.io/v1
kind: StorageClass
...
parameters:csi.storage.k8s.io/node-publish-secret-name: juicefs-secretcsi.storage.k8s.io/node-publish-secret-namespace: defaultcsi.storage.k8s.io/provisioner-secret-name: juicefs-secretcsi.storage.k8s.io/provisioner-secret-namespace: defaultcsi.storage.k8s.io/controller-expand-secret-name: juicefs-secret # 与 provisioner-secret-name 相同即可csi.storage.k8s.io/controller-expand-secret-namespace: default # 与 provisioner-secret-namespace 相同即可
allowVolumeExpansion: true # 表示支持扩容
然后通过编辑 PVC 的 <font style="color:rgb(28, 30, 33);background-color:rgb(246, 247, 248);">spec</font>
字段,指定更大的存储请求,可以触发 PersistentVolume 的扩充:
kind: PersistentVolumeClaim
apiVersion: v1
metadata:name: myclaim
spec:accessModes:- ReadWriteOnceresources:requests:storage: 20Gi # 在此处指定更大的容量
上述方法对存量 PV 不生效,如果需要对扩容存量 PV,需要手动修改 PV,为其增加 Secret 配置:
apiVersion: v1
kind: PersistentVolume
metadata:name: pvc-xxxx
spec:csi:controllerExpandSecretRef:name: juicefs-secretnamespace: default
4.4.3 回收策略
静态配置下仅支持 <font style="color:rgb(28, 30, 33);background-color:rgb(246, 247, 248);">persistentVolumeReclaimPolicy: Retain</font>
,无法随着删除回收。
动态配置支持 <font style="color:rgb(28, 30, 33);background-color:rgb(246, 247, 248);">Delete|Retain</font>
两种回收策略,按需使用。<font style="color:rgb(28, 30, 33);background-color:rgb(246, 247, 248);">Delete</font>
会导致 JuiceFS 内的 PVC 子目录随着 PV 删除一起释放,如果担心数据安全,可以配合 JuiceFS 的回收站功能一起使用:
- 社区版回收站文档
- 企业版回收站文档
4.4.4 给 Monut Pod 挂载宿主机目录
如果希望在 Mount Pod 中挂载宿主机文件或目录,可以声明 <font style="color:rgb(28, 30, 33);background-color:rgb(246, 247, 248);">juicefs/host-path</font>
,可以在这个字段中填写多个文件映射,逗号分隔。这个字段在静态和动态配置方式中填写位置不同,以 <font style="color:rgb(28, 30, 33);background-color:rgb(246, 247, 248);">/data/file.txt</font>
这个文件为例。
静态配置:
apiVersion: v1
kind: PersistentVolume
metadata:name: juicefs-pvlabels:juicefs-name: ten-pb-fs
spec:...csi:driver: csi.juicefs.comvolumeHandle: juicefs-pvfsType: juicefsnodePublishSecretRef:name: juicefs-secretnamespace: defaultvolumeAttributes:juicefs/host-path: /data/file.txt
动态配置
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:name: juicefs-sc
provisioner: csi.juicefs.com
parameters:juicefs/host-path: /data/file.txt