TT Lab
はじめる
学ぶ 学習パス コース

Istioサービスメッシュ

メトリクス・アクセスログ・トレース — プロキシがタダでくれるものとそうでないもの

TT Labで続きを見る

一言でいうと

メッシュは、リクエストがプロキシを通るついでに、メトリクス・アクセスログ・スパンを作ってくれます。ただし、トレースだけは、アプリケーションがヘッダーを引き渡さないと途切れます。

なぜ必要なのか

オブザーバビリティをアプリケーション側で用意すると、2つの点でずれが生じます。第一に、定義がサービスごとに違います。あるチームは5xxだけをエラーとして数え、別のチームは4xxも数えます。あるチームはクライアント基準で、別のチームはサーバー基準でレイテンシを測ります。ダッシュボードを並べても比較になりません。第二に、計装されないサービスが残ります。急いで作った社内ツール、引き継いだチームのレガシー、外注で受け取ったコンポーネントには計装がなく、それがいつも障害の死角になります。

メッシュはこの問題を、「リクエストはどうせプロキシを通るのだから、そこで測ろう」という発想で解きます。標準メトリクスの名前とラベルが、すべてのサービスで同じになります。この均一性は、計装を新しく付けて回るよりもはるかに大きな価値です。

どう動くのか

メトリクス: 各サイドカーは、ポート15090でPrometheus形式の統計を公開します。核心は次の3つです。

メトリクス 種類 使う場所
istio_requests_total カウンター リクエスト数、エラー率
istio_request_duration_milliseconds ヒストグラム p50/p99のレイテンシ
istio_request_bytes / istio_response_bytes ヒストグラム ペイロードのサイズ

ラベルの中で、特に知っておくべきものが3つあります。reporterは、source(送る側のプロキシ)とdestination(受け取る側のプロキシ)に分かれますが、同じリクエストが両側でそれぞれ記録されるため、2つを合算すると2倍に数えてしまいます。response_flagsは、アクセスログのフラグと同じ値なので、503の性質をメトリクスだけでも区別できます。connection_security_policyはmutual_tlsかnoneで、STRICT切り替えの完了基準は、このラベルがnoneであるリクエストが0件になることです。

落とし穴の1つはカーディナリティです。ラベルにリクエストのパスやユーザーIDのような値を入れると、時系列が爆発します。カスタムタグには、値の種類が有限なものだけを入れる必要があります。

アーキテクチャが変わった歴史も知っておく価値があります。以前は、Mixerという別のサービスがリクエストごとに呼び出されてメトリクスを集めており、それがレイテンシと障害の原因でした。今は、プロキシ内部のフィルターが直接作ります(Telemetry API v2)。そのため、オブザーバビリティのためにリクエスト経路にホップが追加されることは、もうありません。

アクセスログ: プロキシが、リクエストごとに1行を残します。人が読むべき部分は、レスポンスコードと、その隣のフラグです。

フラグ 意味 最初に見るもの
UH 正常なアップストリームなし subsetのラベルとPodのラベル
UF アップストリームへの接続失敗 片方だけSTRICTのmTLSの不一致
UO 接続プールの超過 サーキットブレーカーの上限
NR ルートなし catch-allルートがあるか
URX リトライの使い切り 根本原因は他のフラグと一緒に
UAEX 外部認可の拒否 CUSTOMポリシーと認可サーバーの状態

全件のログ記録は高くつきます。Telemetryリソースのフィルターで、response.code >= 400のような条件を付けて、失敗だけを残す構成がよく使われます。

分散トレーシング: ここが「タダではない」部分です。プロキシは、スパンを作り、タイミングを測り、コレクターへ送るところまでやってくれます。ところが、インバウンドリクエストのトレースヘッダー(B3系、またはW3Cのtraceparent)を、アウトバウンドリクエストにコピーする作業は、アプリケーションが行わなければなりません。これをしないと、サービスごとに別々のトレースが作られて、呼び出しの連鎖が途切れます。「メッシュを入れたのに、トレースが1ホップ分しか見えない」の答えは、ほとんどいつもこれです。

サンプリングの既定値は1%です。最初のプロキシがサンプリングするかどうかを決めてヘッダーで伝播するので、後ろのプロキシはその決定に従います。デバッグのときだけ上げて、常時100%にはしません。

可視化: Kialiは、Prometheusのメトリクスでサービスグラフを描き、Kubernetes APIとIstioの設定を読んで、参照整合性まで検査します。つまり、Kialiの設定検証は、istioctl analyzeと同じ種類の仕事を画面で見せてくれるものです。

現場での姿

第一に、sourceとdestinationを混ぜて数えるダッシュボードです。リクエスト数がちょうど2倍になっていたら、十中八九、reporterのフィルターを入れ忘れています。クライアントの観点ならsource、サーバーの観点ならdestinationのどちらか1つに固定する必要があります。

第二に、メッシュのメトリクスはアプリケーションのメトリクスの代わりにはなりません。プロキシが知っているのは「リクエストが200を返した」ところまでです。レスポンスの本文が間違っていたか、注文が実際に保存されたかはわかりません。メッシュのオブザーバビリティはインフラ層の均一な土台であり、ドメインの指標は、やはりアプリケーションが出す必要があります。

第三に、サイドカーのない経路は見えません。メッシュの外のcronや、注入されていないネームスペースのトラフィックは、グラフにまったく現れません。グラフがきれいだからといって、トラフィックがないという意味ではありません。

次のラボですること

最初に正直にお伝えしておきます。このラボ環境には、実際にトラフィックを運ぶEnvoyがありません。サイドカーが付いたPodがRunningになっても、リクエストは流れず、15090をスクレイプすることも、15000の管理APIを叩くこともできません。そのため、メトリクスの値やトレースの図を作り出すようなラボは作っていません。

その代わり、すぐあとのラボでは、シグナルを設計する側を扱います。メッシュ全体に既定のアクセスログを敷き、レスポンスコードで失敗だけを残すフィルターをかけ、ワークロード1つにサンプリング率とリテラルのタグを付け、標準メトリクスを1つオフにします。そのあと、カーディナリティを爆発させるタグを、デプロイ前に弾く検査ツールを作り、セレクターのないTelemetryが1つのネームスペースに2つあると、istioctl analyzeがエラーとして検出するところまで見ます。値が流れなくても、設定が有効か、範囲が正しいかは、そのまま検証されます。現場で人がつまずく場所も、たいていその2つです。