SLI/SLO運用の実践 shimesabaによる指標モニタリング

カヤックSREの池田です。
先月は、カヤックのプロダクトの一つ『Tonamel』で導入したエラーバジェット算出ツール『shimesaba』の話をしました。

techblog.kayac.com github.com

今回は、実際にどのようにSLI/SLOを運用しているのか?という内容をshimesabaを使った設定例を交えつつ話します。 SLI/SLOの運用にお悩みの方の助けになれば幸いです。

最初のSLI/SLOはどう決定したのか?

SLI/SLOの運用を始めるにあたって、多くの人が悩むのは以下の2つだと思います。

  • 一体何をSLIとすれば良いのか?
  • 最初のSLOはどのくらいにしたら良いのか?

つまりは、最初の1歩をどうしたら良いか?と言う話ですが、こちらに関しては2つ参考になるものがあります。

  1. 『SLO決定のためのArt of SLO』 https://sre-next.dev/2022/schedule/#jp49 *1 を参考にする。
  2. サイトリライアビリティワークブックを参考にする。

先月の記事で紹介した、『shimesaba』を導入したプロダクト『Tonamel』では、2つ目のサイトリライアビリティワークブックを参考にしました。

より具体的には、こちらの書籍の2章全体、特に2.2.2と2.3.3を参考にしました。 最初のSLIについては、書籍には「プロダクトのメインになるアプリケーションのタイプによって異なる "一般的なもの" を採用するのが手堅い」とありました。以下はその例です。

  • リクエスト駆動: いわゆる普通のHTTPサービスなど
    • 可用性: レスポンスに成功したリクエストの比率
    • レイテンシー: 閾値よりも高速に処理されたリクエストの比率
    • 品質: レジリエンスやグレイスフルデグレーション等を備えてる場合、品質低下の起きてない正常なリクエストの比率
  • パイプライン: バッチプロセスや機械学習パイプライン等
    • 新鮮さ: 時間の閾値よりも最近に更新されたデータの比率
    • 正確性: 正しい出力につながった入力データの比率
    • カバレッジ: 正常に処理された有効なデータの割合
  • ストレージ: Amazon S3やGoogle Cloud Storageのようなサービスなど
    • 耐久性: 期待するデータのうちロストしてない比率

Tonamelの場合は、アプリケーションがHTTPサービスの形をとっているのでリクエスト駆動となります。
グレイスフルデグレーション等は特に行っていないので以下の2種類のSLIからはじめました。

  • 可用性: Application Load Balancer(ALB)のTarget 5xx の比率
  • レイテンシー: Application Load Balancer(ALB)のTarget Response time (p95,p90,平均)

SLOに関しては、直近のエラーバジェットを計算してみるのが手っ取り早かったです。 現在進行系でエラーバジェットが減り続けるようなSLOの場合は最初の一歩としては厳しすぎましすし、 逆に、エラーバジェットの残りが100%で張り付く場合は、最初の一歩としては緩すぎます。
現時点でのエラーバジェットの残りが80~95%くらいで落ち着くSLOを設定しました。

具体的には、図のように、エラーバジェットが減り続けるわけでもなく、かといって1%も減ってない状態ではないSLOを設定しました。 皆様も同様の調整をすれば、最初のSLI/SLOをそれほど悩まずに決定できると思います。

shimesabaを使う場合

shimesabaではMackerelで発報されたアラートを元にエラーバジェットを計算するので、Mackerel側に以下のようなアラートを設定します。

  • 可用性のSLOとして
    • 式監視: ALB Target 5xx / (ALB target 5xx + ALB target 2xx) > 0.1%
  • レイテンシーのSLOとして
    • ホストメトリック監視: ALB Target response time p90 > 300ms
    • ホストメトリック監視: ALB Target response time p99 > 500ms
    • ホストメトリック監視: ALB Target average response time > 200ms

この監視ルールをMackerelのCLIツールmkrで出力したものが以下となります。

