亚马逊AWS官方博客

通过 AWS DTH 和 Amazon S3 File Gateway 实现海外数据的定时同步和本地访问

项目背景

A 公司是一家专注于计算机三维影像和数字动画内容的制作和服务的公司。公司以数字信息技术应用和工业化生产能力为核心,为全球众多的客户提供高品质的 3D 数字内容制作服务。

公司 A 不但自己在全球各地有多个分公司,而且和很多兄弟公司有很多合作关系,日常有大量的媒资数据需要进行交换,但是 A 公司本部位于国内,所以和海外的兄弟单位之间数据传输一直存在问题,要么就是效率低,要么就是代价过高(搭建专用线路),客户需要一个性价比而且高效的方案来满足客户需求。

客户需求分析

  • 多家海外的兄弟单位有不同的媒资数据(数百 TB 到数 PB 不等)需要和 A 公司进行交互(主要是 A 公司需要读取)
  • 兄弟单位的媒资数据会不断更新的,更新无规律,但是 A 公司读取的时候接受 1-2 天的延时
  • 客户国内的制作人员会根据自己的制作需求,读取自己需要的数据,并不需要读取/下载全部的数据集
  • 有部分兄弟单位的数据集长期存放在 AWS 海外区域 S3 上,并且定期更新。

实现原理

根据客户的需求,首先在中国区(宁夏)开启 Amazon S3 服务,用于存放从其他数据源同步过来的数据,我们可以采用 AWS 数据传输解决方案(以下简称 DTH)和 AWS Storage Gateway 为核心,加上 Lambda/eventbridge/Dynamodb 等服务给客户构建一套定时同步,通过 SGW 的 NFS 或者 SMB 协议缓存并访问 S3 的数据,无需任何干预,同时也可以得到相关通知事件,整个解决方案都是基于按需付费的方式,提供高效复制的同时,本地访问的性能也能得到保证,同时成本也能得到控制,此方案的主要组件说明如下:

DTH(AWS 数据传输解决方案)

  • DTH 可以轻松帮助客户实现跨区域数据传输,传输速度快而且成本极低。
  • DTH 采用无服务器构架,客户只需要根据传输任务按需付费,随用随付。
  • DTH 提供友好的用户界面供客户操作,简单易用,当客户的传输任务比较恒定,不需要经常变更操作的时候也可以采用无操作界面的 plugin 构架,部署方式非常灵活。
  • DTH 目前支持其他云服务商的对象存储服务(包括阿里云 OSS,腾讯 COS,七牛 Kodo 以及其他兼容 Amazon S3 的云存储服务)和 Amazon S3 之间的数据传输;同时支持公共容器镜像仓库(例如 Docker Hub、Google io 和 Red Hat Quay.io)和 Amazon ECR(Amazon Elastic Container Registry )之间的容器镜像传输。

AWS Storage Gateway

  • AWS Storage Gateway 提供对本地部署应用程序对云端数据的低延迟数据访问,同时利用 AWS 在云中的敏捷性、经济性和安全性功能。
  • AWS Storage Gateway 无需部署新的存储硬件,即可为用户和应用程序提供几乎无限容量的云存储。
  • 此方案中,AWS Storage Gateway 可以实现客户数据对 Amazon S3 的数据的轻松访问

方案拓扑

这个方案中,主要是海内外的 Amazon S3 同步,由于客户的账号是在中国区,客户本地办公室采用 vmware 的环境,安装 AWS S3 File Gateway 所需 vm 环境,SSD 作为缓存,经常访问的内容在本地 SSD 内,同时 Amazon S3 File Gateway 设置为只读模式,可以最大程度上节省成本。相关的部署主要在中国区完成,采用 AWS DTH 的 Amazon S3 数据传输插件,定时从海外的 Amazon S3 同步到中国区域 S3,同步完毕之后,可以通过监控同步传输任务是否结束,如果结束可以触发一个 Storage Gateway(Amazon S3 File Gateway)的 cache 刷新操作,从而客户端可以看到最新的数据,而且有本地 SSD 缓存,经常访问的数据不会产生多次的 Amazon S3 读取费用。

