JuiceFS 在 Ceph RGW 上的生产部署实践:Redis Cluster 元数据与 S3 对象存储解耦
在 AI 训练、数据湖、离线分析和多节点共享数据场景里,单机文件系统很快会遇到容量、并发和多客户端一致性问题。JuiceFS 的价值在于把文件系统语义拆成两层:元数据放在独立的 Metadata Engine,文件数据切块后落到对象存储。
本文以 Redis Cluster + Ceph RGW/S3 + JuiceFS Client 的组合为例,整理一套可以落地的生产部署方法。文中的地址、凭据、卷名、Bucket 和路径均使用占位符,实际发布和交付时不要把真实环境信息写入文档、命令历史或截图。
1. 架构拆分
这套架构可以分成 4 个平面。
第一层是业务客户端。训练任务、推理服务、数据加工任务通过 POSIX 接口访问挂载点,不需要感知对象存储的分片、命名和生命周期。
第二层是 JuiceFS Client。客户端负责 FUSE 挂载、元数据访问、读写缓冲、预读、本地缓存、对象上传下载和后台任务。
第三层是 Redis Cluster。Redis 保存文件名、目录树、inode、权限、chunk/slice/block 映射、会话等元数据。Redis 需要按核心生产组件对待,必须做持久化、备份、访问控制和容量监控。
第四层是 Ceph RGW/S3。对象存储保存真实数据块。RGW 可以通过同一个 Ceph 集群、同一个 RGW zone 内的多个入口做负载均衡,但不要跨异步复制 zone 或跨独立集群做同一个 JuiceFS 卷的数据入口。
2. 生产前置条件
Redis Cluster 要开启持久化,并设置 maxmemory-policy noeviction。如果 Redis 因内存策略主动淘汰元数据,文件系统会出现严重风险。Redis 的 RDB/AOF、快照、备份恢复演练都要纳入常规运维。
Ceph RGW 建议启用 HTTPS,对外提供稳定的 S3 endpoint。内网测试环境可以使用 HTTP,但公开最佳实践不要把 HTTP 写成生产推荐。Bucket 建议按文件系统隔离,至少要做到不同业务使用不同访问凭据。
JuiceFS Client 建议统一版本,并在上线前完成 juicefs bench、业务 fio/vdbench、长稳读写、重启自动挂载、元数据恢复、RGW 故障切换等验证。
3. 文件系统创建示例
创建文件系统时,命令里不要直接写真实密钥。更稳妥的做法是通过受控的环境变量、密钥管理系统或 systemd EnvironmentFile 注入。
export META_PASSWORD='<redis-password>'
export S3_ACCESS_KEY='<s3-access-key>'
export S3_SECRET_KEY='<s3-secret-key>'
juicefs format \
--storage s3 \
--bucket https://<bucket>.<rgw-domain> \
--access-key "$S3_ACCESS_KEY" \
--secret-key "$S3_SECRET_KEY" \
--trash-days 1 \
--capacity <capacity-gib> \
--inodes <inode-limit> \
"redis://<redis-user>@<redis-cluster-endpoints>/<fs-prefix>" \
<volume-name>
--capacity 的单位是 GiB,--inodes 用来限制 inode 数量。它们是文件系统配额,不会自动发现 Ceph/RGW 的真实容量。设置这两个值的意义是让容量展示、配额治理和业务预期保持一致。
--trash-days 默认会启用回收站。回收站可以降低误删风险,但会增加对象存储实际占用。高频覆盖写或删除场景要同时监控逻辑用量和对象存储用量。
4. 挂载参数分层
生产环境不要把某一组参数当成所有场景的唯一答案。JuiceFS 的缓存参数本质上是在一致性可见性、元数据压力、对象存储读放大和吞吐之间做取舍。
4.1 一致性优先配置
多客户端同时写同一批目录、对跨客户端可见性敏感、或者排障阶段希望减少缓存变量时,可以使用保守配置。
export META_PASSWORD='<redis-password>'
juicefs mount \
--attr-cache=0 \
--entry-cache=0 \
--dir-entry-cache=0 \
--negative-entry-cache=0 \
--open-cache=0 \
--prefetch=0 \
--max-readahead=0 \
--cache-size=0 \
"redis://<redis-user>@<redis-cluster-endpoints>/<fs-prefix>" \
/mnt/<volume-name>
这组参数会减少内核元数据缓存、客户端 open 缓存、本地数据缓存和预取带来的变量,但代价是 Redis 请求、对象存储请求和客户端延迟都会上升。它适合一致性排查和强可见性场景,不适合直接作为所有读密集任务的性能配置。
4.2 读密集配置
AI 数据集、模型权重、离线样本等大量只读或读多写少场景,可以保留 close-to-open 语义,同时开启本地缓存、预读和预取来提升吞吐。
export META_PASSWORD='<redis-password>'
juicefs mount \
--attr-cache=1 \
--entry-cache=1 \
--dir-entry-cache=1 \
--open-cache=0 \
--prefetch=1 \
--max-readahead=256 \
--cache-size=<cache-size-mib> \
--cache-dir /var/jfsCache/<volume-name> \
"redis://<redis-user>@<redis-cluster-endpoints>/<fs-prefix>" \
/mnt/<volume-name>
如果业务明确是只读训练数据集,可以进一步评估 --open-cache、juicefs warmup 和更大的本地 SSD 缓存。但一旦存在多客户端频繁修改同一批文件,就要谨慎放大元数据缓存 TTL。
4.3 后台任务配置
--no-bgjob 不是一致性开关,而是运维负载分配开关。它可以让重负载业务客户端不承担后台清理、session 清理、回收站过期处理和元数据备份等任务。
生产环境可以让业务客户端使用 --no-bgjob,但必须至少保留一个维护客户端或独立运维挂载点不加 --no-bgjob,并显式开启元数据备份。
juicefs mount \
--backup-meta 1h \
"redis://<redis-user>@<redis-cluster-endpoints>/<fs-prefix>" \
/mnt/<volume-name-maintenance>
--backup-meta 默认间隔是 3600 秒,0 表示关闭。它能把 JuiceFS 元数据备份到对象存储,但不能替代 Redis 自身的 RDB/AOF、快照和恢复演练。
5. systemd 自动挂载
不建议用 --update-fstab 把包含凭据的 META URL 写入 /etc/fstab。生产环境更建议使用 systemd service,并把敏感变量放到权限受控的 EnvironmentFile。JuiceFS 支持用 META_PASSWORD 或 META_PASSWORD_FILE 提供元数据密码,因此 URL 中可以不直接出现密码。
# /etc/systemd/system/juicefs-<volume-name>.service
[Unit]
Description=JuiceFS <volume-name> Mount
After=network-online.target
Wants=network-online.target
[Service]
Type=simple
EnvironmentFile=/etc/juicefs/<volume-name>.env
ExecStartPre=/usr/bin/mkdir -p /mnt/<volume-name>
ExecStart=/usr/local/bin/juicefs mount \
--attr-cache=0 \
--entry-cache=0 \
--dir-entry-cache=0 \
--negative-entry-cache=0 \
--open-cache=0 \
--prefetch=0 \
--max-readahead=0 \
--cache-size=0 \
redis://<redis-user>@<redis-cluster-endpoints>/<fs-prefix> \
/mnt/<volume-name>
ExecStop=/bin/fusermount -uz /mnt/<volume-name>
Restart=on-failure
RestartSec=5
[Install]
WantedBy=multi-user.target
环境文件示例:
# /etc/juicefs/<volume-name>.env
META_PASSWORD=<redis-password>
S3_ACCESS_KEY=<s3-access-key>
S3_SECRET_KEY=<s3-secret-key>
如果使用的是 redis://:<password>@... 这类 URL 形式,应改成 redis://<redis-user>@... 或 redis://... 并由 META_PASSWORD 注入密码,避免凭据出现在进程参数、配置文件和审计日志里。
sudo chown root:root /etc/juicefs/<volume-name>.env
sudo chmod 600 /etc/juicefs/<volume-name>.env
sudo systemctl daemon-reload
sudo systemctl enable --now juicefs-<volume-name>.service
如果系统使用 fusermount3,需要把 ExecStop 改成对应路径。不同发行版的 FUSE 包名和命令路径可能不同,上线前要在目标 OS 上验证。
6. 多业务隔离
持有元数据地址和密码的客户端,基本等同于拥有该 JuiceFS 文件系统的管理能力。多业务共享时,不要只依赖 Linux 用户权限做隔离。
推荐模型是“一个业务域一个文件系统”。每个文件系统使用独立 Volume Name、独立 Redis ACL 用户、独立 key 前缀、独立 S3 凭据,最好使用独立 Bucket。
业务 A -> Redis ACL user-a + key prefix {a}* -> bucket-a -> mount-a
业务 B -> Redis ACL user-b + key prefix {b}* -> bucket-b -> mount-b
业务 C -> Redis ACL user-c + key prefix {c}* -> bucket-c -> mount-c
在 Redis Cluster 场景里,URL 里的 /<fs-prefix> 更适合理解成 key 前缀或 hash tag 隔离,而不是传统单机 Redis 的多 DB 隔离。ACL 要在 Redis 节点上限制对应 key 前缀,并配合网络 ACL 限制客户端来源。
7. 监控与运维闭环
JuiceFS 客户端侧需要关注吞吐、延迟、buffer、cache 命中、对象存储错误和后台任务状态。常用命令包括 juicefs stats、juicefs profile、juicefs status、juicefs info。
Redis 侧要监控内存、key 数、持久化状态、主从复制、Cluster 状态、慢查询、连接数和过期/淘汰风险。noeviction、持久化成功率和恢复演练比单纯看存活更重要。
RGW/S3 侧要监控 4xx/5xx、请求延迟、带宽、连接重试、bucket 用量、对象数量和多 part 上传异常。负载均衡必须限定在同一个 Ceph 集群和同一个 RGW zone 内。
日志要接入 logrotate 或集中日志系统。root 用户通常写 /var/log/juicefs.log,非 root 用户通常写 $HOME/.juicefs/juicefs.log,具体路径以实际版本为准。
8. 小结
Redis Cluster + Ceph RGW/S3 + JuiceFS Client 是一套工程上清晰的共享文件系统架构。真正决定稳定性的不是单条 mount 命令,而是元数据保护、对象存储可靠性、缓存策略、后台任务、自动挂载和监控告警能否形成闭环。
一致性优先参数适合强可见性和排障场景,读密集任务则应该结合业务访问模式开启缓存和预读。生产部署时要把参数写成“场景化策略”,而不是一组固定模板。
参考资料:
- JuiceFS Architecture
- JuiceFS Cache
- JuiceFS Command Reference
- JuiceFS Redis Best Practices
- JuiceFS Metadata Backup and Recovery
- JuiceFS Object Storage Setup