跳转到主要内容

这是本节的多页打印视图。 .

返回本页常规视图.

兼容性

SILO 能否直接替换 MinIO?按用户影响分为 12 类兼容或改进、4 类轻微差异、8 类需要按条件检查的变化。

普通 S3 应用通常可以不改代码,用 SILO 替换 MinIO。 常用 S3 API、SigV4、SDK 接入方式和对象磁盘布局延续上游;部署、权限及复制状态需要按下列条件检查。因此,SILO 是有条件的 drop-in replacement。

当前发布基线为 20261026。 本页汇总分叉以来的源码与配套组件变化,标明各项修复首次发布的版本。当前组件组合与旧版缺失的修复见组件版本矩阵。

20261026 正式版变化

Server 20261026合入了 LDAP 长 DN 登录、内置策略 Reset、实时桶清单、版本桶生命周期过期、分片复制及多池删除修复。读仲裁与自愈策略保持不变;租约失效、部分元数据更新与存量不一致对象的边界详见组件版本矩阵。

20261018 正式发布

Server 20261026保留 20261018 已交付的修复。升级检查包括 Object Lock、IAM 管理凭据授权、普通 LIST 恢复、strict 分片列表退役及 OIDC/JWK 密钥限制,见服务端兼容性。下方列出的 strict 前提仅适用于 Server 20260916 的可选模式。

🟢 兼容或改进:12 类

这些能力在正常用法下无需迁移适配;依赖旧错误行为、混合版本或历史异常状态的情况另列于橙色项。

类别与一句话变化 触发条件 影响范围与操作 详情索引
G01 · 完整 Web 管理控制台
恢复桶、对象、用户、策略和系统的完整 Web 管理。
通过浏览器管理部署。 管理界面增强;普通 S3 应用无需改动。 Console 功能
G02 · 中文界面与文本预览
增加中英双语和有界、安全的文本预览。
切换界面语言或预览文本对象。 影响 Console 使用体验,不改变对象内容。 双语界面、文本预览
G03 · 桶级 CORS
原有 CORS 接口开始实际保存和执行逐桶跨域规则。
浏览器跨域访问,并配置了桶级 CORS。 该桶规则覆盖全局 CORS;对象访问仍需授权。 CORS 行为
G04 · 原生健康检查
新增 silo healthcheck 命令,便于容器和运维探测。
主动采用新探针命令。 原有 HTTP 健康端点继续可用。 命令与范围
G05 · 客户端校验和审计
新增 mcli checksum verify,读取对象并核验校验和。
主动运行完整性审计。 只读检查和报告,不修改或修复对象。 审计命令
G06 · 上传与复制校验和修复
合法上传、分片完成和复制更准确地计算、保存及返回校验和。
使用相关上传或复制路径。 改善 SDK 互操作;非法请求的变化见 O04。 分片上传、S3 修复
G07 · 加密与压缩处理修复
修正 SSE-C、KMS、压缩与复制组合中的数据及逻辑大小处理。
使用这些加密、压缩或复制组合。 修正新请求,不修改存量对象。 SSE-C 与历史对象、联邦复制
G08 · 桶配置并发更新修复
桶配置共用元数据锁,防止并发更新互相覆盖。
同时修改策略、生命周期、加密等桶配置。 管理操作更可靠,现有调用方式不变。 共享配置锁
G09 · 标签与对象锁复制修复
复制更准确地保留并排序标签、保留期与锁状态。
使用标签、Object Lock 的复制或修复。 减少状态丢失与旧事件覆盖;混合版本见 O07。 标签排序、对象锁排序
G10 · 池迁移与数据修复改进
再平衡、退役及修复更准确地处理标签、版本和删除标记。
迁移存储池、执行 heal 或恢复复制。 改善元数据保留与重试;历史异常仍需检查。 多池一致性、复制恢复
G11 · 通知与流式推送修复
修正 NATS/AMQP 配置识别,以及通知、Select 等流式响应刷新。
使用相应通知目标或流式接口。 配置与事件输出更准确;旧数据库配置见 O03。 通知配置、流式响应
G12 · 运行稳定性与资源回收
修复并发采集、缓冲区所有权和连接回收等问题。
并发读写、指标采集或取消请求。 消除相关崩溃与资源泄漏。 读缓冲修复、运行与观测

🔵 轻微差异:4 类

普通应用通常无需调整;硬编码产品文案、指标含义或响应字段的工具仍应检查。

类别与一句话变化 触发条件 影响范围与操作 详情索引
B01 · 产品名称与展示标识
横幅、日志、HTTP 产品身份及界面展示改为 SILO。
阅读输出,或按产品名称匹配规则。 展示变化;硬编码名称的脚本需调整,安装变化见 O01。 身份变化、客户端输出
B02 · 控制台列表改为分页
对象列表按游标加载,排序、筛选和选择作用于当前页。
在 Console 浏览、筛选或批量选择对象。 操作习惯有变化,应用直接调用 S3 的方式不变。 分页边界
B03 · 监控与诊断信息更完整
新增诊断指标,并修正配额、复制等计数或状态含义。
使用对应指标、仪表盘或告警。 原指标命名空间保留;核对相关展示和告警规则。 指标变化、Console 指标
B04 · API 返回字段更丰富
部分复制、分片和 Console 响应增加校验和或会话字段。
读取这些 API 的返回结果。 标准客户端通常可处理;拒绝未知字段的解析器见 O05。 分片响应、复制响应、Console API

🟠 按条件检查:8 类

命中条件,就检查对应项。

类别与一句话变化 触发条件 影响范围与操作 详情索引
O01 · 安装与启动配置
交付物改名为 silo / mcli,需核对服务、镜像、目录和权限。
从 MinIO 软件包、容器、systemd 或 Helm 迁移。 管理员执行一次部署迁移检查,通常不改业务代码。 容器迁移、软件包与账号、客户端配置
O02 · 自定义权限策略
改密、永久删除版本及部分桶操作采用修正后的授权规则。
自定义 Allow/Deny、对象 ARN 授权桶操作,或使用来源 IP 条件。 谁能做什么可能变化;验证有效权限和代理信任配置。 密码权限、版本删除、桶授权、代理信任
O03 · 旧认证及通知配置
旧式认证、数据库通知及部分 TLS、环境文件用法需调整或验证。
OIDC HMAC token、旧数据库分散参数、老代理/TLS 或特殊环境文件写法。 可能影响登录、通知或启动;按对应配置迁移。 OIDC 算法、通知连接串、TLS、环境文件
O04 · 依赖旧错误行为的程序
校验、条件、错误码、退出码和列表上限不再沿用部分旧行为。
依赖错误请求成功、忽略 If-Match,或启用 Server 20260916 strict 模式后仍假设分片列表一次超过 1,000 条。 检查错误处理、重试、分页与批处理的最终退出码。 校验错误、条件删除、分片列表、CLI 退出码
O05 · 自制客户端与管理工具
私有接口、签名覆盖、Console 自动化及 Go 包路径存在变化。
使用 ReadMultiple、手写签名、严格响应解析、Go 嵌入或定制 Console。 定制集成和编译需单独验证;普通 S3 SDK 不使用私有存储接口。 私有接口、签名、Console API、Go 模块
O06 · 多池操作与 strict 分片模式退役
多池写删核实元数据;20260916 的可选 strict 列表模式已退役。
多池条件写/删除,或升级曾启用 strict 列表的部署。 故障时可能返回 503,即使 GET 仍成功;Server 20261018 与 20261026 忽略 strict 开关并警告,不提供持久列表与严格取消。 多池条件、当前分片契约
O07 · 跨站复制、混跑和回滚
IAM 撤销与桶配置删除状态要求协调升级和恢复。
多站点、共享 IAM、不同版本混跑或降级恢复。 保留完整恢复点并在回滚时同步恢复所有参与端。 IAM 升级、配置收敛、回滚边界
O08 · 自更新及上游在线服务
原地自更新、SUBNET 与上游托管支持集成被停用。
使用 admin update、mcli update 或 MinIO 在线支持流程。 改用软件包、镜像或编排器升级;常规 S3 访问不受此项影响。 服务端更新、客户端更新、SUBNET

比较范围与版本边界

服务端对照的是分叉时的上游源码 27742d469462(2025-12-03,位于 2025-10-15 上游最后正式发行版标签之后)。Console、mcli 的各自基线见控制台说明与客户端说明。本页覆盖 API、功能、可见行为与运维变化,同一修复可涉及多个场景。

SILO 对上游 MinIO/MC 保持尽最大努力兼容;正式支持和发布验收的组合为 SILO + SILO Console + mcli + silo-pkg。保留协议、环境变量和磁盘布局,不构成任意上游版本混跑或双向降级的承诺。服务端详细审计保留历史基线和逐项说明,组件版本矩阵列出全栈已发布组件版本。

曾加入后撤回的访问频率池间分层不属于上述 24 类:它不在分叉时的上游功能中,也从未进入任何公开 Server 版本:20260903 早于该特性,20260916 发布前已将其移除。普通生命周期过期、远程分层、再平衡和池退役仍然保留。

准备迁移时,从 O01–O08 筛选与你有关的条件,再按迁移指南执行。

1 - 组件版本

SILO 各组件的正式版本、独立发布的 mcli 20261109、silo-pkg 3.16.0 与升级边界。

SILO 20261026 是当前正式服务端版本,内嵌 Console 2.5.1、mcli 20261026 与 silo-pkg 3.15.2。最新独立客户端为 mcli 20261109。KES 20261026 是独立、可选的外部密钥服务。正式支持维护的 PGSTY 组件组合,对原厂 MinIO/MC 尽最大努力兼容。

独立 Console

最新正式发布的独立 Console 为 2.7.0, 源码提交为 4e91ae506e706ccdecb512b1d8b5ab4d9871d505。 该版本加入十种界面语言、阿拉伯语 RTL、容器 CA/临时目录修复,以及用量后台任务、普通 HTTP 与上传修复, 使用 Go 1.27.3、silo-pkg v3.16.0 与正式 mcli 20261109(Go 伪版本 v0.0.0-20261109021353-e1d4cc5abfe0)。 2.6.0(源码 f8ab146695fd1df74e4b84128a286d552921bf00)加入了用量扫描、保留版本统计与存储桶管理修复。 Server 20261026 仍内嵌 Console 2.5.1,采用新版源码需要单独发布 Server。

mcli 20261109

独立客户端发布使用 tag RELEASE.2026-11-09T00-00-00Z,包版本为 20261109000000.0.0,源码为 e1d4cc5abfe00b674eb36347399e7398990be467。 该版本使用 Go 1.27.3、silo-pkg v3.16.0 与上游 minio-go v7.4.2-0.20261025165926-320af050c445 构建。既有 Server 与 Console 制品保留各自内嵌的客户端版本,需重新构建才能采用新客户端。

共享包 v3.16.0

silo-pkg v3.16.0 是独立的源码库发布,要求 Go 1.27.3。该版本更新 JOSE、网络、CPU 检测与 YAML 依赖,保持公开 API 和策略语义兼容。应用需选择 github.com/pgsty/silo-pkg/v3 v3.16.0 并重新构建。 下列历史应用制品仍包含各自原有的依赖版本;库发布不会更新这些制品。

20261026 正式组件

组件 正式版本 固定源码 / 模块
Server RELEASE.2026-10-26T00-00-00Z c3ad836aed0d8a7d23c2e44a5eaa3009d08525e3
内嵌与独立 Console v2.5.1 v0.0.0-20261026153924-fff1618d9abb
mcli / MC 模块 RELEASE.2026-10-26T00-00-00Z v0.0.0-20261026120214-0ceb298cdcd0
公共包 github.com/pgsty/silo-pkg/v3 v3.15.2 0416eb1f450536ca2cc3592c2c2a06a3df88d4e0
上游 S3 SDK github.com/minio/minio-go/v7 v7.4.2-0.20261025165926-320af050c445
可选 KES RELEASE.2026-10-26T00-00-00Z e9b4f1acebc11d61b42f876da8df48f548750cc9
Go / 平台归档 Go 1.27.3 Windows ZIP;Linux/macOS tar.gz

20261026 的 Server、mcli 与 KES 制品使用软件包版本号 20261026000000.0.0。单独升级独立部署的 Console 不会替换旧版 Server 内嵌的控制台或服务端逻辑;内置策略 Reset、实时存储桶清单、生命周期过期与复制修复均需配合 Server 20261026 生效。

三合一发布日志 · Console 2.5 · pkg 3.15 · 升级检查 · 下载

官方容器镜像发布于 Docker Hub:pgsty/silo、pgsty/mc、pgsty/silo-console 与 pgsty/kes(软件源镜像同步可能略晚于 GitHub Release)。下文保留各历史版本的依赖矩阵,供升级与回滚核对。

Server 20261018 正式发布

目标标签为 RELEASE.2026-10-18T00-00-00Z,包版本为 20261018000000.0.0,选定源码为 0cd388c66。GitHub Release 已正式发布,匿名下载与 Docker Hub 镜像于 2026-10-19 完成核验。完整功能、安全、兼容性与剩余限制见 20261018 发布说明。

20261015 保留为历史未发布草稿,由 20261018 正式版取代并交付 10 月的 Object Lock、IAM 与 LIST 修复(Server 20260916 不含这些修复)。

10 月组件依赖图

组件 Server 20261018 选用版本
嵌入式 Console v2.4.2,v0.0.0-20261017112417-ef2dd2c41d21
MC 模块/镜像内置 mcli 20261018,v0.0.0-20261017101407-fa3b8bf72458
Server 共享包 github.com/pgsty/silo-pkg/v3 v3.14.3
上游 S3 SDK github.com/minio/minio-go/v7 v7.4.1
构建工具链 Go 1.27.2;Console 前端使用 Node 24.22.0 LTS

历史版本 Console v2.4.2 与 mcli 20261018 声明 pkg v3.14.2;Server 的模块图选用 v3.14.3。v3.14.2 的依赖更新与 v3.14.3 的 admin action 分类优化保持 API、策略格式和授权语义。Server 必须显式选择 Console 与 MC 的 replacement,Go 不会继承依赖的替换配置。正式支持 PGSTY 四组件组合,对原厂 MinIO/MC 兼容尽最大努力。

9 月 16 日依赖图

Console v2.4.1 选择以下已发布的 pkg 与 MC 源码, 各模块身份已通过公共 Go proxy 与校验和数据库验证。

  • Console: v0.0.0-20260916075814-1360e26d976d → 1360e26d976d,标签 v2.4.1。
  • pkg: v3.14.1 → fa657ef431ae22e720df37e5144cf00f67102945。
  • MC: v0.0.0-20260916070421-e952aa78f10a → e952aa78f10a,标签 RELEASE.2026-09-16T00-00-00Z。
  • 上游 minio-go: v7.3.1-0.20260915093545-32e1f32cb176。
  • JWX / strfmt / React Router: v3.3.0 / v0.27.2 / v7.18.4。

Console 嵌入前端已按此依赖图重新构建。历史 Go 模块路径没有 /v2 后缀, 所以通过规范伪版本引用 Console。Server 嵌入方必须同时复制 Console 与 MC replacement, 见Console 集成说明。

升级前请检查密码权限迁移: admin:ChangeMyPassword 与 admin:CreateUser 分别控制不同操作。 Server changelog 和下列源码链接 说明协调升级 Server 时涉及的存储、IAM 与 HTTP 变化。

存储、IAM 与 HTTP 修复

以下改动已随 Server 20260916 发布;Server 20260903 不包含这些修复。实现范围可通过所链接的 PR 与源码记录核对。

范围 已合并 PR 运维可见行为
多池存储 #188
#189
普通单对象版本 DELETE 协调各池副本,副本协调保留标签状态;移除可选的 GET 访问频率池间分层功能。
分片完成条件 #190 前置条件使用所有池中的逻辑最新对象,避免旧副本接受过期 ETag,或拒绝当前 ETag。
分片发现与取消 #198
#213
Server 20260916 默认使用 legacy 列举与取消。显式启用严格模式后,跨 pool/set 发现持久上传、在原生 marker 对应上传消失后继续分页,并要求多数盘确认取消。严格模式要求所有 writer 升级并排空旧上传,见升级契约。
普通条件 PUT #207 公开写入条件使用所有池中的逻辑当前对象,包括正在退役或再平衡的池;可读性及目标版本行为变化见下文。
IAM 撤销 #191
#192
节点间删除通知重新加载已提交状态;持久化删除版本与撤销边界,防止旧站点事件重放恢复已撤销身份或旧授权。
标签与删除标记 #193
#196
SSE-KMS 复制保留标签修订时间;删除标签推进修订并抵御延迟事件;删除标记清除在 MRF 恢复时保留标记身份和重试状态。
删除标记清除 eb4f5e5b3
254b19ac0
358ab38fb
指定版本的清除不再在缺少该标记的盘上创建标记;对已缺失版本的重试须有写仲裁多数的缺失票才确认;heal 后的标记保留复制与清除元数据;排队中的标记创建任务在发送前先在复制锁内复核源端。剩余边界见下文、#217 与复制可靠性记录第三轮。
盘间分歧下的列举 8d06424b1 当更新的少数盘排在前面时,仍保留达到列举仲裁的 null 对象版本。滚动重启叠加并发覆盖写时,成功的 LIST 仍可能漏掉可读的 key;见下文、#218 与设计记录。
跨池迁移标签 fced86303 rebalance 与 decommission 对普通和分片写入都把对象标签及其修订字段带到目标池。此前迁移已丢失的标签不会恢复;见多池对象一致性。
复制元数据 #194 恢复复制元数据时,不再把传输用的 aws-chunked 编码重新写入对象元数据。
请求头超时 #196 --read-header-timeout / MINIO_READ_HEADER_TIMEOUT 正确传入 HTTP 服务,对 HTTP/1 请求头设置绝对读取期限,持续少量发送字节也无法延长;正文保留既有滚动空闲超时。

升级与兼容性要求:

  • IAM 要求所有参与服务器协调升级。 不支持共享 IAM 后端的新旧节点混用,也不支持滚动降级。备份完整 IAM 存储及所需加密材料,普通管理导出不包含删除历史。同名父身份重建前签发的旧凭据可能需要重新签发;升级前已经丢失的删除历史无法自动重建。具体操作见 IAM 升级与回滚说明。
  • 不可读池会更一致地使写入、删除失败。 即使另一个池还能处理 GET/HEAD,只要任一池元数据不可读,条件式分片上传完成就会失败。普通版本 DELETE 在池不可读或清理失败时也返回错误;读取仲裁不足返回 503 SlowDownRead,应在恢复后重试。出站删除复制尚未完成时,请求成功不代表每块磁盘都已立即物理删除。
  • Server 20260903 从未包含访问频率池间分层。 只有使用过该实验功能的构建需要按迁移说明清理配置和 XML。普通生命周期过期、远程层迁移、再平衡与池退役仍可使用。
  • 清除操作的审计状态由 COMPLETE 规范为 COMPLETED。历史异常标签修订可能失败并重试,本次修复不会重建其历史。较短的请求头超时也会限制 TLS 握手读取窗口;它不会给 HTTP/1 上传、下载新增总时长限制。
  • 带已记录标签修订的对象在显式 resync 或 heal 时每对象多一次元数据 COPY;当目的端按桶默认做 KMS 加密时,该复制会重写对象数据。带标签过滤的复制规则仍按删除后的(空)标签状态评估目标资格;任意站点时钟偏差不在修复后的顺序保证之内。复制双方必须都运行修复后的构建,墓碑才会被尊重——旧对端仍会丢弃空值修订。见复制标签排序。

R4–R8 集成记录保留了源码哈希、本地测试及验收边界。PR #196 合并前的 11 项检查全部通过。

Console 分享下载