实施步骤

一、首先我们需要建立海外 Amazon S3 到中国区 Amazon S3 的同步关系,这里采用 DTH 的 Amazon S3 数据传输插件,实施步骤如下:

1. 准备 VPC(可选)

此解决方案可以部署在公共和私有子网中。 建议使用公共子网。

  • 如果您想使用现有的 VPC,请确保 VPC 至少有 2 个子网,并且两个子网都必须具有公网访问权限(带有 Internet 网关的公有子网或带有 NAT 网关的私有子网)
  • 如果您想为此解决方案创建新的默认 VPC,请转到步骤 2,并确保您在创建集群时选择了为此集群创建一个新的 VPC。

2. 配置 ECS 集群

此方案需要 ECS 集群才能运行 Fargate 任务。

打开 AWS 管理控制台 > Elastic Container Service(ECS)。 在 ECS 集群首页上,单击创建集群。

步骤 1:选择集群模版,确保选择仅限联网类型。

步骤 2:配置集群,指定集群名称,点击创建即可。 如果您还想创建一个新的 VPC(仅限公有子网),还请选中为此集群创建新的 VPC 选项。

3. 配置凭据

您需要提供 AccessKeyIDSecretAccessKey(即 AK/SK)才能从另一个 AWS 账户或其他云存储服务读取或写入 S3 中的存储桶,凭证将存储在 AWS Secrets Manager 中。您不需要为此方案部署的当前账户里的存储桶创建凭证。

打开 AWS 管理控制台 > Secrets Manager。在 Secrets Manager 主页上,单击存储新的密钥。对于密钥类型,请使用其他类型的秘密。对于键/值对,请将下面的 JSON 文本复制并粘贴到明文部分,并相应地将值更改为您的 AK/SK。

{
  "access_key_id": "<Your Access Key ID>",
  "secret_access_key": "<Your Access Key Secret>"
}

然后下一步指定密钥名称,最后一步点击创建。

注意:如果该 AK/SK 是针对源桶, 则需要具有桶的权限, 如果是针对目标桶, 则需要具有桶的读与写权限。

4. 启动 AWS Cloudformation 部署

请按照以下步骤通过 AWS Cloudformation 部署此解决方案。

  1. 登录到 AWS 管理控制台,切换到将 CloudFormation Stack 部署到的区域。
  2. 单击以下按钮在该区域中启动 CloudFormation 堆栈。
  • 单击下一步。相应地为参数指定值。 如果需要,请更改堆栈名称。
  • 单击下一步。配置其他堆栈选项,例如标签(可选)。
  • 单击下一步。查看并勾选确认,然后单击“创建堆栈”开始部署。

部署预计用时 3-5 分钟,这里我们客户账号是中国宁夏区域,所以采用第一个启动模版。

至此,配置已经完毕,我们已经建立了海内外的 Amazon S3 的复制关系,建立好之后要注意看 EventBridge 里面的定时任务,看看什么时候开启复制,截图如下:

规则名称是以 DTHS3Stack-ECSStackDTHFinderSchedule 开头的,记住按照客户要求的时间进行同步,目前此 case 同步是定义在凌晨零点进行,每天执行一次。

二、部署 S3 File Gateway

1. 创建 Storage Gateway

在宁夏区域选择 Storage Gateway 服务,然后选择“创建网关”,如下图所示:

选择 Amazon S3 File Gateway:

在页面的下方,选择 VMware ESXi 并下载 OVF 文件进行本地部署:

OVF 的部署过程这里就不赘述了,部署完毕以后,上面的页面勾选“我已下载 OVF 模板并完成部署,并且已遵循上述所有步骤。”然后点击下一步,如下图所示:

这里的激活密钥要通过刚才部署的虚拟机获得。

