亚马逊AWS官方博客

利用Data Transfer Hub在专线或VPN内网环境搬迁对象存储数据

1. 背景说明

Data Transfer Hub(DTH)是亚马逊云科技解决方案团队开发的用于搬迁对象存储数据和容器镜像的一个解决方案。DTH解决方案包含两个Plugin,分别是S3 PluginECR 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而消失

screen

# 1. 创建VPC,分别是ningxia_vpc_idbeijing_vpc_id

ningxia_vpc_id=$(aws ec2 create-vpc --cidr-block 10.0.0.0/16 --region cn-northwest-1 --query "Vpc.VpcId" --output text)
beijing_vpc_id=$(aws ec2 create-vpc --cidr-block 172.17.0.0/16 --region cn-north-1 --query "Vpc.VpcId" --output text)

 

# 2. 创建Subnet

# 2.1 亚马逊云科技宁夏区域

# AZ1中创建ningxia_subnet_id_az1

ningxia_subnet_id_az1=$(aws ec2 create-subnet --cidr-block 10.0.0.0/24 --vpc-id $ningxia_vpc_id --region cn-northwest-1 --availability-zone cn-northwest-1a --query "Subnet.SubnetId" --output text)

 

# AZ2中创建ningxia_subnet_id_az2

ningxia_subnet_id_az2=$(aws ec2 create-subnet --cidr-block 10.0.1.0/24 --vpc-id $ningxia_vpc_id --region cn-northwest-1 --availability-zone cn-northwest-1b --query "Subnet.SubnetId" --output text)

 

# AZ3中创建ningxia_subnet_id_az3

ningxia_subnet_id_az3=$(aws ec2 create-subnet --cidr-block 10.0.2.0/24 --vpc-id $ningxia_vpc_id --region cn-northwest-1 --availability-zone cn-northwest-1c --query "Subnet.SubnetId" --output text)

 

# 2.2 亚马逊云科技北京区域

# AZ2中创建beijing_subnet_id_az2

beijing_subnet_id_az2=$(aws ec2 create-subnet --cidr-block 172.17.1.0/24 --vpc-id $beijing_vpc_id --region cn-north-1 --availability-zone cn-north-1b --query "Subnet.SubnetId" --output text)

 

 

# 3. 创建路由表,分别是ningxia_route_table_idbeijing_route_table_id

ningxia_route_table_id=$(aws ec2 create-route-table --vpc-id $ningxia_vpc_id --region cn-northwest-1 --query "RouteTable.RouteTableId" --output text)
beijing_route_table_id=$(aws ec2 create-route-table --vpc-id $beijing_vpc_id --region cn-north-1 --query "RouteTable.RouteTableId" --output text)

 

 

# 4. 更改路由表

# 分别获取route_table_association_id_ningxiaroute_table_association_id_beijing

route_table_association_id_ningxia=$(aws ec2 describe-route-tables --region cn-northwest-1 --filter "Name=vpc-id,Values=$ningxia_vpc_id" "Name=association.main,Values='true'" --query "RouteTables[].Associations[].RouteTableAssociationId" --output text)
route_table_association_id_beijing=$(aws ec2 describe-route-tables --region cn-north-1 --filter "Name=vpc-id,Values=$beijing_vpc_id" "Name=association.main,Values='true'" --query "RouteTables[].Associations[].RouteTableAssociationId" --output text)

 

# 4.1 通过替换route_table_association_id使用创建的路由表

aws ec2 replace-route-table-association --association-id $route_table_association_id_ningxia --route-table-id $ningxia_route_table_id --region cn-northwest-1
aws ec2 replace-route-table-association --association-id $route_table_association_id_beijing --route-table-id $beijing_route_table_id --region cn-north-1

 

# 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,修改安全组

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)

 

  • 通过搭建VPC Peering模拟内网环境

# 6. 创建Peering Gateway