$ mkr monitors | jq '.[] | select(.name | startswith("SLO"))'
{
  "id": "<monitor_id>",
  "name": "SLO availability request_error_rate > 0.1%",
  "type": "expression",
  "expression": "alias(scale(divide(\nhost(\n  <host_id>,\n  custom.alb.httpcode_count_per_group.<target_id>.target_5xx\n),\n sum(group(host(\n  <host_id>,\n  custom.alb.httpcode_count_per_group.<target_id>.target_2xx\n),host(\n  <host_id>,\n  custom.alb.httpcode_count_per_group.<target_id>.target_5xx\n))\n\n)\n),100), 'request_success_rate')",
  "operator": ">",
  "warning": 0.1,
  "critical": null
}
{
  "id": "<monitor_id>",
  "name": "SLO latency ALB target response time p90 > 300ms",
  "type": "host",
  "metric": "custom.alb.response_per_group.<target_id>.time_p90",
  "operator": ">",
  "warning": 0.3,
  "critical": null,
  "duration": 1,
  "maxCheckAttempts": 1,
  "scopes": [
    "prod"
  ]
}
{
  "id": "<monitor_id>",
  "name": "SLO latency ALB target response time p99 > 500ms",
  "type": "host",
  "metric": "custom.alb.response_per_group.<target_id>.time_p99",
  "operator": ">",
  "warning": 0.5,
  "critical": null,
  "duration": 1,
  "maxCheckAttempts": 1,
  "scopes": [
    "prod"
  ]
}
{
  "id": "<monitor_id>",
  "name": "SLO latency target response time average > 200ms",
  "type": "host",
  "metric": "custom.alb.response_per_group.<target_id>.time",
  "operator": ">",
  "warning": 0.2,
  "critical": null,
  "duration": 1,
  "maxCheckAttempts": 1,
  "scopes": [
    "prod"
  ]
}

監視設定の最初の閾値は、かなり野心的で厳しい基準にしておくところがポイントです。 上記の監視ルールを使った最初のshimesabaの設定としては以下のようになります。

required_version: ">=1.2.0"

destination:
  service_name:  'prod'
rolling_period: 1d       # 運用を開始したら 28dくらいの長めのものに増やす
calculate_interval: 1m   
error_budget_size: 0.5% 

slo:
  - id: availability
    alert_based_sli:
      - monitor_name_prefix: "SLO availability"

  - id: latency
    alert_based_sli:
      - monitor_name_prefix: "SLO latency"

最初の設定では rollikng_period1d くらいの短めにしておきます。 最初はエラーバジェットがすぐに枯渇すると思います。
しかし、監視ルール側の閾値を徐々に緩めていけば、エラーバジェットが減り続けるわけでもなく、かといって1%も減ってない状態ではないSLOにたどり着くと思います。 そして、SLOが決まったら長めのrolling_periodをとって、最初の一歩を踏み出すと良いでしょう。

SLOの継続的な改善

最初のSLI/SLOを設定できたので、運用が始まりました。 Tonamelでは週次の定例があり、その定例のタイミングでSLOに関する見直しをすることがありました。 最初のうちは、ほぼ毎週見直しをしました。 SLOの見直しには、サイトの信頼性に関わる定性・定量とエラーバジェットの関係があるのかを考えました。

例えば、以下のようなものとエラーバジェットが関係しているのか?ということに注目しました。

  • お問い合わせ件数
  • 『つながらない』『見えれない』などの反応の多さ (可用性のエラーバジェット)
  • 『重い』『遅い』などの反応の多さ (レイテンシーのエラーバジェット)

プロダクトにとって『サイトの信頼性』に関係する現象というのは、様々でこれを見ておけばいいというものがあるとは思えません。
自分たちのプロダクトでは、何を重要視していてどういう事が起きたら、エラーバジェットが損失するというのが良いのか?ということを考えていく必要はあります。Tonamelの場合は、カスタマーサポートの担当者が週に1度、お問い合わせの件数をその内訳も含めて共有する機会があるので、エラーバジェットの増減とお問い合わせの件数についてを注視していました。
他にも開発チームのエンジニアに、なにか問題が起こっていないか?というヒアリングも行なっていました。

その経験を踏まえて、以下の表のようにして見直していくと、ある程度野心的なSLOに収束していくと思います。

