Silo
silo 是 Pigsty 社区维护的 MinIO 分支:S3 兼容对象
存储、内置 Web 控制台,并完整保留了 MinIO 的对外契约——S3 API、MINIO_*
环境变量、server /data --address :9000 --console-address :9001 命令行、
--certs-dir 目录布局、以及纠删码集群模式。pgcli 将其作为独立的顶层插件
运行,功能面与 minio 插件 完全一致——install、TLS、BYO 证书、
分布式模式、logs、autostart 一一对应。如果你跟随 Pigsty 的发布节奏就选 silo;
两者可以在同一台主机并存(共用一个端口池,统一游标分配,不会冲突)。
平台支持: silo 插件两个平台都支持。Linux 上通过主机网络提供服务; macOS 上加入
pgcli-netbridge 网络并发布两个端口,Mac 用127.0.0.1:<port>即可访问 API 与控制台。公开镜像为双架构(amd64 + arm64)。两个客户端——pg mcli(silo 自带)与pg mc(MinIO 的)——也都双平台可用,且都能 直连 silo 存储。
工作原理
一个容器、一个目录:silo server /data --address <listen>:<api-port> --console-address <listen>:<console-port>,其中 /data 是实例主机数据目录
(默认 <base-dir>/addon/silo/<name>/data)的 bind mount。silo 存储的一切
都在这个目录里,因此它的生命周期长于容器。
镜像是公开的官方 tag docker.io/pgsty/silo:RELEASE.2026-09-16T00-00-00Z——
双架构、控制台内置、并且连 mcli 客户端一起打包——所以 pg addon install silo 只负责拉取;pgcli 运行时从不构建镜像(pgcli-minio 是自建 tag,因为
MinIO 官方镜像移除了控制台,silo 没有这个问题)。pgcli 通过显式
--entrypoint silo 直接驱动 silo 二进制,绕开镜像自带的 entrypoint 包装
脚本,与驱动 MinIO 的方式一致。
凭据的处理方式与 Patroni 相同:
root_user默认admin;root_password首次 install 时自动生成(也可以用--root-password显式指定),存入pg.yaml(addons.silo.<name>.root_password),并在安装摘要中打印一次方便记录。
二者就是 silo root 的 access key / secret key——经由 silo 从 MinIO 继承的
MINIO_ROOT_USER / MINIO_ROOT_PASSWORD 环境变量传入——所有 S3 客户端(包括
pg mcli alias set <名称> <URL> <root_user> <root_password>)所说的 access
key 与 secret key 就是它们。
容器按 MinIO 官方部署建议(契约原样沿用)带上 --ulimit nofile=1048576:1048576 和 --stop-timeout 60;macOS 上 podman machine
虚拟机的 RLIMIT_NOFILE 上限更低,因此该平台改用 65536——单机 dev/test
足够。root 凭据通过 -e 传入会出现在 podman inspect 里——与手工运行容器的
暴露程度相同;对 rootless 单机部署(本插件的定位)可以接受。
安装
输出会报告端点与 root 凭据:
用打印出的 root 用户和密码登录 Console: URL 的控制台。S3 客户端(包括
pgBackRest)指向 S3 API: URL,或在终端里用下文的
pg mcli 操作。
对存活实例重复执行 install 是 no-op:容器不会被重建(已停止的会直接启动
并给出提示),命令行参数会合并进已存储的配置,root 密码保持不变。想改端口、
监听地址、endpoint 列表或凭据,用 --force 重建容器——数据目录不会丢。
绑定地址: 默认
127.0.0.1让存储保持本地可见。--listen 0.0.0.0(或pg.yaml里的listen键)会把它暴露到网络。届时任何能连到端口的 人都可以尝试 root 凭据,所以只在防火墙后面、或配合 TLS(下述--tls) 使用。
TLS(--tls)
--tls 让 silo 以 HTTPS 提供服务。pgcli 用标准库生成自签 CA 与叶子证书——
SAN 覆盖回环名、localhost 和主机的所有网卡 IP——写入
<base_dir>/tls/silo/<name>/:public.crt / private.key 供 silo 的
--certs-dir 使用,ca.crt 用于分发。证书目录以只读方式挂载,端点 URL
变为 https://。
为什么需要它:pgBackRest 对 S3 仓库强制 HTTPS(明文是上游明确拒绝的
选项),所以用于接收 Patroni archive-push 的 silo 必须讲 TLS。把
backup.repo.s3.ca_file 指向 ca.crt,pgBackRest 就会做完整证书验证——见
备份 → S3 对象存储仓库。该页
关于 MinIO 仓库的一切对 silo 同样逐字适用:客户端契约完全相同。
关于存储与集群配对的一点:backup.repo.s3 每个配置文件只有一个全局仓库,
所以第一个接入的 TLS 存储(无论 minio 还是 silo)会接收该环境下所有
stanza。确实需要两个目的地时,请再维护一份配置(见
备份 → 共享备份容器,以及完整示例
HA 集群 + 自签 CA MinIO)。
pg mcli 在命令通过回环 alias 访问 TLS 存储时自动加 --insecure(mcli
不会按 alias 持久化 CA 信任;同机回环下这样可接受)。指向局域网 IP 的 alias
不算回环——自己补 -- --insecure,或正规配置 CA。外部 https:// 端点保持
完整验证。对已有实例切换 --tls 需要 --force 才生效。
有效期与其他主机的访问。 CA 与叶子证书都是长生命周期;pgcli 在
--force 时、或主机地址变化时重新签发叶子(silo 监视证书文件并热加载重新
签名的一对,部署因此无需重建即可拿到新链),所以把 ca.crt 交给客户端是
每个存储一次性的动作。TLS 客户端用自己拨出的地址校验叶子证书的 SAN——
客户端自身的地址无关紧要。远程主机因此把 backup.repo.s3.endpoint 指向存储
主机的某个 IP(回环名与所有网卡 IP、含虚拟网桥,都在 SAN 里;裸主机名不在
——除非设置 MINIO_SERVER_URL,其 host 会被加入)。
把 CA 拿到远程主机上——不需要 scp。 服务端证书以叶子+CA 链的形式提供, 另一台机器上的消费方可以直接从 TLS 握手中取回根证书:
此取回是 trust-on-first-use——先与存储主机上 sha256sum ~/.pgcli/tls/silo/<name>/ca.crt 比对指纹再信任。随后一次 setup 会把 CA
重新发布进 Patroni 集群的 etcd 注册表,其他集群主机零手工步骤即可获得
(见备份 → S3 对象存储仓库)。
自带证书(--tls-cert / --tls-key)
--tls 永远只服务 pgcli 自签的一对。要服务你已有的证书——公共 CA 为真实
域名签发的、或你的私有 CA 签发的——改用 --tls-cert <leaf(+chain).pem> --tls-key <key.pem>。它隐含 --tls(无需重复传),取代生成的证书:两个文件
以只读方式直接挂到 silo --certs-dir 要求的文件名上
(/opt/silo/certs/public.crt、/opt/silo/certs/private.key),pgcli 从不
复制或重签——私钥始终只在你放置的那一个位置。
BYO 模式的其余一切——install 校验什么、为什么续期必须 --force(单文件
挂载锁定源 inode)、客户端如何选取信任锚、以及用 pg cert 生成测试证书——
与 MinIO 插件完全相同,见
MinIO → 使用自带证书。pg cert 示例
改写如下:
关闭 BYO。 没有 off 开关——跨重跑的 config 合并是单向的,与 --tls
本身一致。要回到生成模式,删除 pg.yaml 里该插件下的
cert_file/key_file,再 pg addon install silo --name store --force 重建。
部署形态
silo/MinIO 对自身的部署布局有明确分类;本插件四种全部支持:
| 形态 | 结构 | 适用场景 |
|---|---|---|
| SNSD(单机单盘) | 单节点、单个数据目录——不给 --endpoint 也不给 --drive 时的默认 |
开发、测试、演示 |
| SNMD(单机多盘) | 单节点、多块盘——每个 --drive 传一块盘,见下文 SNMD |
单机部署要扛住坏盘,又不想额外搭文件系统层 |
| MNSD(多机单盘) | 多节点、每节点一块数据盘——即下文的分布式模式 | 紧凑的高可用部署 |
| MNMD(多机多盘) | 多节点、每节点多块盘——--drive 传本节点的盘,--endpoint 传全集群矩阵 |
既要扛坏盘、又要扛坏机,且不额外搭文件系统层 |
pg addon install silo 开箱即是 SNSD。要得到 MNSD,传入集群的
endpoint 列表(至少四节点)——见下文分布式 / 集群模式。
MNMD 把两个 flag 组合起来:--drive 传本节点的盘(与 SNMD 完全一致),
--endpoint 传整个集群的 host×drive 端点矩阵(每台每个盘各一条 URL)——
见下文多机多盘(MNMD)。SNSD/MNSD 下的磁盘冗余另一条路仍然
可用——把 ZFS 池垫在 --data-dir 底下——它能让底层布局随时可换,空间利用上
也往往更省。S3 存储高可用方案 对比了原生
MNMD 与 ZFS 两条路,也覆盖"4 主机、每主机多块盘"这个既能扛坏盘又能扛坏机的
混合形态。
单机多盘(SNMD)
一个 silo 进程、多个宿主目录、盘之间做纠删码。每个 --drive 传一块盘,替代
--data-dir:
每个 --drive 是一块独立设备上的宿主目录;第 N 块盘挂到容器路径
/dataN,服务进程以 silo server /data1 /data2 ... /dataN 启动。--drive
与 --data-dir 互斥——多盘模式的数据位置只由 --drive 决定;--drive 再加
上 --endpoint 就是 MNMD,即多盘模式的多机版本,见下文多机多盘
(MNMD)。和 silo/MinIO 所有盘一样,与宿主根设备共享的盘会
在启动时被拒绝;pgcli 会列出越界的盘、在 install 时给出警告。
EC 换来什么(在活的 4 盘 silo 集上实测):4 盘集默认 2 片校验——可容忍 2 块盘故障。坏 1 块盘时读写都照常;坏 2 块盘时读仍成功、写被拒——这就是 quorum 边界,和 MNSD 用的是同一套算术,只不过成员是盘而不是节点。可用容量约 为原始总量的一半。回来的盘由 silo 自己 heal,pgcli 无需介入。校验片默认值随 盘数变化——本文只实测了 4 盘这一种形状。
pg addon remove silo --name store --clean-data 会删除每一块盘的目录——但
拒删仍处于挂载状态的盘,所以一次误操作的 --clean-data 绝不会穿透挂载点把
底下的盘 rm -rf 掉。真要丢弃下面的数据,先 umount。
分布式 / 集群模式
silo 的纠删码(EC)集群模式与 MinIO 完全一致——命令形状相同,规则也相同。
它要求至少四个互不相同的 host:port endpoint,且与其他插件不同,没有
中心协调者:每个节点各自运行 pgcli 和各自的 pg.yaml,每一份 pg.yaml
携带相同的完整 endpoint 列表与相同的 root 凭据。pgcli 只为本节点的容器
执行启动——组环的握手由 silo 自己跨主机完成。
三条硬性规则(endpoint 必须可路由且互不相同、数据目录必须位于与根文件系统
分离的磁盘——否则 pgcli 在 install 时告警、集群模式下不设置逐节点的
MINIO_SERVER_URL)以及 quorum 计算,与
MinIO → 分布式 / 集群模式相同;silo 因为继承
了这些检查,执行得同样严格。
多机多盘(MNMD)
MNMD 与 MinIO 下的做法完全一致:用 --drive 传本节点的盘,用 --endpoint
传整个集群的 host×drive 端点矩阵——每台、每个盘各一条 URL。每个端点必须指
名该节点的一个 /data1../dataN 盘槽,矩阵长度必须是每节点盘数的整数倍且至少
包含一台远端节点,--tls 节点的端点必须全部是 https://——这四项 pgcli 都会
在启动容器前检查。完整步骤见
MinIO → 多机多盘(MNMD)。
在活体的 4 节点 × 4 盘 silo 集(16 × 2 GiB)上实测到的形状与 MinIO 一致:
16 块盘在线,EC:4,位于单个 stripe 大小为 16 的纠删码集合里;损失一整台
节点(12/16 在线)时读和写都照常工作,64 MiB 往返逐字节一致;再损失第二台
节点(8/16 在线)时写被拒(Resource requested is unwritable)、读也失败,
节点重启后集合自愈回 16/16。16 盘 EC:4 保留原始字节的 12/16。
TLS 集群的推荐与 MinIO 下一条完全一致——一张 pg cert 叶子、SAN 覆盖所有节
点地址、每个节点 --tls-cert/--tls-key 同一对文件——并在 silo 上按与 minio
相同的方式验证过:grid 直接成环,没有逐节点 CA 需要对齐。配法见
MinIO → 多机多盘(MNMD)。
使用 mcli 客户端
pg mcli 从 pgsty/silo 镜像(经 --entrypoint mcli 选择——镜像默认
entrypoint 起的是服务端)在一次性容器里运行 silo 自带的 mcli 客户端——本机
零安装:
mcli 与 mc 的 alias 契约相同,因此互通——对 silo 存储、MinIO 存储或任何 S3
端点都可用。pgcli 有意把两个客户端指向同一个文件:alias 持久化在主机
~/.mc/config.json(mc 的原生默认路径),所以 pg mc 注册的 alias 对
pg mcli 同样可见,反之亦然——只设一次,不必每个客户端各设一次(无状态的
MC_HOST_<name> 形式两边也都识别)。原生 mcli 若按自身默认运行则读
~/.mcli/config.json,除非把 MC_CONFIG_DIR 指过去,否则看不到这个共享文件。
alias set 在写入前会对端点校验凭据,密码错误时配置文件保持不变。cp /
mirror / diff 的本地路径参数会按真实绝对路径解析并挂载,与 pg mc 行为
一致(macOS 上请保持在 home 目录内)。会被 pg 自身解析器拒绝的 mcli
参数放到 -- 之后:
两个客户端共用 MinIO 页面记录的命令表——
常用命令——把 pg mc 换成 pg mcli 即可。
端口
每个实例从一个池中取两个连续端口,起点为 minio_start_port(默认
9000):先 S3 API,后控制台。该池与 minio 插件共享——minio 与 silo
实例在同一游标上分配,同机并存不冲突;先 minio 表(按名称),后 silo 表:
配置
实例位于 pg.yaml 顶层 addons.silo 映射,以实例名为键:
对 listen、端口、root_user、root_password、image_tag、data_dir、
tls/cert_file/key_file 或 endpoints 的修改,在下一次
pg addon install silo --name store --force 后生效——普通 install 会跳过仍
存在的容器,--force 重建它(数据目录永不触碰)。
查看列表
pg addon list 永不打印密码——从 pg.yaml 读取。
启停
主机重启后,不重新应用配置地拉回实例:
install 跳过仍存在的容器(已停止的则启动);start 只启动已存在的容器
(状态异常时依配置重建自愈)。TLS 生成模式下 start 还会重新校验、必要时
重签叶子证书(silo 热加载挂载的证书)。
开机自启
容器带有 --restart unless-stopped 策略(管崩溃,不管重启)。要在主机重启
后拉起实例:
这会设置 autostart: true 并安装/刷新 boot service(见
开机自启)。boot 是只启动的。silo 独立于 PostgreSQL
栈,因此排在最后启动;无顺序约束。pg autostart status 列出所有目标的状态。
删除
数据目录就是对象存储——丢了它等于丢掉其中所有 bucket——所以 remove
默认保留并打印其位置。--clean-data 删除它(并清理默认为空的默认布局父
目录;data_dir 覆盖路径及其父目录永不触碰)。
日志
silo 输出到 stdout:启动行(API:/Console: 地址、Documentation:)与请求
错误。API: http://... 块确认监听已就绪。
故障排查
- install 报
pulling silo image ... : ...。 公开 tagdocker.io/pgsty/silo:RELEASE.2026-09-16T00-00-00Z不可达——检查到 docker.io 的网络/registry 访问,或用podman pull预先拉取。 - 手工
--api-port撞端口。 选择自动池(minio_start_port及以上) 之外的端口,否则自动分配器会视其为已占用;该池与 minio 插件共享,所以 silo 实例也要避开 minio 实例的显式端口,反之亦然。每个存储都需要一对 连续端口。 - 主机重启后
pg addon start无效 / 失败。 看pg logs addon silo --name store -f——多半是数据目录被删(--clean-data或手工),silo 拒绝在曾格式化过的空目录上启动;或绑定端口变了。 - 控制台可访问但 S3 客户端超时。
MINIO_SERVER_URL由listen+ API 端口构成;绑127.0.0.1却从其他主机访问时,客户端会被重定向到回环 URL。把listen设成客户端真正可达的地址。(集群模式完全不设MINIO_SERVER_URL。) - 用
pg mc设的 alias 在pg mcli里看不到(或反之)。 两者按设计共 享~/.mc/config.json,出现这种情况说明 alias 确实没写进去——pg mc alias list(同一文件)核对一下,或用环境变量传MC_HOST_<name>。原生 mcli 读 的是~/.mcli,不指MC_CONFIG_DIR就看不到这个共享文件。 - macOS。 受支持:插件在
pgcli-netbridge 上服务并发布两个端口,Mac 的127.0.0.1:<port>即可访问(容器内部绑0.0.0.0,MINIO_SERVER_URL声明 Mac 使用的回环地址)。改端口/凭据后--force重建容器。pg mcli的容器不能用127.0.0.1alias——见 MinIO mc 页的 端点说明。