在启用版本的 amazon s3 存储桶上恢复文件

Restoring files on a version enabled amazon s3 bucket

我正在尝试在我的 Amazon S3 存储桶上启用版本控制和生命周期策略。我知道可以先启用版本控制,然后在该存储桶上应用生命周期策略。如果你看到下图,就会证实这个想法。

然后我多次上传了一个文件,创建了同一个文件的多个版本。然后我删除了文件,仍然可以看到几个版本。但是,如果我尝试恢复文件,我会看到启动恢复选项显示为灰色。

我想问问任何有类似问题的人,或者让我知道我做错了什么。

谢谢,

我已经意识到,一旦对象存储在 Gliacer 上,我就可以执行和启动恢复操作,如对象的存储 Class 所示。要在 S3 上恢复以前的副本,必须删除当前对象上的删除标记。

Amazon S3 上的存储桶版本控制 会保留对象的所有版本,即使它们被删除或在同一键(文件名)下上传新对象时也是如此。

根据您的屏幕截图,该对象的所有先前版本仍然可用。通过选择所需的版本并从操作菜单中选择 打开,它们可以在 S3 管理控制台中 downloaded/opened。

如果选择版本:隐藏,则每个对象只出现一次。其内容等于对象的最新上传版本。

删除版本化存储桶中的对象只会创建一个 删除标记 作为最新版本。这会使对象看起来好像已被删除,但如果您单击控制台顶部的 Versions:Show 按钮,之前的版本仍然可见。删除删除标记将使对象重新出现,内容将是最新上传的版本(删除前)。

如果您希望对象的特定版本成为 "current" 版本,可以:

  • 删除该版本之后的所有版本(使所需版本成为最新版本),或
  • 将所需版本复制回同一对象(使用相同的键,即文件名)。这将添加一个新版本,但内容将与您复制的版本相同。可以在 S3 管理控制台中执行复制——只需选择“复制”,然后从“操作”菜单中选择“粘贴”。

Initiate Restore 与归档存储系统 Amazon Glacier 一起使用。除非您已创建生命周期策略以将对象移动到 Glacier,否则此选项不相关。

使用新控制台,您可以按照以下方式进行操作。

  1. 单击“已删除对象”按钮
  2. 您将在下面看到您删除的对象,Select它
  3. 点击更多 -> 撤消删除

如果您有大量删除的文件要恢复。您可能希望使用脚本来完成这项工作。

脚本应该

  1. 使用 Get object versions API
  2. 获取存储桶中对象的版本
  3. 检查版本数据以获取删除标记(即删除对象)名称和版本 ID
  4. 使用 Delete object API
  5. 删除使用标记名称和版本 ID 找到的标记

Python example with boto:

此示例脚本一次一个地删除删除标记。

#!/usr/bin/env python
import boto

BUCKET_NAME = "examplebucket"
DELETE_DATE = "2015-06-08"

bucket = boto.connect_s3().get_bucket(BUCKET_NAME)

for v in bucket.list_versions():
    if (isinstance(v, boto.s3.deletemarker.DeleteMarker) and
            v.is_latest and
            DELETE_DATE in v.last_modified):
        bucket.delete_key(v.name, version_id=v.version_id)

Python example with boto3:

但是,如果您有数千个对象,这可能是一个缓慢的过程。 AWS 确实提供了一种方法 batch delete objects,最大批量大小为 1000。

以下示例脚本使用前缀搜索您的对象,并测试它们是否被删除(即当前版本是删除标记)并批量删除它们。设置为每批在你的bucket中搜索500个object,并尝试删除一个batch不超过1000个object的多个object。

import boto3

client = boto3.client('s3')


def get_object_versions(bucket, prefix, max_key, key_marker):
    kwargs = dict(
        Bucket=bucket,
        EncodingType='url',
        MaxKeys=max_key,
        Prefix=prefix
    )

    if key_marker:
        kwargs['KeyMarker'] = key_marker

    response = client.list_object_versions(**kwargs)

    return response


def get_delete_markers_info(bucket, prefix, key_marker):
    markers = []
    max_markers = 500
    version_batch_size = 500

    while True:
        response = get_object_versions(bucket, prefix, version_batch_size, key_marker)
        key_marker = response.get('NextKeyMarker')
        delete_markers = response.get('DeleteMarkers', [])

        markers = markers + [dict(Key=x.get('Key'), VersionId=x.get('VersionId')) for x in delete_markers if
                             x.get('IsLatest')]

        print '{0} -- {1} delete markers ...'.format(key_marker, len(markers))

        if len(markers) >= max_markers or key_marker is None:
            break

    return {"delete_markers": markers, "key_marker": key_marker}


def delete_delete_markers(bucket, prefix):
    key_marker = None

    while True:
        info = get_delete_markers_info(bucket, prefix, key_marker)
        key_marker = info.get('key_marker')
        delete_markers = info.get('delete_markers', [])

        if len(delete_markers) > 0:
            response = client.delete_objects(
                Bucket=bucket,
                Delete={
                    'Objects': delete_markers,
                    'Quiet': True
                }
            )

            print 'Deleting {0} delete markers ... '.format(len(delete_markers))
            print 'Done with status {0}'.format(response.get('ResponseMetadata', {}).get('HTTPStatusCode'))
        else:
            print 'No more delete markers found\n'
            break


delete_delete_markers(bucket='data-global', prefix='2017/02/18')