Microservices時代の監視設計

前のエントリの続きです。思ってた以上に反響があったので、主語を控えることも検討しましたがこのまま行きます。前回同様、すでにMicroservicesでバリバリやっている人は読む必要ないと思います。

前回の最後にMicroservices時代になると、開発者がこれまで以上に監視に取り組んでいく必要があると言う話を書きました。多少重複するところもありますが、その辺りから話を始めます。

モノリシック世界観での監視

Webサービスの構成が「モノリシックなWebアプリケーション」と「汎用的なミドルウェア群(Apache/MySQL/memcached etc.)」という世界観においては、単純化すると以下のような監視がとられることが多かったでしょう。

  • 汎用的なミドルウェアに対しては、吊るしのプラグインを利用して監視設定をする
  • Webアプリケーション固有の監視はそれほど入れず、アプリケーションが動いているホストのリソース監視でカバーする

一昔前のWebアプリケーションというのは各ミドルウェアの間をつなぐような薄く単純な作りであったり、もしくはWebサーバーと密結合していたため、アプリケーション固有の監視を作るという発想になることが少なかったように感じます。

例えば、汎用ミドルウェアであるDBでは「クエリの発行数」などに着目し、アプリケーションでは単にサーバーの「CPU利用率」に着目するといった具合です。

アプリケーション監視の浸透

しかし、Webアプリケーションが複雑化する中で、"Health Endpoint Pattern" のようなパターンが編み出され、アプリケーション開発者が監視設計もおこなうプラクティスが徐々に浸透してきています。この流れはMicroservices時代になるとより顕著になるでしょう。

"Health Endpoint Pattern" は古くからある手法ですが、書籍「入門 監視」で名付けられたパターンです。コンポーネント側で監視用のHTTPエンドポイントを用意し、そこに各種監視クライアントがアクセスして観測をおこなうものです。例えば http://127.0.0.1:8080/health のようなパスにアクセスすると、各種統計データやカウンター値がJSON形式で取得できるといったものです。

入門 監視 ―モダンなモニタリングのためのデザインパターン

入門 監視 ―モダンなモニタリングのためのデザインパターン

これは、監視も含めてコンポーネント設計をしましょうという昔からあった話でもあります。昔は、逆にdaemontoolsなどを使って、開発者自身がサーバーのセットアップ、ミドルウェアの設定、自前のサーバープロセスの起動などを一通りやっていた時代もあり、そういう時代の人からすると当たり前かもしれません。

この辺りは、PHPやRailsが普及し、モノリシックなWebアプリケーションを簡単に作る敷居が下がった分、自分でデーモンやサーバープロセスを立てたことがない人の割合が増え、逆にその辺りのコンポーネント設計のノウハウが薄まってきた背景もあるのではないでしょうか。敷居が下がるのは良いことなので、これ自体は悪い話ではないと考えます。

Microservices時代の監視設計

さて、Microservices時代には、冒頭に挙げたようなモノリシックアプリ & 汎用ミドルウェア群というような綺麗な区別にはなりません。システムを構成する各コンポーネントは言ってしまえば独自ミドルウェア的存在になり、それらの群が通信しあって分散協調する形になります。つまり、アプリケーションとミドルウェアの境界は曖昧になります。

だからこそ、開発者自身による監視の設計が必要になり、テスト駆動同様に、監視と開発の両輪を回す必要がでてくるでしょう。

実際、書籍「詳解システムパフォーマンス」の第5章に「アプリケーション」の章がありますが、ここで実際に言われている「アプリケーション」とは、ミドルウェアを含んだユーザーコンポーネントです。

詳解 システム・パフォーマンス

詳解 システム・パフォーマンス

開発者自身が監視する

僕は「入門 監視」の付録Cで、「テスト駆動開発と監視は実は親しい」という主旨のことを書きました。書籍「テスト駆動開発」に以下の記述がありますが、これは実は監視も同じです。

テスト駆動開発は、プログラミング中の不安をコントロールする手段だ。

テスト駆動開発

テスト駆動開発

サービスを運用していると、発生してほしくないこと、不安なことがあるでしょう。例えば、「新規ユーザー登録が止まってしまう」「ガチャの排出率が誤っている」「通知ジョブが詰まっている」などなど。そういうところを監視するのです。そこの監視には開発者自身しか考えが及ばないでしょう。

不安な箇所を監視することで、理想的には心安らかにサービス運用をおこなえます。また、テストを書くのが慣れてくると楽しくなるように、監視も慣れてくると病みつきになります。

どう監視するか

そうは言われても、どの様に監視をすればいいのかわからないかも知れません。まずは、先程出てきたHealth Endpoint Patternを使って、必要なメトリクスを取得できるようにしましょう。

Health Endpointから返すデータフォーマットはJSONを使うのが取り回しがしやすくてオススメです。ちなみに、まだDraftですが、ヘルスチェックフォーマットのJSON Responseに関する議論が進んでおり、これを参考にするのも良いでしょう。

他にはOpenMetricsフォーマットにすればPrometheus等で使いやすいでしょう。

メトリクス設計

Health Endpointから取得させるメトリクス設計については、ガイドラインとして SRE本にある、 "The Four Golden Signals" そしてそれらを補強する "USE", "RED" というメソッドが参考になります

The Four Golden Signals

