跨 AWS 账号同步 S3 存量与新增对象

验证:未记录
适用版本
未记录
验证范围
尚未登记验证记录。

本文缩写(英文全称与中文含义)
缩写 英文全称/名称 中文含义
ACL Access Control List 访问控制列表
AES256 Advanced Encryption Standard, 256-bit key 使用 256 位密钥的高级加密标准
ARN Amazon Resource Name AWS 资源名称,用于唯一标识资源
AWS Amazon Web Services 亚马逊云服务
HTTP Hypertext Transfer Protocol 超文本传输协议
IAM Identity and Access Management 身份与访问管理
ID Identifier 标识符
JSON JavaScript Object Notation 一种结构化数据格式
KMS Key Management Service 密钥管理服务
S3 Simple Storage Service AWS 对象存储服务
SCP Service Control Policy AWS Organizations 服务控制策略
SLA Service Level Agreement 服务等级协议
TLS Transport Layer Security 传输层安全协议
URL Uniform Resource Locator 统一资源定位符,通常指访问地址
VPC Virtual Private Cloud 虚拟私有云网络

1. 需求与推荐方案#

需求:将 AWS Account A 中 source bucket A1 的存量对象,以及启用方案后持续写入的新对象,复制到 AWS Account B 中 destination bucket B2。

推荐使用两项原生能力组合:

新增对象:
    S3 Replication
    持续、异步复制启用规则后产生的新 object version

存量对象:
    S3 Batch Replication
    一次性回填启用规则前已经存在的 object version

不要只运行一次 aws s3 sync:它适合按当前 key 对比后复制文件,但不是持续复制服务,也不能完整保留 version、replication status、Object Lock retention、tag 和 delete marker 等 S3 语义。

Account A                                      Account B

producer -> A1 source bucket                  B2 destination bucket
               |                                          ^
               | S3 Replication: new versions             |
               +------------------------------------------+
               |                                          |
               | S3 Batch Replication: existing versions  |
               +------------------------------------------+

               replication IAM role in Account A
               destination bucket policy trusts that role

S3 Replication 是异步复制,不是事务型实时双写。一般会在较短时间内完成,但没有启用 S3 Replication Time Control(S3 RTC)时,不应承诺固定延迟。需要延迟 SLA 时可启用 S3 RTC,它会增加费用,并提供 99.99% 的新对象在 15 分钟内完成复制的 SLA。

2. 实施顺序#

为避免配置期间产生数据缺口,按以下顺序操作:

  1. 在 Account B 准备 B2,启用 Versioning、Block Public Access 和 Bucket owner enforced。
  2. 在 Account A 创建给 S3 使用的 replication IAM role。
  3. 在 B2 bucket policy 中授权该 replication role 写入副本。
  4. 如果使用 SSE-KMS,配置 source/destination KMS key policy。
  5. 确认 A1 已启用 Versioning,然后先启用持续 replication rule。
  6. 创建 S3 Batch Replication job,回填规则启用前的存量对象。
  7. 监控持续复制和 batch job,抽样校验对象、版本、加密和 tag。

先启用持续复制,再启动存量回填。这样在 batch job 扫描和运行期间新写入的对象已由持续复制规则接管。

3. 前置条件#

示例变量:

SOURCE_ACCOUNT_ID=111111111111
DESTINATION_ACCOUNT_ID=222222222222
SOURCE_BUCKET=account-a-bucket-a1
DESTINATION_BUCKET=account-b-bucket-b2
SOURCE_REGION=ap-east-1
DESTINATION_REGION=ap-southeast-1
REPLICATION_ROLE_NAME=s3-a1-to-b2-replication

必须满足:

A1 和 B2 都启用 S3 Versioning
B2 已存在,bucket name 和 Region 已确认
Account A 有权限创建 IAM role 和修改 A1 replication configuration
Account B 有权限修改 B2 bucket policy
两边的 SCP、permissions boundary、VPC endpoint policy 没有显式拒绝相关操作
使用 SSE-KMS 时,两边都使用 customer managed KMS key,并配置跨账号 key policy

迁移前检查 A1 当前配置#

下面的命令都是只读检查,用来建立 A1 的迁移基线。建议使用 Account A 的实际操作 profile 和 bucket Region;命令返回 AccessDenied 只说明当前身份没有读取权限,不能据此判断该功能没有配置。