vpc_peering_connection_id=$(aws ec2 create-vpc-peering-connection --region cn-northwest-1 --vpc-id $ningxia_vpc_id --peer-vpc-id $beijing_vpc_id --peer-region cn-north-1 --query "VpcPeeringConnection.VpcPeeringConnectionId" --output text)
aws ec2 accept-vpc-peering-connection --region cn-north-1 --vpc-peering-connection-id $vpc_peering_connection_id --query "VpcPeeringConnection.VpcPeeringConnectionId" --output text

 

# 6.1 添加路由,使得亚马逊云科技宁夏区域和亚马逊云科技北京区域可以互通

aws ec2 create-route --region cn-northwest-1 --route-table-id $ningxia_route_table_id --destination-cidr-block 172.17.0.0/16 --vpc-peering-connection-id $vpc_peering_connection_id
aws ec2 create-route --region cn-north-1 --route-table-id $beijing_route_table_id --destination-cidr-block 10.0.0.0/16 --vpc-peering-connection-id $vpc_peering_connection_id

 

备注1:这一章是搭建实验环境的过程。在真实场景中,由于已经具备内网环境,可以省略。虽然内网环境是通过VPC Peering进行的模拟,但是这篇文章描述的方法同样适用于专线和VPN构造的环境。

 

4. 实现步骤

a)创建Endpoint

  • 文章涉及的VPC内服务都不具备公网访问能力,又由于VPC内的服务需要同非VPC内的服务进行交互,因此需要借助Gateway Endpoint和Interface Endpoint服务实现。

# 7. 创建Endpoint

# 7.1 修改VPC属性,需要开启dns-hostnamedns-support才能创建Endpoint

aws ec2 modify-vpc-attribute --region cn-northwest-1 --vpc-id $ningxia_vpc_id --enable-dns-hostnames
aws ec2 modify-vpc-attribute --region cn-northwest-1 --vpc-id $ningxia_vpc_id --enable-dns-support
aws ec2 modify-vpc-attribute --region cn-north-1 --vpc-id $beijing_vpc_id --enable-dns-hostnames
aws ec2 modify-vpc-attribute --region cn-north-1 --vpc-id $beijing_vpc_id --enable-dns-support

 

# 7.2 亚马逊云科技宁夏区域

# 7.2.1 Gateway Endpoint

# 创建S3 Gateway Endpoint,使得EC2实例可以在无公网环境访问S3

gateway_endpoint_s3_ningxia=$(aws ec2 create-vpc-endpoint --region cn-northwest-1 --vpc-endpoint-type Gateway --vpc-id $ningxia_vpc_id --route-table-ids $ningxia_route_table_id --service-name "com.amazonaws.cn-northwest-1.s3" --query "VpcEndpoint.VpcEndpointId" --output text)

 

# 创建DynamoDB Gateway Endpoint,使得EC2实例可以在无公网环境访问DynamoDB

gateway_endpoint_dynamodb_ningxia=$(aws ec2 create-vpc-endpoint --region cn-northwest-1 --vpc-endpoint-type Gateway --vpc-id $ningxia_vpc_id --route-table-ids $ningxia_route_table_id --service-name "com.amazonaws.cn-northwest-1.dynamodb" --query "VpcEndpoint.VpcEndpointId" --output text)

 

# 7.2.2 Interface Endpoint

# 创建Amazon SQS Interface Endpoint,使得EC2实例可以在无公网环境访问Amazon SQS

interface_endpoint_sqs_ningxia=$(aws ec2 create-vpc-endpoint --region cn-northwest-1 --vpc-endpoint-type Interface --vpc-id $ningxia_vpc_id --service-name "cn.com.amazonaws.cn-northwest-1.sqs" --subnet-ids "$ningxia_subnet_id_az1" "$ningxia_subnet_id_az2" "$ningxia_subnet_id_az3" --security-group-ids "$groupid_ningxia" --query "VpcEndpoint.VpcEndpointId" --output text)

 

# 创建Amazon Secrets Manager Interface Endpoint,使得EC2实例可以在无公网环境访问Amazon Secrets Manager

