Mackerel + shimesabaでURL外形監視をSLOモニタリングにしてみた #mackerelio

ある日のこと、社内で「Mackerelで稼働率ってみれましたっけ?」とつぶらな瞳で質問されたため、ついカッとなって以下略
2022.12.19

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

TL;DR

はじめに

本記事は Mackerel Advent Calendar 2022 の 12/19 分の記事です。

Mackerel で SLO モニタリングを、ということで、以下の記事で紹介されていた shimesaba を実際に動かして見ました。

shimesaba とは

shimesabaとは、「面白法人カヤック」で知られる 株式会社カヤック さまにて制作・メンテナンスされている OSS アプリケーションです。
2021 年の 12 月(つまり 1 年前)に公開され、記事執筆時点でバージョン 1.2.1 が最新となっています。

shimesaba は「shimesaba is a tool for tracking SLO/ErrorBudget using Mackerel as an SLI measurement service.」ということで、Mackerel を SLI 計測サービスとして使用した SLO ・エラーバジェットの追跡ツールであるとされてます。

SLO モニタリングとは?

すごくすごく単純化して御説明すると、SLO(サービスレベル目標)とは「一定の期間(スライディングウィンドウ)内で、サービスが正常と定義できる状態だった割合の目標値」のことです。
例えば「過去 30 日間で、正常状態が 99.95%」などです。

実はこれを言うためには、先に「こうなっていたらサービスは正常だ」あるいは「こうなったらサービスに影響が出ている」という状態を定義しなくてはなりません(当然ですね)。例えば「300ms 以内に HTTP で 2xx 系のレスポンスが返ってくる状態」などです。
これを SLI(サービスレベル指標)と呼びます。つまり SLO は「一定の期間内で、SLI が成功していた割合の目標値」と言い換えることができるでしょう。

そしてエラーバジェット(エラー予算)とは、「現在 SLI が成功していた割合と SLO の差分」のことです。
SLI/SLO とエラーバジェットは「達成したから OK ・たくさん余っていたから OK」という守りの数字ではなく、「目標に余裕があるのなら、もっとサービスの改善など挑戦的なリリースを行ってよい」という攻めの数字です。この辺りのことは説明しだすと長くなるので割愛しますが、要は単なる監視アラートとしてではなく、SRE の文脈に沿って攻めのモニタリングツールとして Mackerel を使ってみよう! ということになります。

もしこの辺りのことをもっと知りたいという方は、例えば下記のドキュメントを参照してみて下さい。

本ツールである shimesaba は、Mackerel の監視ルールを SLI として SLO とエラーバジェットを計算、利用者の「攻めの監視」を助けてくれる OSS 神ツールとなっています。

やってみた

さて本題です。

shimesabaは Go で記述された、単独でも CLI として動作するツールですが、実運用上は定期的に自動実行される必要があります。
実際のところ AWS Lambda として動作させることが想定されていますので、実際にやってみました。

流れとしては、以下のようになります。

  1. Mackerel の準備
    • API キーの発行(Read/Write)
    • サービスメトリックの送信先「サービス」の用意
    • SLI とする監視ルールの用意
  2. 設定ファイル(YAML)の作成、ローカルで実験
  3. AWS Systems Manager ParameterStore への Mackerel API キーの保管
  4. AWS Lambda の作成
  5. AWS EventBridge による定期実行設定の追加

少々長くなりますが、順にみてまいりましょう。

1. Mackerel の準備

shimesaba が使う API キーを用意します。
default でも動作はしますが、用途が異なるので別途作成する方がよさそうです。APIキー設定 タブから作成して、わかりやすく用途をメモしておくと良いでしょう。

shimesaba は各メトリックを サービスメトリック として送信します。そのための「サービス」も用意しておきましょう。

既存のものでもよいですし、SLO モニタリングのために専用のサービスを用意しても良いです。
今回は「SLO」という名前のサービスを用意しました。

最後に監視ルールを用意します。

shimesaba は こちらの記事 にもあるように「Mackerel のアラートに基づいて SLO を評価」する実装となっています。つまり「SLI とする監視ルールにて、期間内にアラートが上がった回数 (割合)」が SLO 算出の元となります。

shimesaba は複数の監視ルールを指定することができますが、今回は URL外形監視 の監視ロール「SLO availability example.com」を対象としました。
こちらの監視ルールにて、レスポンスタイム 450ms より遅い場合にアラートを発呼するように設定しました。つまり、

SLI = 特定 URL へのレスポンス(4xx ・ 5xx 以外)が 450ms を下回ること

ということになります。

2. 設定ファイル(YAML)の作成、ローカルで実験

以下のドキュメントを参考に設定ファイルを作成します。

