:跨集群 IAM/存储桶/对象同步的原理与实战)
MinIO 自动站点复制Automatic Site Replication跨集群 IAM/存储桶/对象同步的原理与实战【免费下载链接】minioMinIO is a high-performance, S3 compatible object store, open sourced under GNU AGPLv3 license.项目地址: https://gitcode.com/GitHub_Trending/mi/minio本文基于 MinIO 仓库中的 自动站点复制文档 及其配套多站点演练脚本、cmd/site-replication.go核心实现展开。它系统讲解如何把多个使用同一身份提供方IDP的 MinIO 站点配置为互相复制的“对等站点”peer sites覆盖 IAM 用户/组/策略、存储桶与对象、桶级特性策略、标签、Object Lock、加密的自动同步读完后你不仅能完成mc admin replicate的完整配置与验证流程还能从源码层面理解状态持久化、站点恢复heal与全量重新同步resync机制。一、什么是自动站点复制自动站点复制允许多个相互独立的 MinIO 站点或集群在共用同一外部身份提供方IDP的前提下被配置为复制关系。被纳入复制关系的站点集合称为 peer sites对等站点。当这组站点启用 site-replication 后以下变更会自动复制到所有其他站点存储桶与对象的创建和删除所有 IAM 用户、组、策略的创建和删除以及它们与用户/组的映射关系STS 凭据的创建服务账号Service Account的创建和删除root 用户拥有的服务账号除外桶级特性的变更包括Bucket Policy桶策略Bucket Tags桶标签;Bucket Object-Lock 配置含 retention 与 legal hold 配置Bucket 加密配置Encryption configuration。注意所有新创建和已存在的桶会在所有被复制站点上自动启用版本控制versioning。这一点在源码中也有对应实现——对等站点建桶时通过PeerBucketMakeWithVersioningHandler强制携带versioningEnabledtrue选项见 cmd/site-replication.go因此跨站点的对象删除会以版本化的 tombstone 形式同步保证删除操作也能在各站点间保持一致。以下桶级特性不会被复制设计上允许各站点保持不同Bucket notification桶事件通知配置Bucket lifecycle / ILM桶生命周期配置。这一取舍的原因是合理的通知目标和生命周期规则通常绑定站点本地的下游系统如各站点的消息队列、各站点的归档存储桶跨站点强制统一反而会破坏本地语义。二、前置条件Pre-requisites在配置站点复制之前必须满足以下条件这也是 cmd/site-replication.go 中AddPeerClusters加入对等站点时校验的内容初始数据只能存在于一侧站点。配置复制时只有加入复制的站点中的一个可以已有数据站点复制配置成功后该数据会被复制到其余初始为空的站点。此后对象可以写入任意站点并自动复制到所有其他站点。站点一经加入复制组便不允许移除“Removing a site is not allowed from a set of replicated sites once configured”。运维上应把它当作不可逆的拓扑决策。所有站点必须使用相同的外部 IDP若使用了 IDP。源码中对应的校验逻辑是validateIDPSettings它逐站取回各站的IDPSettings并比对不一致时返回errSRIAMConfigMismatch见 cmd/site-replication.go错误信息会明确指出是哪两个站点的 IDP 配置不一致。使用 SSE-S3 / SSE-KMS 加密时所有站点必须能访问同一中心 KMS 部署。可以通过一个中心 KES 服务器实现也可以通过多个 KES 服务器例如每站点一个挂接到同一个中心 KMS如 Vault实现。原因在于站点复制同步的是对象的密文与元数据若各站点密钥独立对端站点将无法解密。三、配置步骤mc 命令实操3.1 为每个站点配置 alias首先为每个站点配置mcalias。假设你有三个 MinIO 站点可以运行mc alias set minio1 https://minio1.example.com:9000 adminuser adminpassword mc alias set minio2 https://minio2.example.com:9000 adminuser adminpassword mc alias set minio3 https://minio3.example.com:9000 adminuser adminpassword或者改用环境变量方式声明各站点凭据export MC_HOST_minio1https://adminuser:adminpasswordminio1.example.com export MC_HOST_minio2https://adminuser:adminpasswordminio2.example.com export MC_HOST_minio3https://adminuser:adminpasswordminio3.example.com3.2 加入站点复制mc admin replicate add minio1 minio2 minio3该命令会以minio1为发起方通过管理 APISiteReplicationAdd见 cmd/admin-handlers-site-replication.go把三个站点加入同一复制组。执行期间站点间会互相校验 IDP 配置、生成本站的服务账号并交换凭据。3.3 查询复制配置mc admin replicate info minio13.4 关于凭据模型的重要变更原文档特别强调了一点早期站点复制要求各对等站点的 root 凭据完全一致现在不再需要。因为 STS token 现在改用**站点复制服务账号site replicator service account**的凭据签名从而允许各站点的 root 账号独立管理并具备最终禁用 root 账号的能力。这一变更在源码中可以得到印证服务账号固定名为site-replicator-0常量siteReplicatorSvcAcc见 cmd/site-replication.goAddPeerClusters在本地创建该服务账号并把其 access key 写入持久化状态srStateV1.ServiceAccountAccessKey见 cmd/site-replication.go对等站点则依据该 access key 在自身侧创建对应的服务账号。随之而来的两个运维注意事项原文档明确说明升级到包含该变更的版本后此前由 root 凭据签名的 STS token 将全部失效需要按常规方式重新生成如果站点复制被解除removedSTS token 同样会失效也需要重新生成。四、端到端演练三站点 OIDC 复制场景仓库提供了完整的可运行演练脚本最典型的是 docs/site-replication/run-multi-site-oidc.sh。它在本机拉起三个 MinIO 站点各 4 盘共用一个 Dex OIDC 身份提供方然后逐步验证文档中列出的每一项复制能力。以下按脚本顺序讲解。4.1 启动三个使用相同 IDP 的站点三个站点使用完全相同的 IDP 环境变量满足“所有站点必须使用相同 IDP”的前提仅监听端口和回调地址不同export MINIO_ROOT_USERminio export MINIO_ROOT_PASSWORDminio123 export MINIO_IDENTITY_OPENID_CONFIG_URLhttp://localhost:5556/dex/.well-known/openid-configuration export MINIO_IDENTITY_OPENID_CLIENT_IDminio-client-app export MINIO_IDENTITY_OPENID_CLIENT_SECRETminio-client-app-secret export MINIO_IDENTITY_OPENID_CLAIM_NAMEgroups export MINIO_IDENTITY_OPENID_SCOPESopenid,groups export MINIO_IDENTITY_OPENID_REDIRECT_URIhttp://127.0.0.1:10000/oauth_callback minio server --address :9001 --console-address :10000 /tmp/minio1/{1...4} export MINIO_IDENTITY_OPENID_REDIRECT_URIhttp://127.0.0.1:11000/oauth_callback minio server --address :9002 --console-address :11000 /tmp/minio2/{1...4} export MINIO_IDENTITY_OPENID_REDIRECT_URIhttp://127.0.0.1:12000/oauth_callback minio server --address :9003 --console-address :12000 /tmp/minio3/{1...4} 若使用 LDAP 作为 IDP可参考 docs/site-replication/ldap.yaml 用 Docker 快速起一个 OpenLDAP 实例并改用 docs/site-replication/run-multi-site-ldap.sh 演练使用 MinIO 自身作为 IDP 的完整流程见 docs/site-replication/run-multi-site-minio-idp.sh。随后声明各站点 alias 并确认就绪export MC_HOST_minio1http://minio:minio123localhost:9001 export MC_HOST_minio2http://minio:minio123localhost:9002 export MC_HOST_minio3http://minio:minio123localhost:9003 ./mc ready minio1 ./mc ready minio2 ./mc ready minio34.2 启用站点复制./mc admin replicate add minio1 minio2 minio34.3 验证 IAM 层复制策略在 minio1 上创建一个名为projecta的策略策略内容取自 docs/site-replication/rw.json即admin:*s3:*全放行./mc admin policy create minio1 projecta ./docs/site-replication/rw.json sleep 5 ./mc admin policy info minio2 projecta # 应成功 ./mc admin policy info minio3 projecta # 应成功删除同样是双向的./mc admin policy remove minio3 projecta sleep 10 ./mc admin policy info minio1 projecta # 应失败 ./mc admin policy info minio2 projecta # 应失败4.4 验证 STS 凭据跨站点可用脚本通过 docs/site-replication/gen-oidc-sts-cred.go 模拟一次完整的 OIDC 用户交互先由 Dex 换取 OIDC token再调用 MinIO 的 STSAssumeRoleWithWebIdentity接口拿到临时凭据STS_CRED$(MINIO_ENDPOINThttp://localhost:9001 go run ./docs/site-replication/gen-oidc-sts-cred.go) MC_HOST_foohttp://${STS_CRED}localhost:9001 ./mc ls foo # minio1 可用 MC_HOST_foohttp://${STS_CRED}localhost:9002 ./mc ls foo # minio2 可用 MC_HOST_foohttp://${STS_CRED}localhost:9003 ./mc ls foo # minio3 可用这正是“STS token 用站点复制服务账号凭据签名”的实际收益在任意一个站点签发的 STS 凭据可以在复制组内所有站点使用而不需要各站点 root 凭据一致。4.5 验证服务账号复制用 STS 用户的 access key 在 minio2 上创建服务账号STS_ACCESS_KEY$(echo ${STS_CRED} | cut -d : -f 1) ./mc admin user svcacct add minio2 $STS_ACCESS_KEY --access-key testsvc --secret-key testsvc123 sleep 10 ./mc admin user svcacct info minio1 testsvc # 已同步到 minio1 ./mc admin user svcacct info minio2 testsvc # 本地可见删除同样同步./mc admin user svcacct rm minio1 testsvc sleep 10 ./mc admin user svcacct info minio2 testsvc # 应失败 ./mc admin user svcacct info minio3 testsvc # 应失败4.6 验证桶与对象复制含大对象分片校验./mc mb minio1/bucket2 ./mc mb minio1/newbucket # 上传 17MB 大对象会触发 multipart 上传到 minio1 truncate -s 17M lrgfile ./mc cp ./lrgfile minio1/newbucket sleep 5 ./mc stat --no-list minio2/newbucket # 桶与对象已在 minio2 出现 ./mc stat --no-list minio3/newbucket # 桶与对象已在 minio3 出现 # 反向写入 minio2 的对象应复制到 minio1/minio3 ./mc cp README.md minio2/newbucket/ sleep 5 ./mc stat --no-list minio1/newbucket/README.md ./mc stat --no-list minio3/newbucket/README.md删除同样同步./mc rm minio3/newbucket/README.md sleep 5 ./mc stat --no-list minio2/newbucket/README.md # 应失败 ./mc stat --no-list minio1/newbucket/README.md # 应失败对 multipart 大对象脚本还会在 minio3 上重新下载并做 md5 比对确认分片对象复制后内容一致sleep 10 ./mc stat --no-list minio3/newbucket/lrgfile actual_checksum$(./mc cat minio3/newbucket/lrgfile | md5sum) # 与上传前 lrgfile 的 md5sum 比对不一致即视为复制失败带版本删除--versions后各站点对象也应永久消失./mc rm -r --versions --force minio1/newbucket/lrgfile sleep 5 ./mc stat --no-list minio1/newbucket/lrgfile # 应失败4.7 验证 Object Lock 与桶标签复制在 minio3 上创建启用 Object Lock 的桶两个对等站点应都能观察到 Object Lock 已启用./mc mb --with-lock minio3/newbucket-olock sleep 5 ./mc stat --json minio2/newbucket-olock | jq -r .ObjectLock.enabled # Enabled ./mc stat --json minio1/newbucket-olock | jq -r .ObjectLock.enabled # Enabled桶标签更新同样同步./mc tag set minio2/newbucket keyval1 sleep 10 ./mc tag list minio1/newbucket --json | jq -r .tagset | jq -r .key # val14.8 站点离线期间的变更恢复heal演练的最后一部分验证了故障恢复能力先kill -9掉 minio1然后在 minio2 上更新标签keyval2、创建新桶newbucket2、删除bucket2再重启 minio1等待约 200 秒后# 最新标签更新已补齐 ./mc tag list minio1/newbucket --json | jq -r .tagset | jq -r .key # val2 # 离线期间发生过的桶创建/删除也已补齐 diff -q (./mc ls minio1) (./mc ls minio2) # 无差异这个“自动补齐”能力来自源码中的站点级 heal 例程SiteReplicationSys.Init在启动时即拉起startHealRoutine见 cmd/site-replication.go由healBuckets、healBucketPolicies、healTagMetadata、healVersioningMetadata、healSSEMetadata、healOLockConfigMetadata、healIAMSystem、healUsers、healGroups、healPolicies等一批恢复函数见 cmd/site-replication.go负责在对等站点短暂不可用后按“最新状态优先”原则把桶元数据、IAM 实体等差异对齐。4.9 解除复制后的全量重新同步resync脚本最后演示了 resync 流程先彻底移除站点复制人为制造不一致再重新建立并触发全量重同步./mc admin replicate rm --all --force minio1 ./mc rb minio2 --force --dangerous ./mc admin replicate add minio1 minio2 ./mc admin replicate resync start minio1 minio2 sleep 30 # 比对两站点的对象版本清单应完全一致 ./mc ls -r --versions minio1/newbucket /tmp/minio1.txt ./mc ls -r --versions minio2/newbucket /tmp/minio2.txt diff -qpruN /tmp/minio1.txt /tmp/minio2.txtresync 的实现在startResync见 cmd/site-replication.go整体站点级重同步状态保存在.minio.sys/buckets/site-replication/resync/deployment-id.meta单个桶的重同步进度复用桶复制的replication/resync.bin。相关状态查询与指标由 cmd/site-replication-utils.go 和 cmd/site-replication-metrics.go 提供。五、源码级实现要点5.1 复制状态如何持久化站点复制的组内状态保存在每站的系统桶中。从源码看cmd/site-replication.gosrStatePrefix minioConfigPrefix /site-replicationsrStateFile state.json状态结构srStateV1记录组名Name、按部署 ID 索引的对等站点表Peers map[string]madmin.PeerInfo、本站复制服务账号的 access keyServiceAccountAccessKey以及UpdatedAt时间戳见 cmd/site-replication.go。SiteReplicationSys.Init启动时会带指数退避地反复从磁盘加载状态cmd/site-replication.go因此即使站点重启复制关系也会自动恢复无需重新执行mc admin replicate add。5.2 站点间如何互相“推”变更对等站点之间的变更传递走 HTTP 管理 API。服务端关键入口在 cmd/admin-handlers-site-replication.goSiteReplicationAdd处理mc admin replicate addSiteReplicationInfo/SiteReplicationStatus/SiteReplicationMetaInfo查询复制配置与状态SRPeerReplicateIAMItem/SRPeerReplicateBucketItem接收来自对等站点的 IAM 项与桶项变更策略、用户、桶元数据等的落地入口SiteReplicationEdit/SiteReplicationRemove编辑/移除对等站点SiteReplicationResyncOp触发 resync。发起站点在本地完成变更后调用这些接口把变更广播给其余对等站点对等站点落地时以UpdatedAt时间戳做新旧判定避免旧数据覆盖新数据例如服务账号同步逻辑中会先检查sa.UpdatedAt.After(updatedAt)见 cmd/site-replication.go。5.3 版本控制为何“自动开启”站点复制的对象删除需要以版本化 tombstone 的形式复制否则对端无法区分“删除”与“桶/对象从未存在”。因此在加入复制组时服务端会给已有桶启用版本控制、并对后续新建桶强制携带versioningEnabledtruecmd/site-replication.go。这与文档中“所有新桶和已存在的桶都会在所有被复制站点上自动启用 versioning”的说明一一对应。六、更多配套演练脚本docs/site-replication/ 目录下还有一组面向不同加密与复制组合的端到端脚本可直接作为回归测试模板参考脚本用途run-multi-site-oidc.sh三站点 OIDCDexIDP 的完整站点复制演练本文第四节依据的脚本run-multi-site-ldap.sh三站点 LDAP IDP 演练ldap.yaml 提供 OpenLDAP 容器配置run-multi-site-minio-idp.sh以 MinIO 自身作为 IDP 的多站点演练run-sse-kms-object-replication.shSSE-KMS 加密对象在站点间复制对应“所有站点必须能访问中心 KMS”的前置条件run-ssec-object-replication.shSSE-C 客户自带密钥对象的站点复制run-ssec-object-replication-with-compression.shSSE-C 传输压缩组合场景run-replication-with-checksum-header.sh带校验和请求头的复制场景七、运维要点小结拓扑不可逆站点加入复制组后不允许移除规划站点成员时要预留足够余地。IDP 一致性是硬约束新增站点前先用mc admin idp info核对各站 IDP 配置validateIDPSettings会在 add 阶段拒绝配置不一致的对端。STS 凭据要纳入密钥轮转计划升级跨越“服务账号签名”变更的版本后或任何一次mc admin replicate rm之后此前签发的 STS token 都会失效需重新生成。依赖自愈机制兜底站点重启后由 heal 例程自动对齐离线期间的变更若曾整体移除过复制关系并重新建立则应显式执行mc admin replicate resync start 本站 对端做全量重同步并用mc ls -r --versions比对结果。KMS 中心化SSE-S3/SSE-KMS 场景下各站点必须共享中心 KMS中心 KES 或多 KES 挂中心 Vault否则复制过去的对象无法解密。参考资料站点复制功能文档docs/site-replication/README.md核心实现cmd/site-replication.go、cmd/site-replication-utils.go、cmd/site-replication-metrics.go管理 API 入口cmd/admin-handlers-site-replication.go端到端演练脚本docs/site-replication/【免费下载链接】minioMinIO is a high-performance, S3 compatible object store, open sourced under GNU AGPLv3 license.项目地址: https://gitcode.com/GitHub_Trending/mi/minio创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考