部署虚拟机的时候,本地最好增加 1-2 块 150G 以上的 SSD 作为本地缓冲区,如果经常访问的数据量比较大,可以扩大这个 SSD 的容量,登录虚拟机的用户名为 admin,密码为 password,其中本地虚拟机的相关操作就不做赘述了,这里有文档介绍描述:https://docs.aws.amazon.com/zh_cn/filegateway/latest/files3/create-gateway-file.html

启动之后一定要 Test Network Connectivity,看看和宁夏区的 endpoint 是否通讯正常,然后选择 0 可以获得激活密钥,然后在上图激活密钥处输入密钥,点击下一步,会出现激活等待页面(之后可以看到配置了缓存 SSD):

几分钟后检测到网关后会显示如下界面:

点击底部的“配置”即可,网关配置完毕,如下图所示:

2. 创建文件共享

接下来,需要创建文件共享,这里主要是本地的设计工程师使用(windows 平台),所以只需要 SMB 共享。

在宁夏区域 storage gateway 的主页面选择“文件共享”,然后点击“创建文件共享”,如下图所示按照实际填写:


注意:这里不需要刷新缓存,后面会介绍刷新缓存的机制,点击下一步,下一个页面保持默认,继续下一步,到如下页面:

这里我们采用来宾访问,直接设置访问密码,共享设置为只读(此 case 中非常重要,后面会解释),然后继续下一步点击创建即可。然后点击创建的文件系统共享,最下面有客户端挂载的命令,复制命令挂载(比如 Z 盘)即可:

3. 创建定时刷新 storage gateway 缓存方案

Storage Gateway 会维护一份元数据,也就是客户端能看到 Amazon S3 里面的内容的列表,比如你通过 Gateway 的文件共享上传/修改/创建的文件是能够正确识别的,但是如果你通过 Amazon S3 桶的 API 直接操作的数据,访问的文件共享并不能感知,因为没有元数据,所以存在一个刷新缓存的动作,使得 Amazon S3 对应的数据能够被挂载的文件系统发现,这也是这个 case 中需要注意的地方,通过远程同步到宁夏区 Amazon S3 桶的数据,如果不做刷新缓存的动作,这些数据并不会被客户端所看见。

所以最理想的状态是,每天的同步完成之后,我们做一次刷新缓存的操作,但问题是,由于我们不知道每天同步数据需要多久完成,所以无法定时执行这个刷新缓存的操作。

DTH 方案中,使用了 Amazon SQS 消息队列服务来记录需要同步的对象,如果消息队列中有未处理的消息,那么表示还存在未同步的对象,所以可以跟据这个指标来监控传输任务是否结束。此方案在 cloudwatch 里面已经设置了数个监控指标,其中一个指标,名称为 ApproximateNumberOfMessagesNotVisible,此指标就是对应消息队列中的活动消息数量,最终对应的就是目前运行的传输的 job 个数,一般没有 job 的时候这个指标为 0,如果有数据传输的时候,这个值大于 0,传输完成之后,数值归 0,那么按照这个原理就很好办了。

  • 首先设置一个 Cloudwatch 告警,就是针对这个指标的,指标大于零,就进行告警
  • 然后使用 Amazon SNS 服务(消息传输服务)来及时收到数据传输服务以及 Storage Gateway 缓存刷新的相关信息,需要创建一个主题并且订阅主题,其中主题的 arn 需要记录下来,后面会用使用到,详细的操作步骤可以参考以下链接:https://docs.aws.amazon.com/zh_cn/sns/latest/dg/sns-getting-started.html
  • 在 EventBridge 规则里面添加一个对这个 Cloudwatch 告警指标的规则,状态发生变化就触发,目标是刷新 Storage Gateway 缓存的 Lambda 函数
  • 在 Lambda 函数里面新建一个 Lambda 函数,版本使用最新版本的 python,需要设置两个环境变量
    • 第一个环境变量名为 SNS_TOPIC,对应的值就是刚才创建的 Amazon SNS 的主题 ARN
    • 第二个环境变量名为 FileShare,对应的值就是上文中创建的文件共享的 ARN
  • Lambda 函数内容如下:
