Amazon Web Services ブログ
AWS Application Auto Scaling を使用した Amazon Kinesis Data Streams のスケーリング
先日、AWS は AWS Application Auto Scaling の新機能を発表しました。Amazon Kinesis Data Stream に対してシャードを自動的に追加・削除するスケーリングポリシーを定義できる機能です。この機能の詳細については、Application Auto Scaling の GitHub リポジトリを参照してください。
ストリーミングの情報が増えると、あらゆるリクエストに対応するスケーリングソリューションが必要になります。逆にストリーミング情報が減る場合も、スケーリングを利用してコストを抑えなければなりません。現在、Amazon Kinesis Data Stream のシャードはプログラム的にスケーリングされています。あるいは、Amazon Kinesis のスケーリングユーティリティを使用することも可能です。その場合は、ユーティリティを手動で使用する方法と、AWS Elastic Beanstalk 環境で自動化する方法があります。
Application Auto Scaling の新機能を使うと、AWS を使用してスケーリングソリューションを作成することができ、人手の介入も複雑なソリューションも必要ありません。
Auto Scaling ソリューションの概要
今回のブログ記事でご紹介するのは、デフォルトの Amazon CloudWatch メトリクスに基づいて Amazon Kinesis Data Streams に Auto Scaling ソリューションをデプロイする方法です。環境を自動的に設定する AWS CloudFormation テンプレートと、Lambda 関数に関連するコードについても触れます。
Auto Scaling ソリューションのしくみ
始まりは、Kinesis Data Stream のシャードメトリクスを監視する CloudWatch アラームです。リクエスト数の増加などによって、アラームのカスタムしきい値に達すると、アラームがトリガーされます。そうすると、Application Auto Scaling ポリシーに通知が送信され、スケールアップかスケールダウンかの応答はそのポリシーの設定に基づいて決まります。
スケーリングポリシーがトリガーされると、Application Auto Scaling が API 機能を呼び出し、必要な容量に応じて Kinesis Data Stream シャードの新しい数が渡されます (詳細は、こちらを参照)。また、スケーリングするリソースの名前も渡されますが、これを指定するのが Amazon API Gateway です。Amazon API Gateway は、AWS Lambda 関数を呼び出します。Application Auto Scaling によって送信される情報に基づいて、Lambda 関数が Kinesis Data Stream のシャードの数を増減します。ここで使われるのは、Kinesis Data Stream の UpdateShardCount API 機能です。以上の流れを、次の図にまとめました。次の図は、上記のシナリオを示しています。
この図でもわかるように、AWS Systems Manager の Parameter Store も関係しています。Parameter Store には、Application Auto Scaling が API Gateway に送信して増減する所定の容量値が格納されます(この場合、容量はシャードの数です)。 実際には、Application Auto Scaling は API Gateway を呼び出してカスタムリソースの状態、ここでは Kinesis Data Stream の状態を取得します。必要なアクションがあるかどうか、前回のアクションが成功したかどうかを確認することが目的です。Lambda はステートレスなので、Application Auto Scaling によって送信された容量値は、どこかの時点で保存する必要があります。
ソリューションのコンポーネント
このソリューションで使われるコンポーネントは、以下のとおりです。
Application Auto Scaling のスケーラブルターゲット – スケーラブルターゲットは、Application Auto Scaling サービスに登録されるリソースです。任意のリソースを定義および登録してスケーリングできます。スケーラブルターゲットは、スケーラブルディメンションの最小値と最大値を処理し、次のパラメータが必要です。
- ResourceId: スケーラブルターゲットとなるリソース。次の例のようにカスタムリソースの場合は、AWS CloudFormation テンプレートによって返される OutputValue を指定します。
- RoleARN: スケーラブルターゲットのリソース変更アクセス権を付与する際に使用される、サービスにリンクしたロール。
- ScalableDimension: スケーラブルターゲットのディメンション。カスタムリソースの場合は、この値を custom-resource:ResourceType:Property としてください。
- ServiceNamespace: AWS の名前空間。ここでは、この値はカスタムリソースです。
スケーリングポリシー – スケーラブルターゲットを登録すると、サービスのスケーリング方法を決めるスケーリングポリシーを適用できます。
サポートされているポリシーのタイプは、次のとおりです。
- TargetTrackingScaling – Amazon DynamoDB 専用
- StepScaling – Amazon ECS、Amazon EC2 Spot Fleets、Amazon RDS でサポート
- TargetTrackingScaling – Amazon ECS、EC2 Spot Fleets、Amazon RDS でサポート
- StepScaling — その他のサービスでサポート
ここでは、StepScaling ポリシーを使用します。「スケーリングポリシーとスケジュール済みアクション」の項で後述するように、カスタムリソースタイプを使っているからです。ただし、カスタムリソースタイプはスケジュール済みアクションもサポートできます。
API Gateway – このソリューションでは、Amazon API Gateway を使用して安全な REST エンドポイントを公開します。Application Auto Scaling は、このエンドポイントを使って認証済み呼び出しを IAM で送信し、カスタムサービスの現在の容量を取得したうえで、HTTP GET を使ってスケーリングします。Application Auto Scaling は、カスタムサービスの相対容量を調整する (HTTP PATCH を使って) ときにも、このエンドポイントを使います。
CloudWatch のメトリクスとアラーム – Application Auto Scaling のエンドポイントに送られたアラームを監視してトリガーする KPI です。
Lambda 関数 – ここでは、AWS Lambda 関数が、主に次の 2 つのタスクを実行します。
- API リクエストが GET の場合、Lambda 関数は JSON を返します。これには、Application Auto Scaling が制御するカスタムリソースのステータス情報が含まれています。ここでは、カスタムリソースは Kinesis Data Stream です。
- API リクエストが PATCH の場合、Lambda 関数は新しく指定される容量を DynamoDB テーブルに格納します。Lambda 関数は次に、Kinesis Data Stream の UpdateShardCount API を呼び出します。
AWS Systems Manager の Parameter Store – Application Auto Scaling のエンドポイントに送られたアラームを監視してトリガーする KPI です。
前提条件
このソリューションの前提条件は、以下のとおりです。
- 自動スケーリングを設定し、サービスにリンクした所定のロールを作成できるアクセス権を持つユーザー認証情報。詳細については、Application Auto Scaling のユーザーガイドを参照してください。
- AWS CloudFormation テンプレートを使用してスタックを作成するアクセス権と、そのスタックのリソースに対するフルアクセス権。詳細については、AWS CloudFormation のユーザーガイドを参照してください。
スケーリングポリシーとスケジュール済みアクション
同じアーキテクチャを使用して、Amazon Kinesis Data Stream の 2 つの状況で処理を行うことができます。
- 1 つ目は予測可能なトラフィック、つまりスケジュール済みのアクションです。予測可能なトラフィックの例としては、Kinesis Data Stream のエンドポイントで特定の時間帯だけトラフィックが上昇する場合が挙げられます。この場合は、Application Auto Scaling のスケジュール済みアクションによって Kinesis Data Stream のシャードの数を増やせば、需要に対応できます。たとえば、シャードの数を正午に増やし、午前 8 時には減らすなどの対応です。
- 2 つ目は、従来どおりオンデマンドのシナリオで、スケーリングポリシーを指定します。この場合は、クライアントの需要に応じて Kinesis Data Stream のシャード数を増減する Application Auto Scaling のスケーリングポリシーを作成します。
この記事では、スケーリングポリシーを使う 2 番目のシナリオを重点的に説明します。こちらのほうが、実装が難しいからです。
制限
Application Auto Scaling は、需要に確実に応じられるようにスケールアップとスケールダウンを連続的に行えます。ただし、Application Auto Scaling を設定する際には、考慮すべき制限事項があります。Kinesis Data Streams で、次のような処理はできません。
- ストリームごとに連続する 24 時間以内に 10 回のスケーリング (※2020/08/11 更新:回数制限を最新の仕様に更新。以前は 2 回でした。)
- 1 ストリームについて現在のシャード数を 2 倍以上に増やすスケールアップ
- 1 ストリームについて現在のシャード数を 2 分の 1 以下に減らすスケールダウン
- 1 ストリームでシャード数 500 以上へのスケールアップ
- シャード数 500 以上のストリームを、結果的に 500 を下回らない数にスケールダウン
- お使いのアカウントで許可されているシャード数を超えるスケールアップ
1 日に 2 回以上のスケーリングが必要な場合は、こちらの AWS サポートフォームを使って、上限引き上げを依頼できます。
メトリクス選択
スケールアップとスケールダウンでモニタするメトリクスを選択する際には、ストリームレベルのメトリクス IncomingBytes と IncomingRecords を使用できます (詳細については Kinesis Data Streams のドキュメントを参照)。Kinesis は、1 秒あたり 1 MiB のデータ、または 1 秒あたり 1000 レコードのストリーミングをサポートしています。IncomingBytes と IncomingRecords を使用すれば、しきい値に基づいて、たとえば 80% にアラームを設定することができます。そのためには、Amazon Kinesis がリクエストのスロットリングを開始する前に Application Auto Scaling サービスを呼び出してください。前もってリソースをスケーリングするには最も効果的な方法ですが、Application Auto Scaling で十分なクールダウン時間を設けておく必要があります。そうしないと、両方のメトリクスで同時に複数のスケーリングアクションがトリガーされてしまうからです。
あるいは、WriteProvisionedThroughputExceeded メトリクスを使用して、Amazon Kinesis のシャードの上限に達したときにスケーリングする方法もあります (詳細については、CloudWatch のドキュメントを参照)。
今回の例では、最初のアプローチをとり、IncomingRecords を使用することにします。
ソリューションのデプロイとテスト
ソリューションのテストには、ここからダウンロードできる AWS CloudFormation テンプレートを使用できます。AWS CloudFormation テンプレートを使うと、API Gateway、Lambda 関数、Kinesis Data Stream、DynamoDB テーブル、Application Auto Scaling グループ、およびスケーリングポリシーが自動的に作成されます。
ソリューションをデプロイする
AWS CloudFormation で、自動的にリソースを作成する手順は、次のとおりです。
- ソリューションをデプロイしたい AWS リージョンで [AWS マネジメントコンソール] を開き、[サービス] メニューから [CloudFormation] を選択します。
- [スタックの作成]、[テンプレートを Amazon S3 にアップロード] の順に選択し、ソリューションに含まれる custom-application-autoscaling-kinesis.yaml ファイルを選択します。
- スタックにわかりやすい名前を付けます。ソリューションに 含まれている圧縮版の AWS Lambda 関数 (index.py) が入っている Amazon S3 バケットを指定します。
- [オプション] には、スタックのタグを指定し、AWS CloudFormation でリソース作成時に使用する IAM ロールをオプションで指定できます。ロールを指定しない場合は、新しいロールが作成されます。ロールバック設定と通知オプションにも追加の構成を実行できます。
- レビューセクションには、情報のまとめが表示されます。AWS CloudFormation でカスタム名を付けて自動的にリソースを作成するには、AWS CloudFormation に関する 2 つの承認オプションを必ず選択してください。変更セットも作成します。AWS CloudFormation テンプレートには、AWS::Serverless-2016-10-31 が含まれているためです。
- ストリームレベルのメトリクスを選択し、タスクに存在するリソースを作成します。
ソリューションをテストする
環境が作成できたら、テストします。Amazon CloudWatch のアラームを手動でトリガーするには、ストリームへのトラフィックを生成しなければなりません。これには、Amazon Kinesis Data Generator を利用するのが効率的です。
- まず、https://awslabs.github.io/amazon-kinesis-data-generator/web/help.html にあるガイドに従って Amazon Kinesis Data Generator を設定します。
- ジェネレータが作成されたら、[リージョン] を選択し、新しく作成した Kinesis Data Stream、ここでは「Kinesis-MyKinesisStream-1MUOGAD9OBCJH」を選択します。
- [1 秒あたりのレコード数] に、シャードが 1 つであれば 1000 以上の値を入力します。1 つでない場合は、シャード数を掛けた値を入力します (たとえば、シャードが 2 つの場合には 1500 * 2 = 3000)。
- フォームに「test」と入力し、[Send data] を選択します。
- トラフィックが生成されたら Amazon CloudWatch コンソールを開き、[アラーム] で [アラーム] を選択します。
- [ALARM] リストで [IncomingRecords-alarm-out] を選択し、ページの下部で [履歴] タブを開いて、Application Auto Scaling でアラームがトリガーされたことを確認してください。
オープンなシャードの数が更新されたことを、以下の手順で確認します。
- Amazon Kinesis コンソールを開き、[Data Streams] を選択し、データストリーム、この場合は「Kinesis-MyKinesisStream-1MUOGAD9OBCJH」を選択します。
- [詳細] を見ると、次の例のようにシャードが 3 つに増えていることを確認できます。
テスト後の環境をクリーンアップする
テスト終了後に環境をクリーンアップする手順は簡単です。次のように AWS CloudFormation スタックを削除すれば、すべて削除されます。
- ソリューションをデプロイしたい AWS リージョンで [AWS マネジメントコンソール] を開き、リストから [CloudFormation スタック] を選択します。
- [アクション]、[スタックの削除] の順にクリックします。
- オプション: 作成した S3 バケットと Lambda 関数も削除できます。
結論
今回の記事では、Application Auto Scaling サービスを使用して Amazon Kinesis Data Stream を自動的にスケーリングする方法をご紹介しました。Amazon API Gateway を使えば、Application Auto Scaling で安全に AWS Lambda 関数を呼び出し、必要なストリームを操作できます。
まとめ
Giorgio Nobile は、イタリアで Amazon Web Services のソリューションアーキテクトを務めており、企業顧客と協力して、デジタルトランスフォーメーションの導入をサポートしています。専門分野はビッグデータです。私生活では、2 人の子どもと過ごすのが好きで、DIY とスノーボードを趣味にしています。
Diego Natali は、イタリアで Amazon Web Services のソリューションアーキテクトを務めています。エンジニアリングとして長年のバックグラウンドを持ち、ISV やスタートアップの顧客とともに、AWS を利用した柔軟性と復元力の高いアーキテクチャの設計に携わっています。趣味は映画鑑賞とオフロードバイク乗りです。