← 一覧へ戻る

Claude が書いた記事

ネットワーク屋が見る AKS:LB は入口やなく出口、AGC は Pod IP へ直接届く

Application Gateway for Containers (AGC) を入口に AKS の north-south を解剖した学習ログ。「VMSS があるから LB が受け口やろ」という思い込みを、宛先 IP 中心の見方へ切り替えるまでの記録。テスト環境で見える Standard LB は入口でなく出口 (egress) で、AGC は Pod IP へ直接届く。

俺の最初の疑問

前回 Pod ネットワーク で、Pod 同士の横の通信 (east-west) が物理 LAN の上のオーバーレイに乗っている、まで降りた。

俺はネットワークの技術サポートをやっている。次に知りたいのは縦の通信 (north-south)── 外のインターネットから、中の Pod まで、リクエストがどう届くか。その入口として Azure の Application Gateway for Containers (AGC) を選んだ。

ここで一番引っかかったのは、自分の手癖から来る三段論法だった。

AKS (Azure Kubernetes Service) には VMSS (複数の VM) がある。VM があれば前段に Load Balancer がある。だから その LB が AGC からの受け口やろ?

テスト環境を見ると、確かに Standard Load Balancer がいる。これがほんまに AGC の入口なんか? ここを潰すのが今回の目的。

まず一言でいうと

AGC は、受け口に Load Balancer を置かない。宛先 = Pod の IP を直接指して届ける。

普通の Application Gateway なら、バックエンドプールに VM の IP を手で登録する。AGC では、そのバックエンドが Pod、つまり秒単位で増減し IP も変わる相手になる。それでも AGC は前段に LB を挟まず、今いる Pod の IP を宛先にして直接つなぐ

公式 (AGIC のドキュメント、AGC はその後継) も言い切っている。

… eliminate the need for another load balancer or public IP address in front of the AKS cluster … communicates with pods by using their private IP address directly and doesn’t require NodePort or KubeProxy services.

じゃあテスト環境で見えていたあの LB は何やったのか。 ── あれは「入口」やなく「出口」だった。詳しくは後述。

何と比べるとわかるか

宛先 IP (dst) で見ると、似て見える経路がきれいに分かれる。

入口の種類宛先 IP (dst)経路
type: LoadBalancer Service (public / internal)LB の VIPLB → ノードの NodePort → kube-proxy → PodL4
AGCPod IPAGC → VNet ルーティング → Pod が載ったノード → veth → PodL7

ルータで例えると、AGC の中も コントロールプレーンと データプレーン に分かれている、と見ると整理がつく。

  • コントロールプレーン=どう運ぶか「決める」係。ルータでいう CPU が経路表を作る部分。AGC では ALB Controller (AKS 内で動く Pod) が、設定を組んで Azure 側へ伝える。
  • データプレーン=実際にパケットを「運ぶ」係。ルータでいう ASIC。AGC では Microsoft 管理の proxy 群が、受けたリクエストを Pod へ流す。

これは前回記事で掴んだ「flanneld (制御) / kernel (データ)」の型と同じ。スケールが VNet になっただけ。

何が問題なのか

Pod は短命で、増減も移動も激しい。そこへ「前段に L4 LB を置いて、ノードの NodePort 経由で kube-proxy が振り分ける」という古典的な経路を取ると、余計なホップが挟まる。AGC が Pod へ直接届けるのは、このホップを減らすため。

ただ、本当の引っかかりは技術というより見方の側にあった。ネットワーク屋は「VM の塊の前には LB がいる」と体に染みついている。だから「LB が入口」と思い込む。これを 宛先 IP で考える見方 に切り替えると、「AGC の入口に LB はいらない」が腹に落ちる。

図で見る

まず、どこまでが AKS で、どこからが Azure リソースか。混乱の元は、コントローラだけが AKS の「中」にいて、操作する相手は「外」にいることだった。

緑の枠が AKS クラスタ (k8s が管理)。Worker Node も app Pod も、そして ALB Controller も全部この中にいる。一方 AGC のデータプレーン (青) と ARM 上の AGC リソース (オレンジ) は AKS の外。AKS の中にいる ALB Controller だけが、制御線 (③) で外の AGC を設定しに行く。AGIC も全く同じ形で、これが「どこまでが AKS か」が見えにくい正体。

次に、パケットの話に入る前に住所の地図を頭に置く。VNet・subnet・ノード・Pod CIDR がどこにいるか。Pod IP (10.10.x.x) が VNet (192.168.x.x) とは別レンジ=overlay だ、というのがここで見える。

上が Pod overlay レイヤ (10.10.0.0/16)、下が VNet (192.168.0.0/16)。Pod IP (10.10.x.x) は VNet には存在しない別レイヤで、各ノードに / 24 ずつ配られる (Node1=10.10.1.0/24・Node2=10.10.2.0/24)。両者を橋渡しするのが各ノードの CNI Overlay Plugin。AGC 自身は VNet 側 (192.168.2.0/24) にいて、overlay の Pod へは routing domain 経由で届く (次図)。

そのうえで、AGC から Pod まで 1 つのパケットがどう届くか。上のマップの Pod「10.10.2.2」を宛先に、Azure CNI Overlay で外箱を VXLAN とした図解で追う (後述の通り基盤の encap 詳細は非公開なので、これは理解用の模型)。

① AGC は素のパケット (src=自分, dst=Pod IP) を出すだけ。② 送信元ホストの VFP が routing domain を引いて、宛先ノードを載せた物理ホストの PA 宛に VXLAN で包む。③ 物理網は外箱の PA しか見ない。④ 宛先ホストが decap し、routing domain ID で顧客空間を確定してから、Pod CIDR の所有ノードの vNIC へ落とす。⑤ ノードの中の Linux が veth で該当 Pod へ。Node IP はどのヘッダにも出てこない。

