ZeroFS
ZeroFS 是把一切关在桶里的 S3 文件系 统:不像 JuiceFS 依赖外部元数据引擎,它自己在对象存储上跑一套 LSM 树,且每个 对象都用卷数据密钥加密——该密钥由你的加密口令包裹(wrap)。快照与一致性 由后台 compaction 负责——没有要备份的数据库、没有要养活的 Redis。它经本地 9P 一跳再以 FUSE 挂载,日常使用与普通文件系统无异;而桶本身就是这个卷完整的、 加密的副本。
和 JuiceFS 一样,ZeroFS 是宿主二进制 addon——没有容器。
pg addon install zerofs 下载官方 release 二进制(sha256 校验;PATH 上已有
zerofs 则复用),自己写出卷的 config.toml,并运行两个宿主进程:
- server(
zerofs run -c config.toml)——掌管 S3 与加密侧,在 loopback 端口上讲 9P(默认 5564)。9P 没有认证,所以 pgcli 硬拒非 loopback 的--listen; - client(
zerofs mount 127.0.0.1:<port> <mount-point>)——你实际使用的 FUSE 挂载,server 重启时自动重连。
平台:仅 Linux(宿主 FUSE;与 BeeGFS 同样拒绝 macOS)。挂载点是普通宿主 目录,不会传播进 PG 实例容器。
一切全显式
对象存储是一个外部 S3 服务(云,或另一台机器上的 MinIO),在命令行上点名 ——pgcli 不做同主机 addon 的自动识别或凭据继承:
--s3-endpoint是裸的http(s)://host[:port](不带桶路径、不内嵌凭据); pgcli 在起 server 前先探一次,不可达的主机快速失败,而不是陷进 server 的 重试循环。--access-key/--secret-key必填,且必须成对。- 桶从不由 pgcli 创建——用
pg mc包装命令自己供给;安装时会原样打印那两条 命令。 - ZeroFS 会对请求签名,因此
--s3-region有效(可选——zerofs 自身默认us-east-1,多数 MinIO 兼容存储接受默认值)。
挂载点完全由你指定——默认落在 pgcli 的 addon 目录下,用 --mount-point 指到
任意位置。目录要你亲手建好(mkdir -p),且运行 pg 的用户对其有读写权限——
pgcli 从不创建挂载点:
目录不存在或不可写时,安装(以及之后的每次 mount)都会在下载和启动任何东
西之前失败,并给出逐字的 mkdir -p 补救命令。
两个后端都可以就用 pgcli 自己的服务——先用 pgcli 建好,再作为普通的"外部 URL"显式接线(安装代码从不自动查找它们;换成云桶或远端 Redis 也一模一样):
以上示例中 pg 与存储同机,loopback(默认 127.0.0.1)即可。zerofs 客户端
在别的机器上时,把存储发布到网络、--s3-endpoint 指向它的地址——端点写在
config.toml 里,之后要改就 --force 重渲染:
(redis 默认就绑 0.0.0.0——口令即门禁。注意这里说的只是 S3/redis 后端:
zerofs 自己的 9P --listen 必须保持 loopback——9P 没有认证。)
口令即数据
⚠️ 🔑
pg addon remove会销毁口令的唯一副本——动手前先存好。remove保留桶,但删除配置条目,而口令只活在那个条目和它的config.toml里。没有 原口令,被保留的桶就永远无法解读——不存在任何恢复途径。任何将来可能反悔的remove之前:pg addon password zerofs --name z1 > /某处安全的地方(放在 pgcli 目录之外)。
加密口令包裹着桶的数据加密密钥(DEK)。首次安装自动生成——随时取回:
丢了它,桶里的内容就无法恢复。这对 pg addon remove 尤其关键:它刻意保留
桶,但配置条目(连同口令的副本)没了——于是朴素的 reinstall 会生成新口
令,无法 unwrap 旧 DEK,server 起不来并报 Invalid password or corrupted key。要重新接上保留的桶,把原口令传回去:
(真要推倒重来:清空桶,或换一个 --bucket。)
Fencing:conditional put
ZeroFS 用 S3 conditional put(If-None-Match)对并发写者做 fencing。
--conditional-put 三选一:
| 模式 | 含义 |
|---|---|
auto(默认) |
用存储原生 If-None-Match——需要 MinIO RELEASE.2022-08+(pgcli 默认镜像满足)或真 S3 |
redis |
改经 Redis fencing——给不支持 conditional-put 的存储(如 silo);必须显式给 --redis-dsn redis://…(无同主机自动解析) |
none |
不 fencing——只在绝无他人碰这个桶时才安全 |
若 server 因存储缺少 conditional-put 支持而起不来,安装会识别日志特征并提示你
改用 --conditional-put redis --redis-dsn … 重试。
--redis-dsn 就是一个普通的 redis:// URL——DSN 会原样写进 config.toml,
任何 Redis 都行,包括 pgcli 自己的 redis addon(接法见上文示例;pg addon password redis 裸输出随机口令,/N 选逻辑库)。TLS 端点与 pgcli 其他处一
致:rediss://user:pass@redis-host:6380/1。
9P 端口每个实例独占:bind 撞车的 zerofs server 会静默启动、什么都不监听,所
以 install 和 start 对已被占用的 --port 直接拒绝——多卷并存请各给一个端口。
参数
| 参数 | 默认 | 说明 |
|---|---|---|
--name |
zerofs |
卷名(配置 map 的键) |
--s3-endpoint |
— | 必填。外部 S3 服务,形如 http(s)://host[:port] |
--s3-region |
zerofs 自身的 us-east-1 |
端点的 SigV4 region |
--bucket |
zerofs-<name> |
桶——pgcli 不创建 |
--access-key / --secret-key |
— | 必填且成对。S3 凭据 |
--encryption-password |
生成 | wrap 口令;重接保留的桶时传回原口令 |
--mount-point |
<base>/addon/zerofs/<name>/mnt |
挂载的宿主目录——pgcli 从不创建:先 mkdir -p 建好,且运行 pg 的用户可写 |
--cache-dir |
<base>/addon/zerofs/<name>/cache |
服务端磁盘缓存目录 |
--server-cache-gb |
100 | 服务端缓存大小(GiB) |
--listen |
127.0.0.1 |
9P 绑定地址——必须 loopback(9P 无认证) |
--port |
5564 | 9P 端口(已有应答者时直接拒绝——每个 zerofs 实例一个) |
--conditional-put |
auto |
auto / redis / none(见 Fencing) |
--redis-dsn |
— | Redis fence 后端,--conditional-put redis 时必填 |
--install-dir |
/usr/local/bin |
宿主二进制落点(不可写退到 ~/.local/bin) |
--version |
内置 pin(2.3.5) |
要下载的版本(摘要已 pin 在 pgcli 源码里) |
--no-mount |
关 | 写好配置、起好 server,但不挂载 |
--force |
关 | 重渲染 config.toml 并重启——保留存的加密口令(新口令无法 unwrap 既有数据) |
FUSE(/dev/fuse + fusermount3)只探测、不安装。
日常管理
config.toml、server/client 日志与 pid 文件都在 <base>/addon/zerofs/<name>/
下;口令与 S3 密钥放在 0600 的 config.toml 里——同时,和 pgcli 所有 addon
凭据一样,也明文存在于你的 pg.yaml。
换挂载路径的做法与 JuiceFS 完全一致:先 umount,用
mkdir -p 把新目录建好(可写——与安装契约相同),再带覆盖参数挂载;新路径
会持久化进 pg.yaml,之后的普通 mount(含 autostart)都用它:
仍在挂载时尝试迁移会被拒绝并提示先 umount;FUSE 挂载点与 pgcli 的簿记完全
解耦(9P server 照常跑在自己的端口上,config.toml/日志/pid 始终在
<base>/addon/zerofs/<name>/),迁移从不触碰卷本身。
开机自启
开机时 pg start --autostart 先起 9P server(等端口监听)再起 FUSE
client。后端是外部服务——只有 S3 端点重新可达时开机才能成功。不重渲染、不重
生成:既有的 config.toml 与存的口令原样复用。