これは、SRE本の「6.6 4大シグナル」で言及されているものです。原文の "The Four Golden Signals" の方がカッコいいし、よく使われるので英語表記を使います。以下の4つです。

  • Latency - レスポンスを返すまでにかかる時間
  • Traffic - リクエストの量
  • Errors - 処理に失敗したリクエストの数のレート
  • Saturation - システムの飽和や利用率

SRE サイトリライアビリティエンジニアリング ―Googleの信頼性を支えるエンジニアリングチーム

SRE サイトリライアビリティエンジニアリング ―Googleの信頼性を支えるエンジニアリングチーム

  • 作者: 澤田武男,関根達夫,細川一茂,矢吹大輔,Betsy Beyer,Chris Jones,Jennifer Petoff,Niall Richard Murphy,Sky株式会社玉川竜司
  • 出版社/メーカー: オライリージャパン
  • 発売日: 2017/08/12
  • メディア: 単行本(ソフトカバー)
  • この商品を含むブログ (1件) を見る

SRE本のこの章には以下のように書かれています。

ユーザーが直接利用するシステムで、メトリクスを4つだけ計測できるなら、この4つに集中してください。

なぜこの4つなのか。それを考える上で"USE"と"RED"という2つのモニタリングメソッドを見てみます。

USEメソッド

まずはBrendan D. Gregg氏による、USEメソッドです。以下のURLにまとめられています。

http://www.brendangregg.com/usemethod.html

For every resource, check utilization, saturation, and errors.

以下の3つの頭文字を取って"USE"と言われています。

  • Utilization - 利用率
  • Saturation - 飽和
  • Errors - エラー

これは内部のリソース状況を観測するためのメソッドで、ブラックボックス的な観測方法と言えます。

同氏の著書「詳解システムパフォーマンス」2.5.9 USEメソッドでも触れられており、調査の際にErrors、Utilization、Saturationの順でチェックすると良いと書かれています。

UtilizationとSaturationを分けて考える必要があると言及されている点も特徴的です。均した利用率が100%に達していなくても、一時的に飽和して刺さっていた時間が無いとは言えないため、Utilizationで異常が見られなかった場合には、Saturationに着目するべきだと論じられています。

REDメソッド

REDはサービスを観測するためのメソッドです。初出は恐らく以下の"Monitoring Microservices"というそのものスバリなタイトルのスライドで、USEと対比されて書かれています。

説明としては以下のエントリに詳しいです。

https://www.weave.works/blog/the-red-method-key-metrics-for-microservices-architecture/

これもUSE同様、3つのキーメトリクスの頭文字を取って"RED"と命名されています。

  • (Request) Rate - 単位時間当たりにさばいたリクエスト数
  • (Request) Errors - 失敗リクエスト数
  • (Request) Duration - リクエストにかかる時間の分布

Rateが「リクエスト数」なのは少し分かりづらく感じますが「単位時間辺りのリクエスト頻度」だと理解しています。

これらのメトリクスは外部からの振る舞いに着目したもので、アクセスログから取得することも可能です。これはホワイトボックス的なチェックだと言えるでしょう。

USEとREDの補完関係

こうしてみると、USEとREDはそれぞれ補完しあうものである事がわかります。以下にまとめてみます。

USE RED
対象 リソース サービス
観点 ブラックボックス ホワイトボックス
観察 内部の状態 外部の振る舞い

The Four Golden Signalsの素晴らしさ

改めてThe Four Golden Signalsを見ると、USEとREDが網羅されていることがわかります。

  • Latency - REDにおけるDuration
  • Traffic - RED におけるRate
  • Errors - USE/RED両方におけるエラー
  • Saturation - USEにおけるUtilization/Saturation

USEの説明で述べられているように、Saturationは本来的にはUtilizationを分離したほうが良いかもしれませんが、おそらくホワイトボックス的な振る舞いの方が重要なので、ブラックボックス的なチェックはSaturationにまとめられているのでしょう。また、Saturationはサービスが応答可否という、サービスレベルでもクリティカルなメトリクスでもあるため、そちらが優先されてリストアップされているとも考えられます。

実際、SRE本のSaturationの項目の中でも、Saturationを早い段階で捉えるためにUtilizationも併せて取得するべきだと説明されています。

Note that many systems degrade in performance before they achieve 100% utilization, so having a utilization target is essential. https://landing.google.com/sre/sre-book/chapters/monitoring-distributed-systems

例: ある認証コンポーネントの監視設計

最後に、ここまでの話を踏まえて、ある認証コンポーネントに対する監視設計を考えてみましょう。

The Four Golden Signalsに照らしてみると、単なるプロセスの死活監視だけではなく、以下のようなメトリクスや監視項目を取得すると良いことがわかるでしょう。

  • レスポンスタイムの平均、分布、分位数 (Latency)
  • リクエスト数 (Traffic)
  • 認証成功・失敗 (Traffic/Errors)
  • エラー数・エラーレート (Errors)
  • 内部エラーログ (Errors)
  • 内部ワーカー・スレッドの利用状況 (Saturation)

ちなみに、認証成功、失敗、エラーなどについては、コンポーネントをHTTPサーバーとして提供し、2xx/4xx/5xxのHTTPステータスのセマンティクスに従っておけば、簡単に集計が可能でしょう。

まとめ

  • Microservices時代には開発者自身がこれまで以上に監視設計をおこなうことになる
  • Health Endpoint Patternを利用してサービスのObservabilityを高める
  • The Four Golden Signalsに従うと設計がやりやすい