混乱しやすいポイント

① 見えていた LB は「入口」やなく「出口」

AKS がデフォルトで作る Standard Load Balancer の本職は egress (送信側の SNAT) だった。

By default, AKS creates a Standard Load Balancer to be set up and used for egress.

しかもこの LB すら必須ではない。outboundType を NAT Gateway や userDefinedRouting に変えれば消せる。「VMSS があるから入口の LB が要る」という必然はなかった。

type: LoadBalancer は LB の別の顔

type: LoadBalancer の Service を作ると、public でも internal (azure-load-balancer-internal アノテーション) でも、L4 の Azure LB ができる。ただしそれは dst = その LB の VIP 宛で、AGC (dst = Pod IP) とは宛先が別物。同じクラスタに並んでいても干渉しない。

③ AGC は overlay を「学習」していない

「どの Pod か」と「どう届くか」は別の係が担う。

  • どの Pod か (コントロールプレーン):ALB Controller が k8s API の Service / EndpointSlice を watch し、生きた Pod IP のリストを AGC へ push する。
  • どう届くか (ルーティング):Azure の SDN がもともと持っている。ノード作成時に Pod CIDR を /24 ずつ各ノードへ配り、routing domain を作る。AGC をデプロイすると、その routing domain を AGC の subnet へ 延伸 (join) する。AGC は SDN の知識を相続するだけで、自分でルートを学習しない。

ダメ押しに、overlay の外から Pod IP には普通は届かない、と公式も書いている。AGC が届けられるのは、subnet を routing domain に入れてもらう特権があるから。

④ TLS を終端するのは誰か

k8s には「TLS を終端する組み込み部品」はない。Service も kube-proxy も L4 で、TLS の中身は見ない。

  • クライアント側の TLS は AGC が終端する。
  • AGC ↔ Pod の区間は、デフォルトは平文 HTTP。End-to-End SSL を設定したときだけ AGC が Pod へ張り直し、終端するのは Pod の中のプロセス (アプリのコンテナ、またはサイドカーの proxy)

⑤ CNI Overlay の Pod IP は VNet の外 (ここは一部、基盤構造からの推定)

Azure CNI Overlay では、Pod IP は VNet に存在しない別レンジ (顧客アドレス=CA)。基盤は VM 間通信と同じく、その CA を物理ホストのアドレス (PA) の外箱で包んで運ぶ。Node の VNet IP は、AGC → Pod のどのヘッダにも出てこない (外箱は PA、内側は Pod IP)。

なお、公式が明言しているのは「CNI レベルの encapsulation は不要」「routing domain が Azure networking stack に作られる」まで。外箱が VXLAN かどうか、PA の振り方といった基盤内部は非公開で、ここは Azure SDN (VL2 / VFP) の一般構造からの推定として持っておく。

たとえ話

宅配で考える。

  • Pod IP = 届け先の番地 (10.10.2.2)。ただしこの番地は、別の市 (別クラスタ) にも同じものがある。
  • routing domain ID (VXLAN なら VNI) = 「市名」。番地だけでは家が決まらないので、市名で空間を区切る。
  • PA (物理ホストのアドレス) = 担当の配送センターの場所。外箱の宛先はこれ。
  • Node 内の veth ルート = 配送センター内で「この棚」と仕分ける最後の一手。

つまり 10.10.2.2 単体では家は決まらない。「市名 (VNI) + 配送センター (PA) + 番地の担当ノード + ノード内の棚 (veth)」の 4 つが揃って、初めて唯一の Pod に着く

ニュースを読むための変換表

ドキュメントの言葉つまり何の話?
Application Gateway for Containers (AGC)AKS 用の L7 ロードバランサー。Pod へ直接届ける。AGIC の後継
ALB ControllerAKS の中で動く Pod。k8s を見て AGC (外の Azure リソース) を設定するコントロールプレーン
データプレーン / コントロールプレーン「運ぶ係」と「決める係」。機能でシステムを輪切りにした担当区分
frontend / associationAGC の入口 FQDN / AGC のデータプレーンを VNet の委任 subnet に生やす接続点
EndpointSliceあるサービスの「今生きている Pod IP の名簿」
routing domain独立したルーティングテーブル=アドレスの名前空間 (VRF の親戚)
Azure CNI OverlayPod に VNet 外の IP を配るモデル。基盤が routing domain でルーティング
outboundTypeクラスタの egress 方式 (loadBalancer / NAT gateway / UDR / none)
End-to-End SSLAGC が Pod へも HTTPS で張り直す設定。終端は Pod 内のプロセス
深掘りメニュー 次におすすめのトピック
  • サイドカーが TLS を終端する仕組み (サービスメッシュ) ── End-to-End SSL の終端役になる Envoy などの proxy。AGC↔Pod 区間の TLS の続き。
  • Gateway API の書き方 (GatewayClass / Gateway / HTTPRoute) ── 今回「コントロールプレーンが読む設定」と呼んだものの実体。実際に手で書くとコントロールプレーンの動きが見える。
  • Workload Identity と OIDC ── ALB Controller が ARM を叩く権限をどう得るか。中 (k8s) の Pod が外 (Azure) を操作する認証の道。
  • flat CNI と CNI Overlay の使い分け ── flat なら Pod が VNet の実 IP を持つので NVA / Firewall を AGC↔Pod 間に挟める。Overlay では挟めない。実務の判断軸。
  • Azure SDN (VL2 / VFP) の CA → PA マッピング ── 今回「推定」とした基盤の中身。アンダーレイ側からこの routing domain を見直す。