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 メインのクラウドエンジニア。
    ソースコードより文章を書く方が好きです。