オブザーバビリティ・エンジニアリングを読んで（１章：オブザーバビリティとは？）

# はじめに
巷で話題の「オブザーバビリティ」についてネットで調べてもなかなかしっくりこなかったので
書籍「オブザーバビリティ・エンジニアリング」を読むことにした。
おかげでだいぶしっくりくるものがあったのでメモ残す

# 総括
- オブザーバビリティとはもともと制御系の用語で、これをソフトウェアシステムに適用したもの
- オブザーバビリティの目的は「障害が起きたときに、それが未知の障害だとしても何らかシステム内部を変更（設定変更、コード修正）しなくても、アプリ内部のどこでどんな問題が起きているのかが説明できるようになること」
- 巷でいわれる「３本柱（メトリクス、ログ、トレース）」は否定しており、あえて言うなら「高いカーディナリティ、高いディメンション、探索可能性のあるツールの利用」を推奨している

# 序文
- ソフトウェア開発業界で「オブザーバビリティ」の話題が頻繁に出るようになった
- 深い見識がないと、単純なトピックのラベルでカプセル化された多くの細部を理解するのが難しくなりがち
- 「オブザーバビリティ」は数学用語、この起源を振り返りソフトウェア開発者がこの用語をどのように適用したのかを検証する
- 現在は管理対象のシステムが限りなく複雑化したにもかかわらず今も多くのエンジニアリングチームが初期のモニタリングツールによるデバッグ手法を使っている
- 深く隠されてつかみどころのない問題を迅速に発見したい場面に従来のやり方ではどう考えても対処できなくなったため、必要性に迫られてオブザーバビリティツールが誕生した

# オブザーバビリティの数学的定義

- この用語は1960年にエンジニアのRudolf E. Kalmanの論文で発表された
- そこではある特徴を「オブザーバビリティ」と呼び、数学的制御システムを説明した
- ここでの定義
    - 外部出力の知識からシステムの内部状態をどれだけうまく推測できるかの尺度
- オブザーバビリティはコントローラビリティとセットで研究されていた。もともとは機械エンジニア向けの用語だった。

# オブザーバビリティのソフトウェアシステムへの適用

- オブザーバビリティの概念をソフトウェアシステムに適用する場合、この領域特有の考慮事項を追加する必要がある
- つまり、ソフトウェアにオブザーバビリティを適用するためには、エンジニアはシステムに対して次のことができなければいけない
    - アプリケーションの内部構造を理解することができる
    - 今まで見たことのない、予測できないことが起こったとしても、アプリケーションがどのようなシステム状態に陥っているかを理解することができる
    - 外部ツールを使って観測し、調査することで、内部動作とシステム状態を理解することができる
    - 新たにコードを回収することなく、内部状態を理解する（コードを改修するには何が起こるかをあらかじめ知っておく必要があるため）ことができる
- もうちょっとかみ砕くと…↓↓ができるシステムが「オブザーバビリティを持つシステム」
    - 障害が起きたときに、何らかシステム内部を変更（設定変更、コード修正）しなくても、アプリ内部のどこでどんな問題が起きているのかがわかる
- 翻って、何らかのコード修正、設定変更が必要ってことは「オブザーバビリティを高める余地がある」と言える
- オブザーバビリティの定義がわかると次に気になるのがこちら
    - どんなデータを収集しておけばいいの？
    - 収集したデータをどう処理・分析したら障害調査に使えるの？そのためにはどんな技術が必要？
    - データを活用するためにはどんなチーム力が必要？

### セルフチェック：うちのシステムオブザーバビリティある？テスト

- 何か障害が起きたときに調査中に「中で何が起きてるかわからない」ということがなく、原因を論理だてて説明ができるか？
- システムを利用している人が、いつどこで何をしてるかを個人レベルで追跡することができる
- 気になるシステムパフォーマンス（レスポンス低下など）を、全体の集計ビューから速度低下の原因となっている単一の正確なユーザーリクエストまで素早くみられるか？
- アプリケーションの予期せぬ挙動がおきたときに、その挙動が起きたユーザーの共通の属性ととそうでないユーザーとを比較することができるか？
- どのユーザーが最もシステムに負荷を与えているかを特定することができるか、同様に２番目、３番目なども特定できるか？
- 今発生している負荷が発生したときに一番最初に影響を与えたユーザーが誰かを特定することができる
- 上記の状況が今回初だったとしても、原因と発生箇所を特定することができる
- 調査してみて「ナニコレ？」っていうものが見つかることが多いか？