aws s3api get-bucket-versioning --bucket A1
aws s3api get-bucket-encryption --bucket A1
aws s3api get-bucket-ownership-controls --bucket A1
aws s3api get-object-lock-configuration --bucket A1
aws s3api get-bucket-lifecycle-configuration --bucket A1
aws s3api get-bucket-replication --bucket A1
aws s3api get-bucket-policy --bucket A1
命令 检查内容 重点关注
get-bucket-versioning bucket 的 Versioning 状态 {} 通常表示从未启用、当前为 Disabled;Enabled 可以配置 replication;Suspended 表示曾启用但当前暂停,必须恢复为 Enabled
get-bucket-encryption 新对象默认使用的 server-side encryption AES256 表示 SSE-S3;aws:kms 或 aws:kms:dsse 表示 KMS,需要记录 KMS key ARN,并配置跨账号 key policy
get-bucket-ownership-controls 新对象的 ownership 和 ACL 模式 推荐 BucketOwnerEnforced;如果没有 ownership controls 或仍使用 ACL,需要检查 source/destination object owner 和 ACL 依赖
get-object-lock-configuration bucket 是否启用 Object Lock,以及默认 retention 若为 Enabled,B2 也必须按要求启用 Object Lock,并复制 retention/legal hold;未配置通常返回 ObjectLockConfigurationNotFoundError
get-bucket-lifecycle-configuration Lifecycle filter、transition、expiration 和 noncurrent version 处理 开启 Versioning 后要特别检查 noncurrent version expiration;B2 不会自动继承 A1 的 Lifecycle,需要单独配置
get-bucket-replication A1 是否已有 replication configuration 检查 role、rule priority、filter、destination、delete marker、KMS、metrics 和 RTC,避免新规则冲突或重复复制;未配置通常返回 ReplicationConfigurationNotFoundError
get-bucket-policy bucket resource policy 查找针对 principal、Organization、VPC endpoint、TLS、KMS 或加密 header 的 explicit deny;未配置通常返回 NoSuchBucketPolicy

建议保存这些命令的 JSON 输出作为变更前记录。除 Versioning 外,最容易阻塞跨账号复制的是 SSE-KMS key policy、已有 bucket policy 的 explicit deny、Object Lock 要求和现有 replication rule。

启用 Versioning:

aws s3api put-bucket-versioning --profile account-a --region ap-east-1 --bucket account-a-bucket-a1 --versioning-configuration Status=Enabled

aws s3api put-bucket-versioning --profile account-b --region ap-southeast-1 --bucket account-b-bucket-b2 --versioning-configuration Status=Enabled

A1 从 Disabled 开启 Versioning 的影响#

开启 Versioning 不会重写或删除现有对象:

existing objects:
    remain as null versions

new PUT or overwrite:
    creates a new version ID
    previous current/null version becomes noncurrent

DELETE without version ID:
    creates a delete marker
    previous data version remains stored

首次开启后,关键 PUT/DELETE 或 replication rollout 前建议等待约 15 分钟让配置传播。Versioning 开启后不能恢复为初始 Unversioned,只能改成 Suspended。

普通应用的 PutObject/GetObject/HeadObject/ListObjectsV2 和 presigned URL 通常不需要修改;不指定 versionId 时仍操作 current version。需要检查:

permanent delete/cleanup jobs:
    must handle object versions and delete markers

event consumers:
    may need versionId for idempotency

cost:
    configure Lifecycle for noncurrent versions and incomplete multipart uploads

持续 replication rule 只自动处理规则生效后的新 versions;现有 null/current objects 使用 Batch Replication 回填。开启前已经永久删除或被覆盖的历史数据无法恢复。

推荐让 destination bucket 使用 Bucket owner enforced。Account B 会拥有复制到 B2 的对象,并且不再依赖 ACL:

aws s3api put-bucket-ownership-controls --profile account-b --region ap-southeast-1 --bucket account-b-bucket-b2 --ownership-controls 'Rules=[{ObjectOwnership=BucketOwnerEnforced}]'

这些属性不一定改变 object body,但可能改变目标端的权限、生命周期、HTTP 行为和删除能力。迁移前询问它们,是为了确认 B2 要成为功能等价副本,还是只需要保存对象内容。

