Ztunnel トラフィックリダイレクト
アンビエントモードのコンテキストにおいて、トラフィックリダイレクトとは、アンビエント対応ワークロードとの間で送受信されるトラフィックをインターセプトし、コアデータパスを処理するztunnelノードプロキシを経由してルーティングするデータプレーン機能を指します。場合によっては、トラフィックキャプチャという用語も使用されます。
ztunnelはアプリケーショントラフィックを透過的に暗号化およびルーティングすることを目的としているため、「インメッシュ」ポッドに出入りするすべてのトラフィックをキャプチャするメカニズムが必要です。これはセキュリティ上重要なタスクです。ztunnelをバイパスできる場合、承認ポリシーをバイパスできます。
Istio のポッド内トラフィックリダイレクトモデル
アンビエントモードのポッド内トラフィックリダイレクトを支えるコア設計原則は、ztunnelプロキシがワークロードポッドのLinuxネットワーク名前空間内でデータパスのキャプチャを実行できることです。これは、istio-cni
ノードエージェントとztunnelノードプロキシ間の機能連携によって実現されます。このモデルの重要な利点は、Istioのアンビエントモードが任意のKubernetes CNIプラグインと透過的に連携し、Kubernetesネットワーキング機能に影響を与えずに動作することを可能にすることです。
次の図は、新しいワークロードポッドがアンビエント対応名前空間に開始(または追加)されたときのイベントシーケンスを示しています。
istio-cni
ノードエージェントは、ポッドの作成や削除などのCNIイベントに応答し、アンビエントラベルがポッドまたは名前空間に追加されるなどの基盤となるKubernetes APIサーバーのイベントも監視します。
istio-cni
ノードエージェントはさらに、Kubernetesクラスタ内のプライマリCNIプラグインの実行後にコンテナランタイムによって実行される、チェーン化されたCNIプラグインをインストールします。その唯一の目的は、アンビエントモードに既に登録されている名前空間でコンテナランタイムによって新しいポッドが作成されたときにistio-cni
ノードエージェントに通知し、新しいポッドコンテキストをistio-cni
に伝播することです。
istio-cni
ノードエージェントは、ポッドをメッシュに追加する必要があることを通知されると(ポッドが真新しい場合はCNIプラグインから、ポッドが既に実行中で追加が必要な場合はKubernetes APIサーバーから)、次の操作シーケンスを実行します。
istio-cni
はポッドのネットワーク名前空間に入り、ネットワークリダイレクトルールを確立します。これにより、ポッドに出入りするパケットはインターセプトされ、既知のポート(15008、15006、15001)をリッスンしているノードローカルのztunnelプロキシインスタンスに透過的にリダイレクトされます。次に、
istio-cni
ノードエージェントは、Unixドメインソケットを介してztunnelプロキシに、ポッドのネットワーク名前空間内にローカルプロキシリスニングポート(ポート15008、15006、15001)を確立する必要があること、およびポッドのネットワーク名前空間を表す低レベルのLinux ファイル記述子をztunnelに提供することを通知します。- 通常、ソケットはLinuxネットワーク名前空間内で、そのネットワーク名前空間内で実際に実行されているプロセスによって作成されますが、Linuxの低レベルソケットAPIを利用して、あるネットワーク名前空間で実行されているプロセスが、別のネットワーク名前空間でリスニングソケットを作成することを完全に可能にすることができます(ターゲットネットワーク名前空間が作成時にわかっている場合)。
ノードローカルのztunnelは、内部的に新しいプロキシインスタンスとリスニングポートセットをスピンアップし、新しく追加されたポッドに専念します。
ポッド内リダイレクトルールが設定され、ztunnelがリスニングポートを確立すると、ポッドがメッシュに追加され、トラフィックがノードローカルのztunnelを介して流れ始めます。
メッシュ内のポッドとの間で送受信されるトラフィックは、デフォルトでmTLSを使用して完全に暗号化されます。
データは、暗号化された状態でポッドネットワーク名前空間に出入りするようになります。メッシュ内のすべてのポッドは、ポッド内で実行されているユーザーアプリケーションがそのいずれにも気付かなくても、メッシュポリシーを適用し、トラフィックを安全に暗号化することができます。
この図は、新しいモデルにおけるアンビエントメッシュ内のポッド間の暗号化されたトラフィックのフローを示しています。
アンビエントモードでのトラフィックリダイレクトの監視とデバッグ
アンビエントモードでトラフィックリダイレクトが正しく動作していない場合は、問題を絞り込むためにいくつかの簡単なチェックを行うことができます。ztunnelデバッグガイドに記載されている手順からトラブルシューティングを開始することをお勧めします。
ztunnel プロキシログの確認
アプリケーションポッドがアンビエントメッシュの一部である場合、ztunnelプロキシログを確認して、メッシュがトラフィックをリダイレクトしていることを確認できます。以下の例に示すように、inpod
に関連するztunnelログは、ポッド内リダイレクトモードが有効になっていること、プロキシがアンビエントアプリケーションポッドに関するネットワーク名前空間(netns)情報を受信したこと、およびそのプロキシを開始したことを示しています。
$ kubectl logs ds/ztunnel -n istio-system | grep inpod
Found 3 pods, using pod/ztunnel-hl94n
inpod_enabled: true
inpod_uds: /var/run/ztunnel/ztunnel.sock
inpod_port_reuse: true
inpod_mark: 1337
2024-02-21T22:01:49.916037Z INFO ztunnel::inpod::workloadmanager: handling new stream
2024-02-21T22:01:49.919944Z INFO ztunnel::inpod::statemanager: pod WorkloadUid("1e054806-e667-4109-a5af-08b3e6ba0c42") received netns, starting proxy
2024-02-21T22:01:49.925997Z INFO ztunnel::inpod::statemanager: pod received snapshot sent
2024-02-21T22:03:49.074281Z INFO ztunnel::inpod::statemanager: pod delete request, draining proxy
2024-02-21T22:04:58.446444Z INFO ztunnel::inpod::statemanager: pod WorkloadUid("1e054806-e667-4109-a5af-08b3e6ba0c42") received netns, starting proxy
ソケットの状態の確認
ポート15001、15006、および15008のソケットが開いていてリスニング状態であることを確認するには、次の手順に従ってください。
$ kubectl debug $(kubectl get pod -l app=curl -n ambient-demo -o jsonpath='{.items[0].metadata.name}') -it -n ambient-demo --image nicolaka/netshoot -- ss -ntlp
Defaulting debug container name to debugger-nhd4d.
State Recv-Q Send-Q Local Address:Port Peer Address:PortProcess
LISTEN 0 128 127.0.0.1:15080 0.0.0.0:*
LISTEN 0 128 *:15006 *:*
LISTEN 0 128 *:15001 *:*
LISTEN 0 128 *:15008 *:*
iptables ルールの設定の確認
アプリケーションポッドの内部に設定されているiptablesルールを表示するには、次のコマンドを実行します。
$ kubectl debug $(kubectl get pod -l app=curl -n ambient-demo -o jsonpath='{.items[0].metadata.name}') -it --image gcr.io/istio-release/base --profile=netadmin -n ambient-demo -- iptables-save
Defaulting debug container name to debugger-m44qc.
# Generated by iptables-save
*mangle
:PREROUTING ACCEPT [320:53261]
:INPUT ACCEPT [23753:267657744]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [23352:134432712]
:POSTROUTING ACCEPT [23352:134432712]
:ISTIO_OUTPUT - [0:0]
:ISTIO_PRERT - [0:0]
-A PREROUTING -j ISTIO_PRERT
-A OUTPUT -j ISTIO_OUTPUT
-A ISTIO_OUTPUT -m connmark --mark 0x111/0xfff -j CONNMARK --restore-mark --nfmask 0xffffffff --ctmask 0xffffffff
-A ISTIO_PRERT -m mark --mark 0x539/0xfff -j CONNMARK --set-xmark 0x111/0xfff
-A ISTIO_PRERT -s 169.254.7.127/32 -p tcp -m tcp -j ACCEPT
-A ISTIO_PRERT ! -d 127.0.0.1/32 -i lo -p tcp -j ACCEPT
-A ISTIO_PRERT -p tcp -m tcp --dport 15008 -m mark ! --mark 0x539/0xfff -j TPROXY --on-port 15008 --on-ip 0.0.0.0 --tproxy-mark 0x111/0xfff
-A ISTIO_PRERT -p tcp -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A ISTIO_PRERT ! -d 127.0.0.1/32 -p tcp -m mark ! --mark 0x539/0xfff -j TPROXY --on-port 15006 --on-ip 0.0.0.0 --tproxy-mark 0x111/0xfff
COMMIT
# Completed
# Generated by iptables-save
*nat
:PREROUTING ACCEPT [0:0]
:INPUT ACCEPT [0:0]
:OUTPUT ACCEPT [175:13694]
:POSTROUTING ACCEPT [205:15494]
:ISTIO_OUTPUT - [0:0]
-A OUTPUT -j ISTIO_OUTPUT
-A ISTIO_OUTPUT -d 169.254.7.127/32 -p tcp -m tcp -j ACCEPT
-A ISTIO_OUTPUT -p tcp -m mark --mark 0x111/0xfff -j ACCEPT
-A ISTIO_OUTPUT ! -d 127.0.0.1/32 -o lo -j ACCEPT
-A ISTIO_OUTPUT ! -d 127.0.0.1/32 -p tcp -m mark ! --mark 0x539/0xfff -j REDIRECT --to-ports 15001
COMMIT
コマンド出力は、アプリケーションポッドのネットワーク名前空間内のnetfilter/iptablesで、NATテーブルとMangleテーブルに追加のIstio固有のチェーンが追加されていることを示しています。ポッドに入るすべてのTCPトラフィックは、イングレス処理のためにztunnelプロキシにリダイレクトされます。トラフィックがプレーンテキスト(ソースポート!= 15008)の場合、ポッド内のztunnelプレーンテキストリスニングポート15006にリダイレクトされます。トラフィックがHBONE(ソースポート== 15008)の場合、ポッド内のztunnel HBONEリスニングポート15008にリダイレクトされます。ポッドから出るTCPトラフィックはすべて、エグレス処理のためにztunnelのポート15001にリダイレクトされ、その後、ztunnelによってHBONEカプセル化を使用して送信されます。