1クール続けるブログ

とりあえず1クール続けるソフトウェアエンジニアの備忘録

システム監視の基礎についてまとめてみる

今度、社内でシステムの監視について話す機会があるので、自分用にまとめてみました。   

参考にした書籍は「入門監視」「Site Reliability Engineering」「k8sで実践するクラウドネイティブDevOps」です。 SRE Workbookの方も読んで後で追記したい。

監視の定義

あるシステムやそのシステムのコンポーネントの振る舞いや出力を観察しチェックし続ける行為である by Greg Poirier

監視とはアラートのことだけに関心があるのではなく、監視の中には多くの要素が含まれます。
例えば、メトリクスやログ、オンコール、ポストモーテム(振り返り)、統計などが挙げられるでしょう。

監視の必要性

必要な理由は多く挙げられますが、主なものは下記になります。

  • 長期的なトレンドの予測
    • DBのデータボリュームはどのくらいのペースで増えているか?
    • 日次のアクティブユーザの増加ペースは?
  • 時間や、実験グループ間での比較
    • DBコネクションプールの実装はdbcp2とTomcat JDBC Poolどちらの方が高速か
    • サイトの速度は先週と比べて落ちているか
  • アラート
    • 何かが壊れている(あるいは近い未来に壊れる)ので、誰かが確認するべきだということを通知する
  • ダッシュボードの構築
  • アドホックな振り返り分析の進行
    • レイテンシが急上昇した際に、他になにか同時期に生じていなかったか
    • エラーが急増したときに、バックエンドのレイテンシはどうだったか

書籍やブログ等でメインで取り扱われることは少ないですが、YelpやRedditなどはビジネスにおけるKPIもアプリケーションのメトリクスから取得してモニタリングを行っているそうです。例えば、検索実行数やユーザのサインアップ等です。都度ログを収集することで可視化できますが、リアルタイムで描画することで判断が早く行えるという利点があるようです。

GoogleではSLO(Service Level Objective)を計測し、エラーバジェットという指標を設けることで、運用と開発チームの対立を避けるようにしています。運用チームは稼働時間に対する目標があり、開発チームは新機能などに関する目標があるケースが多いかと思います。つまり、この対立はイノベーションの速度とプロダクトの安定性の間に生まれるものです。
Googleでは、SLOを99.995%(4.5ナインズ)に決めたら、0.005%は損失可能な信頼性となり、四半期のうちこの値に達するまでは新しいリリースをPushできるという仕組みを持っている(現実はもっと複雑な条件分岐によるアクションを持つ)。 定量的な指標を持つことで交渉から政治を取り除くことができます。
※ SLOの例:GETリクエストの99%が100ミリ秒以内に成功する

f:id:jrywm121:20200324230026p:plain

監視の立ち位置

企業がスケールするとメンバは特定の役割を持つことが普通になってきますが、監視は他の仕組みから孤立したものではなくサービスのパフォーマンスのために重要になる要素になります。知らないシステムについての監視(特に高度な監視)は難しいものです。例えば、「アプリケーションが動いているか」どうかを監視したいと思ったときに、何をもって「動いている」かをアプリケーション開発者以外の方は定義することに労力を要するでしょう。HTTP 200が返ってくればいいのか?レスポンスに特定の文字列が含まれているべきか?レイテンシはいくつ以下であるべきか?気になるのは平均なのかテイルレイテンシなのか?高度な監視を行うために検討が必要になります。
役割としての監視はアンチパターンとなっており、監視はスキルとしてチームメンバ全員が持つべきものと言えます。

サービスの健全性はマズローの欲求階層と同様に、サービスとして一通り機能するための最も基本的な条件から、サービスの方向性を能動的にコントロールするような、高いレベルの機能に至るまでの段階に分類できる。
その階層の中で一番下、最も基本的な必要条件がモニタリングとなります。

f:id:jrywm121:20200324230142p:plain

監視サービスの構成要素

専門化されたコンポーネント疎結合で組み合わせて監視プラットフォームを作ります
「あるツールのやり方が合わなくなってきた」ときに、監視プラットフォーム全てを取り替えるのではなく、そのツールだけ削除して他のもので置き換えればよいというわけです

  • データ収集
  • データストレージ
  • 可視化
  • アラート
  • 分析

