※この記事は「AOS 7.0 AHV10.0 Prism Central pc.2024.3」時点の情報をもとに作成しています。その後の機能アップデートについてはメーカーの公開情報をご確認ください。
NutanixのFlow Virtual Networkingの連載については以下の記事にリンクをまとめています。ほかの記事にもこちらからアクセス可能です。
前回の記事では、FVNのVPCでオーバーレイネットワーク上に接続された仮想マシン間の通信を確認しました。今回は、オーバーレイネットワークに接続した仮想マシンが、SNATで送信元IPを変換して外部ネットワークへアクセスする仕組みを確認してみます。
目次
1.今回の環境
3ノードAHVクラスタ
AOS: 7.0.1
AHV: 10.0.1
Prism Central: pc.2024.3.1.1
仮想マシン: Windows Server 2022
環境は一般的なNutanixの3ノードクラスタです。Prism CentralはFVNで推奨となる3台構成としています。
▽Flow Virtual Networkingによる仮想プライベートクラウドのざっくりしたイメージ図は以下の通りです。クラスター上に独立した空間を作成して、そこにオーバーレイネットワークを作成する機能を指します。

2. NAT通信の仕組み
▽今回の環境は以下の通りで、先に答えをお見せします。VPCのオーバーレイネットワークに接続したVMが外部ネットワークへ接続する際は、brAtlasブリッジ内で送信元VMのIPがSNATでexternal subnet上のIPに変換され、パッチポートを通過してアップリンクから外部へ抜けていきます。

パッチポートを持たないAHV03については、「ovn-xx」ポートからgeneveトンネル通信で別のAHVを経由して外部ネットワークへ接続することになります。
ノード間のgeneve通信についてはリンク先で解説しています。
3. external subnetとSNAT IPの確認
▽以前の記事で、VPCを作成する際に、VPCからの出入口となる外部ネットワークとして「external subnet (nat)」を作成しました。
VPCにexternal subnetを接続すると、定義したIPプールの中からSNAT用のIPアドレスが自動or手動で設定できます。▽今回の環境のexternal sunbetとSNAT IPは以下の通りです。

▽これをイメージ図で表現すると以下のようになります。

仮想マシンからVPCの外部宛にアクセスする場合は、このSNAT IPを送信元IPに変換して通信します。
この図からもわかるように、NATを使用する場合は、external subnetおよびNATゲートウェイとして機能するのは2つのAHVホストとなるようです。ノード数やPrism Centralの台数によって増減するかはわかりませんが、今回の環境ではこうなりました。
なお、SNAT IPを使用する場合は、仮想マシンから外部への通信しかできない仕組みになっています。外部からNATでVPC内の仮想マシン宛に通信したい場合は、external subnet内から「Floating IP」を仮想マシンにアサインする必要があります。これはまた別の記事で紹介します。
4. SNAT変換と外部への出力
external subnet上のSNAT IPへの変換は、brAtlasブリッジのFlowテーブルによって実行されています。Flowテーブルの内容をすべて把握するのは大変なので、関係のありそうな部分をピックアップして流れを紹介します。

