dely Tech Blog

クラシル・TRILLを運営するdely株式会社の開発ブログです

クラシルリワードチーム SLO導入の工夫と現在地

こんにちは、クラシルリワードというサービスでSREときどきサーバーサイドを担当しているjoooee000です。

外の空気がほんのりと暖かくなり、春の訪れを感じさせる今日この頃、心まで軽やかになってきました。冬の長い間、凛とした寒さに耐えていた私たちにとって、この季節の変わり目はまさに待ちに待った瞬間です。

ということで、みなさんのチームではSLOを導入していますか?クラシルリワードのサーバーサイドチームでは、SLOを導入しています。

SLOの設定や浸透、導入ってとても難しいですよね。リワードサーバーサイドチームも、SLO導入までの道のりで最初の成果を実感するまでは何回ももやっと感覚を味わってきました。 この記事では、SLO導入の軌跡と、導入方法や改善したことなどを書いていきたいと思います!一つのケースとして、参考になれば幸いです。

導入当時の課題感

SLOの導入は、もともとサーバーサイドチームで下記のような課題感を持っていたことが発端でした。

  • アラート設定の閾値がオレオレ
    • 今設定している閾値より、もっと早い段階でユーザーが不便と感じるかもしれない
  • パフォーマンスが下がっていても気づくことができない (明らかに障害というレベルでしか気付けない)
  • パフォーマンス改善に対する優先順位の意思決定ができない

クラシルリワードはiOS / Android / webでサービス利用できるようになっていますが、まずはサーバー側の計測とスコープを区切り、まずいことが起こったときにアクションが取れるようにしようという意思でSLOの導入をすることにしました。

SLOを導入した結果

まずSLOを導入した結果どうなったかを先にいうと、

  • 大幅なレイテンシ悪化(障害までにはならない)に気づくことができた
  • いくつかの機能でレイテンシを改善し、SLOを満たせるようなパフォーマンス改善ができた🎉
  • 継続的にパフォーマンスがウォッチできる様になった
  • やらないこともSLOを基準に決められるようになった
    • 頻繁にtimeoutが発生しているようにみえていた外部サービスも、計測したらSLOの範囲内だった 等

改善前後の1ヶ月間のSLO(before)

改善後の直近1週間のSLO(after)

SLO導入の軌跡

結果的に改善事例が出来ましたが、そこまでにはいろいろな試行錯誤があった(まだまだ試行錯誤中)なので、導入の軌跡を紹介できればと思います。

導入初期 ~ SLO設定編 ~

まずはじめに、上で書いた課題感からSLIと、SLO基準値を決定することにしました。

SLIの決定は、まずはシンプルにAPIのレイテンシと可用性(5xxエラー)にしました。

この2つの指標は、以前サーバーサイドチームのメンバーで「クラシルリワードを開発するうえで担保すべきこと」を話し合った結果のうちの2つを指標にしています。

下記が、話し合いの結果チームで決定した 「サービスを開発するうえで担保すべきこと」 です。

  • コインやチケットなど、売上に直結する情報が正しく更新・表示される
  • ユーザーがサービスに来た目的を安全に果たせる
    • 動作が快適 ⇒ レイテンシ
    • エラーが起きない ⇒ 可用性
    • 個人情報などセキュリティ面の担保

次にSLOの設定ですが、下記の2項目を考慮しながら最初は最低限のSLOを引くことにしました。

  • 他社の指標などの参考値
  • 「今のレイテンシであれば、許容できる」というEM(兼PDM)のセリフ

しかし、いざごく最低限と思われるラインのSLOを設定してみると、レイテンシのSLOがすでにガッツリ抵触していました。深堀りしていくと、一部の外部サービス連携のある機能のレイテンシに引っ張られているという事がわかりました。その中で下記のような疑問が湧いてきました。

  • どの機能も同じSLOでいいのか?
    • 外部サービスとの依存が激しい機能で、一部外部サービスの基準に合わせてレイテンシを許容する意思決定をしている箇所が存在する
    • 不正防止チェックが重要で、一部レイテンシを許容している箇所が存在する

レイテンシを許容しなければならない箇所が混ざっている状態で、一律でSLOを設定することに意味はあるのか、SLOが下がったときにどこを改善するかの判断が難しくないか、などを考えました。

機能ごとにSLOを分割することに

上記のもやもやがあり、機能ごとにSLOを分割してみることにしました。外部サービスへのリアルタイムのリクエストが発生する機能も一部だったため、機能ごとに分割することでより明快なSLOを設定できると思いました。また、機能ごとに開発メンバーの責任者が決まっていたため、各メンバーやチームがオーナーシップをもって改善しやすいこと、チームによっては、一時的にレイテンシを犠牲にしてスピード開発するPoCを行っているパターンも存在していたため、機能ごとのメリットがあると考えました

そこで、エンドポイントのpathごとに意味のある機能にまとめて、SLOを設定しました。

機能ごとに分割することで、一律ですべて同じSLOを設定しているときよりは納得感のあるSLOが設定できました。また、どのメンバーが修正するべきかの責任範囲と、どこの機能でレイテンシが悪化しているか明確になりました。

導入中期 ~ 可視化編 ~

次に、SLOダッシュボードを作成してサービスの健康状態を可視化しました。

1ページで各機能のSLOを見れるようにし、SLOがどういう動きをするか観察できるようにしました。

ダッシュボード作成やSLOやエラーバジェットのモニタリングはNewRelicのServiceLevel機能を用いて行いました。