などなど…以下略

# ソフトウェアにおけるオブザーバビリティの誤解

- SaaSベンダーの主張は以下のようなものがある
    - 「オブザーバビリティ」は「テレメトリー」の同義語
    - 「モニタリング」と区別がつかないもの
- この手の輩の根源的な思想には以下のものがある
    - オブザーバビリティはソフトウェアがどう動くのかを理解するための一般用語
    - オブザーバビリティの３本柱は「メトリクス、ログ、トレース」
    - 既存のモニタリングツールは、システムの持つメトリクス、ログ、トレース情報をリアルタイムで収集保管し、これを検索することで原因調査を行うことができる
    - つまり、既存のモニタリングツールはオブザーバビリティを実現している！さぁ最新のオブザーバビリティをモニタリングツールを使って体験しよう
- …と言っているがこれはベンダー側がツールの既得権を手放したくないが故の主張で、これには論理的欠陥がある
    - オブザーバビリティのやり方をメトリクス、ログ、トレースと限定しており、オブザーバビリティの可能性を制限してしまっている
- オブザーバビリティは、バラバラのツールをマーケティングでくっつけることでは達成できない
- **オブザーバビリティを実現するためには、効果的なデバッグに必要なデータを収集するための考え方を進化させることが必要**

# なぜ今オブザーバビリティが重要なのか？

- 従来の手法：メトリクスを使ってソフトウェアが何をしているかを理解しようとする
    - 劇的に不十分
    - このアプローチは根本的に受動的（リアクティブ）
- この従来の手法こそが「モニタリング」
- 不十分と言いつつも、これまでのやり方としては最良のものだったのでいつまでもこれを使っていたのが現状と受け止めている
- モニタリングの持つ欠陥
    - ソフトウェア開発者はシステムを完全に見ることができない
    - モニタリングはシステムに対して目を凝らす
    - モニタリングが見ているのは常に既知の障害
    - 閾値を設定して「良し悪し」を判断する
    - その「良し悪し」の判断基準は既知の経験に基づくもの
    - モニタリングの特徴は、この既知の「良し悪し」の判断をリアルタイムを大量＆機械的に行うこと
    - 常に数字に目を光らせて、ご機嫌を伺い続ける庭師と同じようなもの

### これは本当にベストな方法なのでしょうか？

- このやり方は現場の運用担当が数十年続けてきたやり方
- そのため、この方法については、**やるべきかどうか？**ではなく**どうやるか？**になりがち
- モニタリングの実践は、システムに関する多くの暗黙の前提に根差している
- しかし、システムが進化し、より抽象的で複雑になり、その根底にある構成要素が重要でなくなるにつれてそれらの前提は真実でなくなっていきます。
- これは、開発者がより新しいアプローチ（SaaS依存、コンテナオーケストレーション、分散システムなど）を採用し続けるにつれて、亀裂が入ることが明白になる
- つまり、従来のモニタリングのやり方は、システムを理解するためには致命的に効果がない。

### なぜメトリクスとモニタリングでは不十分なのか？

- モニタリングの基礎となるメトリクスは、1988年のRFC1157（SNMPv1）により誕生した
- メトリクスは遠隔地のエンドポイントから収集したデータをモニタリングシステムに自動送信するテレメトリーの基本単位になった
- この基礎をベースに、グラフ作成ライブラリ、ダッシュボード、オンコールローテーション、エスカレーションポリシーといった仕組みができあがった
- このメトリクスで理解できるシステムの複雑さは上限があり、ある境界を超えると一気に機能しなくなる
    - 結果、straceやtcpdumpなど低レベルのコマンドやログの内容を見るというやり方に逆戻りになってしまう
- モニタリングやメトリクスベースのツールは、アーキテクチャや組織に関する前提に基づいて構築されているので、それによって複雑さにふたをするような役割を果たしている。

### セルフチェック：この前提があるからメトリクスベースでもなんとかやれてるんちゃう？チェック

