LoginSignup
6
0

More than 1 year has passed since last update.

AWS DataSync によるクロスアカウントでの S3 のデータ移行

Last updated at Posted at 2021-09-16

はじめに

クロスアカウントの S3 バケット間でデータを移行する場合いくつか選択肢がありますが、
最近 AWS DataSync がクロスアカウントの移行に対応したようなので試しました。
比較的に容易に、かつ柔軟性のある設定でデータの移行ができました。

公式ブログの内容に沿って行っていますが、曖昧な箇所があり分かりづらいため日本語のドキュメントを残します。

送信先 S3 バケットの作成

移行対象の送信元 S3 バケットはすでにあるとして、送信先アカウントでバケットを作成します。
以下、 AWS CloudFormation のコードを示しながら進めます。

送信先バケット
S3BucketDataSyncDist:
  Type: 'AWS::S3::Bucket'
  DeletionPolicy: 'Retain'
  Properties:
    AccessControl: 'Private'
    BucketEncryption:
      ServerSideEncryptionConfiguration:
        - ServerSideEncryptionByDefault:
            SSEAlgorithm: 'AES256'
    BucketName: 'datasync-dist'
    VersioningConfiguration:
      Status: 'Enabled'
    PublicAccessBlockConfiguration:
      BlockPublicAcls: True
      BlockPublicPolicy: True
      IgnorePublicAcls: True
      RestrictPublicBuckets: True

IAM ロールの作成

送信先アカウントで DataSync が送信元、送信先それぞれの Location にアクセスするための IAM ロールを作成します。
実際の移行を行う DataSync の Task も送信先アカウントで実行することになります。

${S3BucketDataSyncSource} には送信元バケット名を渡してください。

送信元LocationのIAMロール
IAMRoleDataSyncSourceLocation:
  Type: 'AWS::IAM::Role'
  Properties:
    AssumeRolePolicyDocument:
      Version: '2012-10-17'
      Statement:
        - Effect: 'Allow'
          Principal:
            Service: 'datasync.amazonaws.com'
          Action: 'sts:AssumeRole'
    RoleName: 'datasync-source-location-role'
    Policies:
      - PolicyDocument:
          Statement:
            - Action:
                - 's3:GetBucketLocation'
                - 's3:ListBucket'
                - 's3:ListBucketMultipartUploads'
              Effect: 'Allow'
              Resource: !Sub 'arn:aws:s3:::${S3BucketDataSyncSource}'
            - Action:
                - 's3:AbortMultipartUpload'
                - 's3:DeleteObject'
                - 's3:GetObject'
                - 's3:ListMultipartUploadParts'
                - 's3:PutObjectTagging'
                - 's3:GetObjectTagging'
                - 's3:PutObject'
              Effect: 'Allow'
              Resource: !Sub 'arn:aws:s3:::${S3BucketDataSyncSource}/*'
        PolicyName: 'datasync-source-location-policy'