interface_endpoint_secretsmanager_ningxia=$(aws ec2 create-vpc-endpoint --region cn-northwest-1 --vpc-endpoint-type Interface --vpc-id $ningxia_vpc_id --service-name "com.amazonaws.cn-northwest-1.secretsmanager" --subnet-ids "$ningxia_subnet_id_az1" "$ningxia_subnet_id_az2" "$ningxia_subnet_id_az3" --security-group-ids "$groupid_ningxia" --query "VpcEndpoint.VpcEndpointId" --output text)

 

# 创建Amazon CloudFormation Interface Endpoint,使得EC2实例可以在无公网环境访问Amazon CloudFormation

interface_endpoint_cloudformation_ningxia=$(aws ec2 create-vpc-endpoint --region cn-northwest-1 --vpc-endpoint-type Interface --vpc-id $ningxia_vpc_id --service-name "cn.com.amazonaws.cn-northwest-1.cloudformation" --subnet-ids "$ningxia_subnet_id_az1" "$ningxia_subnet_id_az2" "$ningxia_subnet_id_az3" --security-group-ids "$groupid_ningxia" --query "VpcEndpoint.VpcEndpointId" --output text)

 

# 创建Amazon CloudWatch Interface Endpoint,使得EC2实例可以在无公网环境访问Amazon CloudWatch

interface_endpoint_logs_ningxia=$(aws ec2 create-vpc-endpoint --region cn-northwest-1 --vpc-endpoint-type Interface --vpc-id $ningxia_vpc_id --service-name "com.amazonaws.cn-northwest-1.logs" --subnet-ids "$ningxia_subnet_id_az1" "$ningxia_subnet_id_az2" "$ningxia_subnet_id_az3" --security-group-ids "$groupid_ningxia" --query "VpcEndpoint.VpcEndpointId" --output text)

 

# 创建Amazon ECR Interface Endpoint,使得EC2实例可以在无公网环境访问Amazon ECR

interface_endpoint_ecrapi_ningxia=$(aws ec2 create-vpc-endpoint --region cn-northwest-1 --vpc-endpoint-type Interface --vpc-id $ningxia_vpc_id --service-name "cn.com.amazonaws.cn-northwest-1.ecr.api" --subnet-ids "$ningxia_subnet_id_az1" "$ningxia_subnet_id_az2" "$ningxia_subnet_id_az3" --security-group-ids "$groupid_ningxia" --query "VpcEndpoint.VpcEndpointId" --output text)
interface_endpoint_ecrdkr_ningxia=$(aws ec2 create-vpc-endpoint --region cn-northwest-1 --vpc-endpoint-type Interface --vpc-id $ningxia_vpc_id --service-name "cn.com.amazonaws.cn-northwest-1.ecr.dkr" --subnet-ids "$ningxia_subnet_id_az1" "$ningxia_subnet_id_az2" "$ningxia_subnet_id_az3" --security-group-ids "$groupid_ningxia" --query "VpcEndpoint.VpcEndpointId" --output text)

 

# 7.3 亚马逊云科技北京区域

# 7.3.1 Gateway Endpoint

# 创建S3 Gateway Endpoint,使得EC2实例可以在无公网环境访问S3

gateway_endpoint_s3_beijing=$(aws ec2 create-vpc-endpoint --region cn-north-1 --vpc-endpoint-type Gateway --vpc-id $beijing_vpc_id --route-table-ids $beijing_route_table_id --service-name "com.amazonaws.cn-north-1.s3" --query "VpcEndpoint.VpcEndpointId" --output text)

 

 

b)创建Amazon Elastic Container Service(ECS)集群,选择Networking only模式

# 8. 创建ECS集群

aws ecs create-cluster <em>--region cn-northwest-1 --cluster-name dth-ecs-cluster</em>

 

 

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

proxy_template_instance_id=$(aws ec2 run-instances --region cn-north-1 --image-id resolve:ssm:/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2 --instance-type t3.micro --key-name id_rsa_test.pub --security-group-ids $groupid_beijing --subnet-id $beijing_subnet_id_az2 --associate-public-ip-address --query 'Instances[].InstanceId' --output text)

 

