Skip to content

Instantly share code, notes, and snippets.

@TrentBartlem
Created June 28, 2017 22:57
Show Gist options
  • Save TrentBartlem/292be37d496361d551fff6659d87fb0e to your computer and use it in GitHub Desktop.
Save TrentBartlem/292be37d496361d551fff6659d87fb0e to your computer and use it in GitHub Desktop.
Dynamodb autoscaling using a combination of CloudFormation and AWS SDK
// snip: imports, applys etc.
// snip: assume 'deploy' task exists that deploys Serverless
task addScalingPolicy(dependsOn: deploy) {
description 'CloudFormation cannot do this yet, so we do it via SDK'
doLast {
final asClient = AWSApplicationAutoScalingClientBuilder.defaultClient()
final putScalingPolicy = { String tableName ->
final ttspReadConfig = new TargetTrackingScalingPolicyConfiguration(
predefinedMetricSpecification: new PredefinedMetricSpecification(
predefinedMetricType: 'DynamoDBReadCapacityUtilization'),
targetValue: 70.0)
final ttspWriteConfig = new TargetTrackingScalingPolicyConfiguration(
predefinedMetricSpecification: new PredefinedMetricSpecification(
predefinedMetricType: 'DynamoDBWriteCapacityUtilization'),
targetValue: 70.0)
final scalingPolicyRequest = new PutScalingPolicyRequest(
serviceNamespace: 'dynamodb',
resourceId: "table/$tableName",
scalableDimension: 'dynamodb:table:WriteCapacityUnits',
policyName: "table/${tableName}_WriteScalingPolicy",
policyType: 'TargetTrackingScaling',
targetTrackingScalingPolicyConfiguration: ttspWriteConfig)
asClient.putScalingPolicy(scalingPolicyRequest)
scalingPolicyRequest.with {
scalableDimension = 'dynamodb:table:ReadCapacityUnits'
policyName = "table/${tableName}_ReadScalingPolicy"
targetTrackingScalingPolicyConfiguration = ttspReadConfig
}
asClient.putScalingPolicy(scalingPolicyRequest)
}
putScalingPolicy 'myTable1'
putScalingPolicy 'myTable2'
// etc
}
}
# snip: various serverless-related provider settings etc
resources:
Resources: # Essentially just CloudFormation
myTable1DynamoTable:
Type: AWS::DynamoDB::Table
Properties:
TableName: mytable1
# insert AttributeDefinitions
# insert KeySchema
ProvisionedThroughput:
ReadCapacityUnits: ${env:MYTABLE1_READCAP}
WriteCapacityUnits: ${env:MYTABLE1_WRITECAP}
myTable2DynamoTable:
Type: AWS::DynamoDB::Table
Properties:
TableName: mytable2
# insert AttributeDefinitions
# insert KeySchema
ProvisionedThroughput:
ReadCapacityUnits: ${env:MYTABLE2_READCAP}
WriteCapacityUnits: ${env:MYTABLE2_WRITECAP}
myAutoscalingRole:
Type: AWS::IAM::Role
Properties:
RoleName: DynamoDBAutoscaleRole
AssumeRolePolicyDocument:
Version: "2012-10-17"
Statement:
-
Effect: Allow
Principal:
Service: "application-autoscaling.amazonaws.com"
Action: "sts:AssumeRole"
Policies:
- PolicyName: "myAutoscalingPolicy"
PolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: Allow
Action:
- dynamodb:DescribeTable
- dynamodb:UpdateTable
- cloudwatch:PutMetricAlarm
- cloudwatch:DescribeAlarms
- cloudwatch:DeleteAlarms
- cloudwatch:GetMetricStatistics
- cloudwatch:SetAlarmState
Resource: "*"
myTable1ReadTarget:
Type: AWS::ApplicationAutoScaling::ScalableTarget
DependsOn: myAutoscalingRole
Properties:
MaxCapacity: 10000
MinCapacity: ${env:MYTABLE1_READCAP}
ResourceId: table/mytable1
RoleARN: {Fn::GetAtt: [myAutoscalingRole, Arn]}
ScalableDimension: dynamodb:table:ReadCapacityUnits
ServiceNamespace: dynamodb
myTable1WriteTarget:
Type: AWS::ApplicationAutoScaling::ScalableTarget
DependsOn: myAutoscalingRole
Properties:
MaxCapacity: 10000
MinCapacity: ${env:MYTABLE1_WRITECAP}
ResourceId: table/mytable1
RoleARN: {Fn::GetAtt: [myAutoscalingRole, Arn]}
ScalableDimension: dynamodb:table:WriteCapacityUnits
ServiceNamespace: dynamodb
myTable2ReadTarget:
Type: AWS::ApplicationAutoScaling::ScalableTarget
DependsOn: myAutoscalingRole
Properties:
MaxCapacity: 10000
MinCapacity: ${env:MYTABLE2_READCAP}
ResourceId: table/mytable2
RoleARN: {Fn::GetAtt: [myAutoscalingRole, Arn]}
ScalableDimension: dynamodb:table:ReadCapacityUnits
ServiceNamespace: dynamodb
myTable2WriteTarget:
Type: AWS::ApplicationAutoScaling::ScalableTarget
DependsOn: myAutoscalingRole
Properties:
MaxCapacity: 10000
MinCapacity: ${env:MYTABLE2_WRITECAP}
ResourceId: table/mytable2
RoleARN: {Fn::GetAtt: [myAutoscalingRole, Arn]}
ScalableDimension: dynamodb:table:WriteCapacityUnits
ServiceNamespace: dynamodb
@cixelsyd
Copy link

cixelsyd commented Jul 6, 2017

This is an excellent gist on a little-documented CloudFormation feature. Note, in order to get the dynamodb scaling working all I needed were the correct CF resources shown here, and not the gradle SDK code.

@sbstjn
Copy link

sbstjn commented Jul 18, 2017

Thanks for the example configurations! If you use serverless to create your CloudFormation Stack, have a look at my serverless-dynamodb-autoscaling plugin to configure Auto Scaling in your serverless.yml with a clean configuration:

custom:
  capacities:
    - name: custom-table  # DynamoDB table name
      read:
        minimum: 5        # Minimum read capacity
        maximum: 1000     # Maximum read capacity
        usage: 0.75       # Targeted usage percentage
      write:
        minimum: 40       # Minimum write capacity
        maximum: 200      # Maximum write capacity
        usage: 0.5        # Targeted usage percentage

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment