亚马逊AWS官方博客
利用Data Transfer Hub在专线或VPN内网环境搬迁对象存储数据
1. 背景说明
Data Transfer Hub(DTH)是亚马逊云科技解决方案团队开发的用于搬迁对象存储数据和容器镜像的一个解决方案。DTH解决方案包含两个Plugin,分别是S3 Plugin和ECR Plugin。
本文中,使用亚马逊云科技北京区域的S3作为源数据桶,使用亚马逊云科技宁夏区域的S3作为目标数据桶。同时,在亚马逊云科技北京区域的EC2实例上部署代理服务器,使用亚马逊云科技宁夏区域的资源部署DTH S3 Plugin,使用VPC Endpoint和跨区域的VPC Peering进行全链路内网通信,实现了一个在内网环境中搬迁对象存储数据的方案。
2. 整体架构
3. 环境搭建 (真实环境中可以省略此章)
- 创建基础网络资源
亚马逊云科技宁夏区域 | 亚马逊云科技北京区域 | 属性 | |
Amazon Virtual Private Cloud(VPC) | 10.0.0.0/16 | 172.17.0.0/16 | |
AZ1中的子网 | 10.0.0.0/24 | ||
AZ2中的子网 | 10.0.1.0/24 | 172.17.1.0/24 | 关闭分配公网IP |
AZ3中的子网 | 10.0.2.0/24 | ||
Gateway Endpoint | Amazon S3, Amazon DynamoDB | Amazon S3 | |
Interface Endpoint | Amazon Simple Queue Service(SQS), Amazon Secrets Manager, Amazon CloudFormation, Amazon CloudWatch, Amazon Elastic Container Service |
# 0. 进入screen模式,以保证环境变量不会因为退出Session而消失
# 1. 创建VPC,分别是ningxia_vpc_id和beijing_vpc_id
# 2. 创建Subnet
# 2.1 亚马逊云科技宁夏区域
# 在AZ1中创建ningxia_subnet_id_az1
# 在AZ2中创建ningxia_subnet_id_az2
# 在AZ3中创建ningxia_subnet_id_az3
# 2.2 亚马逊云科技北京区域
# 在AZ2中创建beijing_subnet_id_az2
# 3. 创建路由表,分别是ningxia_route_table_id和beijing_route_table_id
# 4. 更改路由表
# 分别获取route_table_association_id_ningxia和route_table_association_id_beijing
# 4.1 通过替换route_table_association_id使用创建的路由表
# 5. 修改安全组
# 分别获取宁夏和北京的groupid
groupid_ningxia=$(aws ec2 describe-security-groups –region cn-northwest-1 –filter “Name=vpc-id,Values=$ningxia_vpc_id” –query “SecurityGroups[].GroupId” –output text)
groupid_beijing=$(aws ec2 describe-security-groups –region cn-north-1 –filter “Name=vpc-id,Values=$beijing_vpc_id” –query “SecurityGroups[].GroupId” –output text)
# 基于获取的groupid,修改安全组
- 通过搭建VPC Peering模拟内网环境
# 6. 创建Peering Gateway
# 6.1 添加路由,使得亚马逊云科技宁夏区域和亚马逊云科技北京区域可以互通
备注1:这一章是搭建实验环境的过程。在真实场景中,由于已经具备内网环境,可以省略。虽然内网环境是通过VPC Peering进行的模拟,但是这篇文章描述的方法同样适用于专线和VPN构造的环境。
4. 实现步骤
a)创建Endpoint
- 文章涉及的VPC内服务都不具备公网访问能力,又由于VPC内的服务需要同非VPC内的服务进行交互,因此需要借助Gateway Endpoint和Interface Endpoint服务实现。
# 7. 创建Endpoint
# 7.1 修改VPC属性,需要开启dns-hostname和dns-support才能创建Endpoint
# 7.2 亚马逊云科技宁夏区域
# 7.2.1 Gateway Endpoint
# 创建S3 Gateway Endpoint,使得EC2实例可以在无公网环境访问S3
# 创建DynamoDB Gateway Endpoint,使得EC2实例可以在无公网环境访问DynamoDB
# 7.2.2 Interface Endpoint
# 创建Amazon SQS Interface Endpoint,使得EC2实例可以在无公网环境访问Amazon SQS
# 创建Amazon Secrets Manager Interface Endpoint,使得EC2实例可以在无公网环境访问Amazon Secrets Manager
# 创建Amazon CloudFormation Interface Endpoint,使得EC2实例可以在无公网环境访问Amazon CloudFormation
# 创建Amazon CloudWatch Interface Endpoint,使得EC2实例可以在无公网环境访问Amazon CloudWatch
# 创建Amazon ECR Interface Endpoint,使得EC2实例可以在无公网环境访问Amazon ECR
# 7.3 亚马逊云科技北京区域
# 7.3.1 Gateway Endpoint
# 创建S3 Gateway Endpoint,使得EC2实例可以在无公网环境访问S3
b)创建Amazon Elastic Container Service(ECS)集群,选择Networking only模式
# 8. 创建ECS集群
c)安装和配置Proxy服务器
- 创建Proxy模板实例,此实例具备公网访问能力,用以安装和配置Nginx服务,并最终转换为自定义镜像。然后会以这个自定义镜像在可用区2创建Proxy实例,用以转发访问请求。
- Nginx需要使用Stream模块,此模块会在TLS建连时拿到访问的Amazon S3 Endpoint,并借助Proxy实例最终将请求转发到Amazon S3 Endpoint。
- Nginx无法使用HTTPS模块的原因是,域名的所有者是Amazon,因此无法进行TLS Termination。
# 9. 创建EC2实例
# 9.1 创建Proxy模板实例,请确保北京区域已有名为id_rsa_test.pub的公钥
# 创建Instance
# 等待实例创建完成
# 创建Internet Gateway
# Attach Internet Gateway
# 添加路由
# 获得proxy_template_instance_ip
# 9.2 安装和配置Proxy模板实例(以root用户执行)
下载ProxyInstanceDeploymentProcedure:https://github.com/successzy/For-Blog/blob/main/ProxyInstanceDeploymentProcedure,并根据”ProxyInstanceDeploymentProcedure”中记载的步骤进行配置
# 9.3 生成自定义镜像
# 停止实例
# 等待实例停止完成
# 创建Proxy实例镜像
# 等待镜像创建完成
# 9.4 创建Proxy实例
# 使用上一步创建的镜像创建一台实例
# 等待实例创建完成
# 9.5 删除临时资源,依次删除路由条目、Internet Gateway和删除临时Proxy实例
备注2:这一节描述的是如何创建Amazon EC2实例并安装和配置Nginx服务。虽然创建Amazon资源所使用的API无法进行复用,但是在实例中安装和配置Nginx服务的步骤是可复用的。
d)重新构建Finder镜像
- Finder实例是由ECS Fargate服务启动的容器实例,会使用VPC内的默认DNS进行域名解析。默认情况下,会将cn-north-1.amazonaws.com.cn域名解析到真实的S3 IP地址。但是本篇文章所涉及的场景中,需要将s3.cn-north-1.amazonaws.com.cn域名指向Proxy实例的私网IP,因此需要在启动Finder实例时,自动更新/etc/hosts文件内容,以更高优先级覆盖VPC内的默认DNS的解析记录。
- 通过extra-hosts.sh实现自动更新/etc/hosts文件,再通过Dockerfile中的CMD /app/dthcli run和ENTRYPOINT [“sh”, “/app/extra-hosts.sh”]运行主程序。
- Amazon Private Hosted Zone无法使用带有com.cn或者amazonaws.com的域名,只能使用com.cn或者com域名,因此无法使用Amazon Private Hosted Zone进行域名解析重定向。
# 10. 重新构建Finder镜像
# 10.1 下载dthcli_1.0.0_linux_amd64.tar.gz并解压
# 10.2 修改Dockerfile文件
# 10.3 编写extra-hosts.sh脚本
# 10.4 构建镜像
e)上传Finder镜像到Amazon Private ECR
# 11. 上传镜像
# 11.1 创建ECR Repository
# 11.2 上传镜像到ECR Repository,这一步需要登录控制台并查看Repository中的Push Commands中的命令
f)修改Amazon CloudFormation模板
- 在原始的CloudFormation模板基础上,主要修改了如下两个部分:
- 在模板中添加了Additional Information For Private Transfer Through Proxy段落
- 在ECR Task Definition的Task execution role中增加了下载ECR镜像的权限
- 模板文件:https://github.com/successzy/For-Blog/blob/main/DataTransferS3Stack-Blog.template
5. 搬迁验证
a)由于Worker实例无法访问公网,因此需要创建一个Amazon S3桶,用以存放软件,使得Worker实例可以借助Gateway Endpoint获取软件。
# 12. 创建Amazon S3桶
# 12.1 将软件放入Amazon S3桶
b)创建用于访问源站Amazon S3的AKSK并存入Secrets Manager
# 13. 创建用于访问源站Amazon S3的AKSK并存入Secrets Manager
# 创建用户
# Attach Policy
# 创建AccessKey和SecretAccessKey
aws iam create-access-key –user-name blog-user # 记录输出结果,后面会用到
# 创建Secret
c)通过 实现步骤–>步骤f) 修改Amazon CloudFormation模板下载的模板部署DTH S3 Plugin
下载CloudFormationTemplateParameterExplanation.docx:https://github.com/successzy/For-Blog/blob/main/CloudFormationTemplateParameterExplanation.docx,并根据”CloudFormationParameterExplanation”中记载的步骤进行配置
d)结果展示
- DTH任务运行前查看源桶和目标桶对象
# 源桶文件
- 查看DTH运行日志
- 查看Finder日志
- 查看Proxy实例日志
- DTH任务运行后再次查看源桶和目标桶对象
# 源桶文件
6. 修改dthcli源码以保留源桶对象的Storage Class (Optional)
- Amazon S3提供提供多达8种Storage Class,分别是Standard、Intelligent Tiering、Standard IA、One Zone-IA、Glacier Instant Retrieval、Glacier Flexible Retrieval (formerly Glacier)、Glacier Deep Archive、Reduced redundancy。其中,Reduced redundancy已经不再推荐使用。而Glacier类型对象需要事先解冻才能进行搬迁,因此dthcli对此类对象进行了排除。
- 对于剩下的4种Storage Class,在CloudFormation目标桶对象Storage Class选择时,只能选择某一种Storage Class,即只能在搬迁源桶对象时按照指定的Storage Class搬迁到目标桶,而无法保留源桶对象的Storage Class。
- 在这一章,将通过修改dthcli源码,实现保留源桶对象的Storage Class这一目标。即CloudFormation模板中的Destination Storage Class将不再产生效果。
# 1. 下载1.1.0版本源代码并解压,在1.1.0版本加入了排除GLACIER和DEEP_ARCHIVE的功能
# 2. 修改dthcli源码
- client.go
- common.go
- job.go
# 3. 在X86服务器上编译dthcli,并打包成镜像放入ECR
# 由于Fargate只能部署在X86 Host,因此需要编译X86 dthcli,用于在Fargate上部署Finder
# 编译后参考步骤”10. 重新构建Finder镜像”
# 4. 在Arm服务器上编译dthcli,并放入S3
# 由于Worker节点使用Arm机型,因此需要编译Arm dthcli
# 5. X86 dthcli和Arm dthcli下载
- 结果展示
7. 清理环境
下载Cleanup:https://github.com/successzy/For-Blog/blob/main/Cleanup,并根据”Cleanup”中记载的步骤进行资源删除:
8. 总结
在这篇文章中,通过结合DTH S3 Plugin和代理层实现了对象存储数据在内网环境的搬迁。
同时,针对dthcli在搬迁对象时无法保留源桶对象Storage Class的问题,通过修改dthcli代码补足了这部分能力。