▽VPCのオーバーレイネットワークに接続した仮想マシンの「tap」からの入力はOpenFlowのtable=0で確認できます。(AHV01で確認&抜粋)
cookie=0xded6f111, duration=546957.422s, table=0, n_packets=1503868, n_bytes=133529118, priority=100,in_port=tap2 actions=load:0x10->NXM_NX_REG13[0..15],load:0xf->NXM_NX_REG9,load:0x2712->OXM_OF_METADATA,load:0x2->NXM_NX_REG14,load:0->NXM_NX_REG13[16..31],resubmit(,8)
▽「tap」からの入力された外部宛の通信は、table=46でNAT変換されていることが確認できます。
- ソース: 192.168.10.0/24 → 172.22.7.27へNAT変換
途中のルールは飛ばしていますが、最終的にtable=65でVLAN ID 2207が設定されてパッチポートから出力されるようです。(AHV01で確認&抜粋)
cookie=0xe070fd17, duration=554898.558s, table=45, n_packets=0, n_bytes=0, idle_age=65534, hard_age=65534, priority=153,ct_state=-trk,ip,reg15=0x2,metadata=0x3,nw_src=192.168.10.0/24 actions=ct(commit,table=46,zone=NXM_NX_REG12[0..15],nat(src=172.22.7.27))
cookie=0xe070fd17, duration=554898.558s, table=45, n_packets=14317, n_bytes=7174010, idle_age=14, hard_age=65534, priority=153,ct_state=-rpl+trk,ip,reg15=0x2,metadata=0x3,nw_src=192.168.10.0/24 actions=ct(commit,table=46,zone=NXM_NX_REG12[0..15],nat(src=172.22.7.27))
~~~中略~~~
cookie=0x8505267a, duration=865834.403s, table=65, n_packets=790622, n_bytes=80049428, idle_age=86, hard_age=65534, priority=100,reg15=0x1,metadata=0x2710 actions=mod_vlan_vid:2207,output:"patch-brAtlas-t",strip_vlan
このtable=65で、VLAN IDを設定して「output」後の「strip_vlan」は何か意味があるのか、記述ミスなのかよくわかりませんでした。
なお、「brAtlasブリッジ」からパッチポートを経由して「br0ブリッジ」へ出力された後は、Flowテーブルで通常の動作(action=NORMAL)が適用され、br0ブリッジのMACアドレステーブルを参照してアップリンクに通信を送信します。
▽br0のMACアドレステーブルは以下のコマンドで確認可能です。「port:10」は今回の環境でのofportsの番号で、アップリンクの「eth0やeth1」のインターフェースを指します。(VLANとMACアドレスは適当)
port VLAN MAC Age
10 100 b6:ff:ad:1f:22:46 294
10 101 7c:c2:55:5c:73:69 285
5 0 52:54:00:f5:03:a3 0 ←CVM (vnet0)
10 110 00:50:56:9f:ae:36 281
10 200 c4:cb:e1:ec:0b:7c 281
LOCAL 0 00:62:0b:22:ef:40 0 ←AHV (br0)
10 150 00:50:56:93:8a:63 274
10 0 f8:0b:cb:1d:d6:5c 270
10 1 00:50:56:90:64:95 266
10 1 00:50:56:a0:47:6f 266
10 50 00:50:56:b0:be:e6 264
このような流れで、VPCのオーバーレイネットワークに接続した仮想マシンからの外部向け通信はSNAT変換されています。
なお、AHVホストのアップリンクポート(eth0やeth1)でtcpdumpコマンドを使用して、通信をキャプチャしてみると、VPCの192.168.10.0/24にIPを持つ仮想マシンからの通信が、SNAT IPの172.22.7.27に変換されていることも確認できます。