等待实例创建完成

aws ec2 wait instance-status-ok --instance-ids $proxy_template_instance_id --region cn-north-1 

 

创建Internet Gateway

internet_gateway_id_beijing=$(aws ec2 create-internet-gateway --region cn-north-1 --query "InternetGateway.InternetGatewayId" --output text) 

 

# Attach Internet Gateway

aws ec2 attach-internet-gateway --region cn-north-1 --internet-gateway-id $internet_gateway_id_beijing --vpc-id $beijing_vpc_id <em># Attach Internet Gateway</em>

 

添加路由

aws ec2 create-route --region cn-north-1 --route-table-id $beijing_route_table_id --destination-cidr-block 0.0.0.0/0 --gateway-id $internet_gateway_id_beijing

 

获得proxy_template_instance_ip

proxy_template_instance_ip=$(aws ec2 describe-instances --instance-ids "$proxy_template_instance_id" --region cn-north-1 --query 'Reservations[0].Instances[0].PublicIpAddress' --output text)

 

# 9.2 安装和配置Proxy模板实例(root用户执行)

下载ProxyInstanceDeploymentProcedure:https://github.com/successzy/For-Blog/blob/main/ProxyInstanceDeploymentProcedure,并根据”ProxyInstanceDeploymentProcedure”中记载的步骤进行配置

 

# 9.3 生成自定义镜像

停止实例

aws ec2 stop-instances --region cn-north-1 --instance-id $proxy_template_instance_id

 

等待实例停止完成

aws ec2 wait instance-stopped --instance-ids $proxy_template_instance_id --region cn-north-1

 

创建Proxy实例镜像

proxy_image_id=$(aws ec2 create-image --region cn-north-1 --instance-id $proxy_template_instance_id --name "proxy image" --query "ImageId" --output text)

 

等待镜像创建完成

aws ec2 wait image-available --image-ids $proxy_image_id --region cn-north-1

 

# 9.4 创建Proxy实例

使用上一步创建的镜像创建一台实例

proxy_instanceid_az2=$(aws ec2 run-instances --region cn-north-1 --image-id $proxy_image_id --instance-type t3.micro --key-name id_rsa_test.pub --security-group-ids $groupid_beijing --subnet-id $beijing_subnet_id_az2 --query 'Instances[].InstanceId' --output text)

 

等待实例创建完成

aws ec2 wait instance-status-ok --instance-ids $proxy_instanceid_az2 --region cn-north-1

 

# 9.5 删除临时资源,依次删除路由条目、Internet Gateway和删除临时Proxy实例

aws ec2 delete-route --region cn-north-1 --route-table-id $beijing_route_table_id --destination-cidr-block 0.0.0.0/0
aws ec2 detach-internet-gateway --region cn-north-1 --internet-gateway-id $internet_gateway_id_beijing --vpc-id $beijing_vpc_id
aws ec2 delete-internet-gateway --region cn-north-1 --internet-gateway-id $internet_gateway_id_beijing
aws ec2 terminate-instances --region cn-north-1 --instance-ids $proxy_template_instance_id

 

 

备注2:这一节描述的是如何创建Amazon EC2实例并安装和配置Nginx服务。虽然创建Amazon资源所使用的API无法进行复用,但是在实例中安装和配置Nginx服务的步骤是可复用的。

 

d)重新构建Finder镜像

  • Finder实例是由ECS Fargate服务启动的容器实例,会使用VPC内的默认DNS进行域名解析。默认情况下,会将cn-north-1.amazonaws.com.rproxy.goskope.com.cn域名解析到真实的S3 IP地址。但是本篇文章所涉及的场景中,需要将s3---cn-north-1.amazonaws.com.rproxy.goskope.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并解压

wget https://github.com/aws-samples/data-transfer-hub-cli/releases/download/v1.0.0/dthcli_1.0.0_linux_amd64.tar.gz
tar -xzvf dthcli_1.0.0_linux_amd64.tar.gz

 

# 10.2 修改Dockerfile文件

FROM amazonlinux:latest

