Grafana Tempo v2.2でStructural operatorsが追加されたのでユースケースを考えてみます
- ユースケース1 「NATループバックの可能性のある通信を探す」
Kubernetesにはクラスタ内にあるDNSサーバが名前解決してServiceやPodへ通信する機能があります。Service間の通信はこちらを使うことでクラスタ外に出ずに通信することが出来るので通常はこちらを使うことになります。
しかし、意図せずクラスタ外のDNSで登録されたドメインを使った通信をアプリケーションが実装してしまうこともあるでしょう。この場合にパフォーマンス以外の問題としてNLBを前段においてインスタンスを登録している場合、トラフィック送信元IPをそのままターゲットに送信します。そうなることで送信元と送信先が同一IPとなってしまうことでNATループバック(ヘアピニング)が発生しリクエストがタイムアウトしてしまうことがあります。
この例ではIstioを使っていてIngress Gatewaysをクラスタの入り口とした場合を考えます
とあるService Aから別のService Bに通信するときにservice-b.default.svc.cluster.local.と通信すべきところを外部ドメインのservice-b.example.comで通信してしまったとしています。
なんらかの方法でこのNATループバックが起きる可能性がある通信を検知したとします(eBPFなどでtcp監視してメトリクス送信してアラートで検知など)
そういった場合の調査でStructural operatorsを使うといいかもしれません
{.service.name="service-a.default"} >> {.service.name="istio-ingressgateway.istio-system"}
service-aが記録しているtraceのなかでistio-ingressgateway.istio-systemに通信しているものを洗い出します。その先がクラスタのServiceであればそれはNATループバックのリスクがある通信だということになります。
- ユースケース2 「とあるサービスでDBへの接続に時間がかかっているリクエストを調べる」
メトリクスでやることが適切なような気もしますが雑に調べるとすれば例えばこうです
{.service.name="service-a"} >> {.net.peer.name="db.example.com" && .db.operation = "CONNECT" && duration > 50ms}
先にDBのコネクトに時間がかかっているspanを検索してもいいのですが
{.net.peer.name="db.example.com" && .db.operation = "CONNECT" && duration > 50ms}
Structural operatorsが利用できるのであればServiceを特定することが出来ますね
さいごに
Structural operatorsによって目的のトレースを取得するための選択肢が増えました
便利に使っていこうと思います