属性 含义 为什么需要确认 推荐答案
Object tags object 上独立维护的 key-value 标签 可能被 Lifecycle、IAM condition、成本分类和自动化任务使用;遗漏后,B2 的过期、转存或访问行为可能改变 默认复制,除非明确确认目标端不依赖 tags
Object metadata 随 object version 保存的属性,包括 Content-Type、Cache-Control、Content-Disposition 和自定义 x-amz-meta-* 应用下载行为、浏览器缓存、文件类型和业务处理可能依赖 metadata;只复制 body 可能导致对象在目标端不可正常使用 默认保留业务 metadata,同时允许 destination encryption、storage class 等目标属性按设计变化
Object Lock retention 对一个 object version 设置不可删除/覆盖的截止时间 决定副本在 Account B 中何时可以删除,涉及合规、审计和存储成本 source 使用 Object Lock 时必须保留并让合规负责人确认;未使用时不需要启用
Legal hold 对一个 object version 设置无固定到期时间的法律保留开关 ON 状态会一直阻止删除,直到有权限的人员显式解除;常用于诉讼、调查或证据保全 source 存在 legal hold 时必须保留,不能把迁移当作绕过保留的方法

严格来说,业务/HTTP metadata 在原生 S3 Replication 中通常会随 object version 复制,不是一个常规的“复制/不复制”开关。询问 metadata 的目的主要是确定验收标准,并检查目标端更换 KMS key、storage class 或下载方式后是否仍兼容。Tags 则更直接涉及额外权限以及目标端 Lifecycle/IAM 行为,因此必须明确确认。

Tags#

Tags 和 metadata 不相同。Tags 可在不复制 object body 的情况下单独修改,通常用于:

Lifecycle filter:
    tag=archive -> transition to Glacier

IAM condition:
    s3:ExistingObjectTag/classification=confidential

operations:
    backup=true
    retention-class=finance-7y
    owner=team-a

S3 Replication 可以复制 tags,但 replication role 需要读取 source tags,并允许在 destination 执行 s3:ReplicateTags。本文策略中的 s3:GetObjectVersionTagging 和 s3:ReplicateTags 就是为此准备的。

如果不复制 tags,object body 可能仍然复制成功,但 B2 上基于 tags 的 Lifecycle、IAM 或自动化行为会与 A1 不一致。因此默认答案应为“复制 tags”;只有在 B2 明确不继承这些控制时才选择不复制,并进行单独验证。

检查一个 source object 的 tags:

aws s3api get-object-tagging --profile account-a --bucket account-a-bucket-a1 --key path/to/object --version-id SOURCE-VERSION-ID

Metadata#

Metadata 分为两类:

business/HTTP metadata:
    Content-Type
    Cache-Control
    Content-Disposition
    Content-Encoding
    x-amz-meta-* custom metadata

storage/security metadata:
    storage class
    encryption algorithm and KMS key
    replication status

S3 Replication 通常会让 replica 保留 source object version 的业务/HTTP metadata。Destination storage class、KMS key 和 replication status 可以按 replication rule 使用目标端配置,不要求和 source 完全相同。

S3 metadata 不能直接原地修改。需要修改时,是应用程序、运维脚本、管理员或 S3 Console 主动调用 CopyObject,把对象复制回同一个 key,并通过 MetadataDirective=REPLACE 替换 metadata。S3 Replication 不会为了同步而在 A1 上调用 CopyObject,也不会主动修改 source object。

application / operator calls CopyObject on A1
    -> A1 creates a new object version for the same key
    -> continuous replication detects the new version
    -> S3 asynchronously creates its replica in B2

例如修改一个对象的 metadata:

aws s3api copy-object --profile account-a --bucket account-a-bucket-a1 --copy-source account-a-bucket-a1/path/to/object --key path/to/object --metadata-directive REPLACE --content-type application/json --metadata owner=team-a,classification=internal

REPLACE 会使用请求中提供的新 metadata 取代原 metadata,因此必须重新提供仍需保留的 Content-Type、Cache-Control 和自定义 x-amz-meta-*,否则遗漏字段会丢失。没有修改 metadata 的业务需求时,不要为了 replication 主动执行 CopyObject。

如果 A1 当前是 Disabled,开启 Versioning 后,原有对象通常仍是 null version。随后对同一个 key 执行 CopyObject 会创建新的正式 version,原 null version 成为 noncurrent version;新 version 会在持续复制规则生效后进入 replication。存量对象不需要修改 metadata 时,直接使用 Batch Replication 回填即可。

因此需要确认应用是否会频繁修改 metadata,以及这些变更是否必须在 B2 可见。频繁的同 key CopyObject 会增加 version 数量、复制请求和存储成本。