- システムの構成はすべてWeb-DB構成
- DBはMySQL
- あらかじめ用意されているメトリクスはCPU,メモリ、DISK IO
- 決められたVM上でアプリケーションは動作している
- ノードやコンテナは一定で、常時稼働している
- エンジニアは問題が起きてから行動する
- モニタリングの主たる目的は、稼働確認と障害防止

### セルフチェック２：いつの間にか現場ってこんな状況になってない？チェック

- アプリケーションには多くのサービスがある
- インフラは動的に拡張され、キャパシティは弾力的に増減させることができる
- 遠く離れた疎結合のサービスが多数管理されていて、そのほとんどは自分の管理下ではない
- エンジニアは、小さな問題を早期に発見するためにコードを積極的にチェックする
- ソフトウェアエンジニアは、コードのオーナーで、主体的に実装して、システム変更するときにはパフォーマンスチェックが必要
- 信頼性の焦点は、エラーバジェット、サービス品質、ユーザー体験などの構成を利用して、ユーザーに影響を与える障害に対するレジリエンシーを構築しながら一定且つ継続的な劣化に以下に耐えるかということにある
- 相関関係の検討は、事実上無制限のディメンシションの間で行われる

## メトリクスを用いたデバグとオブザーバビリティの比較

- いまやシステム規模が大きくなりすぎて、頭の中で抱えてる範疇を超えてるのが普通になってしまっている
- これまでは過去の経験に基づく直感でどうにかなったかもしれないけども、今はそれも通用しなくなっている
- メトリクスベースは既知の障害では有効。では新規の障害のときはどうすればよいのか？
- 歴史的に見ると、これまでのシステムは既存のシステムの集合体だったので、ここの仕組みをチェックすればわからないことはなかった。説明のつかない事象が出ることは稀だったともいえる
- しかし、現在の分散アプリケーションは抽象化されたインフラ基盤にもアクセスできるようになっているため、膨大で分解できない複雑さに真正面から対応しなければならない
- 現在のアーキテクチャがモノリスマイクロサービスに分解することを指示し始めたときから、エンジニアは従来のデバッガーでコードをステップスルーすることができなくなってしまった
- 現在のクラウドネイティブシステムにおけるデバグで最も困難なことは、「コードがどのように動いているか」ではなく**「問題のあるコードが、システム内のどこに存在するのかを見つける」**ことにある。
- このようなシステムでは「どこかが遅くなる」と「すべてが遅くなる」
- しかも問題は「自分たちの関係しないところで問題が起きること」にある
- このような状況でメトリクスを使ってデバグしようとすると、、、、
    - 特定のリクエストを実行する過程で記録された何十ものメトリクスを収集する
    - 任意の数のサービスやマシンの間でつなぎ合わせる
    - そこからどこで問題があるかを推測する
- この結果が有効かどうかは「測定値が閾値を上回ったか下回ったか、事前に予測できたか」によって決まる、もはや運任せに陥る
- これに対して、オブザーバビリティを用いたデバグは全く異なるコンテキストからのスタートとなる
    - 事象が発生したリクエストはどこからなのか？
    - そのリクエストはどのようなアクションを行ったのか？
    - そのアクションのどの段階で問題が発生したのか？
- **モニタリングは既知の未知を扱うが、オブザーバビリティは未知の未知を扱う**

### カーディナリティの役割

- カーディナリティとはデータベースの文脈で使われる
- カーディナリティとは集合に含まれるデータの値の一意性
    - 低いカーディナリティ→そのカラムの集合の中に重複する値が多くあること
    - 高いカーディナリティ→列がユニークな値を大きな割合で含んでいること
    - 例：国民データベースがあるとして、マイナンバー列の値は一意なので高いカーディナリティだが、氏名の列は同姓同名の人は多くいるのでマイナンバーと比べて低いカーディナリティと言える
- オブザーバビリティにとって高いカーディナリティは重要
    - 高いカーディナリティの列を使えば、大量のデータの中から特定の情報を容易に拾い上げることができる
