はじめに
4回に分けてDockerとAzure Kubernetes Service(以下、AKS)の内部ネットワーク構造に注目し、深堀りしていきます。最終回では、両者を比較し共通点・相違点についてまとめます。
第2回目は、AKSのkubenetネットワークモデルにおける内部構造について整理していきます。
なお、検証環境は以下の通りです。
検証環境(Azure VM)
OS:Linux (ubuntu 20.04)
Size:Standard D2s v3 (2 vcpus, 8 GiB memory)
前回の記事
注意点
この記事の検証時点でのAKSのネットワークモデルは「kubenet」と「Azure CNI」の2つでしたが、それぞれ2024年6月頃に名称が変更になり技術要素も(微妙に)変わりました。それぞれ現在では「Azure CNIオーバーレイ」と「フラットネットワーク」という名前になりました。
よって「kubenet」ネットワークモデルはレガシなモードとなりましたが、根本的な考え方は同じですし、Dockerとの比較という意味で検証内容自体は参考になると思いますので、以下に整理していきます。
参考
Kubernetesとは
- コンテナ化されたアプリケーションのデプロイメント、スケーリング、および管理を自動化するオープンソースのコンテナオーケストレーションプラットフォームです。以下、k8sと記載します。
- クラウドではサーバ機器や回線など物理的な要素が抽象化されていますが、kubernetesでは負荷分散やIaaSとしてのサーバ、ルーティングテーブルなどのコンポーネントが抽象化されています(ServiceやNode、Podなど)。
- AKSの裏ではAzure Load Balancer、仮想マシンスケールセット(VMSS)、OSのiptablesなどのコンポーネントが組み合わさってk8sの機能が実装されています。
詳しくは以下の以前の記事を参考にしてください。
AKSとは
AKSはフルマネージドKubernetesサービスです。AKSは、Kubernetesクラスタのデプロイ、管理、スケーリングを簡素化することを目的としています。
詳しくは以下の以前の記事を参考にしてください。
AKSにおけるネットワークモデル
AKSには2つのネットワークモデルがありました(先述の通り下記の画像は検証時点でのものです)。
kubenetとは
上記の通り、NodeのサブネットとPodのサブネットが異なることがわかります。
図にすると以下のようなイメージ。
ポイント
- 黄色部分はAKSによって作成される仮想ブリッジで、各Podのvethと接続されています。Pod間で通信するときは、このブリッジを使って通信を行います。コンテナ間ではvethは共有されているため、ローカルホストで通信できます。ちなみに、ブリッジの名前はデフォルトで「cbr0」です
- Podごとに異なるネットワーク名前空間が割り当てられます。これにより、Pod間やPod‐Node間のネットワークを隔離しています
- PodのサブネットとNodeのサブネットはレンジが異なります
ん…?ネットワーク構造もポイントも何かに似ていませんか?
そう、前回の記事で紹介した、Dockerのbridgeネットワークの構造とそっくりなのがkubenetネットワークモデルなのです!
Dockerのbridgeネットワーク構造
DockerにおけるHostとコンテナが、AKSにおけるNodeとPodに対応しているようなイメージですね。
では、今回も本当にその通りになっているか検証してみましょう。
検証
AKSをkubenetネットワークモデルで作成します。
az aks create --name azfooaks01 --resource-group AZ-foo --node-count 2 --kubernetes-version 1.26.3 --node-vm-size Standard_DS2_v2 --generate-ssh-keys --service-principal $APP_ID --client-secret $SP_PWD
※以前はデフォルトでkubenetネットワークモデルでした。
AKSは通常、Nodeの存在は隠ぺいされていますが、以下の記事を参考にすればNodeにログインすることができます。
色々と情報を取得すると以下のようになりました。
1~3のポイントについて全てその通りになっていますね(Podのサブネットは10.244.2.XでNodeのサブネットは10.224.0.Xであり、分かりにくいですがレンジが異なっています)。
ここで疑問なのは、Dockerのbridgeネットワークにあった4つめの以下のポイントです。
- コンテナがホスト外と通信するときはブリッジを経由し、ホストのeth0でIPマスカレード(iptables)されます
kubenetネットワークでPodがNode外と通信するときはどのように通信が行われるのでしょうか?検証してみます。
Node間通信
AKSを作成した時にNodeを2つ作るよう指定したので、もう片方のNodeを使って検証してみます。
左側のNodeのPod(busy-pb4p7)から右側のPod(busy-q7dn2)に対してpingコマンドを実行してみます。
busy-pb4p7のeth0でキャプチャすると、送信元IPアドレスはPodの名前解決名を表す「busy-pb4p7」となっているのでまだNATされていないですね。
Nodeのeth0でキャプチャすると、送信元IPアドレスは「busy-pb4p7」となっていて、NATされていないことがわかります
送信先のPodのeth0でキャプチャしても同じくNATされていません。
Dockerの時はNATされていましたが、kubenetではされていないようですね。
解決
MSLearnをよくよく見てみると、下記の通りNATされるのはAKSクラスター外との通信のみであり、AKSクラスター内の通信はNATされない仕様となっています。
AKSクラスター内の通信はNATされるのではなく、AKSによって自動作成されるUDR(Azureの”ルートテーブル”リソースのこと)に定義されたルートによって、IPフォワーディングされることで通信が成り立っています。
実際にkubenetネットワークのAKSを作成すると”mc_”から始めるリソースグループのUDRが自動的に作成されます(Azure CNIネットワークの場合は作成されない)。
ルートを見てみると、宛先がPodのサブネット(10.244.x.x/24)であるトラフィックについて、対応するNodeのeth0(10.224.x.x/32)にホップするように定義されているのがわかります。
まとめ
kubenetネットワークモデルにおける特徴をまとめると以下の通りとなります。
- Node内にbridgeが作られる
- PodごとにNW namespaceが異なる
- PodのサブネットとNodeのサブネットは、レンジが異なる
- AKSクラスター外の通信の場合、bridgeからNodeのeth0に転送されるときにNATされる
AKSクラスター内の通信の場合、UDRによってIPフォワーディングされる
次回はAzure CNIネットワークモデルについて深堀りします。