Console #56 与 Server #209 修复了 Console #52 报告的匿名代理边界问题。 代理只允许访问已配置 S3 源地址上的对象内容 GET,拒绝跳转、系统路径以及 通过查询参数选择的非下载操作。没有新增关闭分享的环境变量,正常公共对象、 预签名和版本下载继续可用,详见行为与设计权衡。

修复已随 Console v2.4.1 发布。 精确发布源码通过完整 CI 矩阵、漏洞检查与发布工作流;真实 API 和浏览器分享测试 覆盖独立与内嵌部署,实际下载的独立二进制也连接 SILO 测试服务通过了分享回归。

普通条件 PUT

#199 的跨 pool 条件 PUT 问题已在发布版 Server 20260903 上复现。 PR #207 的提交 4620be394b52 于 2026-09-16 通过全部 8 项 CI, 随后以 9b4ae82a29cc 合入。 修复已随 Server 20260916 发布。 具体行为如下:

  • 普通多 pool If-Match / If-None-Match 条件使用所有池中的逻辑当前对象。 即使另一个池仍可处理 GET,只要无法核实某池元数据,条件写入就可能失败;读取仲裁不足返回 503,应恢复可读性或完成 heal 后重试。
  • 请求指定目标 versionId 时,公开写入条件仍比较当前对象,写入的目标版本保持请求指定的值; 内部复制保留按指定版本检查的语义。无条件 PUT 与单 pool 条件写入保持既有行为。
  • 条件覆盖成功不会清理其他池中的旧副本,升级也不能恢复历史上已接受的覆盖。 仍沿用既有修改时间与 pool 排序,不新增全局时钟排序保证。

#190 的分片完成修复既未引入、也未修复此 PUT 问题。 最终打包候选及部署验收仍由 #203 单独跟踪。

仍待完成的工作

  • 升级与存量准备: #200 跟踪 IAM 升级及恢复演练;#201 跟踪历史复制状态检查及修复验证。
  • 发布交付: #202 汇总说明和组件身份;#203 跟踪最终制品与多进程栈验证。
  • 多站删除标记收敛: 254b19ac0 的源端复核覆盖不了已经在网络上在途、或由另一站点重放的创建;多数确认的清除之后崩溃留下的少数标记副本,也没有证明持久的清理责任人。#217 跟踪接收端方案;见设计记录。
  • 滚动重启期间的列举: #239(已随 Server 20261018 发布)承接 #218,对符合条件的最新对象分歧进行确认,区分真实删除与读取故障,并把最终错误传递到分页响应。不增加磁盘格式、客户端参数或迁移开关;详见最新设计与验收边界。
  • **跨池迁移与历史标签:**最终 20261018 制品通过四组本地 2/3 池 rebalance/decommission,覆盖标签、版本、删除标记和中断恢复,见十月迁移修复。修复前已丢失的标签须单独审计。
  • 分片上传列表: #79 保留开放。Server 20261018 撤回默认持久扫描,并退役可选 strict 模式;公开列表重新使用节点本地缓存或精确 key 查询,完整发现、前缀/分页语义和迟到创建写入仍未解决。详见当前契约与容量证据。

依赖与发布顺序

  1. 核验上游 SDK 提交与需要的修复,继续使用 github.com/minio/minio-go/v7;退役的 silo-go 不再属于维护依赖图。
  2. 验证并以 github.com/pgsty/silo-pkg/v3 发布 pkg,同时提供迁移说明;通过 Go proxy 与校验和数据库解析标签。
  3. MC 更新到该 pkg/SDK,验证后发布日历标签的 mcli。Go 消费者引用其规范伪版本。
  4. Console 更新直接 pkg 依赖与 MC replacement,验证嵌入前端和集成;需要正式发布时单独发布 Console,也可明确选择已合入的不可变源码提交。
  5. Server 更新直接 pkg/SDK 依赖、两个 PGSTY replacement、客户端归档哈希、镜像和 Helm 客户端版本。验证完整依赖图后,再分别完成 Server 发布、镜像发布与集群升级。

Go 不继承依赖模块的 replace。即使 Console 已选择 MC,Server 仍必须显式选择受维护的 Console 与 MC。 Console 和 MC 保留历史 MinIO 模块路径,pkg 直接使用自己的路径。 colorjson/dperf 带入的旧 minio/pkg/v3 传递依赖与维护中的策略实现相互独立。