RUN yum update -y

ENV SOURCE_TYPE Amazon_S3

ENV JOB_TABLE_NAME ''
ENV JOB_QUEUE_NAME ''

ENV SRC_BUCKET ''
ENV SRC_PREFIX ''
ENV SRC_PREFIX_LIST ''
ENV SRC_REGION ''
ENV SRC_ENDPOINT ''
ENV SRC_CREDENTIALS ''
ENV SRC_IN_CURRENT_ACCOUNT false
ENV SKIP_COMPARE false

ENV DEST_BUCKET ''
ENV DEST_PREFIX ''
ENV DEST_REGION ''
ENV DEST_CREDENTIALS ''
ENV DEST_IN_CURRENT_ACCOUNT false

ENV MAX_KEYS 1000
ENV CHUNK_SIZE 5
ENV MULTIPART_THRESHOLD 10
ENV MESSAGE_BATCH_SIZE 10
ENV FINDER_DEPTH 0
ENV FINDER_NUMBER 1
ENV WORKER_NUMBER 4

WORKDIR /app
ADD ./extra-hosts.sh /app
RUN touch config.yaml
COPY ./dthcli /app
CMD /app/dthcli run
ENTRYPOINT ["sh", "/app/extra-hosts.sh"]

 

# 10.3 编写extra-hosts.sh脚本

#!/bin/sh

cat >> /etc/hosts << EOF
${PROXY_IP} ${BLOG_SRC_ENDPOINT}
${PROXY_IP} ${SRC_BUCKET}.${BLOG_SRC_ENDPOINT}
EOF

exec "$@"

 

# 10.4 构建镜像

docker build -t myblogimage:latest .

 

 

e)上传Finder镜像到Amazon Private ECR

# 11. 上传镜像

# 11.1 创建ECR Repository

aws ecr create-repository --repository-name myblogimage --region cn-northwest-1

 

# 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

aws s3api create-bucket –bucket blog-software –region cn-northwest-1 –create-bucket-configuration LocationConstraint=cn-northwest-1

 

# 12.1 将软件放入Amazon S3

下载如下两个软件,放入刚刚新建的Bucket:https://aws-gcr-solutions-assets.s3.amazonaws.com/data-transfer-hub-cli/v1.0.0/dthcli_1.0.0_linux_arm64.tar.gz,https://s3.amazonaws.com/amazoncloudwatch-agent/amazon_linux/arm64/latest/amazon-cloudwatch-agent.rpm

 

b)创建用于访问源站Amazon S3的AKSK并存入Secrets Manager

# 13. 创建用于访问源站Amazon S3AKSK并存入Secrets Manager

创建用户

aws iam create-user --user-name blog-user

 

# Attach Policy

aws iam attach-user-policy --user-name blog-user --policy-arn arn:aws-cn:iam::aws:policy/AmazonS3FullAccess

 

创建AccessKeySecretAccessKey

aws iam create-access-key –user-name blog-user # 记录输出结果,后面会用到

{
    "AccessKey": {
        "UserName": "blog-user",
        "AccessKeyId": "111", # 仅仅是示例
        "Status": "Active",
        "SecretAccessKey": "222", # 仅仅是示例
        "CreateDate": "2022-09-07T00:19:03+00:00"
    }
}

 

创建Secret

aws secretsmanager create-secret --region cn-northwest-1 --name MyBlogSecret --secret-string "{\"access_key_id\":\"111\",\"secret_access_key\":\"222\"}"

 

 

c)通过 实现步骤–>步骤f) 修改Amazon CloudFormation模板下载的模板部署DTH S3 Plugin

下载CloudFormationTemplateParameterExplanation.docx:https://github.com/successzy/For-Blog/blob/main/CloudFormationTemplateParameterExplanation.docx,并根据”CloudFormationParameterExplanation”中记载的步骤进行配置

 

d)结果展示

  • DTH任务运行前查看源桶和目标桶对象

源桶文件