import json
import boto3
import os
from datetime import datetime

def lambda_handler(event, context):
    print('Event: {}'.format(event))
    DTHSTATE = event['detail']['state']['value']
    print(DTHSTATE)
    NOW = datetime.now()
    TIMESTAMP = datetime.timestamp(NOW) - 600
    print("时间戳 =", TIMESTAMP)
    
    sns_client = boto3.client('sns')
    sgw_client = boto3.client('storagegateway')
    SNS_TOPIC = os.environ['SNS_TOPIC']
    FileShare = os.environ['FileShare']
    
    if DTHSTATE == 'ALARM':
        sns_client.publish(
            TopicArn = SNS_TOPIC,
            Subject = '数据传输任务开始',
            Message = '数据传输任务开始, 使用 AWS 数据传输解决方案')
    if DTHSTATE == 'OK':
        sns_client.publish(
            TopicArn = SNS_TOPIC,
            Subject = '数据传输任务结束',
            Message = '数据传输任务结束, 马上进行 Storage gateway 同步')
        sgw_client.refresh_cache(
            FileShareARN= FileShare)
    

    return {
        'statusCode': 200,
        'body': json.dumps('数据刷新任务完成')
    }
  • 这里 EventBridge 规则和 Lambda 函数就实现了,当有传输任务的时候,相应的告警状态就发生变化,变为 Alarm 状态,我们可以通过 SNS 通知相应的接收方,数据任务开始了。
  • 当传输任务结束的时候,相应的告警状态就发生变化,变为 OK 状态,我们可以通过 SNS 通知相应的接收方,数据任务结束了,并且刷新缓存。

下面我们进行测试:

  • 先在源存储桶里上传一些数据文件
  • 修改 Eventbridge 里面的定时任务,使之在接下来几分钟内进行
  • 任务启动后,在 Cloudwatch 的监控面板(DTHS3Stack-Dashboard 开头)可以看到任务的运行情况和有多少剩余的数据需要传输,同时 SNS 会对订阅方发送信息“传输任务开始”
  • 通过 Cloudwatch 的监控面板看到任务传输完毕之后,我们可以接收到“传输任务结束”的信息
  • 过一会儿,storage gateway 缓存刷新完毕之后,挂载的对应的驱动器下面的数据就已经刷新了

至此,整个方案部署完毕,客户本地制作工程师可以很方便的访问兄弟单位传输过来的数据,而且完全自动化。

Takeaway

  • 整个方案都是基于 pay-as-you-go 的思路搭建,性价比非常高
  • AWS DTH 的一个 worker 传输大文件速度约为 1GB/min(美东 1 到宁夏区域),而且是增量复制,就算数据变化很大的情况下,也可以在很短的时间内完成同步
  • Amazon S3 File Gateway 收费标准是写入收费,读取并不收费,设置的时候选择了只读,所以 Storage Gateway 除了本地需要投入一台 vmware 的虚拟机环境以外,并不会产生其他的费用
  • Amazon S3 File Gateway 本地的 SSD 可以缓存经常访问的数据,避免了同一数据反复访问产生的 S3 费用
  • 客户的制作工程师并不是对整个数据集进行访问, 只是对必要的数据进行访问,而且本地缓存在提高访问速度的同时,也可以降低 Amazon S3 访问费用
  • Dynamodb 中存放了传输的文件清单,如果客户需要检查也可以通过 API 进行读取并且展示

本篇作者

王京来

亚马逊云科技解决方案架构师,目前专注于存储、数据库相关的解决方案。在加入 AWS 之前,曾就职于惠普、EMC 等科技公司,从事企业级用户 IT 基础架构相关工作,拥有二十余年技术服务经验。