NRIネットコム Blog

NRIネットコム社員が様々な視点で、日々の気づきやナレッジを発信するメディアです

絵で覚える!!! AWS DataSync のクロスリージョン転送

暑い日が続きますね。皆様いかがお過ごしでしょうか、西です。

今日は 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 の作成まで漕ぎ着けることができ、転送も可能です!!!

そしてこのリソース配置方針はなんとチュートリアルに記載がありました、あまりにも灯台下暗しでとても反省しています。

docs.aws.amazon.com

直感的に「転送するための 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 に優位性があると考えています。 その点についてはまた別の機会でお伝えできればと思います。

情報が少なめで資格試験でも取り上げられることの少ないサービスですが、マネージドの手厚さとできることの多さがメリットのサービスだと思いますので、皆さんも機会があればぜひ活用してみて下さい。

執筆者: 西 洋平


AWS メインのクラウドエンジニア。
ソースコードより文章書く方が好きです。
2023 Japan AWS Jr. Champion / 2023 Japan AWS All Certifications Engineer