データ収集

ブラックボックス型/ホワイトボックス型監視

ユーザーが目にする外部の振る舞いをテストするのがブラックボックス監視で、システムの内部によって公開されているメトリクスに基づく監視がホワイトボックス監視になります。

f:id:jrywm121:20200324230737p:plain

ブラックボックス監視には限界があります。

  • 「何が」壊れているのかは分かるが、「なぜ」壊れているのかはわからない
  • 事後対応であり、問題が発生した後にしか通知しない

ですが、ブラックボックス監視は不要というわけではありません。 DNSレコードの誤りやネットワーク分断、ルータの設定ミス、クラウドプロバイダの機能停止などは内部のメトリクスでは拾うことが出来ません。そのため外部の場所からサービスの可用性を監視する必要性があります。サードパーティのサービスが多くあり、MaaS(Monitoring as a Service)と呼ばれれます。
主要なサービスを下記に示します。

オブザーバビリティををより向上させるためには、外部だけでなくアプリケーションからデータを収集する必要があります。それがホワイトボックス監視です。ホワイトボックス監視は、「なぜ」壊れたのか?を答えてくれるものであり、問題の予測に役立ちます。
代表的なホワイトボックス監視において収集するデータとして、ログとメトリクスがあります。

ログ

メトリクスより多くの情報を持てるので、情報を抽出するためにはなんらかのパースが必要になります。パースさせるために構造化してログを収集できるようにするべきです。
例えば、プレーンテキストでログを吐くのではなくJSONで出力させることも検討するほうが良いということです。Cloud Watch InsightやStackdriver Loggingでのフィルタリングが楽になります。下記はCloudWatchInsightでのクエリ例です。

f:id:jrywm121:20200324232014p:plain

ログは役に立つが、ログに何を吐くかはアプリケーションの開発時にプログラマが判断します。 そのため、答えられる疑問や検出できる問題は事前に予想できるものに限られてしまうという側面を持ちます。事前に予想できないものまで検知するためにログの量を増やしてしまうと、雑音が増えてしまい問題の特定が難しくなったり、ログを蓄積するために使用している従量課金のマネージドサービス(例えば AWS CloudWatch)での課金額が高くなってしまうデメリットがあります。

メトリクス 

ログの弱点をカバーするような特徴を持つのがメトリクスです。メトリクスはすべて数値であるため、ログと違い計算や統計を行うことができます。メトリクス値は大きく2つのタイプに分かれます。

  • カウンタ

    • 増えていく(または0にリセットする)ことしかできない
    • リクエストの数や捕捉したエラーの数の測定に優れている
    • 自動車での走行距離計に例えられる
  • ゲージ

    • 増減ともに可能
    • CPU使用率のように継続的に変化する量や他の数量との率を表すのに便利
    • 自動車の速度計に例えられる

アラート

アラート疲れにならないように設定する必要があります。まず、アラートにメールを使うのをやめた方が良いです。あまり見られておらず機能していないことが多いです。そして事象の深刻度に合わせて、どの媒体に通知するかを分けるべきです。

  • すぐに応答/アクションが必要なアラートはPagerDutyやSMSを使う
  • 注意は必要だが、すぐにアクションは必要ないアラートはslackなどの社内のチャットルームに送る
  • 履歴や診断のために保存しておくアラートはログファイルに送る

f:id:jrywm121:20200324233242p:plain

また、うるさいアラートはオンコール担当の疲弊にも繋がるし、いずれ無視されるものなってしまう可能性が高いです。モニタリングやアラートのルールを作成する際には、以下の質問をしてみると良いでしょう。

  • ルールが検出する状況は、そのルールなしでは検出されない状況にあるか?緊急で対応が可能か?その対応は自動化できないか?
  • アラートは間違いなくユーザーに悪影響が生じていることを示すか?

アラートには手順書(runbook)へのリンクも一緒に含めるべきです。

統計

平均値での可視化/アラートには落とし穴があります。特に一方方向に大きな偏りがあるデータセットの場合は気をつける必要があるでしょう。
例えば、静的ファイルの配布もJavaアプリケーションで行っている場合かつそのリクエストが多い場合には、例えば特定のパスが遅くなっていても、レイテンシの小さいリクエストのせいで平滑化されて見えなくなってしまいます。