エラーバジェット サイトの信頼性に対する評価 アクション
損失が20%以下で安定 特に問題はなさそう (そのまま様子見)
損失が20%以下で安定 なにか問題がありそう SLOを厳しくしてみる
減り続けてる 特に問題なさそう SLOを緩めてみる
減り続けてる なにか問題がありそう (早めにプロダクトを改善しよう!)
損失が20%より多くて安定 特に問題なさそう SLOを緩めてみても良いかもしれない
損失が20%より多くて安定 なにか問題がありそう (注意深く様子見)

特にSLI/SLOの運用の開始初期では、非エンジニアのチームメンバーやユーザーにサイトの信頼性に関する情報を収集して、積極的にSLOを厳しくしたり緩めたりするトライアンドエラーが大事だと感じました。
最初から完璧なSLI/SLOを求めるのではなく、徐々に良いものにしていくという運用をすることで、導入もしやすくなると思います。

shimesabaをお使いの場合は、この辺のSLOを緩めたり厳しくしたりすることは、監視ルールの閾値を変更するだけで実現できるので、柔軟に変動させることができると思います。

プロダクト特有のSLOの設定

最初の1歩では、一般的なSLI/SLOだけを設定して開始しました。 SLI/SLOの運用を続けていくと、場合によっては最初に設定したもの以外のプロダクト特有のSLI/SLOを設定する必要性も出てくる可能性はあります。
Tonamelの場合は、SLI/SLOの運用を開始したときは『可用性』と『レイテンシー』のエラーバジェットのみでしたが、途中で『品質』という名の新しいSLI/SLOを設定しました。
このSLI/SLOの設定の背景には、アプリケーションがGraphQLという技術を採用していることが関係しています。

GraphQLという技術ではエラーの取り扱い方にある一定の文化があり、『HTTPリクエストに対するレスポンスはHTTP 200 Okで正常ではあるが、レスポンスの内容としてはエラーである。』という状況があります 具体的には、HTTP 200 Okで以下のようなレスポンスボディを返す場合があるということです。

{
  "errors":[
    {
      "message": "error message.",
      "extensions":{
        "code":"INTERNAL_SERVER_ERROR"
      }
    }
  ]
}

このようなレスポンスを通称GraphQL Errorと呼んでいますが、このGraphQL Errorが発生すると、フロントエンド側でエラーハンドリングをすることになります。 エラーハンドリングした結果、対応できない場合はユーザーに対してエラーメッセージを表示することになります。 ユーザーに見える形でのエラーメッセージが頻出すると、それはサイトの信頼性低下に繋がってしまいます。 ですので、このGraphQL Errorの発生率をSLI/SLOとして追跡することが重要だということがわかりました。 しかしながら、GraphQL ErrorはHTTPリクエストへのレスポンスとしては正常に返せているので、最初に設定した『可用性』というALBのTarget 5xx の比率をSLIとして用いたSLOには反映されません。 そこで別途、Kinesis Data Streamで収集しているアクセスログからGraphQL Errorの発生件数とGraphQLリクエスト件数を集計し、サービスメトリックとしてを投稿しました。 そして、GraphQL Errorの発生件数/GraphQLリクエスト件数 = GraphQL Error rateをSLIとした『品質』と言う名前のSLOを設定しました。

より具体的には、以下のような式監視を追加し、shimesabaの設定を変更しました。

監視ルール

$ mkr monitors | jq '.[] | select(.name | startswith("SLO quality"))'
{
  "id": "<monitor_id>",
  "name": "SLO quality graphql_error_rate > 0.5",
  "type": "expression",
  "expression": "alias(\nscale(divide(\n  service(\n prod,\n \"graphql.error.request_count\"\n)\n,service(\n prod,\n \"graphql.requests.request_count\"\n)),100),'graphql_error_rate')",
  "operator": ">",
  "warning": 0.5,
  "critical": null
}

shimesabaの設定

required_version: ">=1.2.0"

destination:
  service_name:  'prod'
rolling_period: 28d      
calculate_interval: 30m   
error_budget_size: 200m   

slo:
  - id: availability
    alert_based_sli:
      - monitor_name_prefix: "SLO availability"

  - id: latency
    alert_based_sli:
      - monitor_name_prefix: "SLO latency"

  - id: quality
    alert_based_sli:
      - monitor_name_prefix: "SLO quality"

