今回は、SQSのメッセージ数をCloudWatchにカスタムメトリクスとして登録し、そのカスタムメトリクスでAuto Scalingします。
仕様としては、一日一回の頻度でSQSに一気にメッセージを登録して、それを複数インスタンスで処理するものです。
メッセージ数が1以上になれば、10インスタンス立ち上げ、メッセージ数が0になったら、全てのインスタンスをターミネートするようにしています。
SQSのメッセージ数をCloudWatchにカスタムメトリクスとして登録する部分は、SQSのキューのサイズをCloudWatchに登録で、SQSのメッセージを処理するインスタンスは、SQSのキューのメッセージがなくなたらEC2インスタンスをシャットダウン下記で紹介しています。
(ちなみにここでは、シャットダウンはしないようにしています。)
そして、今回もいつも通りPHP(AWS SDK)で実現してみました。
はじめに、共通設定です。
▼ common.php
define("AWS_KEY" , "AAAAAAAA"); define("AWS_SECRET_KEY" , "SSSSSSSS"); define("CP_SQS_URL_CRAWL", "https://sqs.ap-northeast-1.amazonaws.com/000000000000/crawl"); define("CP_AS_NAME" , "crawl"); date_default_timezone_set("Asia/Tokyo");
次に、Auto Scalingのlaunch-configurationを作成します。
指定しているami-xxxxxxxxは、起動と同時にSQSのメッセージを処理し続けるAMIです。
▼ create-launch-configuration
require_once("/opt/cloudpack/bin/common.php"); require_once("/opt/aws/php/sdk.class.php"); $as = new AmazonAS(); $as->set_region(AmazonAS::REGION_APAC_NE1); $response = $as->create_launch_configuration( CP_AS_NAME, "ami-xxxxxxxx", "t1.micro", array( "KeyName" => "suz-lab_ap-northeast-1", "SecurityGroups" => array( "default", "crawl" ) ) ); var_dump($response->isOK());
そして、Auto Scalingのauto-scaling-groupを作成します。
インスタンス数のMINを0、MAXを10としています。
▼ create-auto-scaling-group
require_once("/opt/cloudpack/bin/common.php"); require_once("/opt/aws/php/sdk.class.php"); $as = new AmazonAS(); $as->set_region(AmazonAS::REGION_APAC_NE1); $response = $as->create_auto_scaling_group( CP_AS_NAME, CP_AS_NAME, 0, 10, array( "ap-northeast-1a", "ap-northeast-1b" ) ); var_dump($response->isOK());
PHP側の最後は、scaling-policyの設定です。
ここでは、scale-outのポリシー(10インスタンスになるように起動)とscale-inのポリシー(全て100%のインスタンスをターミネート)を作成しています。
▼put-scaling-policy
require_once("/opt/cloudpack/bin/common.php"); require_once("/opt/aws/php/sdk.class.php"); $as = new AmazonAS(); $as->set_region(AmazonAS::REGION_APAC_NE1); $response = $as->put_scaling_policy( CP_AS_NAME, "scale-out", 10, "ExactCapacity" ); var_dump($response->body->PutScalingPolicyResult->PolicyARN); $response = $as->put_scaling_policy( CP_AS_NAME, "scale-in", -100, "PercentChangeInCapacity" ); var_dump($response->body->PutScalingPolicyResult->PolicyARN);
上記で作成したポリシーを、scale-outはSQSのメッセージ数が1以上の場合、
scale-inはSQSのメッセージ数が0になった場合に実施されるようにするのですが、
この設定はCloudWatchの方で行います。
(下記のようにAWS Management Consoleで行うことも可能です。)
はじめに、CloudWatchのタブからアラームを作成します。
そして、対象のメトリクス名(queue_size)を指定して、統計情報の扱い方(Average)とチェックのインターバル(5分)を選択します。
次に、アラームに名前(has-messages)と条件(queue_sizeが1以上になったらアラーム)を指定します。
アラームの状態が変わったときのアクションを指定します。
今回は、状態がアラームになった時(queue_sizeが1以上)に、先程作成したAuto Scalingポリシーのscale-out(10インスタンスになるように起動)状態が、OKになると(queue_sizeが0)はscale-in(全て100%のインスタンスをターミネート)が、実施されるようにしています。
確認画面にて問題がなければ、AWS Management ConsoleのCloudWatchの設定は終了です。
実際、SQSにメッセージを追加すると、EC2インスタンスが10起動されます。
そしてメッセージの処理が進んで、SQSのメッセージ数が0になった時に、全てのEC2インスタンスがターミネートされることがわかります。
(下記はアラームの状態とSQSのメッセージ数の推移です)
CloudWatchがデフォルトでSQSのメッセージ数を取れれば、
CloudWatchにデータを投入する管理インスタンスがいらなくなるな