本当はpatchポートに対してtcpdumpをしたかったのですが、どうもOVSブリッジのpatchポートまではtcpdumpでみれなそうでした。別のinternalポートを作成して、ミラーリングなどもできそうではありますが、AHVの内部ブリッジ構造に手を加えるのはタブーな気がしますのでやめておきます。
データパスフローでのNAT変換の確認
実は、OVSのFlowテーブルをもとに処理された通信のキャッシュ(的な?)を確認することもできます。ここでNAT変換されている様子も確認できます。
「e0:19:95:ad:56:d0」は、172.22.7.27のMACアドレスです。
recirc_id(0),in_port(3),skb_mark(0),ct_state(-new-rpl-trk),eth(src=f8:0b:cb:1d:d6:7f,dst=e0:19:95:ad:56:d0),eth_type(0x8100),vlan(vid=2207,pcp=0),encap(eth_type(0x0800),ipv4(src=128.0.0.0/224.0.0.0,dst=172.22.7.27,proto=17,ttl=56,frag=no),udp(dst=32768/0x8000)), packets:14, bytes:8628, used:6.829s, actions:pop_vlan,ct(zone=9,nat),recirc(0x322d)
recirc_id(0x322b),in_port(17),ct_state(-rpl+trk),eth(),eth_type(0x0800),ipv4(src=192.168.10.0/255.255.255.0,frag=no), packets:1, bytes:121, used:6.945s, actions:ct(commit,zone=9,nat(src=172.22.7.27)),recirc(0x322c)
5. 戻りの通信の流れ
▽eth0やeth1から戻ってきた172.22.7.27宛の通信は、「br0ブリッジ」でFlowテーブルに従い「action: NORMAL」で通常の処理が適用され、br0のMACアドレステーブルを参照します。
なお、MACアドレステーブルを確認すると「172.22.7.27」に紐づいているMACアドレスが、brAtlasブリッジと接続されているpatchポート(ofports:14番)を指していることが分かります。
[root@ahv-01 ~]# ovs-appctl fdb/show br0 | grep 2207
10 2207 00:50:56:b0:42:b2 115
14 2207 e0:19:95:ad:56:d0 104
10 2207 f8:0b:cb:1d:d6:7f 104
10 2207 00:42:5a:f2:a5:80 58
10 2207 00:50:56:b0:d4:ed 4
この情報に従い、172.22.7.27宛のパケットは「patch」ポートに送られます。
▽そしてbrAtlasの「patch」ポートから入力してきた通信のルールが、brAtlasのFlowテーブルのtable-0で確認できます。(AHV01で確認&抜粋)
cookie=0xae04b038, duration=858253.532s, table=0, n_packets=0, n_bytes=0, priority=180,conj_id=100,in_port="patch-brAtlas-t",dl_vlan=2207 actions=strip_vlan,load:0x1->NXM_NX_REG13[0..15],load:0x2->NXM_NX_REG9,load:0x2710->OXM_OF_METADATA,load:0x1->NXM_NX_REG14,load:0->NXM_NX_REG13[16..31],mod_dl_src:e0:19:95:ad:56:d0,resubmit(,8)
cookie=0xae04b038, duration=858253.532s, table=0, n_packets=0, n_bytes=0, priority=180,dl_vlan=2207 actions=conjunction(100,2/2)
cookie=0x8505267a, duration=858253.532s, table=0, n_packets=1145077, n_bytes=1587856890, priority=150,in_port="patch-brAtlas-t",dl_vlan=2207 actions=strip_vlan,load:0x1->NXM_NX_REG13[0..15],load:0x2->NXM_NX_REG9,load:0x2710->OXM_OF_METADATA,load:0x1->NXM_NX_REG14[],load:0->NXM_NX_REG13[16..31],resubmit(,8)
「in_port="patch-bratlas-t"」でexternal subnetのvlanである「2207」の受信規則が書かれています。
▽戻りのNAT変換ですが、table=13に記載のものが、おそらく該当されると思われます。(AHV01で確認&抜粋)
cookie=0xb0f56809, duration=563219.467s, table=13, n_packets=1144683, n_bytes=1606631520, idle_age=72, hard_age=65534, priority=100,ip,reg14=0x2,metadata=0x3,nw_dst=172.22.7.27 actions=ct(table=14,zone=NXM_NX_REG12[0..15],nat)
▽仮想マシンの「tap」への出力のルールもありますので、最終的にはここのテーブルにて仮想マシンに通信が戻ってきているようです。
cookie=0xded6f111, duration=562031.237s, table=65, n_packets=1906863, n_bytes=1491508947, idle_age=75, hard_age=65534, priority=100,reg15=0x2,metadata=0x2712 actions=output: tap2
次回は、外部からVPC内の仮想マシン宛にNATで通信する際に必要な「Floating IP」について調べてみたいと思います。
以上です。