跨帳號跨地區複製是指將某個帳號某個地區下源儲存空間(Bucket)的檔案(Object)的建立、更新和刪除等操作自動、非同步(近即時)地複製到另一個帳號另一個地區下的目標Bucket。本文介紹如何進行跨帳號跨地區複製。
前提條件
已在帳號A下的某個地區建立Bucket A作為跨地區複製的源Bucket,並記錄帳號A的UID、Bucket A的名稱及所在地區。
已在帳號B下的另一個地區建立Bucket B作為跨地區複製的目標Bucket,並記錄帳號B的UID、Bucket B的名稱及所在地區。
操作步驟
使用OSS控制台
通過帳號A完成以下操作。
建立普通服務角色。
重要您可以選擇通過RAM使用者建立角色,RAM使用者必須擁有以下許可權:
ram:CreateRole
、ram:GetRole
、ram:ListPoliciesForRole
、ram:AttachPolicyToRole
。但是考慮到授予RAM使用者ram:CreateRole
、ram:GetRole
等角色相關的許可權風險較大,您可以通過RAM使用者關聯的阿里雲帳號建立RAM角色並為相應的RAM角色完成授權。授權完成後,RAM使用者可以直接複用阿里雲帳號建立的RAM角色。建立角色過程中,需選擇可信實體類型為阿里雲服務,角色類型選擇普通服務角色,受信服務選擇Object Storage Service。具體步驟,請參見建立普通服務角色。
為角色授予源Bucket執行跨地區複製的許可權。
您可以選擇以下任意方式為角色授權。
為RAM角色授予系統策略
警告您可以選擇為RAM角色授予系統策略
AliyunOSSFullAccess
。AliyunOSSFullAccess
預設擁有當前帳號下所有Bucket的所有操作許可權,請謹慎使用。具體步驟,請參見為RAM角色授權。
為RAM角色授予自訂策略
通過RAM Policy的方式對RAM角色授予源Bucket(src-bucket)複製所需的最小許可權。
說明實際使用時,請相應替換源Bucket名稱。
{ "Version":"1", "Statement":[ { "Effect":"Allow", "Action":[ "oss:ReplicateList", "oss:ReplicateGet" ], "Resource":[ "acs:oss:*:*:src-bucket", "acs:oss:*:*:src-bucket/*" ] } ] }
具體步驟,請參見為RAM角色授權。
通過帳號B授予角色在目標Bucket接收複製對象的許可權。
(推薦)方式一:按圖形策略添加
方式二:按文法策略添加
在左側導覽列,選擇許可權控制>Bucket 授權策略。
在Bucket 授權策略頁面的按文法策略添加頁簽,單擊編輯。
在文法策略輸入框中,輸入以下Bucket Policy。
重要通過Bucket Policy按文法策略的方式進行授權時,新添加的策略會覆蓋已有的策略,請確保新添加策略包含已有策略的內容,否則可能導致關聯已有策略的操作失敗。
實際使用時,請相應替換自訂角色名稱(如果自訂角色名稱包含大寫字母,需轉換為對應的小寫字母。例如已建立的角色名稱為AliyunOssDrsRole,您需要轉換為aliyunossdrsrole)、目標Bucket名稱(dest-bucket)、源Bucket所屬帳號UID(137918634953xxxx)以及目標Bucket所屬帳號UID(111933544165xxxx)。
{ "Version":"1", "Statement":[ { "Effect":"Allow", "Action":[ "oss:ReplicateList", "oss:ReplicateGet", "oss:ReplicatePut", "oss:ReplicateDelete" ], "Principal": [ "arn:sts::137918634953xxxx:assumed-role/aliyunossdrsrole/*" ], "Resource":[ "acs:oss:*:111933544165xxxx::dest-bucket", "acs:oss:*:111933544165xxxx::dest-bucket/*" ] } ] }
單擊儲存。
通過帳號A為源Bucket建立跨地區複製規則。
登入OSS管理主控台。
單擊Bucket 列表,然後單擊源Bucket名稱。
在左側導覽列,選擇資料管理 > 跨區域復制。
在跨區域復制頁簽,單擊跨區域復制。
在跨區域復制對話方塊,按以下說明配置各項參數。
地區
參數
說明
設定目標Bucket
源Bucket
顯示源Bucket所在地區及名稱。
目標Bucket
選中在另一個帳號中指定一個Bucket,然後下拉選擇目標Bucket所在地區,並手動輸入目標Bucket名稱。
設定複製策略
數據複製對象
選擇需要複製的來源資料。
全部檔案進行同步:將該Bucket內所有的Object複製到目標儲存空間。
指定檔案名稱首碼進行同步:將該Bucket內指定首碼的Object複製到目標Bucket。最多可以添加10個首碼。
數據複製策略
選擇資料複製的方式。
增/改 同步:將該Bucket內Object新增和更新操作複製到目標Bucket。
增/刪/改 同步:將該Bucket內Object的新增、更新、刪除操作複製到目標Bucket。
如果某個Object是通過分區上傳的方式上傳至源Bucket,則每個分區的上傳操作都會複製至目標Bucket。最終,對所有分區執行CompleteMultipartUpload後產生的Object,也會被複製到目標Bucket。
有關跨地區複製結合版本控制的複製行為說明,請參見資料複製結合版本控制。
複製歷史數據
選擇是否複製跨地區複製規則生效前源Bucket中已有的歷史資料。
複製:將歷史資料複製至目標Bucket。
重要複製歷史資料時,從源Bucket複製的Object可能會覆蓋目標Bucket中同名的Object。為避免這部分檔案丟失,建議您對源Bucket和目標Bucket開啟版本控制。
不複製:僅複製跨地區複製規則生效後上傳或更新的Object。
授權角色
下拉選擇步驟1建立的角色。
加速類型
僅當跨地區複製涉及的兩個Bucket分別屬於中國內地與非中國內地地區時,加速類型支援傳輸加速。
開啟傳輸加速功能,OSS還會額外收取傳輸加速費用。計費方式,請參見傳輸加速費用。
資料複製時間控制(RTC)
說明僅支援華東1(杭州)、華東2(上海)、華北1(青島)、華北2(北京)、華北 3(張家口)、華南1(深圳)各地區之間的跨地區複製任務開啟RTC。
僅支援美國(矽谷)、美國(維吉尼亞)地區之間的跨地區複製任務開啟RTC。
開啟RTC後,OSS會在幾秒內複製您上傳到OSS的大多數Object,並在10分鐘內複製99.99%的Object。關於RTC的更多資訊,請參見使用資料複製時間控制(RTC)。開啟RTC,將收取額外費用。更多資訊,請參見跨地區複製RTC費用。
單擊確定,然後在彈出的對話方塊,單擊確認開啟。
當跨地區複製規則建立完成後,不允許對此規則進行編輯或刪除。
複製任務會在跨地區複製規則配置完成的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名稱,例如src-bucket。
String bucketName = "src-bucket";
// 指定資料要複製到的目標Bucket。目標Bucket與源Bucket必須屬於不同帳號。
String targetBucketName = "dest-bucket";
// 指定目標Bucket所在地區。目標Bucket與源Bucket必須處於不同地區。
String targetBucketLocation = "oss-cn-shanghai";
// 建立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");
//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.ALL);
// 指定可以被複製到目標Bucket的操作。預設值為ALL,表示源Bucket的所有操作都會複製到目標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-shanghai',
# 指定授權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的操作。預設值為ALL,表示源Bucket的所有操作都會複製到目標Bucket。
# action_list=[ReplicationRule.ALL],
# 指定資料要複製到的目標Bucket。目標Bucket與源Bucket必須屬於不同帳號。
# target_bucket_name='dest-bucket',
# 指定目標Bucket所在地區。目標Bucket與源Bucket必須處於不同地區。
# target_bucket_location='yourTargetBucketLocation',
# 預設複製歷史資料。此處設定為False,表示禁止複製歷史資料。
# is_enable_historical_object_replication=False,
# 指定資料複製時使用的資料轉送鏈路。
# target_transfer_type='oss_acc',
#)
# 開啟資料複製。
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。目標Bucket與源Bucket必須屬於不同帳號。
destBucketName := "yourDestBucket"
// 指定待覆制Object的首碼prefix_1和prefix_2。指定Prefix後,只有匹配該Prefix的Object才會複製到目標Bucket。
// 如果您需要將源Bucket中的所有Object複製到目標Bucket,則無需設定Prefix。
prefix1 := "prefix_1"
prefix2 := "prefix_2"
prefixSet := oss.ReplicationRulePrefix{Prefix: []*string{&prefix1, &prefix2}}
// 在配置跨地區複製規則時,開啟資料複製時間控制(RTC)功能。
enabled := "enabled"
reqReplication := oss.PutBucketReplication{
Rule: []oss.ReplicationRule{
{
PrefixSet: &prefixSet,
//指定可以被複製到目標Bucket的操作。預設值為ALL,表示源Bucket的所有操作都會複製到目標Bucket。
Action: "ALL",
RTC: &enabled,
Destination: &oss.ReplicationRuleDestination{
Bucket: destBucketName,
// 指定目標Bucket所在地區。源Bucket與目標Bucket必須處於不同的地區。
Location: "oss-cn-hangzhou",
// 指定資料複製時使用的資料轉送鏈路。此處設定為oss_acc,表示使用了傳輸加速鏈路。
TransferType: "oss_acc",
},
// 預設複製歷史資料。此處設定為disabled,表示禁止複製歷史資料。
HistoricalObjectReplication: "disabled",
// 指定授權OSS進行資料複製的角色名稱,且該角色必須已被授予源Bucket執行跨地區複製以及目標Bucket接收複製對象的許可權。
SyncRole: "yourRole",
},
},
}
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。