マイクロサービスやマクロサービスの運用と健全性に関する長期的な指標をどのように追跡していますか?サービスレベル指標(SLI)とサービスレベル目標(SLO)は、DevOpsチームとIT運用アナリストにとって非常に重要な(時には意欲的な)メトリクスです。このブログ記事では、SignalFlowを活用して複数のSLOのエラーバジェットをまとめて追跡する方法をご紹介します(Terraformを使って簡単に始めることもできます)。
SLOの目的は組織によってさまざまです。
- アプリケーションチームが各種サービスの成功/失敗率を測定する。
- 各チームが意欲的なサービス目標を設定する(「複数の期間にわたってSLOを上回ったら、信頼性を築いたとみなして新機能の開発に注力する」など)。
- DevOpsチーム、運用チーム、経営幹部に共通のフレームワークを構築して、サービスの長期的な健全性を評価する。
- ダウンタイムやエラーバジェットを測定し、各サービスについて一定期間のダウンタイム、つまり「エラー分数」を許容することで、チームが運用の健全性確保と新機能の開発の間でうまくバランスを取れるようにする。
Google社のSREハンドブックをお読みになったことがあれば、SLOとSLIについてはよくご存じだと思います。まだお読みでない方のために、その中の一節をご紹介します。
「SREの本来の責務は、単に「すべて」を自動化してアラートを待つことではありません。SLOに基づいて日常業務やプロジェクトを行うことであり、短期的にはSLOが守られるようにすること、中長期的にもSLOを維持できるようにすることです。SLOを重視しないならSREなど必要ないと言ってもよいでしょう」- Google社SREハンドブック第2章
SLx (SLO/SLI/SLA)は多くの場合、経時的なトレンドと結び付けて考えられます。SLxに関する議論では、「エラー分数」、「1カ月あたりのバジェット」、「四半期あたりの可用性」などの言葉がよく使われます。では、経時的なトレンドを示すグラフと、イベントを適時に通知するアラートを使ってSLOを追跡するにはどうすればよいのでしょうか。そこでSignalFlowの機能を活用できるというわけです。
図1-1.アラート分数に基づくエラーバジェットの例
SignalFlowを使ってみる…
ここでは「ダウンタイム分数」を基準にSLOを設定します。そのためには何が必要でしょうか?
- サービストラフィックの成功率が99%を下回ったときに、何らかの方法でそれを把握する必要がある
- 何らかの方法で1の状態を分単位で計測することでダウンタイム分数を割り出す必要がある
- 割り出したダウンタイム分数を月/四半期単位で追跡して、ダウンタイム分数のバジェットと比較する必要がある
1番目は、「成功率」に関するアラートを使えばよさそうです。2番目は、アラートの状態が続いている間、1分単位でアラートを生成すればよいでしょう。3番目は、分単位のアラートを合計して定数(ダウンタイム分数のバジェット)と比較すれば解決です。
幸いSignalFlowには、このような分単位のアラートを生成する機能や、特定の周期(週/月/四半期など)でアラート数を追跡する方法が用意されています。
アラートと計測
SignalFlowでは、alerts()関数を使ってアラートを時系列で追跡し、特定の期間に発生したアラート数をカウントできます。
そのために必要なものは以下の通りです。
- 1分で停止するアラート
- アラートの状態が長時間続く場合は、1分ごとにアラートをオン/オフにします。
- 特定の率(一般的にはエラー率)に基づいてアラートを生成します。
- アラートデータを変換し、そのデータに対しstats関数を使用できるグラフ作成メソッド
- この手法には週/月/四半期などの周期でカウントをリセットできる方法を含みます(詳細は後述)。
SignalFlowのアラート例:
filter_ = filter('sf_environment', '*') and filter('sf_service', 'adservice') and filter('sf_kind', 'SERVER', 'CONSUMER') and (not filter('sf_dimensionalized', '*')) and (not filter('sf_serviceMesh', '*')) A = data('spans.count', filter=filter_ and filter('sf_error', 'false'), rollup='rate').sum().publish(label='Success', enable=False) B = data('spans.count', filter=filter_, rollup='rate').sum().publish(label='All Traffic', enable=False) C = combine(100*((A if A is not None else 0)/B)).publish(label='Success Rate %') constant = const(30) detect(when(C < 98, duration("40s")), off=when(constant < 100, duration("10s")), mode='split').publish('Success Ratio Detector')
このコードでは以下の操作を行っています。
- フィルターを定義します。APMデータを使用しているので、このフィルターでは主に、「adservice」という特定のサービスのみに対象を絞り込んでいます。
- 「成功率」(エラー率の逆)を割り出して、その数字を下回った場合にアラートを生成できるようにします。
- Aでは成功したリクエストのみを取得します。
- Bではすべてのリクエストを取得します。
- Cで成功率を割り出します。
- ダウンタイム分数(成功率のしきい値を下回る分数)のディテクターを作成します。
- 定数値(任意の値)を作成します。この値を使って、ディテクターがオンになってから10秒後にオフにします。
- 成功率(C)が40秒間95%を下回ったらディテクターをトリガーします。
- 「off=」設定と「mode=’split’」設定を使って、次の2つの条件が満たされたときにディテクターをリセットします。
- ディテクターが現在トリガーされている
- 定数が10秒間100を下回った
- 「off=」設定と「mode=’split’」設定を使って、次の2つの条件が満たされたときにディテクターをリセットします。
要するにこのコードでは、メトリクスがアラートしきい値を超えている間、1分ごとにアラートが生成されるようにしています。
エラーバジェットを追跡するグラフと周期
次に、このアラート分数を追跡するためのグラフを作成します。さらに、グラフを1カ月ごとにリセットして、各月でエラーバジェットが使い果たされたかどうかがわかるようにします。
エラーバジェットのグラフ作成の例:
## Chart based on detector firing AM = alerts(detector_name='THIS IS MY DETECTOR NAME').count().publish(label='AM', enable=False) alert_stream = (AM).sum().publish(label="alert_stream") downtime = alert_stream.sum(cycle='month', partial_values=True).fill().publish(label="Downtime Minutes") ## 99% uptime is roughly 438 minutes budgeted_minutes = const(438) Total = (budgeted_minutes - downtime).fill().publish(label="Available Budget")
このコードでは以下の操作を行っています。
- 先ほど作成したディテクターからのメトリクスストリームを定義します。
- そのアラートストリームを取得して合計します。これで、アラートが何分間続いたかがわかります。
- ダウンタイム分数のストリームを作成します。
- 合計したアラートストリームを、「cycle=」で指定した周期(月、週など)ごとにさらに合計します。partial_valuesは念のため許可します。
- fill()を使って、データポイントが空だった場合は直前の値を補充します。
- エラーバジェット(ここでは「ダウンタイムバジェット」)の分数を示す定数を作成します。
- 利用可能な総バジェットを計算します。
- バジェットの定数値からダウンタイムのストリームを引き算します。
- fill()を使って、データポイントが空だった場合は直前の値を補充します。
図1-2.アラート分数のグラフ作成の例
SignalFlowの機能を組み合わせて、しっかり監視
SignalFlowがいかに便利なツールであるかおわかりいただけたでしょうか?その高度な機能を活用すれば、面白いことがたくさんできます。
ここに示した例のように、SignalFlowを使ってアラートとグラフを作成し、それらを組み合わせてSLO/SLxを新たな方法で可視化することもできるのです。詳しい例とSignalFlowの使い方については、GitHubのSignalFlowリポジトリをご覧ください。
SignalFlowが活用できたら、次のステップへ
Splunk Observabilityが秘める可能性はほぼ無限です!このブログ記事をSignalFlow活用の出発点として、Splunk Observabilityでもっと高度な機能の開発にチャレンジしてみてください。
Terraformを使って、Splunk ObservabilityでこのSLO/エラーバジェット追跡機能を簡単に実装したい場合は、GitHubのObservability-Content-Contribリポジトリをチェックしてください。現在、Splunk Observabilityで何かすごい機能の開発に取り組んでいる方は、作成したダッシュボードやディテクターをこのリポジトリで公開することをぜひご検討ください。
Splunk Observabilityをまだお使いでない場合は、Splunk Observability Cloud製品スイートの無料トライアルをぜひお試しください。
このブログ記事はSplunkのオブザーバビリティフィールドソリューションエンジニアであるJeremy Hicksが執筆しました。ご協力いただいた以下の同僚に感謝申し上げます(敬称略):Bill Grant、Joseph Ross