同账号同区域复制

重要

本文中含有需要您注意的重要提示信息,忽略该信息可能对您的业务造成影响,请务必仔细阅读。

同账号同区域复制是指将某个账号某个地域下源存储空间(Bucket)的文件(Object)的创建、更新和删除等操作自动、异步(近实时)地复制到当前账号相同地域下的目标Bucket。本文介绍如何进行同账号同区域复制。

前提条件

  • 已在某个账号下的某个地域创建Bucket A作为同区域复制的源Bucket,并记录账号的UID、Bucket A的名称及所在地域。

  • 已在相同账号下的相同地域创建Bucket B作为同区域复制的目标Bucket,并记录Bucket B的名称。

角色类型

执行同账号同区域复制时,需要指定用于源Bucket与目标Bucket之间执行复制操作的角色。您可以选择以下任意角色完成同账号同区域复制任务。

重要

您可以选择通过RAM用户创建角色,RAM用户必须拥有以下权限:ram:CreateRoleram:GetRoleram:ListPoliciesForRoleram:AttachPolicyToRole。但是考虑到授予RAM用户ram:CreateRoleram:GetRole等角色相关的权限风险较大,您可以通过RAM用户关联的阿里云账号创建RAM角色并为相应的RAM角色完成授权。授权完成后,RAM用户可以直接复用阿里云账号创建的RAM角色。

(推荐)新建角色

创建同账号同区域复制规则时,支持选择新建角色来完成复制任务。选择新建角色后,后台将自动创建格式为oss-replication-{uuid} 的角色,并根据是否选择复制KMS加密对象授予不同权限策略。

  • 选择复制KMS加密对象

    新建角色后,您需要按照页面指引完成角色授权操作。授权完成后,该角色拥有源Bucket同步到目标Bucket精准权限策略以及AliyunKMSFullAccess(管理密钥管理服务KMS的权限)。

  • 选择不复制KMS加密对象

    新建角色后,您需要按照页面指引完成角色授权操作。授权完成后,该角色拥有源Bucket同步到目标Bucket精准权限策略。

AliyunOSSRole

创建同账号同区域复制规则时,支持选择AliyunOSSRole角色来完成复制任务。选择该角色后,后台会根据是否选择复制KMS加密对象授予不同权限策略。

  • 选择复制KMS加密对象

    选择AliyunOSSRole角色后,后台将自动为AliyunOSSRole角色授予以下权限策略:AliyunOSSFullAccess(管理对象存储OSS的权限)以及AliyunKMSFullAccess(管理密钥管理服务KMS的权限)。

    警告

    该角色拥有当前账号下所有Bucket以及KMS的所有操作权限,权限范围较大,请谨慎使用。

  • 选择不复制KMS加密对象

    选择AliyunOSSRole角色后,后台将自动为AliyunOSSRole角色授予AliyunOSSFullAccess(管理对象存储OSS的权限)。

    警告

    该角色拥有当前账号下所有Bucket所有操作权限,权限范围较大,请谨慎使用。

自定义角色

创建同账号同区域复制规则时,支持使用自定义角色来完成复制任务。您需要通过RAM控制台创建自定义角色,并为角色赋予相关权限。

  1. 创建普通服务角色。

    创建角色过程中,需选择可信实体类型为阿里云服务,角色类型选择普通服务角色,受信服务选择对象存储。具体步骤,请参见创建普通服务角色

  2. 为角色授权。

    您可以选择以下任意方式为角色授权。

    为RAM角色授予系统策略

    警告

    您可以选择为RAM角色授予系统策略AliyunOSSFullAccessAliyunOSSFullAccess默认拥有当前账号下所有Bucket的所有操作权限,请谨慎使用。

    如果您希望将KMS加密的Object复制到目标Bucket,您还需要为角色授予AliyunKMSFullAccess系统策略。

    具体步骤,请参见为RAM角色授权

    为RAM角色授予自定义策略

    建议您选择为RAM角色授予源Bucket(src-bucket)和目标Bucket(dest-bucket)复制所需的最小权限。

    说明

    实际使用时,请相应替换源Bucket和目标Bucket名称。

    {
       "Version":"1",
       "Statement":[
          {
             "Effect":"Allow",
             "Action":[
                "oss:ReplicateList",
              	"oss:ReplicateGet"
             ],
             "Resource":[
              	"acs:oss:*:*:src-bucket",
                "acs:oss:*:*:src-bucket/*"
             ]
          },
          {
             "Effect":"Allow",
             "Action":[
              	"oss:ReplicateList",
                "oss:ReplicateGet",
                "oss:ReplicatePut",
                "oss:ReplicateDelete"
             ],
             "Resource":[
              	"acs:oss:*:*:dest-bucket",
                "acs:oss:*:*:dest-bucket/*"
             ]
          }
       ]
    }

    具体步骤,请参见为RAM角色授权

    说明

    如果您希望将KMS加密的Object复制到目标Bucket,您还需要为角色授予AliyunKMSFullAccess系统策略。

