通过 CloudFormation 为现有表添加自动缩放到 AWS DynamoDB

Posted

技术标签:

【中文标题】通过 CloudFormation 为现有表添加自动缩放到 AWS DynamoDB【英文标题】:Adding autoscaling to AWS DynamoDB via CloudFormation for already existing table 【发布时间】:2018-02-10 21:52:06 【问题描述】:

我们的团队很高兴看到宣布推出 AWS DynamoDB 的自动缩放功能,在尝试通过在 Web 界面中添加配置时,我们发现这很好地满足了我们应用程序的四个需求。

但是,通过 CF 添加相同配置的尝试被证明有点复杂。本文提供的以下示例 - http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-dynamodb-table.html#cfn-dynamodb-table-examples-application-autoscaling - 下面是结果,它不起作用。堆栈详细信息:

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

我的CF脚本如下:


  "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"
          
        
      
    
  

如果有人能解释为什么会发生这种情况,我将非常感激:)

【问题讨论】:

奇怪的是,似乎只有一个特定的表存在问题 - 通过控制台添加或删除自动缩放没有帮助 - 脚本仍然因上述错误而失败。解决此问题的唯一方法是通过 CF 更新预置容量(不可扩展),然后才通过相同的 CF 脚本添加自动扩展。 【参考方案1】:

按照错误信息进行

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

您正在创建一个名为 "TableName": "TableName" 的 DynamoDB 资源。一个区域内不能有两个同名的 dynamoDB 表。

转到 DynamoDB 控制台并检查您是否有任何此类表并将其删除。发布该模板应该可以正常工作。

选项 2:如果您想继续使用现有表,则可以从 CF 模板中删除 AWS::DynamoDB::Table 资源。

【讨论】:

谢谢。我从错误消息中得到的印象是,该表的 WriteCapacityUnits 已经创建——因为它们已经创建了,因为该表已经存在。但是删除表资源本身是否意味着该表被删除?它有数据,我不想丢失(或迁移,就此而言)。所以要明确一点,表资源是很久以前创建的,我只想为其添加自动缩放 - 通过将 WriteCapacityScalableTarget、ScalingRole 和 WriteScalingPolicy 引入 CF 模板。 我也尝试过模拟。首先使用 CF 模板创建 DynamoDB 表,然后将 WritingCapacityScalableTarget、ScalingRole 和 WriteScalingPolicy 添加到 CF 模板并执行更新堆栈。进展顺利。那么,您是否有可能通过控制台测试了一些东西而忘记清除它?【参考方案2】:

对我来说,在为已经存在的发电机表设置自动缩放时出现此错误。确保您已删除为该发电机表设置的任何手动(通过控制台)自动缩放。然后重新执行,堆栈将到达UPDATE_COMPLETE 阶段。

【讨论】:

已确认。我通过 AWS 控制台创建并随后删除了一个 DynamoDB 表。尝试通过 CloudFormation 创建具有自动缩放规则的同名表时,它抱怨该表的自动缩放策略已经存在。我需要通过 AWS 控制台重新创建表,禁用表的扩展,然后删除表。只有在这样做之后,CloudFormation 才成功。

以上是关于通过 CloudFormation 为现有表添加自动缩放到 AWS DynamoDB的主要内容,如果未能解决你的问题,请参考以下文章

将现有 AWS 资源整合到 CloudFormation 堆栈中

无法通过自定义 cloudformation 资源调用 lambda 函数

无法使用 CloudFormation 将 GSI 添加到 DynamoDB 表

如何使用 CloudFormation 模板更新现有 AWS API Gateway

使用 AWS CLI 将现有资源导入 CloudFormation

使用AWS CLI将现有资源导入CloudFormation