SLI としては上述した監視ルールを使い、SLO の設定として「計測ウィンドウ (rolling_period) : 28 日」「計測インターバル (calculate_interval): 10 分」「エラーバジェット (error_budget_size): 0.1%」としました。

メトリックの送信先(destination)サービスの名前(service_name)は上述の通り SLO、送信メトリクスのプレフィクスは slo_externalとしました。

required_version: ">=1.1.0"

destination:
  service_name: SLO
  metric_prefix: slo_external

  metrics:
    error_budget_remaining_percentage:
      enabled: true
    uptime:
      enabled: true
    failure_time:
      enabled: true

rolling_period: 28d
calculate_interval: 10m
error_budget_size: 0.1%

slo:
  - id: availability
    alert_based_sli:
      - monitor_name_prefix: "SLO availability"
      - monitor_name_suffix: "example.com"
        monitor_type: "external"

これを任意の名前で保存しておきます。今回はconfig.yamlという名前にしました。

ちなみに「計測インターバル: 10 分」は少し短めですが、今回は試験的なものなのでこの時間にしています。同じ時間を後述の EventBridge Scheduler の実行間隔に設定するようにしましょう。

念のため、設定ファイルの内容が正しいか確認します。GitHub 上から最新のshimesabaバイナリをダウンロードして試してみました。

記事執筆時点では v1.2.1 が最新です。
手元の mac0S x86 マシンで実行するため shimesaba_1.2.1_darwin_amd64.tar.gz をダウンロードして解凍、ターミナル上で下記コマンドラインを叩いてみました。

MACKEREL_APIKEY='****'   # 1. で作成した API キーを指定
SHIMESABA_CONFIG=config.yaml # 上で作成したファイルのパスを指定
./shimesaba \
    -config "${SHIMESABA_CONFIG}" \
    -mackerel-apikey "${MACKEREL_APIKEY}" \
    --dry-run \
    --dump-reports

試しに --dry-run を外して実行すると、正常にサービスメトリックが送信されるか確認出来るため、最初は念には念を入れて試しておくといいと思います。

3. AWS Systems Manager ParameterStore への Mackerel API キーの保管

それでは shimesaba を AWS Lambda として動作させる準備に入ります。
先ほどは API キーを環境変数に格納しましたが、Lambda として動作する shimesaba は AWS Systems Manager のパラメータストアからキー文字列を取得出来るため、そのようにしましょう。

API キー文字列を AWS アカウント上に格納する方法ですが、マネジメントコンソールからぽちぽちやってもいいのですが、せっかくなので AWS CLI を使って実施してみます。 *1

適切な AWS プロファイルが指定されている前提で以下のコマンドラインを実行することで、「/shimesaba/MACKEREL_APIKEY」という名前のパラメータストア(暗号化ストア)が作成されます。
なお環境変数 MACKEREL_APIKEY は上で設定したままの状態というつもりです。AWS リージョンは ap-northeast-1 が指定されているとして以下をお読み下さい。

aws ssm put-parameter \
    --name '/shimesaba/MACKEREL_APIKEY' \
    --type "SecureString" \
    --value "${MACKEREL_APIKEY}"

4. AWS Lambda の作成

いよいよ Lambda 関数を作成しますがその前に、Lambda が動作するための IAM ロールを作成します。

aws iam create-role \
    --role-name lambda-shimesaba-poc \
    --assume-role-policy-document '{"Version":"2012-10-17","Statement":[{"Effect":"Allow","Principal":{"Service":"lambda.amazonaws.com"},"Action":"sts:AssumeRole"}]}'

aws iam attach-role-policy \
    --role-name lambda-shimesaba-poc \
    --policy-arn arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole

aws iam attach-role-policy \
    --role-name lambda-shimesaba-poc \
    --policy-arn arn:aws:iam::aws:policy/AmazonSSMReadOnlyAccess

AWSLambdaBasicExecutionRoleAmazonSSMReadOnlyAccessの権限をもつロール「lambda-shimesaba-poc」が作成されたと思いますのでご確認下さい。

続いて、Lambda 関数にするための Zip ファイルを作成します。
Zip ファイルの中身は、Lambda 用の shimesaba バイナリと先ほど作成した config.yaml のふたつだけ、ディレクトリなども作らない状態にします。

今回 Lambda は Graviton アーキテクチャで動作させるので *2shimesabaバイナリは 前述の GitHub から shimesaba_1.2.1_linux_arm64.tar.gz をダウンロードしてください。

tarball を展開したら、バイナリをリネームして bootstrap とします。こうすることで直接 Lambda 関数の bootstrap として動作させることが出来るとのこと。重ね重ねすばらしい設計ですね。。

mv -iv shimesaba bootstrap