操作步骤

使用OSS控制台

  1. 登录OSS管理控制台

  2. 单击Bucket 列表,然后单击src-bucket。

  3. 在左侧导航栏,选择数据管理 > 同区域复制

  4. 同区域复制页签,单击同区域复制

  5. 同区域复制对话框,按以下说明配置各项参数。

    区域

    参数

    说明

    设置目标Bucket

    源Bucket

    显示源Bucket所在地域及名称。

    目标Bucket

    选中在此账号下选择一个Bucket,然后下拉相同地域下的目标Bucket名称。

    设置复制策略

    数据复制对象

    选择需要复制的源数据。

    • 全部文件进行同步:将该Bucket内所有的Object复制到目标存储空间。

    • 指定文件名前缀进行同步:将该Bucket内指定前缀的Object复制到目标Bucket。最多可以添加10个前缀。

    Object标签

    复制拥有指定标签的Object到目标Bucket。设置方法为选中设置规则后添加标签(键-值对),最多可添加10个标签。

    要设置该参数,必须满足以下条件:

    • 已设置Object标签。具体操作,请参见设置对象标签

    • 源Bucket与目标Bucket需同时处于华东1(杭州)地域。

    • 源Bucket和目标Bucket均已开启版本控制。

    • 数据复制策略为增/改 同步

    数据复制策略

    选择数据复制的方式。

    说明

    创建数据复制规则后,源Bucket内通过生命周期规则或者CopyObject修改存储类型后引起的存储类型变更、以及该Bucket内Object的最后访问时间(x-oss-last-access-time)属性,均不会同步到目标Bucket。

    • 增/改 同步(适用于数据容灾的场景):将源Bucket内Object新增和更新操作复制到目标Bucket。

      重要

      该策略下仅新增和更新的Object会被复制,而删除操作不会影响目标Bucket。通过这种方式,可以有效防止因源Bucket手动删除、通过生命周期自动删除的行为导致目标Bucket数据丢失的问题。

    • 增/删/改 同步(适用于共享和访问同一数据集的场景:将源Bucket内Object的新增、更新、删除操作复制到目标Bucket。

      重要

      该策略下新增、更新和删除Object都会被复制到目标Bucket。通过这种方式,确保了数据的一致性,适用于需要共享和访问同一数据集的多用户或应用程序环境。但是配置该策略后,当手动删除或者通过生命周期自动删除源Bucket内的Object时,目标Bucket也会删除对应的Object,且Object删除后无法恢复。

    如果某个Object是通过分片上传的方式上传至源Bucket,则每个分片的上传操作都会复制至目标Bucket。最终,对所有分片执行CompleteMultipartUpload后生成的Object,也会被复制到目标Bucket。

    有关同区域复制结合版本控制的复制行为说明,请参见同区域复制结合版本控制

    复制历史数据

    选择是否复制同区域复制规则生效前源Bucket中已有的历史数据。

    • 复制:将历史数据复制至目标Bucket。

      重要

      复制历史数据时,从源Bucket复制的Object可能会覆盖目标Bucket中同名的Object。为避免这部分文件丢失,建议您对源Bucket和目标Bucket开启版本控制。

    • 不复制:仅复制同区域复制规则生效后上传或更新的Object。

    复制 KMS 加密目标对象

    选择是否将KMS加密的Object复制到目标Bucket。

    • 复制:在源Object或者目标Bucket使用了KMS托管密钥加密方式(即SSE-KMS,指定CMK ID)的情况下,要将Object复制到目标Bucket。

      说明

      您可以通过HeadObjectGetBucketEncryption分别查询源Object和目标Bucket的加密状态。

    • 不复制:不复制KMS加密的Object到目标Bucket。

    使用的 KMS 密钥

    选择将KMS加密的Object复制到目标Bucket,您需要为目标Object指定加密的KMS密钥。

    指定KMS密钥前,您需要提前在KMS平台创建一个与目标Bucket相同地域的KMS密钥。具体操作,请参见创建密钥

    授权角色

    推荐选择新建角色。下拉选择新建角色后,您需要按照页面指引完成角色授权操作。

    您还可以选择AliyunOSSRole或者自定义角色。关于这三种类型角色的更多信息,请参见角色类型

  6. 单击确定,然后在弹出的对话框,单击确认开启

    • 当同区域复制规则创建完成后,不允许对此规则进行编辑或删除。

    • 复制任务会在同区域复制规则配置完成的3~5分钟后启动。您可以在源Bucket的同区域复制页签,查看复制进度。

    • 由于Bucket间的同区域复制采用异步(近实时)复制,数据复制到目标Bucket需要的时间取决于数据的大小,通常几分钟到几小时不等。

使用阿里云SDK

仅Java、Python以及Go SDK支持同账号同区域复制。

Java

import com.aliyun.oss.ClientException;
import com.aliyun.oss.OSS;
import com.aliyun.oss.common.auth.*;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.OSSException;
import com.aliyun.oss.model.AddBucketReplicationRequest;

public class Demo {

    public static void main(String[] args) throws Exception {
        // Endpoint以华东1(杭州)为例,其它Region请按实际情况填写。
        String endpoint = "https://oss-cn-hangzhou.aliyuncs.com";
        // 强烈建议不要把访问凭证保存到工程代码里,否则可能导致访问凭证泄露,威胁您账号下所有资源的安全。本代码示例以从环境变量中获取访问凭证为例。运行本代码示例之前,请先配置环境变量。
        EnvironmentVariableCredentialsProvider credentialsProvider = CredentialsProviderFactory.newEnvironmentVariableCredentialsProvider();
        // 填写源Bucket名称。
        String bucketName = "src-bucket";
        // 指定数据要复制到的目标Bucket。目标Bucket与源Bucket必须属于相同账号。
        String targetBucketName = "dest-bucket";
        // 指定目标Bucket所在地域。目标Bucket与源Bucket必须处于相同地域。
        String targetBucketLocation = "oss-cn-hangzhou";

        // 创建OSSClient实例。
        OSS ossClient = new OSSClientBuilder().build(endpoint, credentialsProvider);

        try {
            AddBucketReplicationRequest request = new AddBucketReplicationRequest(bucketName);

            request.setTargetBucketName(targetBucketName);
            request.setTargetBucketLocation(targetBucketLocation);
            // 默认复制历史数据。此处设置为false,表示禁止复制历史数据。
            request.setEnableHistoricalObjectReplication(false);
            // 指定授权OSS进行数据复制的角色名称,且该角色必须已被授予源Bucket执行同区域复制以及目标Bucket接收复制对象的权限。
            request.setSyncRole("yourRole");
            // 指定OSS是否复制通过SSE-KMS加密创建的对象。
            //request.setSseKmsEncryptedObjectsStatus("Enabled");
            // 指定SSE-KMS密钥ID。如果指定Status为Enabled,则必须指定该元素。
            //request.setReplicaKmsKeyID("3542abdd-5821-4fb5-a425-90adca***");
            //List prefixes = new ArrayList();
            //prefixes.add("image/");
            //prefixes.add("video");
            //prefixes.add("a");
            //prefixes.add("A");
            // 指定待复制Object的前缀Prefix。指定Prefix后,只有匹配该Prefix的Object才会复制到目标Bucket。
            //request.setObjectPrefixList(prefixes);
            //List actions = new ArrayList();
            //actions.add(AddBucketReplicationRequest.ReplicationAction.PUT);
            // 将源Bucket内Object的新增、更新操作复制到目标Bucket。
            //request.setReplicationActionList(actions);
            ossClient.addBucketReplication(request);
        } catch (OSSException oe) {
            System.out.println("Caught an OSSException, which means your request made it to OSS, "
                    + "but was rejected with an error response for some reason.");
            System.out.println("Error Message:" + oe.getErrorMessage());
            System.out.println("Error Code:" + oe.getErrorCode());
            System.out.println("Request ID:" + oe.getRequestId());
            System.out.println("Host ID:" + oe.getHostId());
        } catch (ClientException ce) {
            System.out.println("Caught an ClientException, which means the client encountered "
                    + "a serious internal problem while trying to communicate with OSS, "
                    + "such as not being able to access the network.");
            System.out.println("Error Message:" + ce.getMessage());
        } finally {
            if (ossClient != null) {
                ossClient.shutdown();
            }
        }
    }
}        

Python

# -*- coding: utf-8 -*-
import oss2
from oss2.credentials import EnvironmentVariableCredentialsProvider
from oss2.models import ReplicationRule
# 从环境变量中获取访问凭证。运行本代码示例之前,请确保已设置环境变量OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。
auth = oss2.ProviderAuth(EnvironmentVariableCredentialsProvider())
# 填写源Bucket所在地域对应的Endpoint。以华东1(杭州)为例,Endpoint填写为https://oss-cn-hangzhou.aliyuncs.com。
# 填写源Bucket名称,例如src-bucket。
bucket = oss2.Bucket(auth, 'https://oss-cn-hangzhou.aliyuncs.com', 'src-bucket')
replica_config = ReplicationRule(
    # 指定数据要复制到的目标Bucket。目标Bucket与源Bucket必须属于相同账号。
    target_bucket_name='dest-bucket',
    # 指定目标Bucket所在地域。目标Bucket与源Bucket必须处于相同地域。
    target_bucket_location='oss-cn-hangzhou'
    # 指定授权OSS进行数据复制的角色名称,且该角色必须已被授予源Bucket执行同区域复制以及目标Bucket接收复制对象的权限。
    sync_role_name='roleNameTest',
)

# 指定待复制Object的前缀Prefix。指定Prefix后,只有匹配该Prefix的Object才会复制到目标Bucket。
# prefix_list = ['prefix1', 'prefix2']
# 设置数据复制规则。
# replica_config = ReplicationRule(
     # prefix_list=prefix_list,
     # 将源Bucket内Object的新增、更新操作复制到目标Bucket。
     # action_list=[ReplicationRule.PUT],
     # 指定数据要复制到的目标Bucket。
     # target_bucket_name='dest-bucket',
     # 指定目标Bucket所在地域。
     # target_bucket_location='yourTargetBucketLocation',
     # 默认复制历史数据。此处设置为False,表示禁止复制历史数据。
     # is_enable_historical_object_replication=False,    
     # 复制通过SSE-KMS加密创建的对象。
     # sse_kms_encrypted_objects_status=ReplicationRule.ENABLED
     # 指定SSE-KMS密钥ID。如果指定复制通过SSE-KMS加密创建的对象,则必须指定该元素。
     # replica_kms_keyid='9468da86-3509-4f8d-a61e-6eab1eac****',
  #)

# 开启数据复制。
bucket.put_bucket_replication(replica_config)

Go

package main

import (
	"encoding/xml"
	"fmt"
	"github.com/aliyun/aliyun-oss-go-sdk/oss"
	"os"
)

func HandleError(err error) {
	fmt.Println("Error:", err)
	os.Exit(-1)
}

// 开启数据复制。
func main() {
	// 从环境变量中获取访问凭证。运行本代码示例之前,请确保已设置环境变量OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。
	provider, err := oss.NewEnvironmentVariableCredentialsProvider()
	if err != nil {
		fmt.Println("Error:", err)
		os.Exit(-1)
	}
	// 创建OSSClient实例。
	// yourEndpoint填写Bucket对应的Endpoint,以华东1(杭州)为例,填写为https://oss-cn-hangzhou.aliyuncs.com。其它Region请按实际情况填写。
	client, err := oss.New("yourEndpoint", "", "", oss.SetCredentialsProvider(&provider))
	if err != nil {
		fmt.Println("Error:", err)
		os.Exit(-1)
	}
	// 指定源Bucket名称。
	srcbucketName := "yourSrcBucket"
	// 指定数据要复制到的目标Bucket。
	destBucketName := "yourDestBucket"
	// 指定待复制Object的前缀prefix_1和prefix_2。指定Prefix后,只有匹配该Prefix的Object才会复制到目标Bucket。
	// 如果您需要将源Bucket中的所有Object复制到目标Bucket,则无需设置Prefix。
	prefix1 := "prefix_1"
	prefix2 := "prefix_2"
	// 指定SSE-KMS密钥ID。如果指定Status为Enabled,则必须指定该元素。
	keyId := "c4d49f85-ee30-426b-a5ed-95e9****"
	// 指定OSS是否复制通过SSE-KMS加密创建的对象。
	source := "Enabled"
	prefixSet := oss.ReplicationRulePrefix{Prefix: []*string{&prefix1, &prefix2}}	
	reqReplication := oss.PutBucketReplication{
		Rule: []oss.ReplicationRule{
			{
				PrefixSet: &prefixSet,
				//将源Bucket内Object的新增、更新操作复制到目标Bucket。
				Action: "PUT",				
				Destination: &oss.ReplicationRuleDestination{
					Bucket: destBucketName,
					// 指定目标Bucket所在地域。源Bucket与目标Bucket必须处于不同的地域。
					Location: "oss-cn-hangzhou",					
				},
				// 默认复制历史数据。此处设置为disabled,表示禁止复制历史数据。
				HistoricalObjectReplication: "disabled",
				// 指定授权OSS进行数据复制的角色名称,且该角色必须已被授予源Bucket执行同区域复制以及目标Bucket接收复制对象的权限。
				SyncRole:                "yourRole",
				EncryptionConfiguration: &keyId,
				SourceSelectionCriteria: &source,
			},
		},
	}

	xmlBody, err := xml.Marshal(reqReplication)
	if err != nil {
		HandleError(err)
	}
	err = client.PutBucketReplication(srcbucketName, string(xmlBody))

	if err != nil {
		HandleError(err)
	}

	fmt.Println("Put Bucket Replication Success!")
}

使用命令行工具ossutil

关于使用ossutil开启同区域复制的具体步骤,请参见replication(同区域复制)

使用REST API

如果您的程序自定义要求较高,您可以直接发起REST API请求。直接发起REST API请求需要手动编写代码计算签名。更多信息,请参见PutBucketReplication