【问题标题】:Fastest way to do S3 copy from one bucket to another将 S3 从一个存储桶复制到另一个存储桶的最快方法
【发布时间】:2019-05-24 08:01:05
【问题描述】:

我的 bucket1 中有一个在 KMS key1 中加密的文件。我需要将其传输到 bucket2 并使用 KMS key2 对其进行加密。我最初使用的是 GetObject 和 PutObject API。但是对于较大的文件(5GB 及以上),这需要很长时间。我也在 lambda 上执行此任务,因此超时为 15 分钟。

我尝试使用 TransferManager 下载 API,但它需要一个文件,我遇到了以下错误。我打算先进行多部分下载,然后再进行多部分上传。根据我的理解,由于我需要使用 key1 解密我的文件,然后使用 key2 加密我的文件,我不能使用多部分副本,因为它使用相同的 Amazon S3 客户端。

TransferManager sourceTransferManager = TransferManagerBuilder
                    .standard().withS3Client(sourceS3Client).build();
            GetObjectRequest getObjectRequest = new GetObjectRequest(srcBucket, srcKey);
            File modelFile = File.createTempFile("BigFile", "gz");
            logger.log("Starting download");
            Download download = sourceTransferManager.download(getObjectRequest, modelFile);
            download.waitForCompletion();
            sourceTransferManager.shutdownNow();
            logger.log("Finishing download");

            logger.log("Downloaded the object, let's upload it");
            //For a decrypted object, the content length in metadata still has the encrypted length
            //Set the content length to the unencrypted-data-length

            PutObjectRequest putObjectRequest = new PutObjectRequest(destS3Uri.getBucket(), destS3Uri.getKey(), modelFile);
            transferManager = TransferManagerBuilder
                    .standard()
                    .withS3Client(destS3Client)
                    .build();
            Upload upload = transferManager.upload(putObjectRequest);```

aused by: com.amazonaws.SdkClientException: Unable to store object contents to disk: No space left on device
at com.amazonaws.services.s3.internal.ServiceUtils.downloadToFile(ServiceUtils.java:314)
at com.amazonaws.services.s3.transfer.DownloadCallable.retryableDownloadS3ObjectToFile(DownloadCallable.java:275)
at com.amazonaws.services.s3.transfer.DownloadCallable.downloadAsSingleObject(DownloadCallable.java:92)
at com.amazonaws.services.s3.transfer.internal.AbstractDownloadCallable.call(AbstractDownloadCallable.java:102)
at com.amazonaws.services.s3.transfer.internal.AbstractDownloadCallable.call(AbstractDownloadCallable.java:40)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at java.lang.Thread.run(Thread.java:748)
Caused by: java.io.IOException: No space left on device
at java.io.FileOutputStream.writeBytes(Native Method)
at java.io.FileOutputStream.write(FileOutputStream.java:326)
at java.io.BufferedOutputStream.write(BufferedOutputStream.java:122)
at com.amazonaws.services.s3.internal.ServiceUtils.downloadToFile(ServiceUtils.java:309)
... 8 more

【问题讨论】:

  • 两个存储桶是否在同一个 AWS 账户中?
  • 您是否尝试过简单地使用CopyObject() 方法?它复制一个对象,包括在桶之间,而不需要下载/上传。只要您有权使用与源对象关联的 KMS 密钥,它就可以读取该对象。然后,您将为目标对象指定 KMS 密钥。
  • 我的两个bucket都在不同的账户和不同的地区。我无法使用相同的 s3 客户端复制它。

标签: amazon-web-services amazon-s3 aws-lambda


【解决方案1】:

您可以使用CopyObject() 方法在存储桶之间复制对象,即使存储桶位于不同账户不同地区无需下载/上传对象!

假设您从属于Account-ARegion-A 中的Bucket-A 复制到属于Region-BBucket-B

有两种方法:

拉法

  • 假设Account-B 中有一个 IAM 用户 (User-B)
  • Bucket-A 添加一个存储桶策略,允许User-B 从存储桶中列出/获取
  • 作为User-B,将CopyObject() 命令发送到Region-B 中的Amazon S3(目标存储桶从源“拉取”对象)

推送方式

  • 假设Account-A 中有一个 IAM 用户 (User-A)
  • Bucket-B 添加一个存储桶策略,允许User-A 列出/放入 存储桶
  • 作为User-A,将CopyObject() 命令发送到Region-B 中的Amazon S3(目标存储桶从源“拉取”对象)并确保将ACL 指定为@ 987654344@。这允许目标存储桶(由不同账户拥有)“拥有”复制的对象。这很重要!

我更喜欢 'pull' 方法,因为它不需要额外的访问控制列表 (ACL) 规范,因为 Account-B 拥有它复制的对象(而不是 Account-A 将对象发送到 Account-B )。

如果这是一次性活动,我建议使用AWS Command-Line Interface (CLI),因为它非常易于使用。但是,如果您需要它更频繁地运行,则可能值得对其进行编码。

【讨论】:

猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-11-22
  • 1970-01-01
  • 2023-02-01
  • 2020-07-05
  • 2013-11-01
  • 1970-01-01
相关资源
最近更新 更多