跳转到主要内容

Alias 区域:小配置改动的兼容性边界

2026-10-23 决策:mcli PR #44 已在 91006a587 合入 main。我们接受按 alias 配置区域的方案,保留小范围生产实现并补充回归覆盖。本文记录当时的设计决定。该能力已包含在正式发布的 mcli 20261109 中;以下配置边界按该版本源码复核。

原始补丁和测试由 mr javad seydi 贡献,解决的是上游 issue #5268 所报告的配置能力缺口。

缺少的究竟是什么

原始报告中的内部 S3 服务不实现 GetBucketLocation,调用时返回 501 Not Implemented。SDK 在发送普通对象请求前,先尝试发现桶的区域;发现失败,对象请求也就无法执行。用户向 alias JSON 加入 "region": "us-west-1" 后仍然无效:旧配置结构没有这个字段,会直接忽略它。

访问本身已有绕过办法。MC_REGION 和 AWS_REGION 可以设置 SDK 区域并跳过发现。只访问一个端点时,环境变量已经足够:

MC_REGION=us-west-1 mcli cp example.txt archive/bucket/example.txt

真正缺少的是按 alias 持久保存区域。进程级覆盖值无法在同一条命令中表达两个 alias 各自不同的区域,也不会随 alias 导出。这次新增字段填补了该缺口。它属于新增配置能力,不能把此前未受支持的 alias 字段被忽略说成既有功能回归。SILO 本身实现了 GetBucketLocation,原始报告也不能证明 SILO 服务端缺少这个接口。

最小且完整的配置链

原始生产补丁只改四个文件,新增 13 行、删除两行:

层次 修改 必要性
Alias JSON 在 aliasConfigV10 增加可选 region 能读取、保存和导出这个值
客户端配置 增加 Config.Region 通过现有客户端接口传递区域
Alias 转换 在 NewS3Config 复制字段 接通存储配置与客户端构造
S3 工厂 为 SDK 和缓存键解析区域 使用配置值,并避免复用固定在其他区域的客户端

优先级为:

MC_REGION > AWS_REGION > alias.region > SDK 自动发现

第一个非空值生效。alias 区域缺失或为空时,保留原有发现路径;JSON null 也按空值接受。既有环境变量仍然优先。同名 MC_HOST_<alias> 环境 alias 继续整体替换文件 alias,因此不会继承文件中的区域。

缓存修改是正确性的一部分。两个 alias 可以共用端点和凭据,却分别指定不同区域。如果缓存仍只识别旧身份,第二个 alias 就会复用第一个已经固定区域的 SDK 客户端。把最终生效区域纳入键,才能阻止这种错误复用;当环境变量把两者覆盖成同一区域时,仍可共享客户端。SDK 和缓存使用同一个解析函数,避免两套优先级发生偏差。

SDK 已经支持显式区域,接通现有配置即可,无需 fork SDK、为某个服务增加 501 特判、引入依赖或升级配置版本。遇到发现错误就静默猜测区域,反而会掩盖配置错误,让签名行为更难解释。

固定区域意味着什么

非空区域会固定 SDK 使用的区域,跳过桶区域发现,并可能绕过 SDK 的区域纠正重试路径。它不是“先试这个区域,再发现真实区域”的提示。现有两个环境变量本来就具有同样的强制语义。相关实现见 SDK 的显式区域路径和区域纠正条件。

一个 alias 访问多个区域的桶时,这个区别尤其重要。应留空以使用自动发现,或为不同区域建立独立 alias。端点或服务区域变化时,也要同步更新固定配置。错误区域还会影响生成的签名:share upload 可能生成直到使用时才失败的 POST 表单;share download 会先执行 Stat,因此可能更早失败。

升级后哪些行为可能变化

补丁不会为旧 alias 自动填写区域。旧 CLI 正常生成的配置通常没有该字段,普通升级会保留原有区域发现和环境变量覆盖行为。例外需要分别说明,不能用一句“向前兼容”概括。

场景 后果
旧 alias 没有 region 区域选择行为不变
模板或早先实验在旧 JSON 留下非空 region 原先被忽略的字段开始生效;错误或过期的值可能导致访问失败
旧的未知 region 是数字、布尔值、对象或数组 新字符串字段会拒绝它,整份配置解析失败,操作其他 alias 的命令也受影响
本次验证的改动前客户端读取新配置 JSON 可读,但区域被忽略,恢复旧选择行为
该旧客户端修改任意 alias 并保存配置 整份文件被重写,所有 alias 的未知区域字段都会丢失

最后一种情况很容易漏掉。旧程序只读新配置不会擦除磁盘文件,保存才会,即使用户改的只是另一个 alias。再次升级无法恢复丢失字段。降级前应备份配置;必须混用新旧客户端时,使用独立配置目录。因此,这项改动兼容正常旧配置的升级;对本次验证的前一版本,降级后格式可读,但语义不完整,写回也有损。

更实际的升级意外,是自动化模板一直写着默认区域,或用户早先试填后忘记清理。非字符串值属于更边缘的错误输入。这些风险不足以成为继续忽略新字段的理由,但值得用户检查已有自定义 JSON。

如何配置和维护

对于包含这项改动的客户端,把下面内容保存为 archive.json,替换端点、凭据和实际区域:

{
  "url": "https://s3.example.com",
  "accessKey": "REPLACE_WITH_ACCESS_KEY",
  "secretKey": "REPLACE_WITH_SECRET_KEY",
  "api": "S3v4",
  "path": "auto",
  "region": "us-west-1"
}
chmod 600 archive.json
mcli alias import archive archive.json
mcli stat archive/existing-bucket

导入文档是单个 alias 对象,不是完整的 version 10 配置。Import 会替换目标 alias,轮换凭据时应包含完整的预期配置;导入对象不含 region,就会清除已有区域。Export 命令保留该字段,可以用来检查,但其输出也包含凭据。

alias set 没有 --region 参数。它会重建 alias 并清掉该字段,连接探测也不会继承已保存的区域。因此,启用新能力后,用 alias set 轮换凭据的脚本需要调整。alias list 包括 JSON 输出都不显示区域。这是初版明确的管理边界;CLI 支持可以单独改进,无需扩大本次生产补丁。

建桶另有设置。mb --region 继续使用自己的默认值 us-east-1,alias 区域不会替代它。例如,预期创建在 us-west-1 时,应执行 mcli mb --region us-west-1 archive/new-bucket。固定的客户端配置应与建桶位置一致。

回归覆盖与取舍

正式版本中的区域回归测试通过实际配置 loader 和拒绝 GetBucketLocation 的 HTTP 测试服务,检查固定区域下的 Stat/Put、签名区域、环境变量优先级及客户端缓存隔离。它验证了配置到 SDK 的完整链路,不代表所有第三方 S3 服务都兼容。维护的正式组合是 SILO、SILO Console、mcli 与 silo-pkg;对原厂 MinIO/MC 保持尽最大努力兼容。

这项改动通过 SDK 已有接口解决按 alias 保存区域的需求,正常旧配置仍保留发现行为。运维人员需要管理的边界是固定区域的强制语义、alias 重建和旧客户端写回;新增 CLI 参数可单独评估。