送信先LocationのIAMロール
IAMRoleDataSyncDistLocation:
  Type: 'AWS::IAM::Role'
  Properties:
    AssumeRolePolicyDocument:
      Version: '2012-10-17'
      Statement:
        - Effect: 'Allow'
          Principal:
            Service: 'datasync.amazonaws.com'
          Action: 'sts:AssumeRole'
    RoleName: 'datasync-dist-location-role'
    Policies:
      - PolicyDocument:
          Statement:
            - Action:
                - 's3:GetBucketLocation'
                - 's3:ListBucket'
                - 's3:ListBucketMultipartUploads'
              Effect: 'Allow'
              Resource: !GetAtt S3BucketDataSyncDist.Arn
            - Action:
                - 's3:AbortMultipartUpload'
                - 's3:DeleteObject'
                - 's3:GetObject'
                - 's3:ListMultipartUploadParts'
                - 's3:PutObjectTagging'
                - 's3:GetObjectTagging'
                - 's3:PutObject'
              Effect: 'Allow'
              Resource: !Sub ${S3BucketDataSyncDist.Arn}/*
        PolicyName: 'datasync-dist-location-policy'

送信元バケットのバケットポリシーの追加

送信元アカウントで送信元バケットのバケットポリシーに、作成した送信元 Location の IAM ロール(datasync-source-location-role)と、
このあと aws datasync create-location-s3 を実行する送信先アカウントのユーザ(DataSyncDistAccountUserArn)に対して権限を与えます。

YAML 内の S3BucketDataSyncSource は送信元バケットのリソースです。
AWS CLI を実行する際のユーザの ARN は aws sts get-caller-identity で確認することができます。

送信元バケットのバケットポリシー
S3BucketPolicyDataSyncSource:
  Type: AWS::S3::BucketPolicy
  Properties:
    Bucket: !Ref S3BucketDataSyncSource
    PolicyDocument:
      Statement:
        - Effect: Allow
          Principal:
            AWS:
              - !Sub 'arn:aws:iam::${DataSyncDistAccountId}:role/datasync-source-location-role'
              - !Ref DataSyncDistAccountUserArn
          Action:
            - 's3:GetBucketLocation'
            - 's3:ListBucket'
            - 's3:ListBucketMultipartUploads'
            - 's3:AbortMultipartUpload'
            - 's3:DeleteObject'
            - 's3:GetObject'
            - 's3:ListMultipartUploadParts'
            - 's3:PutObject'
            - 's3:GetObjectTagging'
            - 's3:PutObjectTagging'
          Resource:
            - !GetAtt S3BucketDataSyncSource.Arn
            - !Sub ${S3BucketDataSyncSource.Arn}/*

DataSync Location の作成

送信先アカウントで Location を作成します。
CloudFormation に AWS::DataSync::LocationS3 リソースがありますが、
クロスアカウントの作成に対応していないようで、 Invalid request provided: Please provide a bucket in the us-east-1 region where DataSync is currently used. といったエラーとなるため、
送信元 Location のみ AWS CLI から作成します。

AWS CLI で送信先アカウントに対して以下のコマンドで送信元 Location を作成します。

送信元Locationの作成 
aws datasync create-location-s3 --s3-bucket-arn arn:aws:s3:::[送信元バケット名] --s3-config '{"BucketAccessRoleArn":"arn:aws:iam::[送信先アカウントID]:role/datasync-source-location-role"}'

この時、コマンドを実行するユーザはバケットポリシで許可したユーザである必要があります。

送信先 Location は問題なく CloudFormation で作成することができます。

送信先Location
DataSyncLocationS3DistLocation:
  Type: AWS::DataSync::LocationS3
  Properties:
    S3BucketArn: !GetAtt S3BucketDataSyncDist.Arn
    S3Config:
      BucketAccessRoleArn: !GetAtt IAMRoleDataSyncDistLocation.Arn

S3 のレプリケーションを使うと Prefix によって送信元、送信先で同じフォルダ間でしか移行ができないのに対し、
DataSync は Location で Subdirectory を指定することができるため、
送信元、送信先でそれぞれ別々のフォルダを指定することができるところが良いです。

ロググループの作成(オプション)

送信先アカウントで DataSync の Task 実行時にログを吐くためのロググループとリソースポリシーを作成します。ログが必要ないなら不要です。

LogsLogGroupDataSync:
  Type: AWS::Logs::LogGroup
  Properties:
    LogGroupName: datasync
    RetentionInDays: 14

LogsResourcePolicy:
  Type: AWS::Logs::ResourcePolicy
  Properties:
    PolicyName: datasync-log-resource-policy
    PolicyDocument: "{\"Statement\": [{\"Sid\": \"DataSyncLogsToCloudWatchLogs\", \"Effect\": \"Allow\", \"Action\": [\"logs:PutLogEvents\", \"logs:CreateLogStream\"], \"Principal\": {\"Service\": \"datasync.amazonaws.com\"}, \"Resource\": \"*\"}], \"Version\": \"2012-10-17\"}"

PolicyDocument が String しか受け付けてくれませんが、 AWS::IAM::ManagedPolicy のように JSON で受け付けてくれると良いですね。

DataSync Task の作成

送信先アカウントで DataSync の Task を作成します。
YAML の DataSyncSourceLocationArnaws datasync create-location-s3 の結果で返される LocationArn です。
aws datasync list-locations でも確認することができます。

AWS::DataSync::Task の細かな仕様は公式ドキュメントを参照してください。 

DataSyncTask:
  Type: AWS::DataSync::Task
  Properties:
    SourceLocationArn: !Ref DataSyncSourceLocationArn
    DestinationLocationArn: !GetAtt DataSyncLocationS3DistLocation.LocationArn
    Excludes:
      - FilterType: SIMPLE_PATTERN
        Value: /logs
    Schedule:
      ScheduleExpression: 'rate(1 hour)'
    Options:
      OverwriteMode: NEVER
      TransferMode: CHANGED
      VerifyMode: ONLY_FILES_TRANSFERRED
      LogLevel: BASIC
    CloudWatchLogGroupArn: !Select [0, !Split [':*', !GetAtt LogsLogGroupDataSync.Arn]]

おわりに

S3 のレプリケーションだと同じフォルダ間でしか移行できなかったり、
バッチオペレーションだと定期実行ができなかったりと、不都合があった部分が DataSync によってうまく解決できました。

ただし、もちろん料金は発生するためきちんと見積もりをしてから実行するのが良いでしょう。
https://aws.amazon.com/jp/datasync/pricing/

6
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
0