暑い日が続きますね。皆様いかがお過ごしでしょうか、西です。
今日は AWS DataSync (DataSync) についてお伝えしようと思います。
DataSync はファイル転送に活用できる AWS マネージドサービスなのですが、、情報が比較的少ないため、業務でも調査に難儀する事が多々あります。 さらに言えば、構成要素も思いの外多くて (個人的には) 複雑なのでイメージをうまく掴めずに苦労しました。
ですので、今回は DataSync を クロスリージョン S3 to S3 形式のファイル転送に利用するケースにフォーカスし、実際にハマった点とそれを踏まえた構成図を使ってお伝えします。
AWS DataSync
ということで、まず DataSync についてざっとおさらいです。 公式ドキュメントより、概要は次の通りとなります。
AWS DataSyncは、データ移行を簡素化し、ファイルまたはオブジェクトデータをストレージサービスへ、ストレージサービスから、AWSまたはストレージサービス間で迅速、簡単、安全に転送できるようにするオンラインデータ移動および検出サービスです。
AWS DataSync の概要 - AWS DataSync
ファイル転送やデータ移行の様々なユースケースに活用可能なリージョンサービスです。
AWS から AWS だけでなく、AWS からオンプレミス、AWS から 他クラウドプロバイダのストレージサービスへの転送までサポートされています。 また、帯域幅の調整や転送後のファイル検証が可能であり、リソース制約や検証フェーズまでマネージドでケアしてくれる手厚いサービスです。
構成要素は少し感覚を掴みづらいのですが、
- Location: 転送元 / 先の情報
- Agent: 転送処理を行う実体 (S3 to S3 の場合は必要なし)
- Task : 転送に必要な情報 (転送元 / 先 の Location と Agent) を関連付ける転送リソース
の 3 種類があります。 これらの要素に加えて、実際の転送情報 (進捗の % 情報や転送速度、ファイルサイズなど) は Task Execution というリソースで確認できます。 例えば S3 to S3 のユースケースに当てはめると以下のような構成になります。
クロスリージョン S3 to S3 ファイル転送のユースケースとハマった点
では本題のクロスリージョンなユースケースについてです。 今回のケースを図にすると以下のようになります。
これだけだとかなりシンプルな構図です。
では詳細なリソースの作成を考えます。先にお伝えしたように DataSync はリージョンサービスなので、リージョンを跨ぐ処理を行おうとすると以下の構成図の形で DataSync リソースを配置したくなるのではないでしょうか。少なくとも僕はそうでした。
では、この配置でいざデプロイを進めてみましょう!!!
"Invalid request provided: Please provide a bucket in the ap-northeast-1 region where DataSync is currently used." のメッセージと共に Location の作成に失敗しました......
エラーメッセージから「DataSync が利用されているリージョンに S3 がないとダメ」という主旨が読み取れますね。 では次は転送元情報の Location と Task を 東京リージョンに、転送先情報を バージニアリージョンへ配置してみましょう。
いざデプロイを進めます!!!
しかし今度もエラーです。Location loc-******************** is not found. とのこと......
ここまでのことから、
- 転送先 / 転送元 の S3 と同じリージョンに Location が配置されていないとダメ
- 転送先 リージョンに Location を作成して、転送元リージョンで Task の作成を試みてもダメ
ということがわかりました。
では、いよいよ答え合わせです!!!
この問題は Task と転送先の S3 バケットと転送先情報の Location を同じリージョンに配置することで解決します。
こうすれば DataSync のリソースを複数リージョンに配置することができていますね。
無事 Task の作成まで漕ぎ着けることができ、転送も可能です!!!
そしてこのリソース配置方針はなんとチュートリアルに記載がありました、あまりにも灯台下暗しでとても反省しています。
直感的に「転送するための Task は転送元に近いものだろう」と思い込んでいたのが敗因でした。 まずはチュートリアルページを追うのって大事ですね。 本記事は「チュートリアルページの流れを追いつつ、イメージを掴むために本記事の絵を見る」という使い方をして頂くと理解がよりスムーズかもしれません。
(参考) AWS CloudFormation テンプレート
今回利用した AWS CloudFormation テンプレートが以下のようになります。
リージョンを跨ぐ都合で 2 ファイルでの定義となりましたが、例えば Terraform の場合は multi-provider 機能を利用して 1 枚ものに仕上げることも可能かと思います。
2 枚の template でそれぞれどのようなリソースを定義しているかをまとめた以下の構成図と併せて、よければ参考にして頂ければと思います。
※ サンプルとして東京リージョン内の転送先 S3 も template 1 で作成しています
template 1
AWSTemplateFormatVersion: '2010-09-09' Description: > Template for datasync-cross-region in tokyo Parameters: ResourcePrefix: Type: String Default: datasync-cross-region # template 2 で作成する S3 bucket の ARN (そのままでは流せないので作成までコメントアウト等で対応) S3VirginiaArn: Type: String Default: arn:aws:s3:::datasync-cross-region-dst-virginia Resources: DataSyncExecRole: Type: AWS::IAM::Role Properties: RoleName: !Sub ${ResourcePrefix}-exec-role AssumeRolePolicyDocument: Version: 2012-10-17 Statement: - Effect: Allow Principal: Service: datasync.amazonaws.com Action: - sts:AssumeRole Policies: - PolicyName: !Sub ${ResourcePrefix}-exec-role PolicyDocument: Version: 2012-10-17 Statement: - Effect: Allow Action: - s3:GetBucketLocation - s3:ListBucket - s3:ListBucketMultipartUploads - s3:HeadBucket Resource: - !Sub ${S3TokyoDst.Arn} - !Sub ${S3VirginiaArn}/* - Effect: Allow Action: - s3:AbortMultipartUpload - s3:GetObject - s3:ListMultipartUploadParts - s3:DeleteObject - s3:PutObject - s3:GetObjectTagging - s3:PutObjectTagging Resource: - !Sub ${S3TokyoDst.Arn}/* - !Sub ${S3VirginiaArn}/* - Effect: Allow Action: - s3:GetBucketLocation - s3:ListBucket - s3:ListBucketMultipartUploads - s3:HeadBucket - s3:GetObject Resource: - !Sub ${S3TokyoSrc.Arn} - !Sub ${S3TokyoSrc.Arn}/* DataSyncLogGroup: Type: AWS::Logs::LogGroup Properties: LogGroupName: !Sub /aws/datasync/${ResourcePrefix}/ LogsResourcePolicy: Type: AWS::Logs::ResourcePolicy Properties: PolicyName: !Sub ${ResourcePrefix}-datasync-put-logs PolicyDocument: !Sub | { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": { "Service": "datasync.amazonaws.com" }, "Action": [ "logs:CreateLogStream", "logs:PutLogEvents" ], "Resource": "${DataSyncLogGroup.Arn}" } ] } S3TokyoSrc: Type: AWS::S3::Bucket Properties: BucketName: !Sub ${ResourcePrefix}-src PublicAccessBlockConfiguration: BlockPublicAcls: True BlockPublicPolicy: True IgnorePublicAcls: True RestrictPublicBuckets: True S3TokyoSrcPolicy: Type: AWS::S3::BucketPolicy Properties: Bucket: !Ref S3TokyoSrc PolicyDocument: Version: 2012-10-17 Statement: - Sid: DataSyncExec Effect: Allow Principal: AWS: !GetAtt DataSyncExecRole.Arn Resource: - !Sub ${S3TokyoSrc.Arn}/* - !Sub ${S3TokyoSrc.Arn} Action: - s3:GetBucketLocation - s3:ListBucket - s3:ListBucketMultipartUploads - s3:AbortMultipartUpload - s3:DeleteObject - s3:GetObject - s3:ListMultipartUploadParts - s3:PutObject - s3:GetObjectTagging - s3:PutObjectTagging S3TokyoDst: Type: AWS::S3::Bucket Properties: BucketName: !Sub ${ResourcePrefix}-dst PublicAccessBlockConfiguration: BlockPublicAcls: True BlockPublicPolicy: True IgnorePublicAcls: True RestrictPublicBuckets: True S3TokyoDstPolicy: Type: AWS::S3::BucketPolicy Properties: Bucket: !Ref S3TokyoDst PolicyDocument: Version: 2012-10-17 Statement: - Effect: Allow Principal: AWS: !GetAtt DataSyncExecRole.Arn Resource: - !Sub ${S3TokyoDst.Arn}/* - !Sub ${S3TokyoDst.Arn} Action: - s3:GetBucketLocation - s3:ListBucket - s3:ListBucketMultipartUploads - s3:AbortMultipartUpload - s3:DeleteObject - s3:GetObject - s3:ListMultipartUploadParts - s3:PutObject - s3:GetObjectTagging - s3:PutObjectTagging LocationS3TokyoSrc: Type: AWS::DataSync::LocationS3 Properties: S3BucketArn: !GetAtt S3TokyoSrc.Arn S3Config: BucketAccessRoleArn: !GetAtt DataSyncExecRole.Arn LocationS3TokyoDst: Type: AWS::DataSync::LocationS3 Properties: S3BucketArn: !GetAtt S3TokyoDst.Arn S3Config: BucketAccessRoleArn: !GetAtt DataSyncExecRole.Arn DataSyncTask: Type: AWS::DataSync::Task Properties: Name: !Sub ${ResourcePrefix}-tokyo CloudWatchLogGroupArn: !GetAtt DataSyncLogGroup.Arn DestinationLocationArn: !Ref LocationS3TokyoDst SourceLocationArn: !Ref LocationS3TokyoSrc Options: LogLevel: TRANSFER
template 2
AWSTemplateFormatVersion: '2010-09-09' Description: > Template for datasync-cross-region in virginia Parameters: ResourcePrefix: Type: String Default: datasync-cross-region # 以下の 2 つの ARN は template 1 で作成したリソースのそれ DataSyncExecRoleArn: Type: String Default: arn:aws:iam::123456789012:role/datasync-cross-region-exec-role LocationS3TokyoSrcArn: Type: String Default: arn:aws:datasync:ap-northeast-1:123456789012:location/loc-0123hoge4567fuga8 Resources: DataSyncLogGroup: Type: AWS::Logs::LogGroup Properties: LogGroupName: !Sub /aws/datasync/${ResourcePrefix}/ LogsResourcePolicy: Type: AWS::Logs::ResourcePolicy Properties: PolicyName: !Sub ${ResourcePrefix}-datasync-put-logs PolicyDocument: !Sub | { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": { "Service": "datasync.amazonaws.com" }, "Action": [ "logs:CreateLogStream", "logs:PutLogEvents" ], "Resource": "${DataSyncLogGroup.Arn}" } ] } S3VirginiaDst: Type: AWS::S3::Bucket Properties: BucketName: !Sub ${ResourcePrefix}-dst-virginia PublicAccessBlockConfiguration: BlockPublicAcls: True BlockPublicPolicy: True IgnorePublicAcls: True RestrictPublicBuckets: True S3VirginiaDstPolicy: Type: AWS::S3::BucketPolicy Properties: Bucket: !Ref S3VirginiaDst PolicyDocument: Version: 2012-10-17 Statement: - Effect: Allow Principal: AWS: !Ref DataSyncExecRoleArn Resource: - !Sub ${S3VirginiaDst.Arn}/* - !Sub ${S3VirginiaDst.Arn} Action: - s3:GetBucketLocation - s3:ListBucket - s3:ListBucketMultipartUploads - s3:AbortMultipartUpload - s3:DeleteObject - s3:GetObject - s3:ListMultipartUploadParts - s3:PutObject - s3:GetObjectTagging - s3:PutObjectTagging LocationS3VirginiaDst: Type: AWS::DataSync::LocationS3 Properties: S3BucketArn: !GetAtt S3VirginiaDst.Arn S3Config: BucketAccessRoleArn: !Ref DataSyncExecRoleArn DataSyncTaskVirginia: Type: AWS::DataSync::Task Properties: Name: !Sub ${ResourcePrefix}-virginia CloudWatchLogGroupArn: !GetAtt DataSyncLogGroup.Arn DestinationLocationArn: !Ref LocationS3VirginiaDst SourceLocationArn: !Ref LocationS3TokyoSrcArn Options: LogLevel: TRANSFER
余談ですが、DataSync の実行ログを Amazon CloudWatch Logs へ出力するための権限を DataSync 用の実行ロールに対して渡してあげる必要があります。 この渡し方ですが、AWS::Logs::ResourcePolicy のリソースで実現することができます。 この設定を入れていないと、Task Execution のログ出力が権限不足で失敗します。
おわりに
DataSync の クロスリージョン S3 to S3 形式のファイル転送の場合にフォーカスし、ハマった点を構成図を用いてお伝えしました。
今回取り上げたユースケースのような S3 間のファイル転送は S3 レプリケーション機能でも実現可能です。 しかし、個人的にはトリガー管理や進捗可視性の面では DataSync に優位性があると考えています。 その点についてはまた別の機会でお伝えできればと思います。
情報が少なめで資格試験でも取り上げられることの少ないサービスですが、マネージドの手厚さとできることの多さがメリットのサービスだと思いますので、皆さんも機会があればぜひ活用してみて下さい。