そのためテイルレイテンシをSLOに掲げるところも多いです。例えば、「95パーセンタイルを3秒以下」と定めます。
パーセンタイル(分位数)は昇順に並べ、最小値から数えて何%かというものです。

f:id:jrywm121:20200324233439p:plain

監視の始め方

監視についての取り組みはミッション駆動でなくツール駆動になりがち!後者が前者より効率高くなることはありません。
監視は単一の問題ではない = つまり単一のツールでは対応できないので、成熟した環境においては汎用的なツールと専門的なツールを組み合わせて使うべきです。

ツールは賢く注意深く選ぶべきで、ツールが必要なら増やすことを恐れなくてもよいです。むしろツール統合の名のもとに必要性に見合ってないツールを使うのは良くありません。ツール選定において、使えるのであればSaaS使った方が良いと思われます。ほとんどの場合はそれで事足りるし、結果的に安くなります。Run Less Softwareのphilosophyにも通じます。

一番関心があるのは「ユーザに影響があるかどうか?」です。そのためユーザ視点での開始から始めるのが基本と思います。このことで個別のノードの監視から開放されます。 例えば、DBサーバのCPUが上がっていてもユーザに影響が無いのなら影響になるでしょうか?
監視をどういった指標で扱うかに関しては既にパターンが存在します。

The Four Golden Signals

  • レイテンシ

    • リクエストを処理してレスポンスを返すまでにかかる時間
    • 処理に成功したレスポンスと処理に失敗したレスポンスでレイテンシを区別することが重要
    • 極めて早く返される500エラーが混じるとノイズになる
    • 一方で低速なエラーは高速なエラーよりも厄介なので、エラーをフィルタリングして外すのではなく、分けて追跡するのが大事
  • トラフィック

    • システムに対するリクエストの量
    • 通常は毎秒のHTTPリクエスト数だが、リクエストの性格によって異なる。KVSであれば、毎秒のトランザクションや取得数を計測することになる
  • エラー

    • 処理に失敗したリクエストのレート
    • 失敗には種類があり、例えば下記の3つが挙げられる
      • 明示的な場合(HTTPの500番台)
      • 暗黙的な場合(HTTP200で返却されているものの内容に間違いがある)
      • ポリシーによる場合(レスポンス1秒以下にすると約束しているのであれば、1秒以上かかったリクエストはエラー)
  • サチュレーション

    • サービスがどれだけ「手一杯」になっているかを示す
    • 最も制約のあるリソース(メモリやI/O)に重点をおいてシステムの利用率を計測
    • 近々発生しそうな予測も可能(例えばDBがディスクの空き容量を圧迫し、4時間後にハードディスクの空き容量が無くなりそう等)

RED Method

WeaveWorksが全てのマイクロサービスで共通して取得する3つのメトリクスを定義したものです。ソフトウェアからサチュレーションを取得するのは難しいため、The Four Golden Signalsからそれを除いた3つを挙げています。

Requests-Errors-Duration

  • 1秒あたりの受信リクエスト数
  • エラーを返したリクエストの割合
  • リクエストの持続時間(レイテンシ)

サービスが示している性能と、それをユーザが体験している状況について関心を持つ監視です。元記事はこちらです。

USE Method

NETFLIXのPFエンジニアが考案した性能に関する問題の分析とボトルネックの発見に役立てることを意図したアプローチです。関心はサービスではなくリソースです。

Utilization-Saturation-Errors

  • リソースがリクエストの処理でビジーになっていた平均時間、またはリソースキパシティに対する現在の使用量
  • リソースが過負荷となっている程度、このリソースが利用できるのを待つリクエトが格納されているキューの長さ
  • リソースに対するオペレーションが失敗した回数

元記事はこちらです。

まとめ

真っ先にやらなくてはと思ったのは下記です。副次的な良い効果が得られそうとも思いました。

  • 手順書のリンクをアラートに含める
  • アラートの精査を行う
  • レイテンシをレスポンスの成否で分ける
  • パーセンタイルを利用してレイテンシを計測する