ztunnel が見るのは L4 まで
一言でいうと
アンビエントモードは、サイドカーの代わりにノードごとに1つのztunnel(L4: mTLS・身元・接続単位のポリシー)と必要な場所にだけ置くwaypoint(L7: HTTPルーティング・HTTPポリシー)で仕事を分けます。何を誰が強制するのかを知らずにポリシーを書くと、書いたルールが黙って抜け落ちたり、正常だったトラフィックが途切れたりします。
なぜ必要なのか
サイドカーモードは、PodごとにEnvoyを1つずつ付けます。Podが1000個ならEnvoyも1000個で、それぞれがメモリとCPUを使い、サイドカーを変えるにはPodを作り直す必要があります。そして、ほとんどのサービスが実際に求めるのはmTLSと身元ベースのL4ポリシーだけなのに、HTTPを解釈する重いプロキシをみんなが背負っています。
アンビエントは、この2つの層を切り離しました。mTLSとL4はノードのztunnelが担い、HTTPが必要なサービスにだけwaypoint(Envoy)を置きます。ネームスペースにラベルを1つ(istio.io/dataplane-mode=ambient)付けると、istio-cniがPodのネットワークネームスペースの中にリダイレクト規則を仕込み、トラフィックをztunnelへ送ります。Podを作り直す必要はありません。
どう動くのか
ztunnel(L4)。Podから出る接続は、そのノードのztunnelが受け取り、宛先ノードのztunnelとHBONEトンネル(HTTP CONNECTの上のmTLS、ポート15008)を張ります。ztunnelはリクエストのパスやメソッドは知りませんが、両側のSPIFFEの身元を知っていて、アクセスログにsrc.identity・dst.identityとして残します。セレクターで付けたAuthorizationPolicyは、宛先側のztunnelが接続を受けるときに強制するので、拒否はHTTP 403ではなく接続の切断です。
HTTPルールをセレクターのポリシーに書くと、istiodはztunnelが強制できないルール(メソッド・パスなど)を除いて送り、ポリシーのステータスにZtunnelAcceptedの条件でその事実を書きます。ALLOWポリシーは1つでも一致すれば許可なので、別のALLOWポリシーがすでにその送信元を許可していると、「GETだけ許可」と書いたものは何もしません。
waypoint(L7)。istioctl waypoint applyは、Gateway APIのGateway(gatewayClassName istio-waypoint)を作り、--enroll-namespaceは、ネームスペースにistio.io/use-waypointラベルを付けて、そのサービスにwaypointを使わせます。その後、サービスへ向かうリクエストの道筋は次のとおりです。
client ─(ztunnel)─ HBONE ─▶ waypoint(Envoy: HTTP 라우팅·HTTP 정책) ─ HBONE ─▶ (ztunnel) web
ここで2つのことが変わります。
| waypointの前 | waypointの後 | |
|---|---|---|
| webのztunnelが見る送信元 | client | waypoint |
| HTTPルールを強制する場所 | なし | waypoint(targetRefsで付けたポリシー) |
そのため、clientだけを許可していたL4ポリシーは、waypointを付けた瞬間にサービスのトラフィックを切ってしまいます。そしてwaypointは、デフォルトでサービスへ向かうリクエストだけを担当するので(istio.io/waypoint-for: service)、Pod IPに直接来るリクエストはwaypointを通りません。L7ポリシーを迂回する道です。L4ポリシーでwaypointの身元だけを許可すれば、2つの問題が一緒に解けます。
ルーティングもwaypointが行います。メッシュ内のルーティングは、親がサービスのHTTPRouteで書きます(Gateway APIのGAMMA)。処理するのがwaypointなので、waypointがなければ適用されません。
現場での姿
waypointを付けたらサービスがすべて503になった場合です。宛先のL4ポリシーが、もともとクライアントだけを許可していたケースです。waypointのログにtunnel_response:401が出ます。waypointの導入は、ポリシーの見直しと一緒に行う必要があります。
GETだけ許可したのにPOSTが通る場合です。HTTPルールをセレクターのポリシーに書いています。kubectl get authorizationpolicy -o yamlのstatusがすでに教えています。
L7ポリシーをかけたのに、通過する呼び出しがある場合です。Pod IPに直接呼ぶクライアント(ヘッドレスサービス・StatefulSetなど)が、waypointを通らなかったケースです。
公式ドキュメント: Ambient mode overview・Platform prerequisites — K3s・Configure waypoint proxies・Layer 4 security policy・Layer 7 features
次のラボですること
k3sの上にambientプロファイルでインストールされた本物のztunnelに、ラベル1つでネームスペースを入れ、再起動なしで組み込まれることと、ztunnelが残した2つの身元を見ます。L4ポリシーをかけ、HTTPルールがwaypointなしでどう抜け落ちるかを、ポリシーのステータスで確認した後、waypointを付けて、正常だったリクエストが503になることを自分で体験して直します。最後に、waypointにHTTPポリシーとHTTPRouteをかけます。