# 源桶文件
[ec2-user@ip-172-31-40-220 ~]$ aws s3 ls s3://blog-bucket-source
2022-09-12 10:08:38      	92506 		DataTransferS3Stack-ec2-kervin-modify.template
2022-09-06 10:28:08        386		id_rsa_test.pub
2022-09-12 10:43:40     	205098 		禅道部署私有化方案.docx
# 目标桶文件
[ec2-user@ip-172-31-40-220 ~]$ aws s3 ls s3://blog-bucket-destination
[ec2-user@ip-172-31-40-220 ~]$

 

  • 查看DTH运行日志
    • 查看Finder日志

  • 查看Proxy实例日志

  • DTH任务运行后再次查看源桶和目标桶对象

源桶文件

# 源桶文件
[ec2-user@ip-172-31-40-220 ~]$ aws s3 ls s3://blog-bucket-source
2022-09-12 10:08:38	92506 		DataTransferS3Stack-ec2-kervin-modify.template
2022-09-06 10:28:08	386 		id_rsa_test.pub
2022-09-12 10:43:40	205098 		禅道部署私有化方案.docx
# 目标桶文件
[ec2-user@ip-172-31-40-220 ~]$ aws s3 ls s3://blog-bucket-destination
2022-09-12 13:28:38	92506 		DataTransferS3Stack-ec2-kervin-modify.template
2022-09-12 13:28:39        386 		id_rsa_test.pub
2022-09-12 13:28:38 	205098 		禅道部署私有化方案.docx

 

 

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的功能

wget https://github.com/aws-samples/data-transfer-hub-cli/archive/refs/tags/v1.1.0.tar.gz
tar -xvzf v1.1.0.tar.gz
cd data-transfer-hub-cli-1.1.0/

 

 

# 2. 修改dthcli源码

  • client.go

  • common.go

  • job.go

# 3. X86服务器上编译dthcli,并打包成镜像放入ECR

# 由于Fargate只能部署在X86 Host,因此需要编译X86 dthcli,用于在Fargate上部署Finder

# 编译后参考步骤”10. 重新构建Finder镜像

cd data-transfer-hub-cli-1.1.0; go build 

 

 

# 4. Arm服务器上编译dthcli,并放入S3

# 由于Worker节点使用Arm机型,因此需要编译Arm dthcli

cd data-transfer-hub-cli-1.1.0; go build # 这条命令会产生Arm dthcli
tar -zvcf dthcli_1.0.0_linux_arm64.tar.gz dthcli # 压缩成1.0.0版本的原因是无需再修改CloudFormation模板
aws s3api put-object --bucket blog-software --key dthcli_1.0.0_linux_arm64.tar.gz --body ./dthcli_1.0.0_linux_arm64.tar.gz

 

 

# 5. X86 dthcliArm dthcli下载

X86 dthcli: https://github.com/successzy/For-Blog/blob/main/dthcli
Arm dthcli: https://github.com/successzy/For-Blog/blob/main/dthcli_1.0.0_linux_arm64.tar.gz

 

  • 结果展示

7. 清理环境

下载Cleanup:https://github.com/successzy/For-Blog/blob/main/Cleanup,并根据”Cleanup”中记载的步骤进行资源删除:

 

8. 总结

在这篇文章中,通过结合DTH S3 Plugin和代理层实现了对象存储数据在内网环境的搬迁。

同时,针对dthcli在搬迁对象时无法保留源桶对象Storage Class的问题,通过修改dthcli代码补足了这部分能力。

 

本篇作者

郑毅

西云数据解决方案架构师,曾任职于爱立信、甲骨文、阿里云、中国移动。在8年的从业经历里,做过售前、售中和售后,造就了IT项目全生命周期的支撑能力;又从传统IT行业一路走到云计算行业,具备了扎实的基础知识和丰富的实践经验。目前在西云数据担任解决方案架构师,为客户提供基于亚马逊云科技的售前咨询、上云支撑和技术答疑等工作。

胡益恺

AWS实习解决方案架构师,负责基于AWS云计算方案的设计实现与架构咨询,同时致力于数据分析与AI的研究与应用。