以上の設定で、1分間のGraphQL Errorの比率が0.5%を超えた場合にエラーバジェットが削れるSLOが設定できました。

このように、アプリケーションが採用している技術やプロダクトの性質由来で、追加のSLI/SLOを設定することや最初のSLI/SLOの定義を変えることはありえます。

まとめ

今回は、SLI/SLOを具体的にどう設定するのか、shimesabaを用いながらどう運用していくのかの話をしました。 これからSLI/SLOの運用をこれから開始する場合は、以下の点を踏まえておくと良いでしょう。

  • 何をSLIとするか?: 最初は、一般的なもので良い(リクエスト駆動のアプリケーションの場合は『可用性』と『レイテンシー』)
  • 最初のSLOはどのくらいにするか?: 試しにエラーバジェットを計算して80%~95%になるくらい。
  • 定期的に見直しをして、積極的にSLOを厳しくしたり緩めたりするのは大事。
  • 場合によっては、プロダクト特有の新たなSLI/SLOを設定することもある。

実際にSLI/SLOの運用をしてみたところ、個人的にはエラーバジェットを常に20%くらい使った状態で安定し続けるくらいのSLOが良いと思っています。 エラーバジェットは、文字どおりエラーに関する予算ですので、使いすぎても、使わなさすぎてもあまり良くないと感じています。 以上、皆様のSLI/SLOの運用にお役に立てば幸いです。

カヤックでは、SLO運用に興味があるエンジニアも募集しています

*1:2022/5/15に開催されてた『SRE Next 2022』でグーグル合同会社による素晴らしい発表

SLOの運用のために OSS shimesabaの導入

カヤックSREの池田です。今回は、カヤックのプロダクトの一つ『Tonamel』で導入したエラーバジェット算出ツール shimesabaの話をします。

shimesabaとは?

github.com

shimesabaは監視サービスであるMackerelを用いて、エラーバジェットを計算しサービスメトリックとして投稿することでSLI/SLOの運用を助けるツールです。 このツールを用いることで、以下のようなグラフが得られます。

  • この図の上部は、エラーバジェットの使用率=信頼性の損失率の推移を表すグラフになっています。
  • この図の下部は、エラーバジェットをいつ?どのくらい?損失したのかを表すグラフになっています。

一言で、エラーバジェットと言ってもいくつかの計算方法が存在します。
今のところshimesabaでは、Rolling windowのコンプライアンス期間で、Windows-based SLOによる評価方法 を採用した場合のエラーバジェットを計算します。
Calendar-based のコンプライアンス期間や Request-based SLO による評価方法を採用したエラーバジェットが必要な場合は、v1時点でのshimesabaは未対応ですので他の方法を検討することになると思います。

shimesabaを導入した効果

shimesabaを導入する以前のTonamelでは、SLOの運用について以下の問題がありました。

  • Redshiftを使ってアクセスログを集計しSLIを算出していたが、SLI集計部のメンテナンスコストが高かった。
  • SLOの判定を行っていたが、エラーバジェットの計算までは行っていなかった。 (SLI集計用のSQLのメンテナンスコストが高かったため、Redshiftでエラーバジェットを計算するまで手を出せてなかった)
  • SLI/SLO関係がredash上に存在したため、Mackerelメトリックとの比較が困難であった。
  • サーバーに起こった一時的なエラーやアラートに過敏に反応していた。

これらの問題を解決するためにshimesabaを開発・導入しました。 SLIの集計はMackerelに、エラーバジェットの計算はshimesabaに任せることで、複雑なSQLのメンテナンスが必要なくなりました。 さらに、計算されたエラーバジェットをMackerelのサービスメトリックとして投稿することで、他のアラートやメトリックとの比較も容易になりました。

また、エラーバジェットの導入によって、SLO違反が発生しサーバーに起こった一時的なエラーやアラート起きても、過敏に反応することなく心の余裕を持つことができるようになりました。 週に一度の定例会では、時折以下のような議論が生まれるようになりました。

  • 『エラーバジェットが最近損失していないが、ユーザー影響のある問題は起きてないか?起きてるならSLOを厳しくしたほうが良いのでは?』
  • 『エラーバジェットをすごい勢いで消費しているが、実際にユーザー影響あるの?ないならSLOが過敏すぎるんじゃないの?』