Console v2.4.2、mcli 20261018 与 Server 20261018 使用 Go 1.27.2,9 月版栈使用 Go 1.27.1;pkg v3.14.x 系列保留 Go 1.26 库兼容下限,并通过 Go 1.26.8 race 测试。Server 20261026、独立发布的 Console v2.5.1 与 v2.6.0、mcli 20261026 与 20261109,以及 pkg v3.15.2 与 v3.16.0 均要求 Go 1.27.3。 Go x/* 依赖已刷新。go-systemd 实际仍选 v22.6.0,因为 v22.7.0 在 NetBSD 编译失败; Console 保留 tablewriter v0.0.5 replacement 以兼容所用 MC API。

其他依赖按具体 CVE 与缺陷修复更新。 9 月 13 日 Go 扫描没有发现可达或已导入的易受攻击包,未使用的 OpenPGP 代码保留模块级 GO-2026-5932 记录。

正式支持的集成对象是协调后的 PGSTY 栈;与原版上游 MinIO/MC 和其他 S3 实现的兼容属于尽力保留。

9 月 16 日 Server 源码核对补充

Server 20260916 源码 2a4d51406b7e 已选择 pkg v3.14.1、上游 minio-go 32e1f32cb176、Console v2.4.1 源码 1360e26d976d 和 MC e952aa78f10a(mcli 20260916)。正式 Server 标签为 RELEASE.2026-09-16T00-00-00Z,包版本 20260916000000.0.0。

相关 Server 后续修复均未进入 20260903;文章中的原有 Object Lock 修复及其它已发布前置项按各自明确的版本记载。

最后的存储修复还包括 fced86303 的迁移标签保留、8d06424b1 的 null 版本 quorum,以及 eb4f5e5b3 / 254b19ac0 / 358ab38fb 的版本 purge、标记元数据和排队创建修复。仍需注意 #217 的迟到创建/崩溃残留和 #218 的重启期间列表遗漏。

10 月 15 日源码验收

已纳入 Server 20261015 草稿;Server 20260916 不包含。 PR #233 已以 d94b3b3c9251 合入,修复旧版 xl.meta 头部复用时的缺失字段残留,并使扫描更新与最终缓存保持互斥。 存储格式、RPC 字段与依赖版本均未变化。问题与修复说明 记录了确定性回归测试、双进程扫描验证、合并后 CI 和运维核验方法。 该源码修复已纳入 Server 20261015 草稿,并随 Server 20261018 正式发布。

20261015 之后纳入 20261018 的修复

20261018 在早期草稿基础上纳入提交元数据错误分类(#232)、上传时间解析(#236)、校验和与 Console 错误(#229/#238)、IAM 管理授权及批量自查询(#242、995439260)、LIST 恢复与目录保留(#239、3dd53eb81、2080b3d03)、空上传父目录清理(0f9199e0c),以及撤回公开持久扫描(4733e1423)。共享包已升至 v3.14.3。最终候选还包含跨池迁移旧副本覆盖与删除标记修复(60c7179dd、1748f62c7),以及持久 STS 枚举、撤销传播和漏通知恢复(0cd388c66)。

具体行为、升级步骤与未完成事项以 20261018 发布说明为准。原 strict 用户会失去持久列表与严格取消能力;#79 与 #217 仍未解决。

2 - 密码权限迁移

ChangeMyPassword 与 CreateUser 拆分的适用版本、策略迁移与回滚限制。
重要

适用于 Console v2.4.1、pkg v3.14.1 与配套 SILO Server。 Console 按钮、会话能力与 Server 授权必须使用一致的动作映射。 请按下文协调升级,并核对组件版本矩阵。

这是授权语义的破坏性变更(源自 minio/pkg #262)。 同一份已保存策略在升级前后可能作出不同的允许或拒绝决定。

新旧行为

服务端保留原来的 add-user 管理端点与 mcli 命令,按调用者和目标访问密钥是否相同选择权限:

请求 新权限 判断规则
修改调用者自己的密码 admin:ChangeMyPassword 已附加策略的内部用户隐式允许,显式 Deny 优先
创建其他用户或重置其密码 admin:CreateUser 必须显式 Allow,显式 Deny 优先

Console 的修改密码按钮使用 ChangeMyPassword,用户管理继续使用 CreateUser。 修改自己的密码仍需当前密码。STS、服务账号不能借此修改父用户密码;root 与外部身份提供商密码不属于此端点。

下表假定内部用户已附加策略、条件匹配,且没有其他 Allow/Deny:

现有策略 升级前修改自己的密码 升级后修改自己的密码 创建/重置其他用户,升级前后
只有 S3 读取授权 允许 允许 拒绝
Deny admin:CreateUser 拒绝 允许 拒绝
Deny admin:ChangeMyPassword 允许 拒绝 拒绝
Allow admin:CreateUser 允许 允许 允许
Allow admin:CreateUser 加 Deny admin:ChangeMyPassword 允许 拒绝 允许
同时 Deny 两个动作,或 Deny admin:* 拒绝 拒绝 拒绝

只匹配 CreateUser 的通配 Deny(如 admin:Create*)也存在相同变化。 Allow 不能覆盖匹配的 Deny;只授予 ChangeMyPassword 不会授予用户管理权限。 策略 JSON 格式、已保存文档与端点保留,但语义已经变化;没有恢复旧动作映射的开关。

保留旧限制

如果原策略通过拒绝 CreateUser 来锁定用户自己的密码,升级前在同一个 Deny 语句中加入 ChangeMyPassword:

{
  "Effect": "Deny",
  "Action": ["admin:CreateUser", "admin:ChangeMyPassword"]
}

保留原语句的其他动作、资源范围、条件和其余所有语句。 同时检查用户直接附加与通过组继承的策略。前一版本 pkg 已识别这两个动作名,可以提前准备。 已保存策略不会自动重写,需要管理员在确实希望维持旧限制的地方应用变更。

若要禁止修改自己的密码、同时允许独立授权的用户管理,只拒绝 ChangeMyPassword。 该区别只有包含新实现的 Server 才会执行。

内置只读策略

新 readonly 保留原 S3 读取权限,移除旧 CreateUser Deny,因此:

  • 用户可以修改自己的密码,除非其他适用语句拒绝 ChangeMyPassword。
  • 另一个策略的 CreateUser Allow 不再被内置只读策略压住;同时拥有这两份策略的用户可能获得更广权限。

新增 consolereadonly 还授予 Console 浏览所需的 ListBucket,并采用相同拆分。 这两种只读策略自身都不授予用户管理或 S3 写入权限,S3 只读不再隐含锁定密码。

升级保留已保存策略和同名内置策略的用户覆盖。旧 readonly 副本仍有 CreateUser Deny,继续拒绝其他用户管理, 但在新 Server 上不再拒绝修改自己的密码。没有保存覆盖时,Server 才使用新版内置定义。 应检查实际策略内容,不应仅根据名字判断。要保留两个旧限制,可另附双 Deny 策略,或给旧 readonly 覆盖增加 ChangeMyPassword Deny。

程序调用者

pkg 的 Policy.IsAllowedActions 现在隐式返回 ChangeMyPassword(除非被拒绝),只在明确授权时返回 CreateUser。 Go 函数签名与最低 Go 版本未变,但返回能力发生变化。Console 及其他调用者不能继续用 CreateUser 代替修改密码权限。

配套升级与回滚

Server、pkg 与 Console(包括嵌入版本)应协调升级;mcli 同步共享包与 SDK。 混用新旧版本可能出现按钮与服务端决策不一致,或旧 Server 不执行密码专用 Deny。

升级前导出受影响用户/组策略,按上表检查,并在需要维持旧限制的地方保留双 Deny。 整个升级与回滚窗口内保留这两个拒绝动作,实际验证自己的密码修改、其他用户创建与密码重置。 完成全部 Server 与 Console 更新后,才能依赖新的独立权限。

回滚二进制不会转换策略。旧 Server 忽略此端点的 ChangeMyPassword Deny,必须恢复或保留 CreateUser Deny 才能锁定密码; 它也会同时禁止管理其他用户。旧 Server 无法表达“允许用户管理、仅禁止修改自己的密码”的新组合。

Server 原始迁移指南 是实现侧的依据。 与上游 MinIO 的兼容仍为尽力保留;正式集成目标是 pgsty/silo。

3 - 访问频率分层移除

可选的 GET 频率池分层特性为何被移除,以及包含该特性的中间构建如何迁移。
说明

发布边界: 可选的 GET 频率池分层特性(社区 PR #60)只存在于 main/快照构建中。Server 20260903 早于该特性,Server 20260916 则在移除之后打标签,因此从任一已发布版本升级都无需访问分层配置清理。移除经 PR #188 合入;只有运行过包含该特性的构建的部署需要本页。

为何移除

访问分层是一个默认关闭、按 GET 频率在本地服务器池之间搬移对象的可选调度器。按实际交付的形态,它给配置、生命周期解析、用量缓存、统计和核心多池写入路径带来了不成比例的维护面——换来的收益从未被测量、也从未被宣称(不存在任何吞吐、延迟或锁往返数字)。移除决定保留了所有独立正确的部分:

  • 普通生命周期过期与到远端层的 transition;
  • rebalance 与 decommission;
  • PR #178 的通用多池写入、元数据、heal 与条件删除修复,包括共享远端层引用保护。

保留/移除的切分经过隔离对照验证:整批回退 PR #178 时代的修复会在 13 组检查中失败 10 组,因此这些被刻意保留,而分层特性本身移除。

升级包含访问分层的构建之前

  1. 保存服务器 ILM 配置与每个受影响桶的 lifecycle XML 副本。使用保留非标 XML 的 API 客户端;不要依赖会静默丢弃未知元素的客户端模型。
  2. 在旧服务器上设置 ilm access_tiering=off,移除或禁用所有访问分层环境覆盖。等在途搬移完成后再替换节点。这能减少搬移中间态;移除本身不改变任何存储 RPC 协议。
  3. 删除顶层 AccessTierQuota 与规则级 AccessTransition 元素。只含 AccessTransition 动作的规则整条删除。 混合规则保留其 filter、status、ID 与普通过期/transition 动作。纯访问规则在升级后可以无害加载,但会变成无动作规则,在下一次 lifecycle 编辑时校验失败。若无规则剩余,通过 S3 API 删除 lifecycle 配置。
  4. 使用协调维护窗口:停掉整个部署,在每个节点安装相同的新二进制,再全部重启。bootstrap 检查会比对二进制校验和与服务器环境设置——四节点实验中,第一个新节点在三个旧节点之间无法完成启动;只在部分节点上移除旧环境覆盖也会在二进制一致时阻止启动。请勿逐台替换节点。
  5. 重启后验证对象读取、桶列表、ILM worker 设置与一次 lifecycle 编辑。请检查每个服务请求节点到每池每块盘的存储访问,不要仅依赖 admin 磁盘摘要或固定 sleep。

存储状态的去向

状态 移除后的行为
十个旧 ILM 键 access_tiering、access_pools、access_max_size、access_promote_watermark、access_bin_width、access_bins、access_flush、access_min_residency、access_workers、access_max_tracked 被接受但忽略。既有的 transition/expiration worker 设置保留。
Admin 配置 已弃用键仍可能出现在 mcli admin config get ilm;设置它们可能成功但无任何效果,即使 access_tiering=on。请从部署清单中移除过时环境设置。
Lifecycle XML AccessTierQuota 与 AccessTransition 读取时忽略、重新编码时省略。同一解析器处理新的 PUT 请求,因此这些扩展在那里也被静默丢弃;纯访问规则仍会动作校验失败。
数据用量缓存 v8 与 v9 缓存都可读取,保留普通计数、大小、直方图与远端层统计。退役的热层字节计数丢弃;后续写入使用 v8。无需因特性做全量统计重建。
已搬移的对象 留在当前池中,版本与时间戳不变。没有批量搬回,也没有对象元数据改写。
内部残留 x-minio-internal-ilm-atier 与 .minio.sys/config/ilm/access/ 计数对象可能残留。它们不需要清理服务或对象扫描。

被中断的 rebalance/decommission 本就可能让同一版本存在于多个池,与访问分层无关;移除调度器不会移除这些既有副本。

升级验证与磁盘就绪探测

协调升级流程在本地四节点双池实验(单台 Docker Linux 主机、tmpfs 盘)中验证:就绪检查修正后,三次完整升级验收通过,绑定生产代码 41aa84609。核验完整节点到盘就绪的方法:从每个服务请求节点,对各自唯一、从未写入的对象键执行 GetObjectTagging——该路径会等待所有盘——并与真实 storage.ReadVersion trace 逐条匹配,要求每条节点到盘路径真实返回预期的对象/版本不存在,连续三轮;本例四节点、八盘每轮需要 32 条应答。drive not found、超时或缺失 trace 都判失败。

在就绪检查修正前,同系列中更早的两次升级尝试曾在 DELETE 返回 204 后出现某节点对 HEAD/GET 返回 503。

版本删除范围

此次移除与一项普通单对象 DELETE ?versionId=... 的修复同车:它现在跨池调和被寻址的 UUID、null 版本或删除标记(包括对目录标记 key 的未限定 DELETE)。成功的请求按既有逐池 quorum 规则把删除应用到每个已解析的池副本;待处理的出站删除复制保留 VersionPurgePending 直到复制 worker 完成 purge。若某池不可读,即使另一池有可读副本,这些请求也可能返回 503 SlowDownRead(或保留其他错误码);恢复后重试。批量 DeleteObjects 本就跨池扇出。入站复制删除、lifecycle 过期、free-version 清理与搬移内部调用保持既有契约。

历史记录

特性的引入、后续修复、回退范围、评审历史与未解决的验证发现在钉定提交 40220bd836cb 的归档决策记录与仓库内 docs/bucket/lifecycle/access-tiering-removal.md 中保留;本页承载运维契约,二者都不是必需读物。组件状态见版本矩阵。

4 - Silo 与 MinIO 服务端兼容性

经过源码验证的 Silo 服务端分叉兼容性审计:二进制、配置、S3 与管理行为、存储内部协议、软件包、容器与 Helm。

先看三档兼容性总览:12 类兼容或改进、4 类轻微差异、8 类按条件检查。 本页提供服务端细节,保留 2026-08-06 审计的固定基线,并分别记录后续已发布变化与9 月 16 日源码变化。历史审计基线与最初分叉基线分开记录。

警告

替换 MinIO 部署前请先阅读本页。 二进制、软件包、服务账号、systemd 单元、默认本地配置目录、容器路径、Helm 资源名、内嵌控制台、更新行为、若干授权判定及部分错误响应已经改变;数据盘和 MINIO_* 配置命名空间没有随产品改名。

Server 20261026 之后的候选工作

Server 20261026 仍是正式服务端版本。以下索引汇总后续候选工作的设计与升级说明;每篇记录中的状态、源码提交和验收范围分别生效,不能将整个列表理解为已通过发版验收。Console 与 mcli 独立发布,不会使旧 Server 制品获得这些改动。

范围 设计与升级说明
生命周期、整键删除与恢复 多池生命周期、精确 key 删除、恢复副本过期、两阶段恢复
锁、读取与修复 单池锁域、局部视图读取、Heal 演练、失败写入清理
Batch 与配置重载 Batch 授权及重试、Webhook peer 重载、IAM 撤销
容器 健康检查与 distroless 镜像

Server 20261026 升级检查

本节对应 Server 20261026 正式版,源码为 c3ad836aed0d。

使用场景 行为变化与升级要求
LDAP 规范化长 DN ASCII 文件名分量超过 255 字节的缺失可选 IAM 记录不再阻断组策略登录;不可读撤销记录与真实存储故障继续按 Fail-Closed 报错,对象后端仍不支持写入超长路径记录。见 LDAP 指南。
内置策略覆盖 Reset 删除覆盖内容后立即恢复原生内置定义,并继续执行策略在用检查;延迟到达的对端/etcd 通知重新加载已提交状态,自定义策略仍执行真正删除。见 Console 策略管理。
Console 创建/删除存储桶 account-info 接口改为读取实时存储桶清单(旧版 Server 刷新后可能返回旧缓存);用量统计仍由后台扫描器更新。
存储超时与回滚 保留磁盘与节点间 RPC 的超时及取消传播,并在覆盖写回滚时透传内部删除控制项(草稿阶段的 mutation guard 和无界完成等待未纳入本版)。
多池删除 普通与批量删除先清理非权威旧副本再删除权威副本,并保护共享远端分层引用;若中途遇到存储故障,恢复后重试即可。
版本化远端分层过期 生命周期过期仅生成删除标记时保留上一版本的远端分层对象(含已暂停版本控制桶中的非 null 版本);升级前已误删的历史远端数据需从备份恢复。
分片上传复制 为可合并的 CRC 校验和算法透传 FULL_OBJECT 校验和类型;需升级发送端 Server 并核对待复制队列。
构建与制品 基于 Go 1.27.3 构建,集成 Console v2.5.1、mcli 20261026、pkg v3.15.2 与固定提交的上游 minio-go;Windows 归档改用 ZIP。见组件版本矩阵。

读取与故障边界: 租约失效或网络分区仍可能产生迟到提交,部分元数据更新仍可能暴露旧值或旧标签。既有读仲裁与自愈规则保持不变(更严格的 fencing、回滚与读取恢复诊断保留在 consistency_strict 构建标签下),升级不提供分布式 fencing,也不会自动修复存量不一致对象。下方 20261018 的 Object Lock、IAM 与 strict 分片模式退役要求继续适用。

Server 20261018 升级检查

本节针对 20261018 正式版,现已正式发布;下文旧审计与 20260916 章节保留各自历史范围。

使用场景 本版变化与操作
Object Lock / 指定版本写入 保留期必须满足基本权限和适用的绕过权限;指定写入版本要求可信复制;目录与旧分片完成在写锁内复查保护,失败关闭。升级全部写入站点。
服务账户 / STS / 管理自动化 显式自助 Deny 和会话限制生效;受限凭据不能委派更宽权限,非 root 不能修改 root 派生凭据。核对实际管理身份与外部插件。
对象清单与备份同步 符合条件的不确定 LIST 条目被重新确认,无法确认则返回错误。读取完整分页,不将错误当成空清单;不保证跨页快照。
分片列表与取消 默认仍为缓存/精确 key;strict 开关忽略并警告。原 strict 用户失去持久枚举与严格取消;重启遗漏、前缀/分页边界和延迟创建仍存在。
错误处理 / OIDC 暂存提交元数据丢失返回 503 SlowDownWrite;校验和消息可能变化。JOSE 拒绝超过 4096 位的 RSA JWK,升级前验证登录。

详细契约见 IAM 设计、LIST 恢复、分片决策与安全更新。#79 和 #217 仍未解决;磁盘格式与既有配置命名不变。正式支持 PGSTY 四组件组合,上游兼容尽最大努力。

审计范围与方法

边界 审计值
上游基线 minio/minio@7aac2a2c5b7c882e68c1ce017d8256be2feea27f,2026-02-11
Silo 快照 pgsty/silo@219670d3176a5b27ded60914390d5ee7e763cf58,2026-08-06
提交集合 7aac2a2c..219670d3:共 96 个可达提交;审计时其中 93 个位于 origin/main,最后 3 个已在本地提交
源码净差异 523 个文件,新增 36,715 行,删除 21,450 行
解释口径 记录最终快照的行为;后来被替换或删除的中间状态,不会被写成当前行为

范围内每个提交都对照最终实现、测试、依赖图、构建配方、软件包载荷、容器入口和渲染后的 Helm 清单逐项核实。完整提交覆盖账本跟踪范围内的全部提交(含文档与 CI 更新)。

该范围按 Git 可达性定义,包含 d4cd4b433(作者日期为 2025 年 12 月,后续合入基线后的提交图)。

已打标签的 RELEASE.2026-08-04T00-00-00Z 停在 d88f46cce,比本次 2026-08-06 审计 HEAD 少 18 个提交(这 18 个提交随后随 Server 20260806 发布)。

兼容性总览

表面 状态 实际结论
S3 线协议 除明确列出的例外外保持兼容 路由、XML/JSON 模式、SigV4、S3 头、端口与常规错误码沿用 MinIO 契约;下列安全与正确性修复会有意拒绝部分旧代码曾接受的请求
数据盘 兼容 .minio.sys、纠删码元数据、桶/对象布局、修复、复制和加密格式保留原名与模式;被污染或不可用的元数据会更早被拒绝
配置 基本兼容 既有 MINIO_* 变量、配置键、KMS/KES、IAM、通知与存储设置都保留;用户级默认目录变为 ~/.silo,并带有确定性的 ~/.minio 回退
指标与自动化 API 兼容 minio_* Prometheus 指标、/minio/* 路由、x-minio-* 头、管理/S3 错误标识及 release tag 语法不变
二进制与分发 已改名 minio 变为 silo;软件包、单元、镜像、Chart、归档、校验文件及路径改用 Silo 身份;服务端二进制没有安装兼容别名
运行时身份 已改变 CLI 文本、启动横幅、HTTP Server、User-Agent 应用名、FTP 横幅、日志名、支持链接以及部分人类可读错误改为 Silo
上游网络服务 已禁用 原地更新、更新轮询、callhome、SUBNET 注册与诊断上传不会联系 MinIO 服务
授权与安全 有意收紧 OIDC HMAC token、不安全 LDAP 失败、伪造复制元数据、对象资源对受保护桶写操作的越权、策略输入遮蔽、歧义版本 ID 以及若干畸形节点间请求均改变行为
内嵌 UI 与 Go 依赖 Console 与 MCLI 走兼容 import path,pkg 走自有路径 Silo Console 与 MCLI 由 replace 选中,同时保留 github.com/minio/console / github.com/minio/mc 路径;Silo Pkg 以 github.com/pgsty/silo-pkg/v3 直接消费
混合版本集群 此迁移边界不支持 私有 ReadMultiple storage-REST 操作已删除,却没有提升 storage REST v63;所有节点应作为同一构建整体升级

明确保留的兼容契约

协议、存储与配置名称

下列 MinIO 标识属于兼容性标识,并非尚未完成的品牌替换,必须继续可见:

  • Go 模块路径 github.com/minio/minio 及继承的 github.com/minio/... import;
  • MINIO_* 环境变量命名空间,包括 MINIO_ROOT_USER、MINIO_ROOT_PASSWORD、MINIO_VOLUMES、MINIO_OPTS 和通知变量;
  • /minio/* 下的 S3/管理路由、x-minio-* 头、MinIO 特有 S3 扩展及既有 API 错误码;
  • minio_* Prometheus 指标名称;
  • .minio.sys 内部卷及所有既有磁盘元数据名称;
  • 默认 S3 端口 9000、既有 --address / --console-address 参数,以及 RELEASE.YYYY-MM-DDTHH-MM-SSZ 标签格式;
  • 配置 KV 格式、IAM 数据、KMS/KES 配置、加密元数据、桶元数据、复制状态与修复状态。

rebrand guard 检查显式标识清单。归档的 219670d3 清单包含 137 个 import、436 个环境变量名、19 个指标命名空间、84 个头、330 条路由、1 个根目录、3 个 Grid 命名空间、15 个存储标识、58 个策略标识和 9,014 个导出符号。当前源码清单为版本 4,已不再跟踪导出符号。可在实际源码版本运行 make rebrand-guard 以核对有意的清单变化。

同一组数据盘从 MinIO 切到 Silo 时不需要复制数据或重写元数据。但这并不意味着一切畸形历史对象都会继续被接受:下文的存储加固会拒绝不安全路径、非法纠删码几何、负 part size 以及过去可能继续向下传播的污染元数据。

源码兼容性

服务端模块仍为 github.com/minio/minio;Console 与客户端库通过 replace 选择维护中的分叉,不强迫调用方改写 import:

replace github.com/minio/console => github.com/pgsty/silo-console ...
replace github.com/minio/mc      => github.com/pgsty/mc ...

公共包是刻意的例外。pkg v3.13.0 起它使用自己的模块路径构建,所有维护中的组件——包括服务端——都直接消费它:

require github.com/pgsty/silo-pkg/v3 v3.14.1   // 不再使用 replace 安排

历史的 replace github.com/minio/pkg/v3 => ... 安排已退役;github.com/minio/pkg/v3 现在仅作为遗留的间接依赖出现(经 colorjson/dperf),与维护中的策略实现相互独立。上游 SDK github.com/minio/minio-go/v7 是另一个明确例外:以经过验证的 commit 直接消费上游,退役的 silo-go 分叉不属于维护依赖图。

这保留了大部分源码兼容性,但不表示所有私有或导出 Go 符号永久冻结。内部 ReadMultiple 存储接口已删除,所选 silo-pkg 版本也包含依赖章节所述的开发者可见变化。

维护中的源码 remote 是 github.com/pgsty/silo,默认分支为 main;原 minio 分支已归档。go install github.com/minio/minio@... 仍会解析到上游项目,而不是 Silo,因此需要 clone Silo 仓库或使用显式 module replace。贡献不再要求 MinIO CLA,但提交必须带 DCO sign-off(git commit -s)。

身份、二进制与外联服务变化

表面 上游基线 Silo 快照 兼容性影响
服务端可执行文件 minio / minio.exe silo / silo.exe 脚本及绝对路径必须修改;归档、软件包和镜像不会安装 /usr/bin/minio 服务端别名
版本输出 MinIO 身份 Silo release/commit/runtime、AGPL、上游版权、PGSTY 修改版权与 MinIO 技术沿革 解析器应依赖稳定字段,不能 grep MinIO 文案
本地配置主目录 ~/.minio 新用户主目录默认 ~/.silo 见下述回退规则;与数据盘无关
HTTP 身份 Server: MinIO 与 MinIO 应用 UA Server: Silo;内部 batch/fan-out/perf UA 使用 silo-* / Silo 名称 x-minio-* 等协议头保持不变;按产品身份匹配的监控需要调整
人类可读文本 MinIO 横幅、帮助、错误、样例、FTP 欢迎语、支持链接 Silo 身份;样例优先 mysilo 精确匹配文本的日志解析器和快照会变化;除另行列出外,状态码/错误码不变
集成可见标签 MinIO NATS/Redis 连接名与 Veeam model NATS 名 Silo Notification、Redis CLIENT SETNAME Silo、Veeam model "Silo <release>" Broker 看板、连接名过滤器及 Veeam Inventory 展示会改变
KMS 校验文案 带 MinIO 品牌的冲突错误 中性的“同时存在 KMS/KES/static-key 配置”错误 配置规则不变;精确匹配文本的自动化会改变
更新器 release 轮询与原地更新路径 永久禁用 MINIO_UPDATE 会被解析但无法重新开启;管理更新路由保留并稳定失败,而不是消失
Callhome/SUBNET 注册、callhome、支持上传、内嵌 MinIO 支持公钥 为迁移保留配置解析但强制关闭;不注册/上传/POST;没有兜底加密公钥 删除依赖 MinIO 运营服务的自动化;请求方公钥的 inspect 加密仍可用
内嵌控制台 上游快照已移除 Console Silo Console v2.1.1,中英双语、Metrics V3、无 SUBNET UI 浏览器行为和资源发生变化;S3/Admin API 仍由服务端契约约束
OCI 内置客户端 没有维护分叉契约 /usr/bin/mcli 与 /usr/bin/mc -> mcli 这里的 mc 只是客户端兼容别名,从来不是服务端别名
温层探针 临时对象内容为 MinIO 同长度探针内容为 Silo! 只可能通过后端检查或清理失败残留观察到;协议语义不变
日志轮转默认名 minio-*.log silo-*.log 按文件名匹配的采集器需要修改

被删除的 /api/health/upload 引用是一个 出站 SUBNET URL 路径,并不是 Silo 本地 HTTP 路由。正确的兼容性描述是“Silo 不再发起该 POST”,不能写成“删除了服务端 API”。

默认配置目录选择

未显式给出 --config-dir 时,Silo 会在启动时作一次选择:

用户主目录状态 选择目录 提示
两者都不存在 ~/.silo 无
只有 ~/.silo ~/.silo 无
只有 ~/.minio ~/.minio 旧目录提示;不会移动任何文件
两者都存在 ~/.silo 歧义警告

--config-dir 始终优先。除非同时指定 --certs-dir,证书目录跟随所选配置目录。自动化应明确传入 --config-dir,不要依赖文件系统探测。

分叉只新增了三个会实质改变兼容行为的服务端配置控制项;不存在一套并行的 SILO_* 替换命名空间:

设置 用途 默认值
MINIO_API_TRUSTED_PROXIES 通用来源地址信任边界 未设置:精确保留历史 trust-any 行为
MINIO_IDENTITY_LDAP_STS_TRUSTED_PROXIES / LDAP key sts_trusted_proxies LDAP STS 失败限流的来源分桶 不信任代理;使用 socket peer
MINIO_API_LEGACY_BUCKET_RESOURCE_MATCH 受保护桶/对象 IAM 边界的临时回滚 off

通知 KV 注册修复不会重命名既有环境变量。MINIO_UPDATE、SUBNET 与 callhome 输入仅作为被忽略/迁移兼容的输入保留,详见下一节。SILO_OPTS 只出现在自动生成的 inspect helper 内,不是 MINIO_OPTS 的通用替代品。

更新器、callhome、SUBNET 与 inspect

  • 启动过程不再轮询 dl.min.io;release URL 与上游 minisign 根公钥已移除。
  • 要求开启更新的 MINIO_UPDATE 值会产生警告并被忽略。公开及节点间管理更新 handler 仍然注册,返回 MethodNotAllowed 或稳定的“原地更新已禁用”错误。
  • 旧 subnet 与 callhome 键仍可解析,让旧配置能够启动;注册状态恒为 false,Console 的 SUBNET 变量被清空,callhome 强制关闭,不上传诊断或许可证负载。
  • Inspect 只会用请求方提供的公钥加密,不再回退到 MinIO 内置支持公钥。帮助脚本名为 start-silo.sh、执行 silo,cluster.info 只出现在请求方公钥流程中。
  • 请通过包管理器、镜像滚动或编排器升级;不要把针对 Silo 的 mc admin update / mcli admin update 当作升级方案。

安装与部署兼容性

RPM、DEB 与 APK

Linux amd64/arm64 软件包名为 silo,关键载荷如下:

/usr/bin/silo
/usr/lib/systemd/system/silo.service
/etc/default/silo                 (config, noreplace)
/usr/lib/sysusers.d/silo.conf
/usr/share/doc/silo/LICENSE
/usr/share/doc/silo/NOTICE

软件包会创建无 home 的系统账号 silo:silo。它 不会 chown 既有数据、迁移所有权、在安装时停止运行中的 MinIO 服务,也不会在包管理器层面对 minio 声明 Provides、Obsoletes、Replaces 或 Conflicts。因此两个包可以同时安装,但使用随附 unit 时两个服务不能同时运行。

silo.service 声明 Conflicts=minio.service,以 silo:silo 运行,先读 /etc/default/minio,再读 /etc/default/silo。随包的 Silo 文件没有有效赋值,所以管理员在后一个文件显式覆盖前,旧文件仍然生效。启动命令为:

/usr/bin/silo server $MINIO_OPTS $MINIO_VOLUMES

切换 unit 前,必须确保 silo 可读取所有数据、证书、KMS 凭据和环境文件,并可写所有应写路径。由 minio:minio 持有的旧部署否则会启动失败。真正卸载软件包时会停止/禁用 silo.service;升级时 pre-remove 不会有意停掉运行中的服务。

容器镜像

源码仓库是 github.com/pgsty/silo,预期镜像名是 docker.io/pgsty/silo;不存在 pgsty/minio 在 Registry 层必然重定向到它的承诺。

  • 服务端只存在于 /usr/bin/silo;显式执行 /usr/bin/minio ... 会失败。
  • entrypoint 会把 argv 第一个词 minio 翻译为 silo;当 argv 以 server、fmt-gen 或选项开头时前置 silo。因此常见的 command: minio server /data 形式仍然可用。
  • 显式指定的 shell 或其他工具保持原样。
  • 所有降权路径最终都使用 exec,服务端成为 PID 1 并收到 SIGTERM 完成优雅退出,不会再隔着 entrypoint 超时。
  • 镜像默认 HOME=/tmp;任意 UID 或旧 MINIO_USERNAME 降权流程也会把 HOME 归一到可写目录。
  • 端口 9000、/data 与 MINIO_* 接口不变。amd64/arm64 镜像 manifest 还包含经过校验的 MCLI RELEASE.2026-08-06T00-00-00Z(在本审计头之后的发布提交中提升)和只面向客户端的 mc 符号链接。
  • OCI 法律材料位于 /licenses/{LICENSE,NOTICE,CREDITS}。

Helm Chart

继承的 helm/minio Chart、helm-releases、根 Chart 索引与重建脚本已删除。维护中的 Chart 为 helm/silo;20260806 发布的 Chart 版本为 7.0.1(审计头当时仍是 7.0.0)。

大多数 values 刻意保留原名,包括 minioAPIPort、minioConsolePort 及所有 MINIO_* 环境设置。迁移时需要关注:

  • 镜像仓库改为 pgsty/silo;
  • 生成的资源名和 label 跟随 Chart 名 silo;
  • 默认服务账号改为 silo-sa;
  • 证书/客户端挂载路径从 /etc/minio/{certs,mc} 改为 /etc/silo/{certs,mc};
  • 默认不再创建不安全的 console/console123 用户(users: []);
  • post-job 样例优先使用别名 mysilo,同时注册 myminio,让继承的 customCommands 仍能解析;
  • 新 Chart 执行 silo,因此只把镜像回滚到旧 MinIO 镜像并不安全。

使用新 Chart 且需要保留旧 Kubernetes 对象身份时,应从完整旧 values 开始,至少设置:

nameOverride: minio
fullnameOverride: <旧的完整 release 名>   # 例如 my-release-minio
serviceAccount:
  name: minio-sa
image:
  repository: pgsty/silo
mcImage:
  repository: pgsty/silo

应用前分别渲染新旧 Chart,比较 Service、selector、StatefulSet/Deployment、PVC 模板、Secret、服务账号、存储挂载、环境变量和端口。回滚时必须把 Chart 与镜像一起回滚。

归档、来源证明与法律文件

Release 归档命名为 silo_<version>_<os>_<arch>,包含可执行文件、README、LICENSE 和 NOTICE。校验清单名为 silo_<version>_checksums.txt;每个归档带有 SPDX JSON SBOM,校验集合配有无密钥 Sigstore bundle。静态、禁用 CGO、带 kqueue tag 的二进制只发布 Linux、macOS、Windows 的 amd64/arm64 组合;过去只做编译检查但从不分发的架构不再作为 release gate。RPM/DEB/APK 目标为 Linux amd64/arm64,使用 YYYYMMDDHHMMSS.0.0 形式的时间戳包版本(RPM release 1),并有独立软件包校验清单。常规构建不再把构建机 GOPATH/GOROOT 写入二进制,提高了可复现性并消除路径泄漏。

上游基线 Docker 配方会下载并验证 dl.min.io 的预编译服务端;Silo release 镜像则消费所选 tag 上由源码构建、带 attestation 的精确归档。镜像发布是 GitHub Release 之后显式 dispatch 的独立流程;构建成功本身不会发布镜像。

CREDITS 根据实际链接进服务端的模块重新生成,并由 CI guard 保护。OCI 镜像包含它;考虑到约 1.8 MB 的体积,软件包与归档有意省略。上游 AGPL 与版权声明保留,同时加入 PGSTY 修改声明。

运行时与安全行为变化

即使是漏洞修复,只要用户可感知,也属于兼容性变化。下文的“收紧”表示过去可能成功、或以另一种方式失败的请求、策略、token、配置或损坏内部消息,现在会被拒绝。

认证、IAM 与请求身份

变化 最终行为 谁需要处理
OIDC JWT 校验(d24f449e0) client secret 不再作为验签 key。只接受非对称 JWKS 算法 RS256/384/512、ES256/384/512、RS3256/3384/3512、ES3256/3384/3512。HS256/384/512 失败;未知 kid 仍走既有 JWKS 刷新/重试 使用 HMAC 为 Silo token 签名的 IdP 必须迁移到非对称 JWKS key
LDAP STS 错误(3b950f8fa) 未知用户与错误密码共享同一个外部 InvalidParameterValue 认证失败;LDAP 基础设施错误仍是服务端错误并记日志 客户端不能再从响应文本判断账号是否存在
LDAP STS 限流(18b712d49、9e10f6d9a、f44110890、5e40665ac) 每来源、每节点内存桶:突发 10 次,每 6 秒补 1 个 token,空闲 TTL 15 分钟。只有认证失败消耗 token,成功与基础设施失败会退回。耗尽返回 HTTP 429、ThrottlingException、Retry-After: 6 代理应配置独立的 MINIO_IDENTITY_LDAP_STS_TRUSTED_PROXIES
LDAP 可信代理来源 socket peer 在允许列表中时,优先干净的 X-Real-IP;否则从右向左遍历 XFF 并跳过可信 hop。忽略 RFC 7239 Forwarded。代理 必须覆盖 X-Real-IP 审核 Ingress 头部清洗;该限流不是分布式账号锁
LDAP service-account 查找 对“User DN not found”的匹配改为大小写不敏感,依赖消息大小写变化时仍能得到预期 Admin no-such-user / login-name 错误分类 只有依赖偶然错误分类的脆弱客户端会观察到变化
桶/对象 IAM 边界(97b7d2804) 12 个受保护桶写操作不再仅因 arn:aws:s3:::bucket/* Allow 而获准,必须有裸桶 ARN。Deny/NotResource 与内置 * 策略语义不变 自定义策略中确实需要桶写操作时加入 arn:aws:s3:::bucket;或临时使用全局逃生开关 MINIO_API_LEGACY_BUCKET_RESOURCE_MATCH=on
受保护操作 删除/强删桶;写/删桶策略;写复制、生命周期、对象锁、版本、CORS;删 CORS;写桶 QoS 或 Inventory 配置 读/list、创建桶、标签、加密与通知仍沿用历史匹配行为
有效策略输入(2f55347f7) 服务端派生条件不能被同名 header/query 遮蔽;策略包中精确 key 优先。已有/请求标签、存储类、content/copy/checksum、对象锁、签名年龄与 list 参数均来自操作实际消费的值 误依赖攻击者可控遮蔽值的策略不再匹配
请求标签 PutObject、CreateMultipartUpload、PutObjectTagging 把 s3:RequestObjectTag/* 绑定到已解析输入;ExistingObjectTag 只来自已存元数据;其他操作路径保留旧 header 回退 重新测试带标签条件的写策略
s3:signatureAge 只在已经验证的 presigned SigV4 请求中出现 注入原始 x-amz-signature-age 不再产生该条件
s3:versionid(744a9dcd7) 缺失就真正缺失;空白被归一;DeleteObject/MultiDelete 使用每个对象的有效版本。URL version 不能诱骗不同 XML version 重测基于版本的删除策略及依赖 Null 的策略
复制元数据(56fa63bfd) 普通 PUT/COPY 不能注入内部复制状态/时间元数据;经认证的 replica 请求必须拥有 ReplicateObjectAction;multipart 与 Snowball 的合法复制流程保留 自定义复制调用方必须走受授权的复制路径

桶边界逃生开关在启动时全局生效,而且是全有或全无;它用于迁移,不是长期混合策略模式。空或无法解析的 LDAP 来源不会被放入一个共享限流桶;在能派生出可用来源前不对它限流。

通用来源地址信任

fe6dc4780 新增 MINIO_API_TRUSTED_PROXIES,因为所选客户端地址会进入 aws:SourceIp、审计 remotehost、事件 Host、管理 trace 及节点间转发。

值 结果
未设置 精确保留历史行为:相信任何 peer 提供的来源头;依次选择最左 XFF、X-Real-IP、Forwarded
none 或 off 忽略三种来源地址头,使用 TCP peer
IP/CIDR 列表 只有 TCP peer 在列表中时才相信头;XFF 从右向左越过可信 hop(最多 100 个),随后取最后一行 X-Real-IP,再从右向左遍历 Forwarded

畸形配置、非空但没有任何代理的列表,或远程 env:// 读取失败都会 fail closed 并阻止启动,而不是回退到 trust-any。收到的链中无效值会跳过;没有可用地址时回退 peer。只在 FTP/SFTP peer bridge 中隐式信任 loopback,不会把链内任意 loopback 当成可跳过 hop。

继承的 _MINIO_API_XFF_HEADER=off 保持旧语义和初始化时点:它只关闭 XFF 解析,不影响 X-Real-IP 或 Forwarded,因而不是安全边界。需要把所有合法转发请求的集群节点加入列表,并确保边缘代理覆盖或剥离客户端提供的三种来源头。

S3 请求与响应行为

范围 变化与兼容性影响
Presigned 流式认证 query/presigned SigV4 请求声明 STREAMING-UNSIGNED-PAYLOAD-TRAILER 时返回 SignatureVersionNotSupported,不能降级为匿名授权;header SigV4 会在读取 body 前验证
Snowball 先授权后解包 tar;流式 trailer 绕过无法在后续失败前写入对象
S3 Select 记录限制 CSV 输入、JSON Lines 输入和输出记录超过 1 MiB 时返回 OverMaxRecordSize 事件。JSON Lines 始终使用有界 reader(在支持 SIMD 的 CPU 上可能变慢),JSON 解析错误为 JSONParsingError,已完成记录可先于终止错误送达
流式响应 tracking writer 实现 Flush;Write/Flush 会记录隐式 HTTP 200。ListenBucketNotification/watch 流及 S3 Select keepalive 能及时送达,审计/状态指标也能记录已提交状态
Multipart 整对象 checksum FULL_OBJECT CRC32/CRC32C/CRC64NVME 完成时可完全省略每 part checksum;只要提供任意一个仍会校验;COMPOSITE 仍要求每个 part。即使不提供对象 checksum value,显式 completion type 仍会校验:不匹配返回 BadDigest,未知 type 返回 InvalidArgument。后续 #93/#96 已拒绝 CRC64NVME + COMPOSITE,修复包含在 Server 20260903 中。零字节 multipart 对象 checksum 会正确保存
CopyObject checksum 响应 CopyObject XML 与 HTTP header 使用目标加密上下文报告已提交 checksum。SSE-C 源 key A 与目标 key B 严格分开;同对象换钥会用新 key 返回 checksum 字段。存储数据与 checksum format 均不改变
Multipart part 顺序 重复或非递增 part number 在组装前以 InvalidPartOrder 失败;允许空洞及不从 1 开始;upload 保留供重试
纠删码读缓冲池 恢复正确 shard buffer 所有权,避免池失效以及可能造成卡死、损坏或严重性能下降的错误缓冲关联
更新缓冲 返回的下载 buffer 具有正确所有权;公开更新器随后已禁用,所以当前受支持升级路径不会运行该代码

分布式存储与私有 API

这些变化通常对 S3 客户端不可见,但会影响混合版本集群、自定义内部调用方、损坏磁盘及恶意 peer。

  • ReadMultiple 及私有 storage-REST /rmpl endpoint、客户端方法、导出 Go 类型和指标均已删除。外部 S3 List/Get 不变。storageRESTVersion 仍为 v63,不能据此推断混合节点兼容。
  • 每个远程 StorageAPI 路径字段、嵌套元数据名和原始 volume sink 都在存储边界验证,包括 peer-S3 Grid 消息;拒绝词法遍历、volume root alias 及 Windows 分隔符/盘符形式。
  • 所有解码 sink 及 CheckParts/VerifyFile 都会拒绝非法纠删码几何、非正 block、负 part size 及不可用已存纠删码元数据。
  • 节点间分配声明受限:AppendFile 预分配最多 1 MiB 但仍接受 body;DeleteVersions 边解码边增长并拒绝负声明;旧 ReadFile 上限为 5 GiB。
  • 有 deadline 的工作会把 worker panic 转成错误并记录有界堆栈,不再让进程崩溃。
  • ReadParts 会跨 keepalive frame 保留真实后端错误;空 part 列表成功返回空结果,不触发 trace panic 或 goroutine 泄漏。
  • ReadMultiple 删除后遗留的 HTTP stream helper 随后被清理;该清理没有额外公开行为变化。

该 containment 是词法层面的,不解析文件系统符号链接;审计也没有原生 Windows 服务端 CI。应整体升级所有节点,即使节点间端口有 root 凭据与输入验证,也不要向不可信客户端暴露。

通知配置与审计输出

  • NATS 现在注册解析器实际读取的 user_credentials、nkey_seed、tls_handshake_first;AMQP 注册 immediate;既有环境变量名不变。
  • 旧字面量 MINIO_NOTIFY_NATS_USER_CREDENTIALS 仍只对 NATS 接受;优先级为环境变量、新 key、旧迁移 key。
  • AMQP 旧配置迁移会正确映射 immediate。非法通知配置错误只标识名称,不再回显凭据值。
  • PostgreSQL 与 MySQL 通知配置使用规范 connection_string 或 dsn_string,显式连接串原样透传。保留的 PostgreSQL 内部 fallback builder 会正确引用参数并使用 user 关键字,但离散字段不是受支持的 KV 输入。
  • dangling object 删除审计重新在 merrs 中包含每块盘的错误。

提交 f1ba68358 已关闭继承的数据库通知迁移风险:迁移不再写入未注册的离散连接 key。缺少 connection_string 或 dsn_string 的已启用 pre-KV target 现在会以不含凭据的错误中止启动。升级前必须转换、禁用或删除这类 target;修复前导出的诊断包可能含有历史明文数据库密码,应据此处置。

工具链、依赖与内嵌组件

构建声明从 Go 1.24 + 1.24.8 toolchain 迁移到 go 1.26.5。即便没有修改 Silo 源码,这也可能改变 TLS、HTTP、DNS、调度器、GC 及标准库边缘行为。Go-Jose、OpenTelemetry、Go crypto/network 模块、云 SDK、etcd、NATS 与压缩库等安全敏感依赖也已升级。

这些升级带来的可观察边缘修正包括:Go TLS/X.509/URL/archive、MQTT 超长 UTF-8 packet 编码、畸形 Azure NTLM challenge、Thrift framed transport 与 32 位编译、NATS 认证/授权/身份/拒绝服务,以及 Prometheus remote-read/write 与 UI 加固。jsonparser 的 CVE-2026-32285 调查没有产生补丁:解析到的 v1.1.2 已包含修复,也没有发现可达的脆弱符号,所以本范围内没有相应兼容性差异。

重要的有意依赖决策如下:

组件 最终选择 兼容性理由/影响
Console pgsty/silo-console v2.1.1,保持 github.com/minio/console 路径 恢复内嵌 UI,应用 Silo 品牌和双语文本,加入 Metrics V3,移除 SUBNET 流程并修复指标图例未翻译问题
客户端库 pgsty/mc,保持 github.com/minio/mc 路径 Console import path 不变,同时使用维护中的 MCLI 分叉
公共包 pgsty/silo-pkg/v3,以自有模块路径直接消费(v3.14.1;v3.12.x 及之前经 minio/pkg/v3 replace) v3.13.0 的破坏性模块路径迁移;提供 IAM 精确匹配的一半、LDAP TLS/StartTLS/deadline/close 修复、证书 watcher 清理和 RNG 修复
Kafka Sarama 1.45.1 固定以避免破坏性的 broker 协商漂移
PostgreSQL lib/pq 1.10.9 固定以避免 nil []byte / PostgreSQL 14 以前版本的行为回归;自动 DSN 引用在服务端代码中修复
压缩 klauspost/compress 1.18.7 显式安全/正确性升级
Thrift 0.24.0 修复 32 位构建
systemd 库 require 22.7,replace 为 22.6 在上游修复单调时钟回归前保留 NetBSD 编译能力

LDAP 包现在会在 ldaps:// 中使用 TLS 字段;即便开启 server_insecure,StartTLS 仍保持启用;还修复了 nil TLS panic、StartTLS deadline 以及失败后连接关闭。证书 watcher 停止时不再泄漏;Windows 上轮询可能让 reload 最多延迟约十秒。RNG subkey 熵/reset 行为也已修正,不过服务端不会走 reset 路径。

对外部 silo-pkg Go 使用者,有两项变化比服务端自身调用路径更宽:xtime.Duration JSON 从整数纳秒变为 duration 字符串;部分 AIStor action 词汇/受保护 action helper 与上游不同。特别是 Policy.IsAllowedActions 可能在受保护 action 上产生不同结论,但服务端并不调用它。服务端通过 YAML/msgp 保存相关状态,也没有调用这些有差异的 AIStor/action helper 路径,因此没有发现由这些库变化引起的服务端数据迁移或授权变化。

新工具链重新生成了 String() 文件。合法枚举输出不变;差异来自生成器来源与非法值格式化机制,不单独宣称为 S3 行为变化。

2026-08-06 审计之后的变更

上文各节描述的是 219670d3 快照。下表记录此后合并进 main、并在 20260903 版本中统一交付的行为变更。

领域 变更 出处
授权 显式删除版本按 s3:DeleteObjectVersion 授权,DeleteObjects 逐条目授权;用户与组状态变更要求与目标状态匹配的动作;策略写入拒绝裸 ARN 前缀 #104、58735ee38、229fe2b3c、eee05a17c(SN-2026-005、-009、-010)
复制信任 仅当精确标记与 s3:ReplicateObject / s3:ReplicateDelete 同时成立,复制专用 header 才获得复制语义;否则在签名验证后被移除 #101(SN-2026-008)
SSE-C 零字节对象与 GetObjectAttributes 校验客户密钥;null 版本与原地换钥复制不再把对象重写成不可读密文;CopyObject 以目标密钥报告校验和 b73581b05、474cd5801、05df6e70d、ffb70eb37、e73436c99(SN-2026-006、-007)
校验和 服务端计算分片校验和、联邦 UploadPartCopy、CompleteMultipartUpload 返回 ChecksumType、与 AWS 对齐的完成错误码、拒绝未知算法与 CRC64NVME + COMPOSITE 7fea6d5a5、8d76a255c、d014a12cf、5d152416d、7c103389f、d28885d0e
列表 对不存在的桶,ListObjects 在原先返回空列表的捷径路径上改为返回 NoSuchBucket e9c5340be
桶级 CORS 真实的 ?cors API;桶配置覆盖全局策略;预鉴权查找只读驻留元数据,否则应用全局策略;站点复制以 last-writer-wins 寄存器收敛 CORS #71、#80、#101
桶元数据 metadata.lock 串行化所有桶配置写入;ForceCreate 与站点 adoption 保留既有配置;启用 lock 的桶始终使用纯 Enabled 版本控制 #103、dd3bdb808
站点复制 Object Lock 配置以独立字段复制(仍接受旧的 Tags 载体);按站点统计状态;有效性探针在规则前缀下校验权限 3861f33cb、fb406fdc9、c9ad74673、5db7be4ee
配置 旧版数据库通知目标必须有 DSN;MINIO_CONFIG_ENV_FILE 使用保留命名目标的专用解析器 f1ba68358、6b0998157、2aea7fe9c
工具链与组件 Go 1.27.1;上游 minio-go 固定到 0e78d3f18efe(silo-go 分叉已退役);silo-pkg v3.13.2;Console v2.3.0(见 Console 页);捆绑 mcli 20260903 43f4bb7ed、4d6e1ea8e、最终依赖刷新

公共包迁往自有模块路径(v3.13.0,对 Go 消费者是破坏性变更)已被正式发布的 Server 20260903 采纳:该标签直接 require github.com/pgsty/silo-pkg/v3 v3.13.2。9 月 13 日刷新把维护中的栈升级到 v3.14.0,Server 20260916 则要求 v3.14.1;两者都不是 Server 首次采用新路径。各构建的状态见组件版本矩阵。

Server 20260916 发布的变化

以下变化已随 Server 20260916 发布,不在 Server 20260903 中。逐项修复范围及配套组件见版本矩阵,用户影响按总览编号查阅。

范围 用户可见变化 对应分类与详情
新增管理 API GET /minio/admin/v3/multipart-preflight 只读检查分片迁移准备;站点间新增 GET/PUT /minio/admin/v3/site-replication/peer/iam-revisions 同步修订与撤销状态。 O06 / 分片预检;O07 / IAM 协议
S3 条件与分片列表 多池条件写入、分片完成及版本删除更严格地核实元数据;strict 分片分页上限为 1,000,必须显式启用并完成准备。默认仍为 legacy,其缓存路径仍可能超过请求的页长。 O04、O06 / 多池一致性、分片模式
权限与持久状态 自助改密与创建用户使用独立权限;IAM 持久撤销和桶配置删除状态影响协调升级与恢复,通用桶配置墓碑导出默认关闭。 O02、O07 / 密码迁移、IAM 升级、配置收敛
数据与复制 继续修复多池副本、标签与 Object Lock 排序、删除标记恢复、SSE-C 与联邦复制;不自动重建已丢失的历史状态。 G07–G10 / 复制状态检查、版本说明
HTTP 与 TLS 请求头使用绝对读取期限;TLS 默认选择与旧代理、IdP 的互操作需要核对,正文仍使用既有滚动空闲超时。 O03 / 请求头超时、TLS/OIDC

API 新增、删除和行为变化需要分开理解:桶级 CORS 是既有占位接口的实质启用,ReadMultiple 是私有存储接口删除,在线更新是保留入口但停用功能。silo healthcheck 与 mcli checksum verify 是新增命令,分别调用既有健康端点、读取对象做本地审计。

运行与观测变化

对应 G12、B03。minio_* 命名空间与既有指标路径保留,但指标集合和数值含义并未冻结:

  • MRF 丢弃计数进入管理统计及 Prometheus v2/v3。它统计队列条目,同一对象可对应多个条目,不能当成丢失对象数。
  • IAM 撤销指标反映删除记录、协调失败、耗时与最近成功时间,需按各节点的采集语义解释。
  • 桶配额指标改为报告实际有效配额;CPU 指标采集增加并发保护。它们分别影响监控数值与运行稳定性,不代表统一性能提升。

升级时请同步核对受影响的仪表盘和告警规则。

已知残余风险与未修复项

  1. 默认来源 IP 仍可伪造。 未设置 MINIO_API_TRUSTED_PROXIES 时刻意保留上游 trust-any 行为。直连部署设为 none,代理部署使用精确 allowlist。
  2. 版本条件的后续修复。 #104 已在 Server 20260903 中修复 governance bypass 的逐条目版本授权。Snowball PAX 版本的授权时序是另一条路径;部分身份条件仍保留“存在但为空”的语义。
  3. Multipart parser 防御尚未完整。 Handler 已修复顺序,但 object layer 没有独立 uniqueness 防线;XML root 验证和继承的非数字 part 错误映射未修改。
  4. 旧通知迁移仍有风险。 按上文说明审核。
  5. 存储路径校验为词法层面。 不解析符号链接;未独立覆盖原生 Windows 执行。
  6. 私有 API 不是稳定兼容承诺。 ReadMultiple 表明即便 storage REST 协议号不变,操作仍可能消失。不要跨越该边界滚动运行混合构建。
  7. 信息性 HTTP 响应的跟踪仍不完整。 response tracking 层会把 1xx 当成最终响应;Flush/隐式 200 修复没有引入该行为,也没有声称修复它。
  8. 条件删除存在发布边界。 Server 20260903 的 DeleteObject 忽略 If-Match;Server 20260916 已通过 #145/#178 实现,提供版本时比较指定版本。DeleteObjects 仍忽略逐项 <ETag>,也未实现条件所需的额外 s3:GetObject 授权。详见已实现的契约。
  9. 条件删除有明确版本边界。 Server 20260903 忽略 DeleteObject 的 If-Match;Server 20260916 通过 #145/#178 实现该条件,并在显式指定版本时比较该版本。DeleteObjects 仍忽略每项的 <ETag>,也没有额外引入 s3:GetObject 条件权限。见已实现契约。
  10. 多站点删除桶配置的历史收敛限制。 在 PR #180(随 Server 20260916 发布)之前的版本中,在一个站点删除桶策略、SSE、标签或配额配置后,仍持有该配置的对端可能把它恢复回来(#77);当时只有桶级 CORS 使用带 tombstone 的寄存器。完整删除收敛要求全部节点升级并统一开启删除导出(MINIO_SITE_REPLICATION_METADATA_TOMBSTONES),详见桶配置收敛设计记录。

迁移检查清单

从 MinIO 切换到 Silo 时,建议按此顺序执行:

  1. 记录精确 MinIO 二进制/tag、Chart 与 values、镜像 digest、包载荷、service unit、环境文件、配置目录、数据所有权、IAM 策略、OIDC/LDAP 设置、通知 target 与代理拓扑。
  2. 备份配置与 IAM 元数据。Silo 原地读取旧磁盘,但回滚仍需要旧可执行文件/配置/Chart,以及可用的原所有权。
  3. 把服务端执行名改为 silo,不要假设 /usr/bin/minio 存在。容器可翻译 argv 层的 minio server,不能翻译绝对路径。
  4. 明确决定配置目录:用 --config-dir ~/.minio 复用,或让“只有旧目录”回退选中它。不要意外创建空 ~/.silo,再误以为旧配置丢失。
  5. 使用软件包时,授予 silo:silo 对数据、证书、secret 和日志的权限。把有意覆盖移入 /etc/default/silo,并理解它会覆盖 /etc/default/minio。
  6. 使用 Helm 时,以完整旧 values 分别渲染新旧 Chart;需要时用 nameOverride / fullnameOverride / serviceAccount.name 保留名称;Chart 与镜像原子切换。
  7. 删除 updater、callhome、SUBNET 注册和支持上传自动化,改用软件包/镜像/编排器滚动及自己的诊断传输渠道。
  8. 把 HMAC OIDC token 改为非对称 JWKS。分别测试 LDAP 成功、错密码、未知用户、后端故障和限流路径。
  9. 审核自定义 IAM 策略:受保护桶写操作需具备裸桶 ARN(除非启用 MINIO_API_LEGACY_BUCKET_RESOURCE_MATCH=on),显式版本删除需 s3:DeleteObjectVersion,用户/组启停动作已拆分,并核对密码权限拆分。
  10. 设置 MINIO_API_TRUSTED_PROXIES=none 或精确列表,清洗三种来源地址头,并加入会转发认证请求的集群 peer。
  11. 测试超大 S3 Select 记录、流式通知、unsigned trailer 拒绝、multipart 整对象 checksum、重复 part、复制、修复、KMS、每个通知 target、审计摄取及容器优雅关停。
  12. 把分布式集群所有节点作为同一构建升级。回滚时旧 Chart 与旧镜像成对使用,绝不能只回滚一个。

验证证据

在 2026-08-06 审计快照上完成的验证:

检查 结果/边界
提交枚举 下方账本对 96/96 个提交完成分类;origin/main 93 个,本地准备态 HEAD 另 3 个
净差异审查 523 个变化路径全部归入服务端运行时、内部协议、依赖、分发、文档、测试或被替代变化
Rebrand 兼容 guard 通过;兼容 manifest、分发/运行时断言及 Docker argv 测试保持稳定
Go 测试 在 219670d31 上完整 go test ./... 通过,包括 cmd、OIDC、LDAP、notify、event target、Grid、handler、hash 与全部 S3 Select 包
Helm 迁移 buildscripts/verify-helm-migration.sh 通过:lint、render、旧版升级、归档及 7 个渲染资源的身份比较
软件包生命周期 buildscripts/package/lifecycle_test.sh 通过;包载荷/provenance 断言覆盖空 DEB conflict 元数据、unit/default 路径与法律文件
站点 严格 make check 通过:模块校验、warning-fatal Hugo 渲染(617 EN / 615 ZH 页)以及 1,084 个 HTML 文件中的 388,962 个内部引用;git diff --check、双语锚点及 96/96 提交覆盖也通过

Security 文章提供更深入的威胁模型和测试向量,但其中历史性的“已发布/未发布”状态只描述写作当日。与最终快照冲突时,以本页审计边界为准。

完整提交覆盖账本

哈希按图顺序排列。Merge、文档、测试和 CI 提交也全部列入,因为分发行为和兼容性主张的证据强度同样会影响用户;“无独立运行时差异”只表示这一点,不表示没有审查。

分类 提交 验证后的净效果
初始分叉、Console、CI 与依赖基线 d4cd4b433、8630937e7、68521b37f、00f3cf74f、5abd9a80f、377fc616d、f2f9a40dc、ee55e5391、ce1c537eb、68e0ba997、1869bd30b、ff58df949、e4fa06394 Go/SDK 演进;恢复/分叉内嵌 Console;OCI 内加入 MCLI;替换 CI;修复 LDAP TLS 回归;升级安全依赖。两个 merge 提交没有超出父提交的额外差异
四月安全系列 d24f449e0、3b950f8fa、56fa63bfd、3252d5b7f、f444b6f37、efb6e5b00、db4c0fd5e、18b712d49、9e10f6d9a、f44110890、f48dbe777 OIDC、LDAP STS、复制元数据、S3 Select、unsigned trailer/Snowball、Go 1.26.2、限流计数/来源加固及安全文档
五至六月可靠性与私有 API 65795ee1f、5e40665ac、fd69c89d0、73ac52472、df627ff89、3e61b1d3a、d495d30d5 HTTP Flush、最终 LDAP 分桶、完整 S3 Select 边界、删除 ReadMultiple、Go 1.26.4/依赖更新及文档链接变化
八月前的组件集成 ce01ccbdc、4dfc27ce3、b7f52ca43、7babc0c39、c1aec0518、15fcc3c8a、3f192f3f0 历史 Chart 镜像切换、安全依赖更新、通知流 merge、可移植依赖 pin、压缩库、MCLI replace、Console v2.0
八月运行时正确性/安全 c8590413f、3e14733f1、924717926、89d346bf5、8069a32ac、a36fd8fff、ca7baa670、80e8eaa42、b6f70ab08、1af351a70、38366f654、22c1e41fd、97b7d2804、2f55347f7、744a9dcd7、fe6dc4780、162ded343、0c14d8151、9dd1dc172、2602177ef Multipart、纠删码 buffer、响应提交、panic containment、路径/元数据/分配/ReadParts containment、遗留清理、IAM/有效值/version ID/source trust、通知/libpq 与审计细节
Chart 加固与审计文档 dfe669862、5f4513fd4、b42ee4e8a、8eae745ab 安全的 Chart 用户默认值、门户/文档路由、维护者 ignore 规则与 advisory;只有 Chart 默认值直接改变运行时分发行为
到 20260804 标签的发布工程 9c799f42d、10c7670b8、cf7df097b、32863c852、632ade111、1814ae52f、475236c79、11d79fddc、3b8a55dee、ca674a696、4c185d5a6、2ca4971d9、e064b5555、aa5139369、021110b45、d88f46cce RPM/DEB/APK、provenance、OCI 发布 gate、固定 lint/generation、修复 S3 Select 测试竞态、广泛 CI、PID 1 信号、已发布目标交叉构建、安全 release dispatch、可复现性、删除陈旧配置、systemd 路径、真实失败 gate 与运行镜像关停断言
Silo 切换与 2026-08-06 准备态 HEAD 15def34dc、77bdc4c0c、15ab10833、30749911b、e071bb77e、bd8df5166、6613c2a3c、fd2ca1c6d、c46b16ec6、c47733abc、f1c77d5a2、62717d7bf、6740e6978、b57275be3、05be686b8、a6d6d9b02、6bd9cf77e、219670d31 清理未发布 MinIO 分发残留;Silo 运行身份/离线边界;改名软件包、OCI、Helm 与迁移 guard;固定 fixture;文档/仓库切换;Console 2.1.0→2.1.1;Node 24 action;DCO/法律/文档完善;重生成 CREDITS;交付 LICENSE/NOTICE

账本共 96 个唯一提交。范围内被替换的变化——例如 Console 2.0 → 2.1.0 → 2.1.1、历史 pgsty/minio 镜像/Chart 状态,以及更新器禁用后的下载 buffer 代码——只在留下最终兼容性影响时描述。

参见

5 - 从 MinIO 迁移到 Silo

单节点迁移案例、一致性备份、容器切换、数据验证与恢复边界。

从 MinIO 迁移到 Silo 可直接复用现有对象数据卷,无需逐对象导出与重新导入。普通 S3 应用无需修改代码,管理员只需核对部署配置、权限规则与状态兼容性。

当前最新发布目标为 Server 20261026(升级前请一并核对其升级要求与十月兼容性增量,尤其是曾启用 strict 分片列举的部署)。建议先对照三档兼容性总览中的 O01–O08 筛选适用条件,再执行本页步骤。RPM/DEB 软件包升级见原生软件包迁移,版本配套关系见组件矩阵。

哪些改变

按影响范围从大到小排列:

  1. 容器镜像:minio/minio、quay.io/minio/minio、pgsty/minio 统一替换为 docker.io/pgsty/silo。
  2. 软件包、systemd 服务与服务端二进制:minio → silo。
  3. 上游内置服务:原地自更新(mc admin update)与 MinIO 官方 callhome/SUBNET 已禁用;版本升级统一通过软件包、容器镜像或编排系统执行。
  4. 默认操作系统服务账号:silo(仅影响全新安装;迁移场景继续使用既有数据目录属主运行)。
  5. 默认本地配置目录:~/.minio → ~/.silo(仅影响全新进程;证书回退顺序见服务端兼容性,既有 ~/.minio/certs 仍会被自动识别)。
  6. 品牌呈现:启动横幅、Console 界面、日志措辞与文档链接显示为 Silo。

哪些不变

  • 对象布局、纠删码格式和 .minio.sys 元数据目录完全保留,可直接挂载兼容基线的数据盘(跨版本降级要求见回滚边界)。
  • 既有桶、对象版本、用户、Access Key、IAM 策略、生命周期与加密配置继续生效。授权判定、复制状态和新增元数据的行为收敛见 O02、O07 及目标版本的发布说明。
  • 常用 S3 API、SigV4 签名、SDK、mc/mcli 与预签名 URL 接入方式保持不变;校验和、条件请求和错误码收敛见 O04。
  • 网络与挂载:端点主机名、API 端口 9000、Console 端口与卷挂载路径不变。
  • 运行参数:MINIO_* 环境变量与既有服务端启动参数不变。
  • 管理与监控路径:/minio/* 路由、x-minio-* 响应头、minio_* Prometheus 指标名不变。
  • 策略命名空间标识:IAM 策略、事件通知与审计日志中的 arn:minio:* ARN、minio:s3 等服务命名空间保持原拼写,无需因产品改名而替换字符串(权限语义按 O02 核对)。

上述结论适用于比较基线及兼容的纠删码部署。注意:复用数据卷时,新进程启动、后台任务与后续请求会按新版本格式更新持久元数据(如 IAM 撤销记录或桶配置),因此切换前必须先完成一致性备份。

单节点生产案例

社区贡献者 Paris Y.(@yupoet)在 SILO #228 中记录了 2026-09-26 的一次单节点生产升级(原始报告归档):

项目 报告范围
源版本 MinIO RELEASE.2025-10-15T17-29-55Z
目标版本 SILO RELEASE.2026-09-16T00-00-00Z
部署拓扑 Docker Compose,单节点、单盘,server /data
身份与集成 仅使用 root 凭据;无 IAM 子用户、OIDC、通知目标或反向代理
数据规模 约 5,900 个对象(约 34,000 个底层存储块);数据卷先后历经 2025-09、2025-10、2026-09 三个版本,累计运行约 15 个月
验证结果 原地挂载既有数据卷启动无报错;业务侧分片上传、解析服务读取、列举与删除检查均通过

现代单盘存储与旧 FS 模式

上述案例属于单节点单盘纠删码部署(xl-single),而非早年已废弃的旧 fs 模式。仅凭启动命令 server /data 无法区分盘上格式;迁移前可只读查看数据卷 .minio.sys/format.json 中的 format 字段(切勿手动修改)。服务端加载逻辑接受 xl 与 xl-single,拒绝旧 fs 后端。

旧 fs 与 gateway 模式已于 MinIO 2022-10-29 版本移除。仍在使用旧模式的部署必须先执行 FS/Gateway 导出迁移流程,不能直接替换镜像。

此外,单节点且仅使用 root 凭据的场景不涉及跨节点二进制校验、ReadMultiple 节点间 RPC、子用户密码策略迁移、跨站复制或外部身份源;多节点或启用了 IAM/复制特性的集群请继续核对下文各节。

Docker 迁移步骤

维护中的官方镜像仓库为:

docker.io/pgsty/silo:<RELEASE-tag>

迁移时应指定明确的 RELEASE.YYYY-MM-DDTHH-MM-SSZ 版本标签(建议同时记录并固定镜像 digest),不要在生产环境使用滚动的 latest 标签。历史仓库 pgsty/minio 不会自动跳转到 pgsty/silo。

以下流程适用于 Docker Compose 管理的单存储进程。在完成升级验证前请保持业务写入暂停;共享 IAM、外部 etcd 和跨站复制部署需同步执行各自的协调升级流程。

1. 记录现有部署并准备恢复方案

  • 记录运行环境:保存当前源镜像 ID 与 registry digest、CPU 架构、Compose 项目名与服务名、实际挂载的命名卷或宿主机路径、运行 UID/GID、端口映射与启动参数,并在本地或内部镜像库保留旧镜像制品。
  • 备份配置与密钥:保存原 Compose 文件、环境变量与 secret 来源、TLS 证书挂载以及 KMS/加密密钥恢复材料。盘点桶版本控制、Object Lock、服务端加密、生命周期、IAM、复制和外部 etcd 配置,确定适用的验证项。
  • 采集代表性对象基线:升级前记录一批代表性对象(涵盖历史对象、大对象、分片对象与加密对象)的 key、版本 ID、字节大小与独立计算的内容校验和(注意分片或加密对象的 ETag 不是明文 MD5)。
  • 预发演练:在隔离副本上演练目标版本升级与回滚流程,并阻断演练环境向生产 IAM、复制或分层端点发起连接。

以下片段展示标准镜像与原生健康探针写法。请勿直接覆盖既有 Compose 文件:务必保留原有的 Compose 项目名、卷声明、运行用户、凭据来源与挂载路径(更改 Compose 项目名或卷名会隐式创建全新的空卷)。

services:
  minio:                              # 服务名可保持为 "minio"
    image: docker.io/pgsty/silo:RELEASE.2026-10-26T00-00-00Z
    command: server /data --console-address ":9001"
    environment:                      # 保留既有凭据来源
      MINIO_ROOT_USER: ${MINIO_ROOT_USER}
      MINIO_ROOT_PASSWORD: ${MINIO_ROOT_PASSWORD}
    ports: ["9000:9000", "9001:9001"]
    volumes:
      - minio-data:/data              # 保留实际使用的既有数据卷
    healthcheck:
      test: ["CMD", "silo", "healthcheck", "ready"]
      interval: 30s
      timeout: 10s
      start_period: 2m
      retries: 3
volumes:
  minio-data:

标准镜像的 entrypoint 脚本会自动将首个参数 minio 转换为 silo,因此原有的 command: minio server /data 可继续工作;但写死 entrypoint: /usr/bin/minio 的配置或脚本必须更新。标准镜像内置 curl 和带 mc 别名的 mcli,而 -distroless 变体不含 shell 与外部工具,建议统一使用原生健康检查。

2. 停止写入并获取一致性备份

在旧容器仍在运行时提前拉取目标镜像,缩短停机窗口:

docker compose pull minio

(此处及下文的 minio 代表 Compose 中的存储服务名,请替换为实际服务名。)

先停止业务写入端、定时任务及其他客户端,再停止存储容器,并确保编排器不会在备份期间自动拉起容器:

docker compose stop minio

确认没有任何进程仍在写入数据卷后,再执行离线卷备份或存储快照。仅停止业务客户端并不够,因为存储进程的后台扫描、生命周期与恢复任务仍会修改 .minio.sys 和对象元数据;必须在存储进程完全停止后打包或快照,才能获得一致性备份。

备份须完整包含数据卷及 .minio.sys 目录,保留文件属主、权限与扩展属性,并验证备份可在独立目录正常恢复。切勿在升级过程中执行 docker compose down -v,该命令会直接删除命名数据卷。

3. 启动替换后的存储服务

确认旧容器已停止、挂载的是原数据卷,且运行 UID/GID 对数据、证书和密钥具备读写权限后,仅启动存储服务本身(不连带拉起依赖它的业务容器):

docker compose up -d --no-deps minio
docker compose logs --tail=200 minio
docker compose exec -T minio silo healthcheck ready

切勿让新旧容器同时挂载操作同一数据卷。完成升级验证后再恢复上游业务流量。

Distroless 变体

pgsty/silo:<RELEASE-tag>-distroless 仅包含 /usr/bin/silo 二进制,不含 shell、mc、curl 或兼容转换脚本。其默认 ENTRYPOINT 为 /usr/bin/silo,因此 command 应直接写参数(如 command: server /data --console-address ":9001"),前面不要加 minio 或 silo。

该变体已内置原生 HEALTHCHECK。若 Compose 文件中保留了旧的 curl 或 CMD-SHELL 健康检查,会覆盖镜像默认配置并因缺少 shell/curl 而失败,请将其移除或替换为上文的 ["CMD", "silo", "healthcheck", "ready"]。默认证书搜索路径为 /tmp/.silo/certs;若使用了非默认监听地址或端口,可通过 MINIO_HEALTHCHECK_URL 指定探针目标。同一版本的标准镜像与 distroless 镜像共享完全相同的存储格式,可随时切换。

Kubernetes

Kubernetes kubelet 直接通过 Pod spec 中的 httpGet 探针检查容器,忽略 Docker 镜像内置的 HEALTHCHECK,因此标准镜像与 distroless 镜像在 Kubernetes 下的探针配置完全一致,既有探针无需修改。使用 Helm 升级时,通过 nameOverride / fullnameOverride 保持 release 名称与 PVC 绑定不变,并在应用前对比 helm template 的渲染输出(详见服务端兼容性 — Helm)。

回滚边界

对象目录布局兼容并不代表高版本写入的新元数据都能被旧版本识别。在回滚镜像或二进制之前,必须先确认持久状态是否需要一并恢复:

  • 持久化 IAM 撤销历史:启用新 IAM 撤销机制的版本不支持滚动降级。升级前须按 IAM 升级与恢复完整备份 IAM 存储与密钥材料(常规 mc admin cluster iam export 不包含删除/撤销墓碑记录)。
  • 桶配置收敛与密码策略权限:核对桶配置删除状态与密码权限回滚要求。
  • 恢复操作:若升级验收未通过,保持客户端流量阻断,停止新进程,并使用升级前的一致性卷备份、配置文件与镜像 digest 恢复。如果在备份后已产生新的写入、删除或凭据撤销,需在重新开放端点前完成差异核对与补救。

单节点迁移的行为检查

检查域 核对要点
TLS 握手与证书 20260903 与 20260916 更新了 TLS 行为;20260916 移除硬编码椭圆曲线覆盖,恢复 Go 默认后量子混合密钥交换,并在 macOS 上影响自定义 CA 信任方式。请检查入站客户端及出站 OIDC、通知、复制、分层链路(含中间 TLS 解密设备)。见 Go 1.27 TLS 与 OIDC 发现。
条件删除 自 20260916 起,单对象 DeleteObject 严格执行非空 If-Match,ETag 不匹配时返回 412 PreconditionFailed(批量 DeleteObjects 不包含此语义)。见条件 DELETE。
分片上传列举 20260916 曾提供可选的 MINIO_API_MULTIPART_LISTING=strict 磁盘扫描模式;20261018 已将其撤回并恢复 legacy 内存缓存行为(省略 max-uploads 默认 1,000,但默认缓存路径不执行严格分页)。见 20260916 说明与 20261018 升级要求。
反向代理来源地址信任 未设置 MINIO_API_TRUSTED_PROXIES 时,S3 监听器保留对转发头的历史信任行为。直连部署建议设为 none;经过反向代理时,显式配置代理 IP/CIDR 并确保代理覆盖客户端伪造的转发头。Console 与 LDAP STS 遵循各自的信任规则。见来源地址信任。
身份与对象状态 若部署使用了 IAM 子用户密码策略、服务账号、STS、OIDC、Object Lock 或复制,请按目标发行版说明、密码权限迁移和 IAM 恢复流程逐项核对。

从 RELEASE.2026-08-06 升级

RELEASE.2026-08-06T00-00-00Z 之后的版本收紧了以下曾被 20260806 放行的行为,升级前请逐项核对:

  1. 显式删除版本需要 s3:DeleteObjectVersion。 携带 versionId 的 DeleteObject 与 DeleteObjects 条目按 s3:DeleteObjectVersion 鉴权(与 AWS S3 一致)。请为需要删除指定版本的主体补充该权限;凡是用 Deny s3:DeleteObject 阻止永久删除的策略,必须同步加上 Deny s3:DeleteObjectVersion。
  2. 启用与禁用账户拆分为独立管理动作。 admin:EnableUser / admin:DisableUser(以及用户组的对应动作)严格按请求的目标状态鉴权;仅授予其中一项的策略将无法执行反向操作。
  3. 新建与更新策略拒绝裸 ARN 前缀(如 arn:aws:s3:::)以及同时包含 Resource 与 NotResource 的语句。已落盘的存量策略仍可正常加载,但重复下发此类策略的自动化脚本会报错。
  4. 旧版数据库通知目标必须提供连接串。 已启用的旧版(pre-KV)PostgreSQL 或 MySQL 通知目标若缺少 connection_string / dsn_string,启动时会直接报错退出(错误日志脱敏),而 20260806 在此情况下会静默丢弃所有通知目标。
  5. 严格校验 Checksum 请求头。 未知的 x-amz-checksum-* 算法、CRC64NVME 与 COMPOSITE 组合、以及与创建上传时矛盾的校验和类型断言均返回 400 BadRequest。AWS SDK、minio-go 与 mcli 的默认行为不受影响。
  6. 桶级 CORS 独立生效。 配置了桶级 CORS 的存储桶严格按桶配置响应,MINIO_API_CORS_ALLOW_ORIGIN 仅作为无配置桶的回退默认值。在站点复制集群中,请等所有站点升级后再配置桶级 CORS,否则旧站点会接收但忽略该配置并持续报告不一致。
  7. 回滚至 20260806 会丢失桶级 CORS 配置。 20260806 忽略桶级 CORS 并在重写桶元数据时将其丢弃;若需回滚,请先导出 CORS 配置,待重新升级后恢复。

9 月 3 日版本的 Console 回归与修复

RELEASE.2026-09-03T13-18-01Z 曾停止识别未配置本机代理转发的客户端地址,并忽略了四个 CONSOLE_WS_MAX_* WebSocket 连接限额参数。这会影响基于客户端 IP 的 Allow/Deny 策略判定,并导致管理员无法调整单 IP 默认 8 条匿名连接的上限。

20260916 及后续版本(#147、#148)已修复此问题:除非显式设置 MINIO_API_TRUSTED_PROXIES=none/off,内嵌 Console 默认恢复对环回(loopback)TCP 对端的转发头信任,并正常读取环境变量或 MINIO_CONFIG_ENV_FILE 中的四个 CONSOLE_WS_MAX_* 限额;远程反向代理仍需显式列入 MINIO_API_TRUSTED_PROXIES。详见 Console 设置参考。

若仍停留在 20260903,可将本机代理地址显式加入 MINIO_API_TRUSTED_PROXIES 以恢复客户端 IP 识别,但注意这会同时把 9000 端口的 S3 监听器切换为白名单模式,需将该监听器依赖的所有代理地址一并列入。

一个集群只运行一种二进制

分布式集群节点在 bootstrap 阶段会相互校验二进制校验和。若某个节点与对端节点的二进制不一致,该节点不会报错退出,而是持续停留在 activating 状态并输出:

Expected Silo binary checksum: ..., seen: ...
Waiting for at least 1 remote servers with valid configuration to be online

该校验适用于任意两个不同二进制之间(无论是 MinIO 与 Silo 混跑,还是不同版本的 Silo 混跑)。因此,分布式集群切勿逐节点滚动迁移或跨版本滚动升级,必须一次性全集群切换:先停止所有节点上的旧二进制,再统一启动新二进制(例如在 Compose 中一次性修改所有节点镜像并执行一次 docker compose up -d)。回滚同理。

单节点部署不受此限制。同一版本二进制下的日常维护滚动重启则完全正常,重启每个节点前可用 silo healthcheck --maintenance cluster 检查是否具备停机冗余(退出码 0 表示当前节点可安全下线)。

升级验证

在恢复业务流量前,按以下顺序完成验收:

  1. 核对实例与卷身份:确认运行中的版本/镜像 digest、挂载的原数据卷标识、预期桶列表及启动日志(防止误挂载到新建的空卷)。
  2. 执行就绪探针:在容器内运行 silo healthcheck ready,或从宿主机探测 HTTP 端点(默认本机 HTTP 监听器可执行 curl --fail --silent --show-error http://127.0.0.1:9000/minio/health/ready;TLS 环境请指定正确的主机名与受信任 CA)。
  3. 抽样校验存量数据:通过业务 SDK 或客户端读取升级前记录的代表性历史对象,核对字节内容、大小与独立校验和;按实际启用的功能检查多版本、标签、SSE 加密、Object Lock 保留期与 Legal Hold。
  4. 测试写入与列举路径:在专用测试桶或测试前缀上,使用真实客户端完成普通上传、分片上传合并、列举、回读与删除(切勿删除生产对象做冒烟测试,清理测试数据时注意桶的版本控制与保留期规则)。
  5. 验证权限与外部集成:验证子用户、服务账号、STS/OIDC 以及预期应被拒绝的越权请求;共享 IAM 或跨站复制集群须按 IAM 升级流程逐个检查参与站点。
  6. 重启持久性复核:在流量仍暂停的情况下重启一次存储服务,确认重启后就绪状态、历史对象读取与签名请求均正常,再正式恢复上游业务流量。

若发现历史元数据或对象访问异常,请保留错误日志与对象标识并在隔离副本上排查;迁移观察窗口内建议暂缓写入非必需的新特性状态,以便随时按回滚边界安全恢复。

6 - MCLI 客户端兼容性注记

pgsty/mc 的兼容性、行为变化、安装方式与当前版本

mcli 是 Silo 构建的 MinIO 客户端(mc)。本页记录二者在哪些地方可以互换使用,在哪些地方存在差异。

pgsty/mc 从上游项目 minio/mc 的最终提交 77f82e18(2025-11-06)分叉而来。上游仓库已于 2026 年 7 月归档,且从未发布过包含该提交的版本 —— 因此每一个 mcli 版本都比历史上任何官方 mc 二进制更新。本站记录的分支版本包括:20260313、20260321、20260417、20260804、20260806、20260903、20260913、20260916、20261018 与 20261026。最新版本为 20261109;历史说明保留各自比较基线。

提示

当前正式版: mcli 20261109,包版本 20261109000000.0.0,源码 e1d4cc5abfe0。Windows 使用 ZIP;Linux/macOS 使用 tar.gz,提供 Linux RPM/DEB/APK 与 Docker Hub 镜像。

当前版本变化

20261109 发布说明 覆盖 pgsty/mc#74、#76 和 #77 的修复。完整变更见源码的更新日志。

  • cp 和 mv 在准备某个源失败后继续处理其他独立源,整体返回非零。参数列表中后面的源仍可能被复制或移动;成功移动的源会被删除。成功操作不会回滚。
  • 逐对象 JSON 开始记录中的 totalCount、totalSize 分别是累计准备好的对象数与字节数,会随源列举继续增长。它们不是最终任务总量,也不能用作完成百分比的分母。请检查最终退出码、错误记录与最终字节汇总。
  • share upload 生成 POSIX shell 命令,完整参数使用单引号引用,文本字段使用 --form-string。正确引用并替换占位符后,在 POSIX shell 中执行;若命令保存在 upload 变量中,使用 sh -c "$upload",直接执行 $upload 不会解释其中的引号。Windows 上使用 Git Bash 或 WSL,而不是 cmd.exe。
  • 非法 --attr 会使 cp、mv 在传输前失败。键值对之间用分号分隔,例如 --attr 'key=value;other=value'。cp、mv、mirror、pipe 会忽略空条目,包括末尾和连续分号;不含任何键值条目的输入仍然报错。
  • 删除权限或 WORM 保护错误、IAM 或桶元数据导入的逐项失败都会返回非零,并保留详细报告。IAM 只有收到 NotImplemented 或 XMinioAdminVersionMismatch 才会回退旧 API。
  • mv 拒绝已识别的自身搬移,也拒绝桶和对象路径相同、协议和端口相同且 IP 重叠的端点间搬移,包括 --resolve 映射。同 IP 上的虚拟主机也可能被拒绝;先确认它们的存储实际独立,才能分步复制、核验、显式删除,仅通过两个别名读到相同字节不能证明存储独立。不同地址、端口、代理路由、虚拟主机寻址或 DNS 变化仍可能隐藏同一后端;同一存储的别名应使用一致的端点 URL,不能仅靠 DNS 推断任意后端的身份。经传输层规则选定的 HTTP 代理访问的端点,不会仅因本地 DNS 失败而被拒绝;无法解析的直连端点仍然失败。代理选择遵循 NO_PROXY。
  • 容器镜像预先创建权限为 1777 的 /.mc 目录(供无 passwd 条目且 HOME=/ 的非 root UID 使用),并在 /licenses/ 下包含法律声明文件(#77);--config-dir 与 MC_CONFIG_DIR 仍优先生效。

继承自 20261026 的变化

基于 Go 1.27.3、silo-pkg 3.15.2 与固定提交的上游 SDK(320af050c445)构建。相比 20261018,本版修复了身份与连接配置缓存隔离、admin replicate resync 的 JSON 输出与终态判定、吞吐量及 batch IOPs 计数溢出、无实时指标时的任务状态轮询、部分操作失败的退出码、别名区域配置以及 SDK 分片上传/读取/批量删除行为。自动化脚本需适配新增的 pending 状态,以及部分 resync 变更操作失败时的非零退出码(查询已处于失败状态的任务仍返回退出码 0)。别名 region 支持未引入新 CLI 参数,原有配置可直接沿用。

20261026 对应的模块版本为 github.com/pgsty/mc v0.0.0-20261026120214-0ceb298cdcd0。客户端升级不涉及服务端协议变更,以 SILO 作为正式维护目标。详见完整变更与组件矩阵。

继承自 20260916 的变化

20260916 使用 pkg v3.14.1、上游 SDK 32e1f32cb176、JWX v3.3.0 和 Go 1.27.1。 SDK 会重试并报告单次 CopyObject HTTP 200 响应内嵌的 S3 错误(适用于小于 64 MiB 的对象或显式 --disable-multipart,更大对象默认走 ComposeObject),避免复制失败后触发 mv 删除源对象。 JWX 更新修复输出 JSON 字段名的转义,pkg v3.14.0 的密码权限语义保持不变。

  • mirror 逐对象权限错误会报告并累计失败,继续处理后续对象;有限任务最终返回 1。本地目标删除失败不再被吞掉。无需 --skip-errors 即可继续处理这些权限错误;watch 的列举/监听错误仍保留原有取消重试。
  • 失败的 mirror 普通模式不再输出成功结束统计。显式 --summary 仍输出统计,JSON 的 status 为 failure;文本错误在 stderr、统计在 stdout。
  • legalhold set/clear、递归 retention 部分失败,以及 mv 复制成功但源删除失败都会返回非零;成功对象不回滚。retention 每个失败对象只输出一次诊断。
  • 空 retention 时长和非法 find regex 正常报错,不再 panic;极短传输的 JSON 速度统计不再产生 Inf。

脚本升级注意: 上述失败曾返回 0 的路径现在返回 1,请检查最终退出码与错误记录。配置格式、别名和 MC_* 变量不变。详见本次发布说明。

继承自 20260913 的变化

20260913 使用 pkg v3.14.0、上游 SDK 60bd07042d49 和 Go 1.27.1,刷新 Go x/* 依赖。 它保留 mirror 目标历史版本,修复重启 dry run、非交互行为、传输/SQL 错误退出、空上传显式校验和及 quiet JSON 输出,布尔环境变量支持 on/off。 策略 Deny/NotResource 与有界通配匹配修复会保留原先可能丢失的拒绝语句;已丢失语句需从原始策略恢复。 密码权限拆分配套 Console v2.4.1 与对应 Server;协调升级时需检查现有策略中的 Deny。

继承自 20260903 的变化

20260903 客户端保留上游命令、配置、协议与 JSON 契约;相对 20260806 有以下明确新增与收紧:

  • 只读校验和审计: mc checksum verify 流式读取对象,并比对存储的 FULL_OBJECT CRC32、CRC32C、CRC64NVME、SHA1 或 SHA256。它支持单对象、递归前缀、精确或全部版本、JSON Lines 清单、dry run、受限 worker、大小/时间过滤、SSE-C、机器可读输出、私有权限报告文件与显式失败策略;绝不修复或改写对象。
  • 凭据输出 fail-closed: --debug、admin trace、错误、跳转、trailer、JSON 文档、SSE-C 路径、自定义 header 与运行时登记密钥都会在显示前清洗。支持包与集群导出产物(包括轮转副本)在 POSIX 系统上以 0600 创建。
  • 正确性修复: JSON Prometheus metrics 不再 panic;pipe 空输入使用普通零字节 PUT;S3 Select 在打印有效结果后不再重复关闭响应;app 层格式错误的全局参数不再被忽略;服务账号策略可再次被清除。
  • 严格写入、宽松读取: 命名策略与服务账号写入路径拒绝空或畸形策略、裸 ARN 命名空间,以及混合 S3/admin action 的 statement。既有存储策略仍可读取;服务账号空策略仍表示“清除内联策略”。
  • 依赖与工具链下限: 源码构建要求 Go 1.27.1,并直接使用 github.com/pgsty/silo-pkg/v3 v3.13.2。minio-go 钉在上游 master 提交 0e78d3f18efe,gRPC 为 1.83.2,x/crypto 为 0.56.0。Darwin 二进制要求 macOS 13 或更高版本。
  • 可验证交付: 公开 Release 不可变,包含 19 个通过校验和核验的资产;归档与 DEB/APK 通过 Sigstore 证明绑定到签名标签和精确源码,RPM 携带 PGSTY GPG 签名。版本标签与 latest 容器均发布相同的 linux/amd64、linux/arm64 manifest。

专门场景需要留意两项底层兼容变化:JWX 3.2 会更严格地拒绝不符合标准的 JWT crit 处理;Unicode 宽度实现更新可能轻微改变 Indic 或大量 ZWJ 字符在表格/进度条中的对齐。

兼容原则

本分支只遵循一条规则:改名的是交付物与渠道,不是你手里的工具。

  • 改名 / 更换 —— 磁盘上的制品名(mcli)、--version 与 --help 中的产品身份、分发渠道(GitHub pgsty/mc、Pigsty 软件仓库、docker.io/pgsty/mc),以及制品签名密钥。命令语法没有改 —— 而且取决于你怎么安装,连你敲的名字都可以不变。
  • 保留的接口 —— 熟悉的命令语法、S3/admin 协议与 x-minio-* 标识;输出、授权与错误处理的具体变化以上述版本说明为准;配置文件格式与别名语义;MC_* 环境变量(含 MC_HOST_<alias>);.part.minio 断点续传后缀;以及 Go 模块路径 github.com/minio/mc。
  • 切断 —— 所有连向 MinIO 运营服务的通道:发布/更新源、SUBNET 支持与许可门户、遥测,以及预置的 play 演示别名。受影响的命令为保持脚本兼容而保留,以稳定错误快速失败,而不是直接消失。
  • 保留 —— 上游版权与 AGPL-3.0 许可证。运行时输出同时致谢 MinIO, Inc. 与 PGSTY。

上游 mc 写出的配置文件 mcli 原样可读,反之亦然。SILO 发布以 Silo 服务端作为 mcli 的正式验收对象;对上游 MinIO 与其他 S3 兼容端点的支持属于尽最大努力,使用时应联测实际版本组合。

差异区别

按「影响到你的可能性」从高到低排列。

1. 名字 —— 你敲的是什么,配置就在哪

对许多用户来说这里其实什么都没变:容器镜像的入口仍然是 mc,以 mc 名安装的二进制与上游行为完全一致。变的是我们 交付 的东西 —— 归档包与 Linux 软件包把二进制装为 /usr/local/bin/mcli(软件包名 mcli)。

两个名字都没有被硬编码在任何地方。上游客户端自 2016 年起就根据被调用的名字派生运行时身份,而 mcli 正是上游自己的 CONFLICT.md 为解决与 Midnight Commander 的冲突所推荐的改名方案(issue #873)—— 本分支只是把这个建议扶正为官方发行名,代码零改动。这套机制的实际含义如下:

跟随调用名 与名字无关、恒定不变
配置目录:~/.mc vs ~/.mcli(Windows:%USERPROFILE%\mc\ vs …\mcli\) 环境变量:恒为 MC_* —— 不存在 MCLI_CONFIG_DIR
帮助与用法文本中显示的程序名 config.json 格式 —— 双向完全一致、可互换
shell 自动补全的注册名 全部命令、参数、JSON 输出、退出码
User-Agent 应用后缀(mc/… vs mcli/…) --config-dir 与 MC_CONFIG_DIR 覆盖

唯一真正的坑:第一次运行 mcli 时,你已有的 mc 别名不会出现 —— 它从空的 ~/.mcli 开始。两种解法:继续以 mc 名调用它(一个符号链接即可 —— 起作用的是 argv[0]),或用 cp -a ~/.mc ~/.mcli 一次性搬运状态。自动化与配置模板则应显式设置 MC_CONFIG_DIR:环境变量前缀不跟随名字,一套模板即可通吃两个名字。详见迁移指南。

获取渠道:GitHub Releases(SHA-256 校验文件 mcli_<version>_checksums.txt)、Pigsty 软件仓库(RPM 经 GPG 签名,密钥指纹 9592A7BC7A682E7333376E09E7935D8DB9BD8B20),或 docker.io/pgsty/mc。上游的 minisign 公钥不为这些制品签名,dl.min.io 永远不会被访问。发布标签(RELEASE.YYYY-MM-DDTHH-MM-SSZ)与软件包版本(YYYYMMDDHHMMSS.0.0)沿用上游方案。

容器镜像以 root 运行时,别名保存在 /root/.mc。若要以其他 UID 运行(--user、Kubernetes 的 runAsNonRoot)、使用只读根文件系统,或让别名在容器结束后保留,请把 MC_CONFIG_DIR 指向该 UID 可写的目录 —— 它拥有的绑定挂载目录(需事先创建)、emptyDir 或数据卷:

docker run --rm --user "$(id -u):$(id -g)" -e MC_CONFIG_DIR=/config -v "$HOME/.mcli:/config" pgsty/mc alias list

2. mcli update 恒定失败 —— 这是有意的

自更新已移除。mcli update 不联网、不替换自身二进制,打印明确提示并 恒定以退出码 1 结束。上游 mc update 在已是最新版时返回 0,因此 任何调用它并把非零退出码视为失败的 cron 任务或脚本都会开始报错 —— 请删除该调用,改用软件包管理器或 GitHub Releases 升级。每次执行时向上游发布源的版本探测也已移除,MC_UPDATE / MINIO_UPDATE 不再被读取。

(mcli admin update ALIAS —— 升级 服务端 —— 命令仍在,但 Silo 服务端会在服务侧拒绝就地升级。)

3. SUBNET、许可与遥测命令

所有连向 MinIO SUBNET 的路径均在构建期关闭。受影响的命令保留名称与参数,打印稳定提示 —— “MinIO SUBNET services (registration, licensing, uploads) are disabled in this Silo build of mc; diagnostics remain available locally.” —— 并以退出码 1 结束:

命令 现在的行为 替代方式
mcli license register 提示后退出码 1 ——
mcli license update ALIAS(在线续期) 提示后退出码 1 mcli license update ALIAS license.key(离线,仍可用)
mcli support upload 提示后退出码 1 通过自有渠道传递文件
mcli support proxy set 提示后退出码 1 proxy remove 仍可清除遗留配置
mcli support callhome enable 提示后退出码 1 disable / status 照常工作

诊断能力本身全部保留:mcli support diag / perf / profile / inspect 恒定以本地(airgap)模式运行 —— 结果写入本地文件,不上传任何数据,SUBNET 注册也不再是前置条件。两项相关加固:inspect 不再回退到用内置的 MinIO 公钥加密输出(你的归档始终由你自己解密);自 20260804 起 --debug 输出对 SUBNET 凭证脱敏 —— 如果你分享过旧版本的调试日志,请轮换其中的密钥。mcli license info 与 unregister 在本地照常工作。

4. play 演示别名不再预置

全新配置只预置 local、s3、gcs,不含 play。假定演示别名存在的教程与冒烟脚本需要显式添加:mcli alias set play https://play.min.io <access-key> <secret-key> 即可恢复旧行为 —— 主动连接任何 S3 端点都不受限制。已有配置文件永远不会被修改。

5. 输出文案携带 Silo 身份

mcli --version 保留机器可读的首行,新增身份行与双版权行;--help 显示 “Silo client”,示例使用 mysilo。命令语法分毫未动 —— 只有 grep 上游身份字样(如 “MinIO Client”)的脚本需要调整。

6. 面向开发者

模块路径保持 github.com/minio/mc,现有 import 无需修改即可编译 —— 但 go install github.com/minio/mc@latest 安装的是 已归档的上游版本,不是本分支。请从源码构建(git clone https://github.com/pgsty/mc && cd mc && make)或通过 replace 指令引用。贡献无需 CLA,但每个提交必须携带 DCO 签署(git commit -s)。上游已归档也意味着继承的缺陷只会在本分支修复 —— 最需要注意的是 minio/mc#5139(版本化桶上的 mirror --remove --watch)。

迁移指南

从官方 mc 二进制迁移到 mcli:

  1. 安装 mcli,任选一条分支渠道(校验方式见 §1):GitHub Releases 归档包、Pigsty 软件仓库的 yum install mcli / apt install mcli,或 docker pull pgsty/mc。
  2. 决定用什么名字调用它 —— 这决定它读取哪份配置:
    • 保留 mc 名称(摩擦最小):确认系统中已无上游二进制(command -v mc)后,以 mc 名安装 —— 例如 ln -s /usr/local/bin/mcli /usr/local/bin/mc。以 mc 调用时它原样读取你现有的 ~/.mc,无需迁移任何东西。
    • 改用 mcli 名称:用 cp -a ~/.mc ~/.mcli 一次性搬运状态,或设置 MC_CONFIG_DIR=~/.mc。两个客户端也可以并存,各用各的目录。
  3. 清理自动化脚本:
    • 移除 mc update 调用 —— 现在恒定退出码 1;
    • 移除 license register、support upload、support callhome enable、support proxy set —— 同样是稳定失败;
    • support diag / perf / profile / inspect 照常工作并写本地文件;删除任何期待「上传到 SUBNET」的后续步骤;
    • 检查所有解析 --version 首行之外内容的逻辑。
  4. 复查 play 依赖(见 §4)。
  5. 验证:mcli --version、mcli alias ls,然后对你的服务器执行 mcli ls <alias> 与 mcli ping <alias>。
  6. 回退 始终是平凡操作:配置格式双向一致,保留旧的 mc 二进制即可随时切回。

参考阅读

7 - 原生软件包迁移

silo RPM/DEB 软件包相对 minio 软件包的变化:文件布局、服务账号、接管语义与注意事项。

版本说明: 本页命令与输出示例以 Server 20261026 为蓝本,现已公开发布;下载与升级要求见下载页和发布说明。

Silo 为 amd64/arm64 发布 RPM、DEB 与 APK 软件包,托管于 GitHub Releases,附 SHA-256 校验和与构建溯源 attestation。本页记录相对 minio 软件包安装的变化:文件布局、服务账号与注意事项。迁移的总体范围见迁移指南。

安装

从 release 资产中选取与平台匹配的软件包,安装前先校验:

SILO_TAG=RELEASE.2026-10-26T00-00-00Z
SILO_RPM=silo-20261026000000.0.0-1PGSTY.x86_64.rpm
SILO_URL="https://github.com/pgsty/silo/releases/download/$SILO_TAG"
curl -fLO "$SILO_URL/$SILO_RPM"
curl -fLO "$SILO_URL/$SILO_RPM.sha256sum"
sha256sum --check "$SILO_RPM.sha256sum" && \
  sudo dnf install "./$SILO_RPM"

以上为 x86_64 RPM 示例;ARM64 使用 .aarch64.rpm,Debian/Ubuntu 使用下载页列出的 .deb 文件和对应校验和。

使用 Pigsty 软件仓库时,dnf install silo / apt install silo 解析同样的工件(仓库可能落后于 GitHub Releases)。该软件包刻意不提供任何 minio 别名或 Provides: 关系——minio 与 silo 是并存的独立软件包,接管发生在 systemd 层而不是软件包替换层(见接管)。

文件布局

MinIO 安装 Silo 软件包
/usr/bin/minio /usr/bin/silo(同时提供 silo healthcheck)
minio.service /usr/lib/systemd/system/silo.service
/etc/default/minio 仍然优先读取;/etc/default/silo 按变量覆盖(noreplace/conffile,升级不覆盖)
服务账号 minio-user(上游)/ minio(Pigsty) silo:silo,声明于 /usr/lib/sysusers.d/silo.conf,安装时创建
— /usr/share/doc/silo/LICENSE、NOTICE(AGPL-3.0-or-later)

两项软件包特性:

  • 安装过程不会自动启动或 enable 服务;postinstall 仅创建 silo 账号并执行 systemd reload。
  • 软件包可与 minio 软件包并存安装,无文件冲突,保留旧软件包以便随时回滚。

服务账号

unit 默认 User=silo,而现有数据、TLS 私钥与 KMS 凭据属于原 MinIO 用户。不要 chown 数据,用 drop-in 让 Silo 以现属主运行:

ls -ld /path/to/your/data              # 记录属主,例如 minio-user
sudo mkdir -p /etc/systemd/system/silo.service.d
sudo tee /etc/systemd/system/silo.service.d/10-legacy-user.conf <<'EOF'
[Service]
User=minio-user
Group=minio-user
EOF
sudo systemctl daemon-reload

这同时保证 TLS 可用:Silo 从运行用户的家目录解析证书(~/.silo/certs,仅存在旧 ~/.minio/certs 时回退使用),现有 public.crt/private.key/CAs/ 无需拷贝即被找到。缺少 drop-in 时,TLS 部署启动失败:

FATAL Unable to start the server: HTTPS specified in endpoints,
      but no TLS certificate is found on the local machine

改用 silo 账号是之后的可选变更:把证书移到 silo 可读路径、在 MINIO_OPTS 中设置 --certs-dir,并在迁移窗口之外转移数据属主。

接管与回滚

这是一个接管型 unit:

[Unit]
After=network-online.target minio.service
Conflicts=minio.service

[Service]
Type=notify
EnvironmentFile=-/etc/default/minio
EnvironmentFile=-/etc/default/silo
ExecStart=/usr/bin/silo server $MINIO_OPTS $MINIO_VOLUMES
Restart=always
  • Conflicts=minio.service:systemd 不允许两个 unit 同时运行,起一个即停另一个。
  • EnvironmentFile 链使 /etc/default/minio 中的 MINIO_VOLUMES、MINIO_OPTS、凭据与 KMS 配置原样生效。
  • Type=notify:systemctl start 仅在服务端真正就绪后返回成功。

切换:

sudo cp -a /etc/default/minio /etc/default/minio.migration-backup   # 廉价的保险
sudo systemctl disable --now minio.service
sudo systemctl enable  --now silo.service
silo healthcheck --url https://127.0.0.1:9000 ready    # 未启用 TLS 用 http://
mc admin info <现有别名>

回滚前请核对回滚边界中的 IAM 与桶配置状态要求。单节点切换 systemd unit 的命令如下:

sudo systemctl disable --now silo.service
sudo systemctl enable  --now minio.service

验证完成、回滚窗口关闭后,可选择 mask 旧 unit,使任何操作都无法再直接启动它:

sudo systemctl mask minio.service

注意事项

  • 集群所有节点协调切换。 先在所有节点完成准备(装包、建 drop-in),再停止所有旧进程,确认退出后启动所有新进程,避免新旧版本同时操作存储。混跑和二进制一致性见迁移说明;涉及共享 IAM 或站点复制时,按 IAM 升级流程协调所有参与端。回滚也需满足对应状态恢复条件。
  • 非软件包安装同样适用。/usr/local/bin/minio 加自定义 unit 的部署以相同方式被接管,只要其配置位于 /etc/default/minio。
  • 崩溃循环有频率限制。 配置错误(如缺证书)时 Restart=always 反复重启,直至触发 systemd 启动限制(Start request repeated too quickly)。修复根因后执行 systemctl reset-failed silo && systemctl start silo。
  • 旧 minio.service 停止时可能卡住。 旧 unit 常见 TimeoutSec=infinity。排空流量、等候约定的优雅退出时间后仍卡住时,可由运维者执行 sudo systemctl kill --signal=SIGKILL minio.service 强制结束,确认旧进程退出后再启动 Silo。这会中断残余请求;不带信号参数的 systemctl kill 默认只是再发一次 SIGTERM,不能解决忽略该信号的进程。
  • 桥接期的环境链可能反咬一口。 /etc/default/silo 存在时 /etc/default/minio 仍会被读取:从 /etc/default/silo 删除一个变量并不等于禁用它——/etc/default/minio 里的旧值会重新生效。要禁用请同时从两个文件移除,或在仍携带它的文件里注释掉。
  • 保留回滚窗口。 验证完成前保留 minio 软件包、unit 与二进制;已禁用的 unit 没有开销,之后可按需移除旧包。
  • 迁移后的滚动重启:每次重启前用 silo healthcheck --maintenance cluster 把关;退出码 0 表示停掉本节点仍保有写 quorum,HTTP 412 表示不能停。

8 - Console 兼容性注记

SILO Console 与上游 MinIO Console 的差异
说明

最新正式版: Console v2.7.0(2026-11-09,UTC+8)加入十种界面语言、阿拉伯语 RTL、容器 CA/临时目录修复、用量后台任务的 TLS 与调度修复、普通 HTTP 下的目录大小计算、silo-pkg v3.16.0、正式版 mcli 20261109 及 Swagger 文档更新。Console v2.6.0 新增了用量扫描、保留版本统计与存储桶管理修复。升级独立 Console 不会替换 Server 内嵌控制台;内置策略 Reset 与实时存储桶列表需配合 Server 20261026 正式版生效(Server 20261018 不包含这两项服务端缓存修复)。配套版本见组件矩阵。

SILO Console 是 Silo 构建的 MinIO Console。本页记录二者在哪些地方可以互换使用,在哪些地方存在差异。先看三档兼容性总览,再按下文核对界面与自动化接口。

pgsty/silo-console 延续上游 minio/console 的历史,起点是其最终提交 feff71e4(2026-04-16),品牌重塑自 50797deb(2026-08-04)开始。上游仓库已不再公开 —— github.com/minio/console 现在返回 404,而 minio/mc 只是归档 —— 因此源码谱系只在这个分支中留存。Go 模块路径仍可解析,因为模块代理继续提供它此前缓存的版本。较早版本记录:v2.0.0、v2.1.0、v2.1.1、v2.2.0、v2.2.1、v2.3.0、v2.4.0、v2.4.1、v2.4.2 与 v2.5.1。

2.6.0 用量扫描与存储桶管理

Console 2.6.0 新增可取消的目录与存储桶用量扫描(分别显示当前字节与保留版本字节)、可选的 PostgreSQL 持久化用量后台任务、保留期/配额/复制带宽输入的精确整数范围校验、创建启用对象锁存储桶时的版本排除拦截、路由切换期间隐藏并禁用旧对象详情与版本控件(#81),以及内嵌 Console 服务的三分钟 keep-alive 默认值。

2.5.1 管理修复

仅切换用户组启用/禁用状态时保留原有成员,显式传入成员数组时仍替换成员列表;支持解析 OIDC 字符串数组格式的组声明以保留对应权限,并仅在配置了 HTTPS 或可信代理时启用安全会话标记。凭据导出保持合法的 UTF-8 JSON 格式,流式 ZIP 在写出首字节前失败时透传底层 S3 错误状态;同时修复了键盘焦点、无障碍名称与标签页滚动问题。详见完整 2.5 发布说明。

原则

本分支优先保留既有集成契约,同时明确记录授权、响应与界面变化。

  • 改名 —— 磁盘上的产物(silo-console)、界面与 --version 中的产品标识、分发渠道、签名密钥。
  • 保留的基础契约 —— Go 模块路径 github.com/minio/console、既有 CONSOLE_* 环境变量(含 CONSOLE_MINIO_SERVER 与 CONSOLE_MINIO_REGION),以及打包标识 minio-console.service、console-user、/etc/default/console。REST API 沿用既有体系,具体响应与操作变化见下文。
  • 切断 —— 自动自更新、遥测、分析、信标、外部脚本与字体、以及 call-home。只有在显式配置时才会访问版本目录,入口是 SILO_RELEASE_SERVICE_HOST,并保留 RELEASE_SERVICE_HOST 作为兼容回退。
  • 保留 —— 上游版权与 AGPL-3.0 许可证。运行时输出同时致谢 MinIO, Inc. 与 PGSTY。
说明

SILO Console 不是通用 S3 浏览器。它的管理功能需要 Silo 在 S3 API 之外实现的 MinIO 兼容管理 API。

差异

1. 保留了完整的管理控制台

这是最大的功能差异,方向与通常的分支相反:上游把社区版控制台裁剪成了对象浏览器,SILO Console 保留了完整的管理界面 —— 仪表盘、健康状态、日志、诊断与速度测试;存储桶、对象、生命周期、复制、通知与分层管理;用户、用户组、服务账号、策略、身份提供方与 KMS 配置;以及服务器配置。

2. 仪表盘面向 Metrics V3

仪表盘组件查询 MinIO Metrics V3 指标目录 —— 也就是当前部署实际抓取的那一套 —— 并针对其零值语义与按节点导出的语义做了保护,使面板能区分"真实的零"与"数据缺失"。映射关系记录在 docs/metrics-v3.md。

3. 更小、更安静的产物

内嵌前端从约 10 MB 降到 3 MB 以内,可逐字节复现构建,并由发布门禁强制校验。没有任何形式的遥测,页面本身也没有外部网络依赖。

4. 界面语言

已发布的 Console 2.6.0 提供中英文界面。2.7.0 源码通过统一菜单新增法语、德语、俄语、 西班牙语、巴西葡萄牙语、日语、阿拉伯语和土耳其语,词典全部内置,并支持阿拉伯语 RTL。 英语仍是默认与回退语言;文档保持中英双语,服务器消息和日志正文原样保留。 覆盖范围与维护分层见语言设计。

5. 对象列表按页操作

对应 B02,自 Console v2.4.0 起使用游标分页,v2.5.1 保留该行为。默认每页 100 项,可选 50、100、250、500、1,000;提供首页、上一页与下一页,不提供“加载全部”或任意跳页。

排序、名称筛选和全选只作用于当前页。 只有首页已包含整个目录时,它们才覆盖整个目录。翻页保留筛选文本、清空选择;更换页大小回到首页,更换目录清空筛选。失败的页面保留上一页供重试。

Rewind 与“显示已删除对象”没有游标,最多返回 1,000 个版本,并有时间预算;触及限制会提示结果不完整。详见对象浏览器契约。

6. API 返回与自动化

对应 B04、O05。会话响应增加 accountAccessKey,对象列表显式返回零字节对象的 size: 0;会话能力字段还会随有效权限变化。自制解析器应容忍新增字段,Console 自动化应处理分页、会话失效和 WebSocket 错误。

用户启用/禁用新增独立的 PUT /api/v1/user/{name}/status,旧 PUT /api/v1/user/{name} 保留但已弃用;批量下载沿用原入口,同时接受受限表单以支持原生流式 ZIP。改密权限另见密码权限迁移,分享下载边界见 v2.4.1 说明;定制调用以当前 API 定义为准。

Console v2.4.2 保留桶版本控制操作中被包装的 S3 错误;当 Object Lock 禁止暂停版本控制时,显式返回 InvalidBucketState,让调用方看见 Server 已有的限制。

7. 面向开发者:模块图

Console v2.5.1 要求 Go 1.27.3,直接 require github.com/pgsty/silo-pkg/v3 v3.15.2 与上游 SDK v7.4.2-0.20261025165926-320af050c445,保留历史模块路径 github.com/minio/console。 嵌入方显式选择以下已发布源码:

replace github.com/minio/console => github.com/pgsty/silo-console v0.0.0-20261026153924-fff1618d9abb
replace github.com/minio/mc => github.com/pgsty/mc v0.0.0-20261026120214-0ceb298cdcd0

Go 不继承依赖模块的 replacement,Server 必须同时选择 PGSTY Console 与 MC。 go-systemd v22.6.0 保留 NetBSD 兼容,tablewriter v0.0.5 保留 MC API 兼容。 colorjson 带入的历史 minio/pkg 传递依赖与维护中的 silo-pkg 策略实现分开;不使用旧的 minio/pkg => silo-pkg 或 minio-go => silo-go replacement。 详见组件矩阵和嵌入指南。

发布门禁验证配套 SILO、Console、mcli 与 pkg;上游 MinIO/MC 探针属于非阻塞兼容信号,不要求降低 pkg 版本或复制 API。

迁移

官方镜像为 docker.io/pgsty/silo-console。已核验 v2.5.1 的 Linux amd64/arm64 匿名拉取,签名镜像摘要见统一维护公告。也可使用已发布的 GitHub 二进制或软件包。

镜像以 UID 1000 运行且没有主目录,默认证书目录因此是 /.console/certs:私有 CA 证书挂载到 /.console/certs/CAs/,或用 --certs-dir 指定其他路径。v2.6.0 及更早的镜像还缺少系统 CA 证书库;用这些镜像访问使用公共证书的 HTTPS 端点(SILO、OIDC 提供方)时,请把宿主机证书库以只读方式挂载到 /etc/ssl/certs/ca-certificates.crt。

已有的 MinIO Console 部署可以原地升级。服务单元、服务账号与配置文件名称都不变,全部 CONSOLE_* 变量按原样读取,因此通常的做法是用 silo-console 软件包覆盖安装后重启。

有两处行为会在首次启动后改变,值得提前预期:

  • silo-console 不会自我更新。请通过软件包、镜像或编排系统来推送新版本。
  • 任何依赖控制台访问 MinIO 运营服务的流程 —— 更新源、许可、遥测 —— 都不再有可访问的对端。

从早于 v2.4.1 的版本升级时,还需检查密码权限迁移。 Linux 软件包使用 /etc/silo-console/certs 作为证书目录;重启前迁移旧证书,或在 /etc/default/console 的 CONSOLE_OPTS 中保留旧路径。服务名和配置文件路径不变。 共享代理仅接受对象下载,不需要新增环境变量。详见 v2.4.1 发布说明。

参见

9 - 特性设计

Silo 在上游 MinIO 之外新增能力的设计笔记——先落笔,再落地。

本节的组件页面记录 Silo 与 MinIO 的一致之处;这个子节则记录 Silo 在上游之外扩展的能力:每一页都是在实现落地前撰写的设计笔记,并在落地后作为设计决策与背景依据保留。每页顶部均注明该特性的实现与发布状态。

9.1 - 原生健康检查与 Distroless 镜像

设计笔记:silo 二进制为何新增 healthcheck 子命令、mc ready 为何必须退役、单二进制 Distroless 镜像如何规划。
说明

状态:P1(silo healthcheck 子命令,2ff594f4b)、P2(distroless 镜像 + CI 门禁,4c34d2309,并在 #295 中对齐 UBI CA 信任库)与 P4(健康检查探针指南)已发布;P3(Helm 探针)待办 · 决策日期:2026-08-06 · 归属:pgsty/silo(命令、镜像、Helm chart)与本站(文档)

Silo 将新增一个原生的 silo healthcheck 子命令,并在现有容器镜像之外发布一个新的 Distroless 镜像变体——里面真正要紧的文件只有一个:silo 二进制。本文在动手实现之前把推理过程和设计决策记录下来,让代码有一份可以对照检验的规格,也让"为什么要做成这样"永远有出处可查。

背景

今天的发布镜像(docker.io/pgsty/silo)基于 ubi-micro,装了四样活动部件:silo 服务端、mcli 客户端(带 mc 别名)、一个静态链接的 curl,以及一个 POSIX shell 入口脚本。Compose 示例用镜像内置的客户端做容器健康检查:

healthcheck:
  test: ["CMD", "mc", "ready", "local"]

这套安排继承自上游 MinIO,其脆弱性有案可查:mc 曾短暂从镜像中消失,用户的健康检查随之失效,“除了禁用别无选择”(#9)。上游自己的历史也如出一辙——2023 年 MinIO 切换到 ubi-micro 丢掉 curl 时,维护者的答复是更加依赖 mc ready local(minio/minio#18373、#18389);而上游 minio/minio 如今已经归档,其二进制自始至终只有 server 一个子命令。上游不会有人来修这件事了。

Distroless 镜像把这个问题逼到了台面上。没有 shell、没有 curl、没有 mc——这正是 Distroless 的定义。容器里唯一保证存在的程序就是服务端二进制本身。如果这个镜像还想拥有 Docker 层面的健康检查,就只能由这个二进制自己来提供。

mc ready 为何必须从探针岗位上退役

细读 mc 的实现(cmd/ready-main.go)会发现:现在的健康检查是"碰巧能用",不是设计出来的。四个彼此独立的缺陷:

  1. 它自己永远不报告失败。mc ready 是一个"等到就绪为止"的循环:每 5 秒重试一次,只在成功时以零退出码结束,连接被拒也不会跳出循环。作为 Docker healthcheck 使用时,“unhealthy” 的判定完全来自 Docker 的 timeout 把进程杀掉——探测语义是 SIGKILL 的副作用。
  2. 它检查的尺度是错的。mc ready 请求的是 /minio/health/cluster——全集群写 quorum。于是每个容器的"健康"反映的都是整个集群的状态,这恰好是 Kubernetes 文档明确警告的级联失败反模式:quorum 一丢,所有节点同时被判不健康。
  3. 它有隐藏故障模式。 它需要可写的 ~/.mc 配置目录(只读 rootfs 或 OpenShift 任意 UID 下,服务器明明健康、探测却先失败了);首次运行会向 stdout 打印配置创建噪音;内置的 local 别名硬编码为 http://localhost:9000——一旦启用 TLS 或改了端口就立即失效,上游用户对此公开抱怨过。
  4. 它是镜像里捆绑第二个二进制的最后一个功能性理由。mcli 和钉版本的静态 curl 都有持续的供应链与维护成本(curl 被钉死在 v8.11.0,因为后续版本砍掉了 aarch64 构建),而这些事一个现有二进制的子命令用约 150 行代码就能做完。

决策

三条轨道,刻意解耦:

# 决策
D1 silo 二进制新增 healthcheck 子命令——服务端现有 /minio/health/* 端点的匿名 HTTP 薄客户端。它随每一个构建发布,所有镜像和裸机安装同时获得这项能力。
D2 现有镜像不动。mcli、curl、shell 入口脚本、mc ready local 示例全部保留。当前镜像的用户若想用新探针,覆盖自己的 healthcheck.test 即可选择加入——不拿走任何东西,不移动任何默认行为。
D3 并行发布一个新的 Distroless 变体 作为试点:单二进制、无 shell、原生 HEALTHCHECK 内置。试点验证充分后,它将成为推荐默认并完成切换;无论如何,经典镜像都会为兼容性继续保留。

D2 与 D3 回答了那个显而易见的问题——“为什么不直接给主镜像瘦身?"——因为主镜像的内容物本身就是兼容性表面。#9 的存在,正是因为这个表面曾经在用户脚下被抽换过一次。Distroless 镜像用一个新名字承载一份新契约:在它接受检验期间,没有任何人现有的健康检查、docker exec mc 习惯或入口脚本假设会被破坏。

silo healthcheck 命令

silo healthcheck [FLAGS] [CHECK]

CHECK —— 位置参数,与 /minio/health/<path> 一一对应:
  live          进程在提供服务(默认;不触碰任何外部系统)
  ready         live + KMS 与 etcd 可达(若有配置)
  cluster       全集群写 quorum
  cluster-read  全集群读 quorum

FLAGS:
  --address value   探测目标 host:port(EnvVar: MINIO_ADDRESS;默认 ":9000",
                    空 host 补全为 127.0.0.1)
  --url value       完整基址覆盖(http[s]://host:port);优先于 --address
                    与 TLS 自动判定(EnvVar: MINIO_HEALTHCHECK_URL)
  --maintenance     仅 cluster 有效:附加 ?maintenance=true——问"现在把这个
                    节点下线安全吗?"(HTTP 412 = 不安全,会破坏高可用)
  --timeout value   总超时;默认:live/ready 5s,cluster* 15s
  另继承全局旗标:--certs-dir、--config-dir、--json、--quiet

退出码:  0 = 健康 / 可安全操作 · 1 = 其余一切
输出:    单行,例如
  live: ok (200, 2ms)
  cluster: unhealthy (503) server-status=iam-offline write-quorum=3 healing-drives=2

这个形态背后的设计原则:

  1. 薄客户端,单一事实源。 命令永远只是规范健康 API 的 HTTP 客户端,绝不在进程内重新实现任何检查——“健康"的语义只存在于一个地方:服务端处理器。
  2. CLI 词汇 = API 词汇。 检查名就是端点路径。没有新概念要学,没有第二套词汇要同步。
  3. 共享服务器自己的配置。 端口来自服务器同一份 --address/MINIO_ADDRESS 契约;http 还是 https,由服务器启动时自己执行的那个证书检查(certs 目录下的 public.crt + private.key)来决定。这是 Traefik healthcheck 的模式——最接近的业界先例,它从与服务端相同的静态配置里解析 ping 端点——并把 Traefik 留成 // TODO 的 TLS 处理真正实现掉。这也是对 mc ready“端口靠猜"缺陷的正面修复。
  4. 默认检查是节点本地的。live 回答"这个进程是否在服务”,而这是单容器健康状态唯一应该回答的问题。集群尺度的检查存在,但只放在显式参数之后,并沿用 mc ready 的 --cluster-read/--maintenance 词汇,让运维语言得以延续。
  5. 退出码只有 0 和 1。 Dockerfile 参考手册明文保留退出码 2(vault status 用 2 表示 sealed,是现成的反面教材)。丰富的诊断信息放进那一行输出里——Docker 会把探测输出的前 4096 字节存进 docker inspect,而命令会把服务端的诊断响应头(x-minio-server-status、x-minio-write-quorum、x-minio-healing-drives)解码进去;这些正是裸 curl -f 会丢掉的细节。
  6. 跳过 TLS 证书校验,v1 不提供开关。 这是对匿名端点的环回自探,不传输任何数据——而 kubelet 对 HTTPS httpGet 探针的文档行为恰好也是跳过校验。与之对齐意味着同一套 TLS 部署在 Docker 和 Kubernetes 下得到同一个结论;默认校验只会制造假阴性,因为自签服务器证书极少包含 127.0.0.1 的 SAN。

两条来自服务端源码的关键实现约束:

  • 请求必须严格匿名。 健康路由之所以能豁免保留路径守卫,仅限于被服务器判定为匿名的请求;带上 Authorization 头会改变请求的分类,结果会被直接拒绝(ErrAllAccessDisabled)。
  • HTTP 传输层必须设置 Proxy: nil。 容器经常继承 HTTP_PROXY 却没有把 127.0.0.1 写进 NO_PROXY;环回探测绝不能被路由进公司代理。(Traefik 的 healthcheck 出于同样的原因特意这样做了。)

此外,cluster 检查的默认超时设为 15 秒,是因为服务端评估集群健康时自身受 10 秒 cluster_deadline 约束——客户端若在 5 秒就放弃,会先于服务端返回的 503 响应断开,连同所有诊断头一起丢失。另外补充两个细节:--url 支持环境变量(MINIO_HEALTHCHECK_URL),因为探针进程看不到服务端的命令行——当服务端的地址或 TLS 配置来自 CLI 参数时,这是配置内置 HEALTHCHECK 的正式途径;同时外层(Docker)超时必须大于探针自身的截止时间,否则探针会在打印诊断行之前先被 SIGKILL。

这些端点到底在做什么

下表对照的是处理器源码,不是文档转述——并且修正了一个常见的误读:

端点 返回 200 的条件 失败形态 备注
/minio/health/live 几乎总是——对象层尚未初始化时也返回 200(该状态只通过 x-minio-server-status: offline 响应头传递) 请求队列饱和时 503 不触碰外部系统;唯一安静到适合高频探测的端点
/minio/health/ready 同 live,外加 KMS 能生成密钥、etcd 能应答读取——各自仅在配置了的情况下 KMS/etcd 故障;队列饱和 没有 KMS 与 etcd 时,ready 与 live 是同一条代码路径
/minio/health/cluster 对象层、桶元数据、IAM 均已初始化,且每一个纠删集 都有写 quorum 503 附带 quorum 诊断头;带 ?maintenance=true 时失败为 412 每次评估失败都会在服务端写一条日志——不要高频轮询它
/minio/health/cluster/read 上一行的读 quorum 版本 同上

值得点破的推论:live 和 ready 是 存活 级别的信号——它们不能告诉你节点能否服务对象,只有 cluster 这一对能。这正是 cluster 端点必须远离单容器探针的原因(尺度错位、日志噪音、级联重启),也正是它适合回答运维问题的原因——“我现在可以把这个节点下线吗?"(--maintenance:200 表示安全,412 表示会失去高可用)。

Distroless 变体

基底:gcr.io/distroless/static-debian12——够用,因为 silo 以 CGO_ENABLED=0 构建。这个基底自带 tzdata、/tmp 以及带 root/nonroot 条目的 /etc/passwd,而 #295 从 verify 阶段复制源于 UBI 的 /etc/ssl/certs/ca-certificates.crt 证书包,使经典镜像与 distroless 镜像共享完全一致的根 CA 信任库(用于 KMS/webhook/STS 出站 TLS)。没有 shell、没有包管理器、没有 libc。

契约草图:

FROM gcr.io/distroless/static-debian12:latest
COPY --from=verify /usr/bin/silo /usr/bin/silo
COPY --from=verify /etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pem /etc/ssl/certs/ca-certificates.crt
COPY LICENSE NOTICE CREDITS /licenses/
ENV HOME=/tmp
# /data 在镜像层内创建、全员可写——见 issue #55:
# 这里已经没有入口脚本可以在运行时修补属主了。
VOLUME ["/data"]
EXPOSE 9000
HEALTHCHECK --interval=30s --timeout=10s --start-period=2m --start-interval=2s --retries=3 \
  CMD ["/usr/bin/silo", "healthcheck", "ready"]
ENTRYPOINT ["/usr/bin/silo"]

草图里折叠的决策:

  • ENTRYPOINT 就是二进制本身。docker run pgsty/silo:distroless server /data——没有 argv 翻译脚本,因为没有 shell 来跑脚本。经典镜像的 MINIO_USERNAME/MINIO_GROUPNAME 降权路径(依赖 GNU chroot 和可写的 /etc/passwd)在此变体中 不受支持;受支持的机制是 --user / Kubernetes runAsUser。
  • /data 在镜像层内创建、mode 0777,试点期默认用户保持 root。 Issue #55 证明了:只声明 VOLUME ["/data"] 而不创建它,会让 所有 非 root 运行方式失败,而且事后没有任何入口脚本能修补——Distroless 里更是压根没有入口脚本。在层内以全员可写方式创建它,是唯一让全部权限模式(包括 --user)都能工作的选项,同时与经典镜像保持即插即用的对等;其暴露面被"镜像只运行一个进程"这一事实所限定。nonroot 默认(uid 65532)的姿态经过考虑后推迟:它会在 UID 不匹配时破坏文档记载的 bind-mount 工作流,而试点的任务是测量摩擦,不是制造摩擦。晋升为默认推荐时再议,可能以 -nonroot 标签的形式出现。
  • 健康检查内置、exec 形式。 Shell 形式的 HEALTHCHECK 字符串需要 /bin/sh,在这里不可能存在;JSON 数组形式是唯一选择。Compose 会自动继承镜像的 HEALTHCHECK(逃生门是 disable: true),所以这个变体的 compose 用户零配置就能得到可用的 depends_on: condition: service_healthy。选 ready 而不是 live,是因为 Docker 健康状态的主要用途是 门控(启动顺序),那是就绪语义——况且在没有 KMS/etcd 时两者本就相同。
  • 一项发布前必须完成的验证:HEALTHCHECK 是 Docker 扩展,不在 OCI 镜像规范里(opencontainers/image-spec#749 至今开放),OCI 媒体类型的构建会静默丢弃它。发布流水线必须断言推送后的 manifest 上 docker inspect 能看到 Health 配置,否则就调整构建的媒体类型直到能看到为止。
  • 命名:docker.io/pgsty/silo:<RELEASE>-distroless,外加滚动的 distroless 标签。服务端仓库新增 Dockerfile.distroless——它没有任何下载阶段,完全离线,因此可以在每次发布的 CI 里真实构建并断言,顺带堵上 #55 记录的那个"门禁测的是合成镜像而非发布镜像"的覆盖缺口。
  • 变体文档里要诚实写明用户失去了什么:没有 docker exec <container> sh 式调试(改用 docker debug / kubectl debug 临时容器);镜像内没有 mc(改用 pgsty/mc 镜像或宿主机安装的 mcli);没有 MINIO_USERNAME 路径(改用 --user)。

Kubernetes 完全不需要镜像配合

值得明说,因为它划定了问题的边界:Kubernetes 完全忽略 Dockerfile 的 HEALTHCHECK——kubelet 探针在 Pod spec 里配置,从容器外部以 httpGet 请求执行。因此两个镜像变体在 Kubernetes 下的探测方式完全相同:

startupProbe:            # 启动预算:5s × 60 = 5 分钟,护住大规模 IAM 加载
  httpGet: { path: /minio/health/live, port: 9000 }
  periodSeconds: 5
  failureThreshold: 60
livenessProbe:           # 何时重启:只看进程级信号
  httpGet: { path: /minio/health/live, port: 9000 }
  periodSeconds: 30
  timeoutSeconds: 5
  failureThreshold: 3
readinessProbe:          # 何时摘除流量:可以包含硬依赖(KMS/etcd)
  httpGet: { path: /minio/health/ready, port: 9000 }
  periodSeconds: 15
  timeoutSeconds: 5
  failureThreshold: 3

任何这类配置旁边都应放上三条警示:cluster 端点永远不进探针(放进 liveness 意味着 quorum 一丢整个集群同时重启;放进 readiness 会与分布式引导互相纠缠——chart 的 headless service 设置 publishNotReadyAddresses: true 正是为此);live 在请求队列持续饱和时会有意返回 503,所以饱和节点约 90 秒后被重启是设计使然;scheme: HTTPS 下 kubelet 跳过证书校验,自签部署无需任何额外配置。

Silo 的 Helm chart 目前 一个探针都没有(上游的 chart 也一样,尽管其文档写了探针示例)。把上面三个探针补进 chart 是计划中的独立后续项——它不依赖任何一条镜像轨道,而且相对上游这是差异化优势,不是兼容性风险。

落地路线

阶段 范围 仓库
P1 silo healthcheck 子命令 + 测试;随下一个发布版二进制交付(所有镜像同时继承该能力,镜像行为零变化) pgsty/silo
P2 Dockerfile.distroless + CI 构建与健康门禁 + 以试点身份发布 -distroless 标签 pgsty/silo
P3 Helm chart:补三探针;刷新过期的默认镜像标签 pgsty/silo
P4 文档:命令参考、探针指南、Distroless 迁移说明;试点反馈 → 决定是否将 Distroless 晋升为推荐默认 本站

贯穿所有阶段的兼容性承诺:经典镜像的内容物与示例不变;mc ready local 在今天能用的地方继续能用;健康 HTTP API 不动(子命令纯属增量);/minio/health/* 路径与本分支的其他所有 /minio/* 路由一样,作为兼容性表面继续冻结。

推迟的决定

记录在案,免得将来从零重新争论:

  • --wait 模式(阻塞等待直至健康——mc ready 那个循环唯一真正的正当用途):推迟——仓库内暂无消费者,日后添加完全向后兼容,旗标命名空间已预留。
  • Distroless 镜像默认 nonroot:推迟至晋升默认推荐时再议,理由见上文。
  • --json 的输出 schema:遵循全局旗标惯例;确切 schema 在实现时定稿并写入命令参考。