そして前述したとおり、ディレクトリ構造も持たせずフラットな状態で Zip 化してください。lambda.zipというファイルが作成されます。

zip -r9 - bootstrap config.yaml > lambda.zip

わざわざリダイレクトさせて Zip ファイルを作っているのは、べき等性を担保するための筆者の手癖なので気にしないで下さいw

それではいよいよ、作成した IAM ロールと Zip ファイルを使って AWS Lambda 関数 shimesaba-poc を作成します。
IAM ロールの ARN を作成するために AWS アカウント ID を sts get-caller-identity API で取得しています。

AWS_ACCOUNT_ID=$(aws sts get-caller-identity --query Account --output text)

aws lambda create-function \
    --function-name shimesaba-poc \
    --zip-file fileb://lambda.zip \
    --handler shimesaba \
    --environment '{"Variables":{"SSMWRAP_PATHS":"/shimesaba/","SHIMESABA_CONFIG":"config.yaml"}}' \
    --runtime provided.al2 \
    --architectures arm64 \
    --timeout 10 \
    --role arn:aws:iam::${AWS_ACCOUNT_ID}:role/lambda-shimesaba-poc

ちなみにタイムアウト値ですが、最初は 3 秒前後で実行できていたものの、しばらく実行させていくなかで 5 秒以上かかるケースがみられたためこの数値にしています。

作成した Lambda 関数は、マネジメントコンソール上から「テスト」が普通に実行できるため、実行して試してみましょう。入力は何でも構わないため、テストイベントを作成する必要はありません。

テストが成功したら、Mackerel 上にもサービスメトリックが送信されていると思います(テストなのに!)。

そこまでいけば動作としては成功ですが、忘れないうちに CloudWatch Logs の保存期間を設定しておきましょう。今回は PoC なので、短めの 3 日で設定しました。

aws logs put-retention-policy \
    --log-group-name "/aws/lambda/shimesaba-poc" \
    --retention-in-days 3

5. AWS EventBridge による定期実行設定の追加

さて、ていよく動いた場合は、そのまま EventBridge Scheduler で定期実行させるようにしましょう。
上述したように config.yaml 内の「計測インターバル (calculate_interval): 10 分」と揃えます。

aws events put-rule \
    --name shimesaba-scheduled-rule \
    --schedule-expression 'rate(10 minutes)'

イベントが作成できたら、これを Lambda 関数 shimesaba-poc にひも付けます。

aws lambda add-permission \
    --function-name shimesaba-poc \
    --statement-id shimesaba-scheduled-event \
    --action 'lambda:InvokeFunction' \
    --principal events.amazonaws.com \
    --source-arn arn:aws:events:ap-northeast-1:${AWS_ACCOUNT_ID}:rule/shimesaba-scheduled-rule

aws events put-targets \
    --rule shimesaba-scheduled-rule \
    --targets "Id"="1","Arn"="arn:aws:lambda:ap-northeast-1:${AWS_ACCOUNT_ID}:function:shimesaba-poc"

これで、10 分おきにサービスメトリックが送信されてきたら成功です!

所感とまとめ

社内でもらった質問「Mackerel で稼働率ってみれましたっけ?」に端を発して、ついカッとなった結果 Mackerel の URL 外形監視を SLO モニタリングにしてみました。

前述した こちらのブログ にあるように、ALB のステータスコードカウントのように boolean 値がとれるメトリクスであれば、Mackerel 単体でも「式による監視」機能で稼働率計算が可能です。
しかしながらもう少し複雑な SLI を設定したい・ SLO モニタリングを実現したい場合には、今回のように外部ツールを利用する必要がでてきます。

そういう意味では shimesaba はとても有益なツールです。
設定ファイルがバイナリと共に抱き込まれてしまっていますし、shimesaba 自体も進化している最中であるため、実運用上は GitOps のような仕組みを整えた方が使い勝手が良くなると思いますが、そもそも設定ファイル上のパラメータはあまり変更するものでもない(そのように設計されている)ので、大変なのは最初に何度か試行するときくらいかもしれません。

今回 AWS Lambda として動作させる部分について、既存ドキュメントに記載がなかった部分をうめてみました。今回は CLI でゴリゴリデプロイしてみましたが、CFn や AWS CDK をつかってみるとか、また公式には lambroll を使ってデプロイする方法が載ってますので、そちらを使うと楽だったかもしれません。

最後に、このような有益な OSS ツールを公開して下さっているカヤックさまに感謝しつつ、しめ鯖たべたくなってきたのでまとめとしたいと思います。

脚注

  1. 今回は時間と体力がありませんでしたが、きっと有志がCFnやCDKにしてくれると信じて...!
  2. 何故?と問われたら、趣味です、と答えるしかありません