このようにSLOの品質について、エラーバジェットを用いてユーザーファーストな観点での振り返りができるようになりました。

shimesabaの変遷

このような効果があったshimesabaですが、shimesaba自体は、Mackerel Advent Calendar 2021の7日目の記事でも紹介していました。(当時はv0.5.0)

https://techblog.kayac.com/introducing-shimesaba-for-slo-error-budgets-with-mackerel

この記事の2021年12月頃からTonamelにて試験運用を重ねていました。その結果、2022年4月19日にv1.0.0を迎えて正式運用状態に入りました。 v0時代は Mackerel APIからメトリックを取得して、独自実装の式を用いてSLOの評価を行っていましたが、カヤックのSREチームメンバーやMackerelの皆様にアドバイスを頂き、v1からは大きく変わりました。 詳しくはあとに記述しますが、v1からはMackerelのアラートに基づいてSLOを評価し、1度設置したshimesabaの設定ファイルを極力変更しなくても良くなるようにしました。 そのため、config.yamlの書き方がv0時代から大きく変わっていますので、今回の記事で改めて詳しく導入も含めて説明しようと思います。 現在では、他のプロダクトへより広げていきたいと考えているフェーズになっています。

以下、shimesabaの導入について話します。

shimesaba 導入

今回は、AWS Lambda 上で動かす想定で話します。もちろんCLIツールとしても動きますので、動かし方はいくつか自由度があります。 shimesabaを動かすためには3つの物が必要になります。

  • Mackerel API Key (Writeが可能なもの)
  • SLO評価用の監視ルール
  • config.yaml (設定ファイル)

1. Mackerel API Keyの準備

shimesabaはMackerel APIにアクセスして、エラーバジェットの計算に必要な情報や、サービスメトリックの投稿を行います。 Mackerel API KeyはダッシュボードのAPIキーのタブ から発行できます。

shimesabaは、サービスメトリックの投稿を行いますので、Writeの権限がついているMackerel API Keyが必要になります。

2. SLO評価用の監視ルールの準備

冒頭で、shimesabaは Rolling windowのコンプライアンス期間で、Windows-based SLOによる評価方法 を採用していると述べました。 Windows-based SLOでは、ある時間枠に対して、SLOでもって良好であるのかどうかを判断し、コンプライアンス期間中の良好である時間枠の比率をもとにエラーバジェットを計算します。 shimesabaでは、Mackerelのメトリックにおける時間の最小単位である1分を計算に用いる時間枠として固定しています。 良好であるか?という判断は、設定にて指定された監視ルールのアラートが発生していなければ、良好であると判定します。

よって、shimesabaを動かすためには、SLO評価用の監視ルールを作成する必要があります。

例えば、HTTPリクエストの5xxレート*1をもとにして、可用性に関するSLO評価用の監視ルールを作りたい場合は以下のような式監視を作ることになります。

もちろん、可用性のSLOの定義を外形監視のルールにしても問題ありません。 つまり、具体的なSLOはMackerelの監視ルールの形で表現され、いつSLO違反が起きたかは対象のアラートを追うことで振り返ることができます。 すでにSLOとして活用している監視ルールがある場合は、そちらを用いることも可能だと思います。

また、別途運用しているアラートが存在し、そのアラートの通知と混ざることが煩わしい場合は以下のようにSLO関連のものだけ集めた通知グループを用意すると良いかもしれません。

こうすることで、ほかの通知チャンネルにSLO関連のアラートが送られなくなります。

3. 設定ファイルの準備

ここまで用意したら、設定ファイルを用意します。 yaml形式の設定ファイルの設定例として、以下の例を示します。

required_version: ">=1.1.0" 

destination:
  service_name: prod          # エラーバジェット等のサービスメトリックを投稿する先
  metric_prefix: api          # 投稿されるErrorBudget等のサービスメトリックのプレフィックス (省略した場合は shimesabaになる)
  # 追加のサービスメトリックの有効化設定: いらないサービスメトリックスは、ここでON/OFF可能
  metrics:                    
    error_budget_remaining_percentage:
      enabled: true
    uptime:
      enabled: true  # v1.2.0からデフォルトがOFF
    failure_time:
      enabled: true  # v1.2.0からデフォルトがOFF