- 一方メトリクスベースのツールはカーディナリティの低いディメンションしか扱えない
    - 比較するホストが数百台しかなくても、キー空間のカーディナリティの制限にぶつかってしまい、ホスト名を識別吸うためのタグとしても使用できない
    - 例：あるシステムで、特定のページにアクセスするときにサービスが遅延するとわかったとして、メトリクスで特定するためには、「特定のページにアクセスすると１を出力する」メトリクスを用意する必要があるもしくは「リクエストが来るたびにページの番号を出力するメトリクス」を用意する必要がある。しかもそれは、あらかじめ用意しておく必要があるため、次に問題が発生するのを待たなくてはいけないといった課題もある

### ディメンションの役割

- カーディナリティはデータの値のユニークさを意味するのに対して、ディメンションはデータ内のキーの数を意味する
- あるイベントスキーマがあるとして、そのイベントスキーマは「time,app,host,user,endpoint,status」で構成されている
    - このとき**「ディメンションは６つある」**と言える
    - 異常を探すときには以下のパターンを探すようになる
    - 例：hostがfooで、過去30分間に発生した、すべての502エラー、userがbarで、endpointが/exportのリクエストで発生した、すべての403エラー
- オブザーバビリティを用いたデバグでは、高いカーディナリティのデータをどのように分析して、関心のある問題がシステム内部のどこで起こっているか、なぜ起こっているかを明らかにすることになる

## オブザーバビリティを用いたデバッギング

- オブザーバビリティツールは、以下のようなことを開発者に推奨しています
    - テレメトリーデータのカーディナリティやディメンションを制限することなく
    - 発生するすべてのイベントに関する豊富なテレメトリーを収集し、
    - 任意のリクエストに対するコンテキストをすべて伝え
    - この先のどこかの時点で使用できるようにするために保存する
- オブザーバビリティツールは高いカーディナリティ、高いディメンションを持つデータに対してクエリを実行するように設計されています
- **探索可能性**とは、システムが陥った任意の状態に対しても、たとえそれが今まで見たことがない状態だとしても、事前にそのような状態になることを予測することなく、繰り返し調査して最終的に理解できることを意味する
- オブザーバビリティとは、システムの任意の状態に対して、それが斬新で奇妙だったとしても、新たなコードのリリースなしに状況を理解して説明できることを意味します。
- モニタリングが長い間うまくいっていたのは、システムが単純で、どこに問題があるかをエンジニアが性格に推論できたから。
- エンジニアは概して、可能性のある障害状態の大部分を前もって予測することができ、残りの小ギアはアプリケーションが本番稼働してから発見できた
- しかし、モニタリングはシステム管理に対する基本的にリアクティブなアプローチ
- 事前に予測してチェックする必要があると知っている状態だからキャッチできる
- それゆえ、モニタリングのやり方では、「予測不可能な失敗を引き起こす可能性のある状況」を強く嫌うことになる（＝変化を恐れる）といったよじれたインセンティブが働きます。これが運用チームが新しいコードのデプロイを恐れる理由の一つ
- ハードやインフラの問題は、コードやユーザーによって発生する問題に比べたら簡単です。ただし、状況が「問題のほとんどはコンポーネントの故障です」から「ユーザーの行動や微妙なコードのバグや相互作用に関係しています」に変化していってるようであれば、それはモニタリングからオブザーバビリティに転換する理由になります

## オブザーバビリティは現代のシステムのためにある

- 稼働中のシステム化以下の状態であればオブザーバビリティを備えているといえる
    - 障害モードを事前に予測できる
    - その状態を理解するために新しいコードのデプロイする必要はない
- 分散システムにおいて予測可能な障害っモードは減り、見たこともない障害モードのほうが多いです。
- このような状況では、従来の管理手法よりもオブザーバビリティのほうが、利点を実現するのに適しています。

## まとめ

- オブザーバビリティは何十年も前から定義されているが、ソフトウェアシステムへの適用は新たな事例
- 現在のシステムはますます複雑になり、困難になっている
- このような複雑さを軽減するために、テレメトリーを常時柔軟な方法で収集し、予測できない障害が発生してもデバグできるようにしなければならない
- オブザーバビリティは「３本柱」のテレメトリーデータがある場合に達成されると誤解されることが多いがそんなことはない
- もし「３本柱」とよぶものをつけるのであれば
    - 高いカーディナリティ
    - 高いディメンション
    - 探索可能性をサポートするツール