AWS DMSをCloudFormationでかく

たまたま`DMS(Database Migration Service)`をCloudFormationで書く機会があったので残しておきます。

ほんとにざっくりイメージはこんな感じです。
![dms.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/556143/e5f9cbbf-a63c-3827-351e-d28e22c50be2.png)
VPCとかDBとかセキュリティグループの設定はできてる前提とします。
すいません。

```dms.yml
AWSTemplateFormatVersion: "2010-09-09"
Metadata:
  AWS::CloudFormation::Interface:
    ParameterGroups:
      - Label:
          default: "General Configuration"
        Parameters:
          - ServiceName
      - Label:
          default: "DMS Configuration"
        Parameters:
          - ReplicationSubnetId
          - ReplicationInstanceClass
          - MultiAz
          - InternalSecurityGroupId
          - VPCPeeringSecurityGroupId
          - MyDbUserName
          - MyDbPassword
          - MyDbServerName
          - MyDbSslMode
          - TargetDbUserName
          - TargetDbPassword
          - TargetDbServerName
          - TargetDbSslMode

Parameters:
  Env:
    Description: An environment name that will be prefixed to resource names
    Type: String
    Default: dev
    AllowedValues:
      - dev
      - stg
      - prod

  ServiceName:
    Description: "input your ServiceName."
    Type: String
    Default: "test"

  ReplicationSubnetId: 
      Type: List<AWS::EC2::Subnet::Id>
      Description: Select at two internal subnets in your selected VPC.

  ReplicationInstanceClass:
    Type: String
    Description: input your ReplicationInstanceClass
    Default: dms.t2.micro

  MultiAz:
    Type: String
    Description: Select whether to enable Multi-AZ.
    Default: false
    AllowedValues:
      - false
      - true

  InternalSecurityGroupId:
    Type: AWS::EC2::SecurityGroup::Id
    Description: Select a InternalSecurityGroup

  VPCPeeringSecurityGroupId:
    Type: AWS::EC2::SecurityGroup::Id
    Description: Select a VPCPeeringSecurityGroup

  MyDbUserName:
    Type: String
    Description: Input DB UsreName at Target
    Default: root

  MyDbPassword:
    Type: String
    Description: Input DB Password at Target
    Default: passw0rd

  MyDbServerName:
    Type: String
    Description: Input DB Cluster Endpoint at Target

  MyDbSslMode:
    Type: String
    Description: Select Ssl Mode
    Default: none
    AllowedValues:
      - none
      - require
      - verify-ca
      - verify-full

  SourceDbUserName:
    Type: String
    Description: Input DB UsreName at Source
    Default: root

  SourceDbPassword:
    Type: String
    Description: Input DB Password at Source
    Default: passw0rd

  SourceDbServerName:
    Type: String
    Description: Input DB Cluster Endpoint at Source

  SourceDbSslMode:
    Type: String
    Description: Select Ssl Mode
    Default: none
    AllowedValues:
      - none
      - require
      - verify-ca
      - verify-full



Resources:
  # ------------------------------------------------------------#
  #  DMS ReplicationSubnetGroup
  # ------------------------------------------------------------#
  ReplicationSubnetGroup:
    Type: "AWS::DMS::ReplicationSubnetGroup"
    Properties:
      ReplicationSubnetGroupDescription: !Sub ${ServiceName} DMS SubnetGroup
      SubnetIds:
        - !Select [ 0, !Ref ReplicationSubnetId ]
        - !Select [ 1, !Ref ReplicationSubnetId ]
      Tags:
        - Key: "Name"
          Value: !Sub ${ServiceName} ReplicationSubnetGroup

  # ------------------------------------------------------------#
  #  DMS ReplicationInstance
  # ------------------------------------------------------------#
  ReplicationInstance: 
    Type: AWS::DMS::ReplicationInstance
    Properties:
      ReplicationInstanceIdentifier: !Sub ${ServiceName}-ReplicationInstance
      ReplicationInstanceClass: !Ref ReplicationInstanceClass
      AvailabilityZone: !Select [0, !GetAZs ""]
      MultiAZ: !Ref MultiAz
      PubliclyAccessible: false
      ReplicationSubnetGroupIdentifier: !Ref ReplicationSubnetGroup
      VpcSecurityGroupIds:
        - !Ref InternalSecurityGroupId
        - !Ref VPCPeeringSecurityGroupId
      Tags:
        - Key: "Name"
          Value: !Sub ${ServiceName} ReplicationInstance

  # ------------------------------------------------------------#
  #  DMS EndPoint
  # ------------------------------------------------------------#
  SourceEndpoint:
    Type: "AWS::DMS::Endpoint"
    Properties:
      EndpointIdentifier: Source-db
      EndpointType: source
      EngineName: aurora
      Username: !Ref SourceDbUserName
      Password: !Ref SourceDbPassword
      Port: 3306
      ServerName: !Ref SourceDbServerName
      SslMode: !Ref SourceDbSslMode
      Tags:
        - Key: "Name"
          Value: !Sub ${ServiceName} Source Endpoint

  TargetEndpoint:
    Type: "AWS::DMS::Endpoint"
    Properties:
      EndpointIdentifier: Target-db
      EndpointType: target
      EngineName: aurora
      Username: !Ref MyDbUserName
      Password: !Ref MyDbPassword
      Port: 3306
      ServerName: !Ref MyDbServerName
      SslMode: !Ref MyDbSslMode
      Tags:
        - Key: "Name"
          Value: !Sub ${ServiceName} Target Endpoint

  # ------------------------------------------------------------#
  #  DMS Task
  # ------------------------------------------------------------#
  ReplicationTask:
    Type: "AWS::DMS::ReplicationTask"
    Properties:
      MigrationType: full-load-and-cdc
      ReplicationInstanceArn: !Ref ReplicationInstance
      SourceEndpointArn: !Ref SourceEndpoint
      TargetEndpointArn: !Ref TargetEndpoint
      # ※TableMappingsとReplicationTaskSettings（デフォルトのまま）の設定は、一旦AWSコンソール上DMSを作成してからコピペした。適宜作成してください。
      TableMappings: "{\"rules\": [{\"rule-type\": \"selection\",\"rule-id\": \"1\",\"rule-name\": \"1\",\"object-locator\": {\"schema-name\": \"db\",\"table-name\": \"{任意のテーブル名}\"},\"rule-action\": \"include\"},{\"rule-type\": \"selection\",\"rule-id\": \"2\",\"rule-name\": \"2\",\"object-locator\": {\"schema-name\": \"任意のスキーマ\",\"table-name\": \"任意のテーブル名\"},\"rule-action\": \"include\"}]}"
      ReplicationTaskSettings: "{\"TargetMetadata\": {\"TargetSchema\": \"\",\"SupportLobs\": true,\"FullLobMode\": false,\"LobChunkSize\": 0,\"LimitedSizeLobMode\": true,\"LobMaxSize\": 32,\"InlineLobMaxSize\": 0,\"LoadMaxFileSize\": 0,\"ParallelLoadThreads\": 0,\"ParallelLoadBufferSize\": 0,\"ParallelLoadQueuesPerThread\": 0,\"ParallelApplyThreads\": 0,\"ParallelApplyBufferSize\": 0,\"ParallelApplyQueuesPerThread\": 0,\"BatchApplyEnabled\": false,\"TaskRecoveryTableEnabled\": false},\"FullLoadSettings\": {\"TargetTablePrepMode\": \"DO_NOTHING\",\"CreatePkAfterFullLoad\": false,\"StopTaskCachedChangesApplied\": false,\"StopTaskCachedChangesNotApplied\": false,\"MaxFullLoadSubTasks\": 2,\"TransactionConsistencyTimeout\": 600,\"CommitRate\": 10000},\"Logging\": {\"EnableLogging\": true,\"LogComponents\": [{\"Id\": \"SOURCE_UNLOAD\",\"Severity\": \"LOGGER_SEVERITY_DEFAULT\"},{\"Id\": \"TARGET_LOAD\",\"Severity\": \"LOGGER_SEVERITY_DEFAULT\"},{\"Id\": \"SOURCE_CAPTURE\",\"Severity\": \"LOGGER_SEVERITY_DEFAULT\"},{\"Id\": \"TARGET_APPLY\",\"Severity\": \"LOGGER_SEVERITY_DEFAULT\"},{\"Id\": \"TASK_MANAGER\",\"Severity\": \"LOGGER_SEVERITY_DEFAULT\"}]},\"ControlTablesSettings\": {\"historyTimeslotInMinutes\": 5,\"ControlSchema\": \"index.handler\",\"HistoryTimeslotInMinutes\": 5,\"HistoryTableEnabled\": false,\"SuspendedTablesTableEnabled\": false,\"StatusTableEnabled\": false},\"StreamBufferSettings\": {\"StreamBufferCount\": 3,\"StreamBufferSizeInMB\": 8,\"CtrlStreamBufferSizeInMB\": 5},\"ChangeProcessingDdlHandlingPolicy\": {\"HandleSourceTableDropped\": true,\"HandleSourceTableTruncated\": true,\"HandleSourceTableAltered\": true},\"ErrorBehavior\": {\"DataErrorPolicy\": \"LOG_ERROR\",\"DataTruncationErrorPolicy\": \"LOG_ERROR\",\"DataErrorEscalationPolicy\": \"SUSPEND_TABLE\",\"DataErrorEscalationCount\": 0,\"TableErrorPolicy\": \"SUSPEND_TABLE\",\"TableErrorEscalationPolicy\": \"STOP_TASK\",\"TableErrorEscalationCount\": 0,\"RecoverableErrorCount\": -1,\"RecoverableErrorInterval\": 5,\"RecoverableErrorThrottling\": true,\"RecoverableErrorThrottlingMax\": 1800,\"ApplyErrorDeletePolicy\": \"IGNORE_RECORD\",\"ApplyErrorInsertPolicy\": \"LOG_ERROR\",\"ApplyErrorUpdatePolicy\": \"LOG_ERROR\",\"ApplyErrorEscalationPolicy\": \"LOG_ERROR\",\"ApplyErrorEscalationCount\": 0,\"ApplyErrorFailOnTruncationDdl\": false,\"FullLoadIgnoreConflicts\": true,\"FailOnTransactionConsistencyBreached\": false,\"FailOnNoTablesCaptured\": false},\"ChangeProcessingTuning\": {\"BatchApplyPreserveTransaction\": true,\"BatchApplyTimeoutMin\": 1,\"BatchApplyTimeoutMax\": 30,\"BatchApplyMemoryLimit\": 500,\"BatchSplitSize\": 0,\"MinTransactionSize\": 1000,\"CommitTimeout\": 1,\"MemoryLimitTotal\": 1024,\"MemoryKeepTime\": 60,\"StatementCacheSize\": 50},\"ValidationSettings\": {\"EnableValidation\": true,\"ValidationMode\": \"ROW_LEVEL\",\"ThreadCount\": 5,\"PartitionSize\": 10000,\"FailureMaxCount\": 10000,\"RecordFailureDelayInMinutes\": 5,\"RecordSuspendDelayInMinutes\": 30,\"MaxKeyColumnSize\": 8096,\"TableFailureMaxCount\": 1000,\"ValidationOnly\": false,\"HandleCollationDiff\": false,\"RecordFailureDelayLimitInMinutes\": 0},\"PostProcessingRules\": null,\"CharacterSetSettings\": null,\"LoopbackPreventionSettings\": null,\"BeforeImageSettings\": null}"
      Tags:
        - Key: "Name"
          Value: !Sub ${ServiceName} ReplicationTask

  # ------------------------------------------------------------#
  #  DMS IAM Role
  # ------------------------------------------------------------#
  DMSTaskForCloudWatchRole:
    Type: AWS::IAM::Role
    Properties:
      RoleName: dms-cloudwatch-logs-role # ※この名前じゃないと動かいない
      AssumeRolePolicyDocument:
        Version: "2012-10-17"
        Statement:
          - 
            Effect: "Allow"
            Principal: 
              Service: "dms.amazonaws.com"
            Action: "sts:AssumeRole"
      ManagedPolicyArns:
      - arn:aws:iam::aws:policy/service-role/AmazonDMSCloudWatchLogsRole

```
以上です。