2
votes

Our team was quite excited to see autoscaling feature announced for AWS DynamoDB, and when trying it out by adding configuration in web interface we've discovered that's a good match four our applications' needs.

However, attempts to add the same configuration via CF have proved to be a bit more complicated. Following example as provided in this article - http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-dynamodb-table.html#cfn-dynamodb-table-examples-application-autoscaling - below is the result, which does not work. Stack detail:

17:02:25 UTC+0300 UPDATE_ROLLBACK_IN_PROGRESS AWS::CloudFormation::Stack my-stack The following resource(s) failed to create: [WriteCapacityScalableTarget]. 17:02:24 UTC+0300 CREATE_FAILED AWS::ApplicationAutoScaling::ScalableTarget WriteCapacityScalableTarget table/TableName|dynamodb:table:WriteCapacityUnits|dynamodb already exists 17:02:18 UTC+0300 CREATE_IN_PROGRESS AWS::ApplicationAutoScaling::ScalableTarget WriteCapacityScalableTarget
17:02:15 UTC+0300 CREATE_COMPLETE AWS::IAM::Role ScalingRole
17:01:42 UTC+0300 CREATE_IN_PROGRESS AWS::IAM::Role ScalingRole Resource creation Initiated 17:01:42 UTC+0300 CREATE_IN_PROGRESS AWS::IAM::Role ScalingRole
17:01:37 UTC+0300 UPDATE_IN_PROGRESS AWS::CloudFormation::Stack my-stack User Initiated

My CF script is as follows:

{
  "Resources": {
    "MyCustomTableName": {
      "Type": "AWS::DynamoDB::Table",
      "Properties": {
        "TableName": "TableName",
        "AttributeDefinitions": [
          {
            "AttributeName": "someAttribute1:someAttribute2",
            "AttributeType": "S"
          }
        ],
        "KeySchema": [
          {
            "AttributeName": "someAttribute1:someAttribute2",
            "KeyType": "HASH"
          }
        ],
        "ProvisionedThroughput": {
          "ReadCapacityUnits": 1,
          "WriteCapacityUnits": 1
        },
        "StreamSpecification": {
          "StreamViewType": "NEW_AND_OLD_IMAGES"
        }
      }
    },
    "WriteCapacityScalableTarget": {
      "Type": "AWS::ApplicationAutoScaling::ScalableTarget",
      "Properties": {
        "MaxCapacity": 30,
        "MinCapacity": 1,
        "ResourceId": {
          "Fn::Join": [
            "/",
            [
              "table",
              {
                "Ref": "MyCustomTableName"
              }
            ]
          ]
        },
        "RoleARN": {
          "Fn::GetAtt": [
            "ScalingRole",
            "Arn"
          ]
        },
        "ScalableDimension": "dynamodb:table:WriteCapacityUnits",
        "ServiceNamespace": "dynamodb"
      }
    },
    "ScalingRole": {
      "Type": "AWS::IAM::Role",
      "Properties": {
        "AssumeRolePolicyDocument": {
          "Version": "2012-10-17",
          "Statement": [
            {
              "Effect": "Allow",
              "Principal": {
                "Service": [
                  "application-autoscaling.amazonaws.com"
                ]
              },
              "Action": [
                "sts:AssumeRole"
              ]
            }
          ]
        },
        "Path": "/",
        "Policies": [
          {
            "PolicyName": "root",
            "PolicyDocument": {
              "Version": "2012-10-17",
              "Statement": [
                {
                  "Effect": "Allow",
                  "Action": [
                    "dynamodb:DescribeTable",
                    "dynamodb:UpdateTable",
                    "cloudwatch:PutMetricAlarm",
                    "cloudwatch:DescribeAlarms",
                    "cloudwatch:GetMetricStatistics",
                    "cloudwatch:SetAlarmState",
                    "cloudwatch:DeleteAlarms"
                  ],
                  "Resource": "*"
                }
              ]
            }
          }
        ]
      }
    },
    "WriteScalingPolicy": {
      "Type": "AWS::ApplicationAutoScaling::ScalingPolicy",
      "Properties": {
        "PolicyName": "WriteAutoScalingPolicy",
        "PolicyType": "TargetTrackingScaling",
        "ScalingTargetId": {
          "Ref": "WriteCapacityScalableTarget"
        },
        "TargetTrackingScalingPolicyConfiguration": {
          "TargetValue": 70.0,
          "ScaleInCooldown": 60,
          "ScaleOutCooldown": 60,
          "PredefinedMetricSpecification": {
            "PredefinedMetricType": "DynamoDBWriteCapacityUtilization"
          }
        }
      }
    }
  }
}

If anyone can shed some light as to why this is happening, I'd be much obliged :)

2
Oddly enough, it seems that there was an issue with just a particular table - and adding or removing autoscaling via console did not help - script still failed with the mentioned error. The only way to resolve this was to update provisioned capacity (not scalable) via CF, and only then add auto-scaling via same CF script.Alexey Danilov

2 Answers

5
votes

Going by the error message

CREATE_FAILED AWS::ApplicationAutoScaling::ScalableTarget WriteCapacityScalableTarget table/TableName|dynamodb:table:WriteCapacityUnits|dynamodb already exists

You are creating a DynamoDB resource with the name "TableName": "TableName". You cannot have two dynamoDB tables with same name within a region.

Go to the DynamoDB console and check if you have any such table and delete it. Post that the template should work fine.

Option 2: If you want to go ahead with the existing table, then you can remove the AWS::DynamoDB::Table resource from your CF Template.

2
votes

For me this error came while setting up auto-scaling for an already existing dynamo table. Make sure you've removed any manual (via console) auto-scaling that you've set up for that dynamo table. Then re-execute and the stack would reach the UPDATE_COMPLETE stage.