检查一个对象的 metadata:

aws s3api head-object --profile account-a --bucket account-a-bucket-a1 --key path/to/object --version-id SOURCE-VERSION-ID

Object Lock retention#

Object Lock 是 WORM(write once, read many)保护,作用对象是具体的 object version,而不是整个 key 的抽象名称。

Retention 会设置 RetainUntilDate:

GOVERNANCE:
    默认不能提前删除
    具有 s3:BypassGovernanceRetention 的受控角色可以显式绕过

COMPLIANCE:
    retention 到期前不能删除
    包括 root user 在内也不能提前缩短或绕过

例如一个 version 的 retention 截止到 2030-12-31,即使业务已经不再需要该对象,在此日期前也不能删除该 version。Retention 到期后只是“允许删除”,不会自动删除;是否删除仍由 Lifecycle 或显式 DELETE 决定。

Legal hold 只有 ON/OFF,没有自动到期时间,并且独立于 retention:

retention 已到期 + legal hold ON:
    仍然不能删除

retention 未到期 + legal hold OFF:
    仍然不能删除

retention 已到期 + legal hold OFF:
    可以按 IAM 和 Lifecycle 规则删除

Legal hold 常用于诉讼、监管调查、安全事件证据或审计资料。它必须由有权限的人员显式设为 OFF,迁移过程不能擅自解除。

Object Lock 对复制的影响#

如果 A1 启用了 Object Lock,则 B2 也必须启用 Object Lock,replication role 需要读取 source retention 和 legal hold。Replica 应保留这些保护状态,否则目标 bucket 不能作为合规副本。

检查 bucket 是否启用 Object Lock:

aws s3api get-object-lock-configuration --profile account-a --bucket account-a-bucket-a1

检查一个 object version:

aws s3api get-object-retention --profile account-a --bucket account-a-bucket-a1 --key path/to/object --version-id SOURCE-VERSION-ID

aws s3api get-object-legal-hold --profile account-a --bucket account-a-bucket-a1 --key path/to/object --version-id SOURCE-VERSION-ID

Object Lock 依赖 Versioning。若 A1 当前确实是从未启用过 Versioning 的 Disabled 状态,正常情况下它不会已经启用 Object Lock,也不会存在 retention 或 legal hold;仍建议运行上面的 bucket-level 命令确认,并区分“未配置”与调用者没有读取权限导致的 AccessDenied。

4. Account A Replication Role#

创建 trust policy replication-role-trust.json,只允许 S3 service assume 该 role:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "Service": "s3.amazonaws.com"
      },
      "Action": "sts:AssumeRole"
    }
  ]
}
aws iam create-role --profile account-a --role-name s3-a1-to-b2-replication --assume-role-policy-document file://replication-role-trust.json

创建权限策略 replication-role-policy.json:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "ReadSourceBucketConfiguration",
      "Effect": "Allow",
      "Action": [
        "s3:GetReplicationConfiguration",
        "s3:ListBucket"
      ],
      "Resource": "arn:aws:s3:::account-a-bucket-a1"
    },
    {
      "Sid": "ReadSourceObjectVersions",
      "Effect": "Allow",
      "Action": [
        "s3:GetObjectVersionForReplication",
        "s3:GetObjectVersionAcl",
        "s3:GetObjectVersionTagging",
        "s3:GetObjectRetention",
        "s3:GetObjectLegalHold"
      ],
      "Resource": "arn:aws:s3:::account-a-bucket-a1/*"
    },
    {
      "Sid": "WriteDestinationReplicas",
      "Effect": "Allow",
      "Action": [
        "s3:ReplicateObject",
        "s3:ReplicateDelete",
        "s3:ReplicateTags"
      ],
      "Resource": "arn:aws:s3:::account-b-bucket-b2/*"
    }
  ]
}
aws iam put-role-policy --profile account-a --role-name s3-a1-to-b2-replication --policy-name replicate-a1-to-b2 --policy-document file://replication-role-policy.json

