本日も乙

ただの自己満足な備忘録。

Amazon LambdaでCloudWatchのメトリクスをMackerelに監視させる

[toc]

最近、監視ツール(サービス)をMackerelに移行しました。GUIが見やすいことと監視追加・停止が容易なこと、そしてあらゆる操作をAPIで実行できることが気に入っています。最近リリースされたAWSインテグレーション機能によってEC2、RDS、ELB、ElastiCacheのメトリクス取得と監視がとても楽になりました。 しかし、Redshift、DynamoDB、CloudSearchを使っているのですが、こちらの製品はまだ対応していません。また、RDS(Aurora)の場合、Aurora特有のメトリクスが取得することができません。したがって、メトリクス取得及び監視をMackerelで行うには一工夫する必要があります。

具体的には、定期的(1分間隔)にCloudWatchからAPIでメトリクスを取得して、MackerelにAPIでサービスメトリクスとして登録します。やることは簡単ですが、問題はどのサーバから実行するかです。EC2などサーバで実行する場合、スクリプトをバッチ実行すると思いますがバッチが落ちていないかを監視しなければなりません。それだけのためにEC2インスタンスを作るのはお金が勿体無いので、大抵の場合本番稼働させているバッチサーバに同居させてもらうことになると思いますが、設置した後にバッチの存在を忘れてしまうとどのサーバで実行しているか分からなくなり、思わぬトラブルになりかねません。

そんなときはAmazon Lambdaを使うと大変便利です。Lambdaを定期的に実行させることで同じことが実現できます。Lambdaなら実行する度にインスタンスが起動されるため、こちら側から監視する必要がありません。エラーが出た場合はAmazon SNSと連携してメールやSlackに通知させれば異常終了してもすぐに気づくことができます。 今回は、Amazon Lambdaを利用してMackerelにサービスメトリクス及びホストメトリクスを登録させてみます。

Lambda Functionの登録

こんな感じのスクリプトをLambda Functionに登録します。 ENCRYPTED_API_KEYの箇所はKMSで暗号化したキーを入力してください。 KMSを使った暗号化はこちらの記事が参考になりました。

KMSで認証情報を暗号化しLambda実行時に復号化する | Developers.IO

CloudWatchのメトリクスが取得できる権限が必要になるため、以下のようなIAM Rolesを設定してLambda Functionに紐付けてください。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "Stmtxxxxxxxxxx000",
            "Effect": "Allow",
            "Action": [
                "logs:CreateLogGroup",
                "logs:CreateLogStream",
                "logs:PutLogEvents"
            ],
            "Resource": "arn:aws:logs:*:*:*"
        },
        {
            "Sid": "Stmtxxxxxxxxxx000",
            "Effect": "Allow",
            "Action": [
                "cloudwatch:GetMetricStatistics",
                "cloudwatch:DescribeAlarms"
            ],
            "Resource": [
                "*"
            ]
        }
    ]
}

定期実行の設定(CloudWatch Events)

作成したLambda Functionを定期実行していきます。

CloudWatchの「Rules」をクリックします。

rules_1.png

「Create rule」をクリックします。

rules_2.png

各種設定をしていきます。

rules_3.png

Event selectorでは、タイプはScheduleFixed rate of1 Minutesにします。 Targetsでは、先程作成したLambda Functionを指定し、Configure inputConstant (JSON Text)にしてLambda FunctionにJSONで投げます。 JSONパラメータは以下のようにします。service_nameはMackerelで登録しているサービス名を入れてください。 JSONの中身はCloudwatch、Mackerelそれぞれで取得したいメトリクス、登録したいメトリクスを指定します。

Redshiftの設定例

Aurora Clusterの設定例

最後にこのRulesの名前と説明文を記入して「Create rule」をクリックすると完了です。

rules_4.png

しばらくすると、Mackerelにサービスメトリクスが登録されてグラフ表示できるはずです。 しばらくしてもグラフが表示されない場合は、CloudWatch Logsを見て、Lambda Functionのエラーを確認してください。

ホストメトリクスとしてMackerelにPOSTする

上の方法で、Redshift、DynamoDBなどMackerelにホスト登録されていないものでも監視できるようになりました。 次は、RDS(Aurora)のDBインスタンスのようにホストとして登録されているものの、足りないメトリクスを追加したい場合です。 やり方は先程と同じようにLambda FunctionとCloudWatch Logsを設定するだけですが、Lambda Functionに登録するスクリプトは以下のようにします。

そして、CloudWatch LogsのConstant (JSON Text)に入力するパラメータ(サンプル)は以下の通りです。

<MACKEREL_HOST_ID>はMackerelのホストID、<AURORA_INSTANCE>AWS AuroraのDBインスタンス名に置き換えてください。

登録してしばらくしてから、https://mackerel.io/orgs/Organization_name/hosts/MACKEREL_HOST_ID を見るとメトリクスが追加されているかと思います。 しばらくしてもグラフが表示されない場合は、CloudWatch Logsを見て、Lambda Functionのエラーを確認してください。

最後に

Amazon LambdaとCloudWatch Eventsを組み合わせてMackerelにサービスメトリクス、ホストメトリクスを投げる方法を紹介しました。 一昔なら単純なスクリプトでもサーバを容易してcronなどで定期実行しなければならなかったのですが、AWSのマネージドサービスを活用するとサーバを自前で用意する必要がなくなるのでとても楽ですね。