また、下記terraformで設定することでNewRelicのSLO機能の作成と、サービスごとのSLOをまとめて閲覧できるダッシュボード(機能ごとのSLOをタブ化)とを自動生成できるようにしました。

  • 対象機能
  • 機能ごとの対象エンドポイント
    • 例) /api/v1/surveys/*
  • SLO

機能ごとのSLOダッシュボード
この時点では、サーバーサイドチームにダッシュボードを共有し、SLOの活用方法として5xxアラートがきたときに修正対応すべきかどうかという基準にのみ利用していました。例えば、外部サービスとのつなぎ込みがある機能のtimeoutをどの程度気にして改善するかなどです。SLOに抵触していない限りは、対応不要という意思決定ができるようになりました。

しかし、SLOが下がったときにはどういうアクションをとるかということに関しては、仕組み化出来ていませんでした。SLOを普段目にすることがなくそのうちSLOの存在を忘れてしまいそうな状況でした。

現在 ~ アラート設定編 ~

上で述べた通り、新しいフィーチャーのデプロイなどによりSLOに抵触した時、対応するフックやルールが何も無いため、そのうち見なくなるだろうなという感覚がありました。

SLOに抵触した際に気づけるよう、アラートの設定をしました。

まずは、SLOのバーンレートアラートを設定し、slackのwarnチャンネルに流せるように、さきほどのダッシュボードの作成時に、terraformによって同時にNewRelicアラートが設定されるようにしました。

(リワードのサーバーサイドチームでは、アラートチャンネルがcritical / warn / noticeチャンネルに分類されており、warnチャンネルは、「オンコール担当者(サーバーサイドメンバー含む)が業務時間内に見て対応が必要かどうか判断する必要がある」という基準を設けています。)

SLO slackアラート
しかし、アラート化するとメンバーには絶対に対応するべきもの、または対応が必要かどうか都度判断するべきものとして今まで以上に認識されるようになります。ここで、SLO設定時の「本当に追うべき指標になっているのか」「メンバーの時間をとって改善すべきと強く言えるか」という問題と再度向き合う必要がありました。

そのときのもやもやポイントとして、設定したSLOの値の妥当性がわからないというところにありました。

そこで、機能ごとに分割してあるレイテンシのSLOをさらに、GET / POSTごとのリクエストメソッドでも分割しました。このことで、なぜその値に設定しているかわからないSLOよりは、GETで外部サービスとのつなぎこみもなくこの閾値を下回っているのは、なにか実装面で問題がありそう。というように、より指標を一般化できると思いました。例えば、GETとPOST関係なく500ms、99%を目指しましょう。というと、GETだと妥当かな、POSTだとちょっと厳しい、というようにより共通の感覚が持てます。

また、サービスの性質上、POSTリクエストに不正リクエストを防ぐための重めの処理が入っている箇所もあり、サービスによってはPOSTのレイテンシに引っ張られてGET系のレイテンシの低下を正しく判断できない箇所もありました。そのため、確認したところで「POSTなので許容します」みたいなコミュニケーションになってしまうのではと思っていたこともあります。

実際にやってみると、わりとしっくり来るSLOを設定することができました。基準として、

  • 各サービスごとに一律でGETとPOSTリクエストで基準となるSLOを作成
  • その上で、外部サービスの連携があり一部レイテンシを許容する意思決定をしている機能に関しては、外部サービスが提示している目標レスポンスタイムを基準となるSLOに足す

これで無理なくSLOを守っていける、アラートが上がったらかなりの高確率で実装上の問題があるという感覚のSLOを設定できました。

また、対応ルールは最初は修正を強制にせず、各機能チームの意思決定に委ねるという運用から始めました。

アラート化することで、SLOのチーム内の認識度が上がった

ちょうどそのタイミングで、チームが注力している機能のレイテンシが大幅に下がる事象が発生しました。 (計測してて良かった!)

この頃には、当初SLOを計測し始めた頃よりも大きくサービスが成長し、些細な実装がレイテンシに影響するようになってきており、SLOの必要性も当初より上がってきたように思います。

そして、SLOに抵触したサービスに関わっていたメンバーが、迅速に対応してくれて、SLOに基づいてパフォーマンス改善をすることが出来ました。

パフォーマンス改善によってレイテンシをV字回復してくれたメンバー

チームでSLOを意識するようになってきた

最近では、サーバーサイドチームでSLOを意識することが出来ています。

アラートにしたことでチームに認識されて改善点の意見もでてきたり

開発速度の計測を担当してくれているメンバーが「意識すること」で言及してくれたり

開発速度計測レポートの一部

レイテンシを改善したことによって事業にどういうインパクトがあったかを計測してくれたりしました。 (このときの改善は残念ながらあまりKPIには影響がなかったので、SLOを下げた)

また、パフォーマンス改善などによって技術的知見を得る機会も増えたため、サーバーサイドチームのMTGに技術シェアというコーナーができました 🎉

チームミーティングの議事録の一部

まとめや今後の展望

クラシルリワードのサーバーサイドチームでは、機能ごと、リクエストメソッドごとにSLOを計測しています。

また、まだまだSLOの運用を始めたばかりなので、今後は下記にも注力できたらなどと妄想しています。

  • バックエンド側に閉じないSLOの設定やモニタリング
  • SLOの値の調整
    • 今も、パフォーマンス改善した際にKPI周りをみて変化がなければSLOを緩めてみたりしています
  • SLOと離脱率の相関の分析

最後まで目を通していただき、ありがとうございました。