Application Auto Scalingのcustom-resourceによるKinesis Data Streamsのオートスケール設定
awsApplication Auto Scalingは、Auto Scaling groupによるEC2のオートスケールのようなことを他のリソースでも行えるようにするサービスで、 DynamoDBのキャパシティやECSのServiceなどコンソール上から設定できるものだけではなく、自前のAPIでハンドリングすることで任意のリソースをこの仕組みに乗せることができる。これを用いてKinesis Data Streamsのオートスケールを行う手法を紹介しているのが次の記事。
Scale Amazon Kinesis Data Streams with AWS Application Auto Scaling | AWS Big Data Blog
サンプルテンプレートの設定項目を見ていく。
ScalableTarget
ServiceNamespace
でdynamodb
やecs
といった名前空間を、ScalableDimension
でdynamodb:table:ReadCapacityUnits
やecs:service:DesiredCount
といった増減する値を指定する。
ResourceId
にはScalableDimension
のResourceTypeに応じた対象を指定するわけだが、
custom-resource
の場合は状態を確認したり更新するためのAPIのURLを指定するようだ。
ドキュメントにはOutputValueの値と書いてあるが、特に関係ないように見える。
Roleにはcloudwatch:Describe/Put/DeleteAlarms
およびexecute-api:Invoke*
の権限を与える。
KinesisAutoScaling:
Type: AWS::ApplicationAutoScaling::ScalableTarget
DependsOn: LambdaScaler
Properties:
MaxCapacity: 8
MinCapacity: 1
ResourceId: !Sub https://${MyApi}.execute-api.${AWS::Region}.amazonaws.com/prod/scalableTargetDimensions/${MyKinesisStream}
RoleARN: !Sub ${CustomApplicationAutoScalingServiceRole.Arn}
ScalableDimension: 'custom-resource:ResourceType:Property'
ServiceNamespace: custom-resource
ScalingPolicy
AdjustmentType
とScalingAdjsutment
の値によって増減値を設定する。
AdjustmentType
にはChangeInCapacity | ExactCapacity | PercentChangeInCapacity
のいずれかを指定する。
AutoScalingPolicyOut:
Type : "AWS::ApplicationAutoScaling::ScalingPolicy"
DependsOn: KinesisAutoScaling
Properties:
PolicyName: KinesisScaleOut
PolicyType: StepScaling
ResourceId: !Sub https://${MyApi}.execute-api.${AWS::Region}.amazonaws.com/prod/scalableTargetDimensions/${MyKinesisStream}
ScalableDimension: "custom-resource:ResourceType:Property"
ServiceNamespace: custom-resource
StepScalingPolicyConfiguration:
AdjustmentType: ChangeInCapacity
Cooldown: 600
MetricAggregationType: Average
StepAdjustments:
- MetricIntervalLowerBound: 0
ScalingAdjustment: 1
CloudWatch AlarmのActionにこのPolicyを指定して、メトリクスが閾値に達したときに通知されるようにする。
この例ではストリームのIncomingRecords
を見ている。
もしパーティションキーが乱数でなかったり、各シャードに対応するハッシュキーのレンジが均等でなかったりして、
ホットシャードが発生する可能性があるなら、
拡張メトリクスを有効にすると得られるシャードレベルの値を基にしても良いかもしれない。
CWAlarmOut:
Type: AWS::CloudWatch::Alarm
DependsOn: MyKinesisStream
Properties:
AlarmName: !Ref CloudWatchAlarmNameOut
AlarmDescription: 'incomingRecord exceeds threshold'
MetricName: 'IncomingRecords'
Namespace: 'AWS/Kinesis'
Dimensions:
- Name: StreamName
Value: !Ref MyKinesisStream
Statistic: 'Sum'
Period: 60
EvaluationPeriods: 1
Threshold: 1000
ComparisonOperator: 'GreaterThanThreshold'
AlarmActions:
- !Ref AutoScalingPolicyOut
API
通知が飛ぶとApplication Auto ScalingがResource IDに指定したAPIをGET
で呼び出すので、次のフォーマットで状態を返す。
returningJson = {
"actualCapacity": float(actualCapacity),
"desiredCapacity": float(desiredCapacity),
"dimensionName": resourceName,
"resourceName": resourceName,
"scalableTargetDimensionId": resourceName,
"scalingStatus": scalingStatus,
"version": "MyVersion"
}
スケールが必要な場合はPATCH
でdesiredCapacity
が渡ってくるので、この値になるようにUpdateShardCount
し、アラームの閾値を更新する。
UpdateShardCount
も内部ではSplit/MergeShard
が行われるので倍や半分といった値にすると速く変更できる。
"body": "{\"desiredCapacity\":3.0}"
併せてコンシューマーの数も調整する。 また、KDSのリシャーディング回数や変更幅の制限については別に考慮する必要がある。