rolling_period: 28d         # コンプライアンス期間: ローリングウィンドウのサイズ (28d とかくと 28日, 52h とかくと52時間) 
calculate_interval: 30m     # 計算の期間 = メトリックの投稿間隔  (1hと指定すると最終的に投稿されるメトリックは1時間毎,30m と書くと30分毎, 最低1分)

error_budget_size: 0.1%     # エラーバジェットのサイズ いくつかの指定方法がある。
                            #   %で指定した場合は、rolling_periodの長さに対して、何%の時間をエラーバジェットとして取るのか? (分で切り捨て)
                            #   1h とか 40m とか指定した場合は、その指定した時間の分だけエラーバジェットのサイズをとる。

slo:
  # 可用性に関するSLOを定義する例: 『SLO availability』というprefixを持つアラート もしくは、『api.example.com"』というsuffixを持つ外形監視のアラートのどれかが発生した場合は、SLO違反とみなします。
  - id: availability
    alert_based_sli:
      - monitor_name_prefix: "SLO availability"
      - monitor_name_suffix: "api.example.com"
        monitor_type: "external" 
  # レイテンシーに関するSLOを定義する例: 『SLO latency』というprefixを持つホストメトリック監視のアラートが発生した場合はSLO違反とみなします。 
  - id: latency
    alert_based_sli:
      - monitor_name_prefix: "SLO latency"
        monitor_type: "host"

rolling_period は特に規定がなければ SRE本*2のサンプルに載っている4weeks=28daysを指定しておくのが、最初は短くも長くもなくちょうどよい感じになります。
error_budget_size はエラーバジェットの損失がない場合の最大値ですが、rolling_periodの値に対して 0.1% くらいがちょうどと感じています。 もちろん、厳しく取り扱いたい場合は 100m (100分) などの値を指定して、エラーバジェットを低くしておくのもありだと思います。
calculate_interval は 投稿されるサービスメトリックのtickになりますので、shimesabaの起動間隔と同じにしておくことをおすすめします。
ある程度、高解像度なサービスメトリックが欲しい場合はcalculate_interval5m程度に設定して、5分ごとにshimesabaを起動することになるでしょう。
それほど、細かくなくて良い場合は、30m程度が良いと思います。

slo は複数定義できます。 idは被らずユニークになるように指定してください。投稿されるサービスメトリックが、このidの値によって決まります。 仮に上記の設定で、idlatencyの場合は以下のサービスメトリックが投稿されます。

  • api.error_budget.latency : エラーバジェットの残り時間 (単位:分)
  • api.error_budget_percentage.latency: エラーバジェット使用率。100%なら全て使い切った。0%ならエラーバジェットは損失していない。
  • api.error_budget_remaining_percentage.latency: エラーバジェット残存率。100%なら損失していない。0%ならエラーバジェットはすべて使い切った。
  • api.error_budget_consumption.latency : その時刻に消費したエラーバジェットの時間 (単位:分)
  • api.error_budget_consumption_percentage.latency: その時刻に消費したエラーバジェットのパーセンテージ。最大量の何%を消費したのかを表す
  • api.failure_time.latency: その時刻を基準とするローリングウィンドウ内での合計のSLO違反となった時間 (単位:分)
  • api.uptime.latency : その時刻を基準とするローリングウィンドウ内での合計の良好な時間 (単位:分)

各値の間には以下の関係があります。 - 100 - api.error_budget_percentage.latency = api.error_budget_remaining_percentage.latency - api.uptime.latency + api.failure_time.latency = error_budgetの最大値 - api.error_budget_consumption.latency / error_budgetの最大値 * 100 = api.error_budget_consumption_percentage.latency - api.error_budget.latency / error_budgetの最大値 * 100 = api.error_budget_remaining_percentage.latency

3.5 手元での動作確認

ここまでが、動かし方によらない共通部分となります。 この時点で、お使いの環境のビルド済みバイナリを使って、CLIとして動作確認をすることをおすすめします。 以下のように、--dry-run--dump-reports のオプションを付けることで、実際にはサービスメトリックを投稿せずに、手元で計算のみをしてくれます。