如果只同步某个 prefix,应同时缩小 replication rule 的 filter 和 IAM policy 的 object resource,例如 arn:aws:s3:::account-a-bucket-a1/data/*。

5. Account B Bucket Policy#

在 Account B 为 B2 添加 bucket policy。下面只展示 replication 相关 statement;如果 bucket 已有 policy,需要合并到现有 Statement,不能直接覆盖其他 guardrail:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "AllowReplicationFromAccountA",
      "Effect": "Allow",
      "Principal": {
        "AWS": "arn:aws:iam::111111111111:role/s3-a1-to-b2-replication"
      },
      "Action": [
        "s3:ReplicateObject",
        "s3:ReplicateDelete",
        "s3:ReplicateTags"
      ],
      "Resource": "arn:aws:s3:::account-b-bucket-b2/*"
    }
  ]
}
aws s3api put-bucket-policy --profile account-b --region ap-southeast-1 --bucket account-b-bucket-b2 --policy file://destination-bucket-policy.json

如果 B2 policy 有 Deny 条件,例如只允许指定 aws:PrincipalAccount、VPC endpoint、AWS Organization 或加密方式,必须把 replication role 和 S3 replication 请求纳入条件设计。Allow 无法覆盖任何 explicit Deny。

6. 启用持续复制#

SSE-S3 或未指定 SSE-KMS#

创建 replication.json:

{
  "Role": "arn:aws:iam::111111111111:role/s3-a1-to-b2-replication",
  "Rules": [
    {
      "ID": "replicate-all-to-account-b",
      "Priority": 1,
      "Status": "Enabled",
      "Filter": {
        "Prefix": ""
      },
      "DeleteMarkerReplication": {
        "Status": "Enabled"
      },
      "Destination": {
        "Bucket": "arn:aws:s3:::account-b-bucket-b2"
      }
    }
  ]
}
aws s3api put-bucket-replication --profile account-a --region ap-east-1 --bucket account-a-bucket-a1 --replication-configuration file://replication.json

检查规则:

aws s3api get-bucket-replication --profile account-a --region ap-east-1 --bucket account-a-bucket-a1

SSE-KMS#

如果 source object 使用 SSE-KMS,仅有 S3 和 IAM 权限不够。需要:

source KMS key:
    replication role 可以 kms:Decrypt

destination KMS key:
    replication role 可以 kms:Encrypt 和 kms:GenerateDataKey

replication rule:
    启用 SseKmsEncryptedObjects
    指定 destination ReplicaKmsKeyID

应在 KMS key policy 中授权 replication role,并在 role policy 中加入相同的 KMS actions。不要使用 AWS managed key aws/s3 做跨账号授权,因为它的 key policy 不能由客户修改。

SSE-KMS replication rule 需要增加:

{
  "SourceSelectionCriteria": {
    "SseKmsEncryptedObjects": {
      "Status": "Enabled"
    }
  },
  "Destination": {
    "Bucket": "arn:aws:s3:::account-b-bucket-b2",
    "EncryptionConfiguration": {
      "ReplicaKmsKeyID": "arn:aws:kms:ap-southeast-1:222222222222:key/DESTINATION-KEY-ID"
    }
  }
}

如果 source bucket 同时存在 SSE-S3 和 SSE-KMS 对象,启用上述选项后两类对象都可进入同一规则;SSE-KMS 对象会使用指定的 destination KMS key 创建 replica。

7. 回填存量对象#

持续 replication rule 只自动处理规则生效后的新 object version,不会自动复制更早存在的对象。存量回填使用 S3 Batch Replication,不要暂停生产写入。

最稳妥的操作路径是 Account A 的 S3 Console:

  1. 打开 A1 的 Management > Replication rules。
  2. 确认上一节的持续复制规则状态为 Enabled。
  3. 选择该规则,然后选择 Replicate existing objects 或创建 Batch Replication job。
  4. 让 S3 生成 manifest,范围选择整个 bucket 或目标 prefix。
  5. 为 Batch Operations 选择单独的 job role;该 role 需要对 source object 执行 s3:InitiateReplication,并能读取 manifest、写 completion report。
  6. 设置 completion report bucket,先 Review manifest,再确认运行 job。
  7. 等待 job 完成,并检查 failed task 数量和 completion report。

Batch Operations job role 和第 4 节的持续 replication role 是两个不同角色:

continuous replication role:
    trusted service = s3.amazonaws.com
    reads source versions and writes destination replicas

Batch Operations job role:
    trusted service = batchoperations.s3.amazonaws.com
    calls s3:InitiateReplication for each source object in the manifest

Batch Operations job role 的 trust policy 核心内容:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "Service": "batchoperations.s3.amazonaws.com"
      },
      "Action": "sts:AssumeRole"
    }
  ]
}

job role 的 operation permission:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "InitiateReplicationForSourceObjects",
      "Effect": "Allow",
      "Action": "s3:InitiateReplication",
      "Resource": "arn:aws:s3:::account-a-bucket-a1/*"
    }
  ]
}

还需要根据实际 bucket 增加 manifest 的 s3:GetObject/s3:GetObjectVersion 和 report prefix 的 s3:PutObject。使用 S3 generated manifest 时,Console 创建 role 的流程会补充生成 manifest 所需的 bucket 权限;上线前仍要检查最终 policy 是否只覆盖 A1、manifest 和 report 的指定位置。

对于关键数据,建议先用一个小 prefix 建 job 验证策略、KMS 和 ownership,再执行全量 job。Batch Operations 会产生请求、manifest、inventory、report、KMS 和跨 Region data transfer 等费用,先估算对象数量,不要只看总容量。

“历史数据”的范围#

在执行前明确业务所说的“历史数据”:

范围 做法
每个 key 的当前版本 Batch Replication manifest 只包含当前 version
所有非当前版本 manifest 必须包含对应 VersionId,并逐版本执行 replication
delete marker Batch Replication 不用于回填历史 delete marker;需要单独评估目标端应呈现的删除状态
已删除且没有保留版本的对象 S3 已无可复制数据,只能从其他备份恢复

如果要求 B2 完整重建 A1 的版本时间线,不能把“复制当前可见对象”当作完成。必须检查 manifest 是否包含所有需要的 version ID,并接受历史 delete marker 等限制。

8. 删除与一致性语义#

什么是 delete marker#

在启用 Versioning 的 bucket 中,对一个 key 执行不带 version-id 的普通 DeleteObject 时,S3 通常不会删除已有 object version,而是创建一个新的 delete marker,并让它成为该 key 的 current version。

Delete marker 只有 key 和自己的 version ID,没有 object body。它的作用是让不指定 version ID 的 GET/HEAD 看起来像对象已经不存在,通常返回 404 Not Found;此前的数据版本仍作为 noncurrent version 保存在 bucket 中。

before DELETE:
    reports/a.csv version v2  <- current and visible
    reports/a.csv version v1

after DELETE without version-id:
    reports/a.csv delete marker d1  <- current
    reports/a.csv version v2        <- data still exists
    reports/a.csv version v1

GET reports/a.csv:
    returns 404 because d1 is current

GET reports/a.csv?versionId=v2:
    can still read v2 if the caller has permission

如果显式删除 current delete marker 的 version ID,之前的数据版本可重新成为 current version,对象也会再次可见。这是 Versioning 能从普通误删中恢复对象的原因之一。

A1 当前为 Versioning Disabled 时还没有 delete marker 机制:普通 DELETE 会直接删除对象。启用 Versioning 后产生的删除才会创建 delete marker;启用前已经删除且没有其他备份的对象无法通过 replication 恢复。

检查某个 key 的版本和 delete marker:

aws s3api list-object-versions --profile account-a --bucket account-a-bucket-a1 --prefix path/to/object

输出中的 Versions 是数据版本,DeleteMarkers 是删除标记;IsLatest=true 表示当前版本。

是否需要复制 delete marker#

DeleteMarkerReplication=Enabled 表示:持续复制规则生效后,A1 中普通 DELETE 创建的新 delete marker,也会异步复制到 B2。复制后,B2 上相同 key 的普通 GET/HEAD 也会返回不存在,但此前复制的数据版本仍然保留,除非被 B2 自己的 Lifecycle 或显式删除清理。

B2 用途 建议 原因
灾备副本、故障切换、迁移后接管 通常 Enabled B2 的当前可见 key 集合需要尽量与 A1 一致,否则源端已删除对象在切换后会重新出现
分析副本,且查询应反映源端当前状态 通常 Enabled 避免分析程序继续读取已从业务侧删除的 key
隔离备份、审计归档、防源端误删 通常 Disabled 源端误删不应自动隐藏目标对象;目标端使用独立 Lifecycle、Object Lock 或 retention 控制保留
法规要求删除必须传播 Enabled,但先做合规确认 delete marker 只隐藏当前对象,不等于物理删除所有历史版本,未必满足数据彻底删除要求

对本文的 A1 -> B2 需求,如果 B2 是迁移副本或可直接接管业务的灾备 bucket,推荐启用 delete marker replication。如果 B2 的核心目标是提供不受 Account A 误操作影响的独立恢复副本,则推荐禁用,并限制 Account A 对 B2 的删除权限。

以下行为不要混淆:

delete current key without version ID:
    creates a delete marker
    can be replicated when DeleteMarkerReplication is enabled

permanently delete a specific source version:
    is not propagated as a permanent deletion of the corresponding replica

lifecycle expires source objects or versions:
    do not assume destination lifecycle follows it
    destination needs its own lifecycle policy

额外限制:使用 tag-based filter 的 replication rule 不支持启用 delete marker replication。需要传播删除时,应使用整个 bucket 或 prefix-based filter,并在测试 prefix 中验证 create、overwrite、delete 和 restore 行为。

因此 replication 不是镜像文件系统,也不是双向同步。即使启用了 delete marker replication,显式永久删除某个 source version 也不会自动永久删除对应 replica;历史 delete marker 也不能依靠 Batch Replication 完整回填。不要在 B2 上配置反向规则复制回 A1,除非已经设计好 loop prevention、ownership、冲突和删除语义。

9. 验证与监控#

先写一个 canary object:

printf 'replication-check\n' > /tmp/replication-check.txt

aws s3api put-object --profile account-a --region ap-east-1 --bucket account-a-bucket-a1 --key replication-canary/replication-check.txt --body /tmp/replication-check.txt

检查 source object 的 replication status:

aws s3api head-object --profile account-a --region ap-east-1 --bucket account-a-bucket-a1 --key replication-canary/replication-check.txt --query '{VersionId:VersionId,ReplicationStatus:ReplicationStatus}'

常见状态:

PENDING     等待或正在复制
COMPLETED   已复制成功
FAILED      复制失败,需要检查权限、KMS、bucket policy 和 replication metrics
REPLICA     当前对象本身是 replica

检查 destination:

aws s3api head-object --profile account-b --region ap-southeast-1 --bucket account-b-bucket-b2 --key replication-canary/replication-check.txt --query '{VersionId:VersionId,ReplicationStatus:ReplicationStatus,SSE:ServerSideEncryption,KMSKey:SSEKMSKeyId}'

生产环境应启用 S3 replication metrics 和 EventBridge failure events,并关注:

OperationsFailedReplication
OperationsPendingReplication
BytesPendingReplication
ReplicationLatency
s3:Replication:OperationFailedReplication EventBridge event
Batch Operations job failed task count and completion report

验证至少覆盖:

新对象可以自动复制
覆盖同一个 key 后,新 version 可以复制
普通 DELETE 的 delete marker 行为符合预期
对象 tag 已复制
SSE-KMS destination key 正确
Account B 对 replica 有读取和 lifecycle 管理权限
存量 batch job 的 manifest 数量、成功数、失败数可以对账

10. 常见失败#

现象 优先检查
新对象一直 PENDING replication rule status、role trust policy、destination bucket policy
FAILED 且对象是 SSE-KMS source key kms:Decrypt、destination key kms:Encrypt、key policy、key Region
新对象成功但旧对象不存在 只配置了持续 replication,没有运行 Batch Replication
destination 拒绝写入 bucket policy/SCP/VPC endpoint policy 中的 explicit deny
replica owner 不符合预期 B2 是否为 Bucket owner enforced,是否仍依赖 ACL
tag 没有复制 role 和 destination policy 是否允许 s3:ReplicateTags
删除后两边结果不同 delete marker 与指定 version 永久删除的语义不同
batch job 大量失败 completion report、manifest version ID、Batch Operations role、KMS policy

11. 上线 Checklist#

[ ] A1/B2 Versioning 都是 Enabled
[ ] B2 Block Public Access 已启用
[ ] B2 Object Ownership 是 Bucket owner enforced
[ ] replication role trust 只允许 s3.amazonaws.com
[ ] role policy 只覆盖 A1 source 和 B2 destination
[ ] B2 bucket policy 精确授权 replication role
[ ] SSE-KMS 两边 key policy 和 role policy 已配置
[ ] 先启用持续 replication,再启动存量 Batch Replication
[ ] Batch manifest 明确是当前版本还是全部历史版本
[ ] completion report 有独立保存位置并完成失败项复核
[ ] canary 的 create/overwrite/delete/tag/encryption 已验证
[ ] replication metrics、EventBridge failure event 和告警已配置
[ ] B2 lifecycle、retention、Object Lock 需求已独立确认

搜索文档

输入关键词,搜索所有文档。

↑ ↓ 选择 · Enter 打开 · Esc 关闭