フローはどこにどれだけ残っているのか
一言でいうと
Hubbleは、eBPFデータパスが生成したイベントをノードローカルのリングバッファに溜め、relayがそれをクラスター単位でまとめます。リングバッファはローテーションするため、長期の分析にはexportが必須です。
なぜ必要なのか
ポリシーを強制適用し始めると、疑問が噴き出します。「さっき決済APIがなぜ切れたのか」「このドロップはポリシーのせいか、ルーティングのせいか」。データパスがカーネルの中に入った以上、観測手段も同じ深さから取り出す必要があります。
従来の方式は、サイドカープロキシを付けてリクエストを観測していました。Podごとにプロキシが1つずつ付くのでリソースが2倍になり、Podスペックを変える必要があるので再起動も必要です。Hubbleは、すでにデータパスに付いているeBPFプログラムが生成したイベントをそのまま読み取るので、追加のプロキシもPodの変更も必要ありません。
どう動くのか
構造は3層です。
[eBPF 데이터패스] --perf 링버퍼--> [cilium-agent 안의 Hubble 서버]
gRPC :4244
|
[hubble-relay] :4245
|
+-------------+-------------+
v v
[hubble CLI] [hubble-ui]
ここから、運用上重要な性質が3つ出てきます。
1つ目は、フローがノードローカルのメモリにしか一時的に存在しないことです。デフォルトのバッファはノードあたり4095フローで、拡張しても、よく使われる値は16383です。フロー1つが約500バイトを占めるので、16383ならノードあたりおよそ8MiBです。トラフィックの多いノードでは数秒でローテーションすることがあるので、監査の証跡や事後分析には、必ずファイルへのexportを付ける必要があります。
2つ目は、relayは集約役にすぎず、保存先ではないことです。relayが落ちても、データパスとノードローカルの観測はまったく影響を受けません。ポートは、relayが4245、ノードのHubbleサーバーが4244、メトリクスエンドポイントが9965です。
3つ目は、ペイロードは保存しないことです。フローは、送信元・宛先のアイデンティティとラベル、判定(verdict)、ドロップの理由、HTTP/DNSのメタデータを含む構造化イベントです。パケットの内容が必要なら、別のツールを使う必要があります。
判定値の読み方が、実戦の核心です。
| verdict | 意味 |
|---|---|
| FORWARDED | 許可されて転送された |
| DROPPED | ブロックされた(ドロップの理由が一緒に付く) |
| AUDIT | 監査モードだったが、強制状態であればブロックされたトラフィック |
| ERROR | 処理中のエラー |
ドロップの理由ごとに、最初に疑う箇所を整理しておくと時間を節約できます。POLICY_DENIEDはポリシーで許可されていないのでアイデンティティとポートを見直し、CT_MAP_INSERT_FAILEDはconntrackマップが満杯なのでマップのサイズを調整し、UNSUPPORTED_L3_PROTOCOLはIP以外のトラフィックであり、STALE_OR_UNROUTABLE_IPはipcacheの不一致なので、ノード間の同期を点検します。
最後に、必ず区別しておくべきことがあります。L7の拒否は、L4のドロップとログの形が異なります。 L4で止められると接続が成立せず、リクエスト1行で終わりますが、L7ルール違反は、すでに確立された接続の上でプロキシが403を作って返すので、リクエストはDROPPED、応答はFORWARDEDと記録されます。この非対称を知っていれば、ログ2行を見るだけで、どの層の問題なのかを判定できます。
現場での姿
筆者がホームラボにHubbleを導入したとき、hubble-relayとhubble-uiがPendingのまま動きませんでした。イベントは次のとおりです。
Warning FailedScheduling 0/1 nodes are available: 1 node(s) had untolerated taint(s).
原因はスケジューリングでした。コントロールプレーンノードにはnode-role.kubernetes.io/control-plane:NoScheduleのtaintがかかっていますが、hubble-relayとhubble-uiはDaemonSetではなくDeploymentなので、tolerationがありませんでした。CoreDNSは、デフォルトでcontrol-planeのtolerationを持っているため、正常に起動できたのと対照的です。ワーカーノードが参加するとすぐに解消され、これはエラーではなく、正常な動作でした。
ここで身に付けたい感覚があります。Cilium AgentとHubbleサーバーは、ノードごとに必要なのでDaemonSetであり、relayとUIは、クラスターに1つあれば足りるのでDeploymentです。デプロイの形が違えば、スケジューリングの制約も違います。「agentはすべて起動したのに、hubble CLIだけが接続できない」場合は、relay Podの状態から見るのが順番です。
同じクラスターでL7ポリシーをかけて得たログは、前のモジュールで見たとおりです。GETリクエストはFORWARDED、POSTリクエストはDROPPED、そしてそのPOSTに対する403応答はFORWARDED。ログ3行が、ポリシーが意図どおりに動作したことの証拠でした。
次のラボですること
Hubbleを有効にする値と、メトリクス・exportの設定を作成し、実際のワークロードにラベルを付けて、アイデンティティに含まれるラベルと除外されるラベルをConfigMapで整理し、よく使うフローフィルターのクエリとドロップ理由の診断表、そしてドロップ急増のアラートルールまで作ります。