$ shimesaba -config config.yaml -mackerel-apikey <Mackerel API Key> --dry-run --dump-reports  
2022/06/20 18:45:32 [info] start run in the `test-mashiike` organization.
2022/06/20 18:45:32 [notice] **with dry run**
2022/06/20 18:45:34 [info] service level objective[id=availability]: start create reports 
2022/06/20 18:45:34 [info] service level objective[id=availability]: finish create reports 
2022/06/20 18:45:34 [info] error budget report[id=`availability`,data_point=`2022-06-20T08:30:00Z`]: size=200.0000[min], remaining=195.0000[min](2.5%), consumption=0.0000[min](0.0%)
2022/06/20 18:45:34 [info] error budget report[id=`availability`,data_point=`2022-06-20T09:00:00Z`]: size=200.0000[min], remaining=195.0000[min](2.5%), consumption=0.0000[min](0.0%)
2022/06/20 18:45:34 [info] error budget report[id=`availability`,data_point=`2022-06-20T09:30:00Z`]: size=200.0000[min], remaining=195.0000[min](2.5%), consumption=0.0000[min](0.0%)
2022/06/20 18:45:34 [info] service level objective[id=availability]: start save reports 
2022/06/20 18:45:34 [info] service level objective[id=availability]: finish save reports 
2022/06/20 18:45:34 [info] service level objective[id=latency]: start create reports 
2022/06/20 18:45:34 [info] service level objective[id=latency]: finish create reports 
2022/06/20 18:45:34 [info] error budget report[id=`latency`,data_point=`2022-06-20T08:30:00Z`]: size=200.0000[min], remaining=185.0000[min](7.5%), consumption=0.0000[min](0.0%)
2022/06/20 18:45:34 [info] error budget report[id=`latency`,data_point=`2022-06-20T09:00:00Z`]: size=200.0000[min], remaining=185.0000[min](7.5%), consumption=0.0000[min](0.0%)
2022/06/20 18:45:34 [info] error budget report[id=`latency`,data_point=`2022-06-20T09:30:00Z`]: size=200.0000[min], remaining=185.0000[min](7.5%), consumption=0.0000[min](0.0%)
2022/06/20 18:45:34 [info] service level objective[id=latency]: start save reports 
2022/06/20 18:45:34 [info] service level objective[id=latency]: finish save reports 
2022/06/20 18:45:34 [info] run successes. run time:1.633562403s

4.0 AWS Lambda 関数としてデプロイ

shimesabaはGo言語製のアプリケーションで、AWS Lambda関数のbootstrapとしても機能します。 linuxのamd64のビルド済みバイナリをダウンロードしてきて、bootstrapという名前に変更してconfig.yamlとともにzipファイルにまとめることで、そのままLambda関数として動きます。

lambda.zip
├── bootstrap
└── config.yaml

また、弊社の長田が制作したssmwrapを内包しており、Mackerel API KeyはSSM Parameter Store経由で与えることが可能になっています。

例えば、 /shimesaba/MACKEREL_APIKEY というパラメーター名でMackerel API Keyを保存した場合は、以下のような環境変数を与えることで動作すると思います。

  • SSMWRAP_PATHS=/shimesaba/
  • SHIMESABA_CONFIG=config.yaml

あとは、Amazon EventBridgeで定期的にこのLambda関数を起動するルールを作成すれば終了です。 EventBridgeルールのscheduled_expressionは、config.yamlのcalculate_intervalと同じにしておくことをおすすめします。

まとめ

今回は、 Rolling windowのコンプライアンス期間で、Windows-based SLOによる評価方法を採用したエラーバジェットを計算するツールshimesabaの導入について話しました。 このツールを使うことで、Mackerelをお使いの場合は、SLOの導入をある程度お手軽にできると思います。 もっと細かいツールの使い方等は、Mackerel User Groupのslackに#shimesabaのチャンネルがありますので、そちらでお聞きいただければ幸いです。

カヤックでは、SLOの実践について一緒に悩めるエンジニアについても募集しています。

*1:ここではMackerelのAWSインテグレーションで取得したAWS Application Load Balancerのメトリクスを使用しています

*2: