由之前的介紹,透過Floating IP存取VM,或是由VM對外連線到Internet,流量一定都會經過Network node。一旦網路流量很大,Network Node就會成為瓶頸。而Distributed Floating IP(就是官方文件上指的Distributed Virtual Router, DVR)的目的是當採用Floating IP時,流量直接由compute node進出,而不是經由Network Node;如果VM沒有Floating IP的話,仍然是透過Network Node。看下面二張圖,應該就很好理解二者的差異。我們今天就來了解OVN是如何實現這項功能吧
Non-DistributedFloating IP | Distributed Floating IP |
---|---|
前二天的Network HA 與 今天的Distributed Floating IP,好像有點類似,讓我們先來釐清一下。
ovn-nbctl list gateway_chassis
會看到network node上的chassis;若同時又啟用Distributed FIP, 因為Compute Node也必需擔任FIP在Network node的DNAT功能,所以ovn-nbctl list gateway_chassis
除了network node的chassis外,也會看到Compute Node的Chassis.預設沒有啟用Distributed Floating IP, 修改network-controller node上的ml2_conf.ini
$ vim /etc/neutron/plugins/ml2/ml2_conf.ini
[ovn]
...
enable_distributed_floating_ip=True
# 重啟neutron 服務
$ systemctl restart neutron-*
This requires the user to configure the physical network map (i.e. ovn-bridge-mappings) on each compute node.
如同官方文件提到的,Distributed FIP是直接在compute node提供對外連線,這代表compute node需要和physical network有所對應關係,換句話說,就是compute node也要有br-ex bridge。這可以透過修改packstack的參數--os-neutron-ovn-bridges-compute=br-eth2,br-ex
就可以囉。
也可以直接透過vagrant建立今天的環境,所要做的設定,在Vagrantfile都已經設定好了。
git clone https://github.com/ogre0403/iTHome-2023.git
cd iTHome-2023/day-27
vagrant up
這裡把前幾天用了好多次的指令列出來,讓大家方便建立FIP,細節就不再重複。
openstack network create --provider-network-type geneve --provider-segment 123 n1
openstack subnet create --subnet-range 172.16.100.0/24 --network n1 n1subnet
openstack network create --provider-network-type flat --provider-physical-network extnet0 ext_n2 \
--external
# for VirtualBox
SUBNET_RANGE=10.0.2.0/24
GATEWAY=10.0.2.2
ALLOCATION_RANGE=start=10.0.2.210,end=10.0.2.220
openstack subnet create --subnet-range ${SUBNET_RANGE} --network ext_n2 extsubnet \
--no-dhcp \
--gateway ${GATEWAY} \
--allocation-pool ${ALLOCATION_RANGE}
IMAGE_ID=$(openstack image show cirros --format json | jq -r .id)
openstack server create --nic net-id=n1,v4-fixed-ip=172.16.100.10 --flavor m1.nano --image $IMAGE_ID vm_1
openstack router create r
openstack router add subnet r n1subnet
openstack router set r --external-gateway ext_n2
openstack floating ip create ext_n2
FLOATING_IP=$(openstack floating ip list --format json | jq -rc '.[]."Floating IP Address"')
openstack server add floating ip vm_1 ${FLOATING_IP}
openstack server add security group vm_1 allow-icmp-ssh
在這個環境有一個Network Node與2個Compute Node,因為2個Compute Node也有對外的Bridge Mapping,所以會看到共有3個gateway_chassis
ovn-nbctl list gateway_chassis | abbrev
_uuid : f6548a
chassis_name : "a807ec"
external_ids : {}
name : lrp-1107c2_a807ec
options : {}
priority : 3
_uuid : 33d2ff
chassis_name : "1d03fd"
external_ids : {}
name : lrp-1107c2_1d03fd
options : {}
priority : 2
_uuid : 97dcaf4
chassis_name : "3c2e27"
external_ids : {}
name : lrp-1107c2_1d03fd
options : {}
priority : 1
建立FIP後,查NB DB nat table,和 [[Day-22_Floating-IP]]的nat table內容相比,會看到FIP的欄位會多EXTERNAL_MAC
與LOGICAL_PORT
這二個欄位
LOGICAL_PORT
會對應到OpneStack 裡 private IP的port的UUIDEXTERNAL_MAC
則是 OpenStack分配給FIP用的MAC addrovn-nbctl lr-nat-list 4e2aa017-44a4-4cc8-b5b5-fd7cbf2ce521
TYPE GATEWAY_PORT EXTERNAL_IP EXTERNAL_PORT LOGICAL_IP EXTERNAL_MAC LOGICAL_PORT
dnat_and_snat 10.0.2.216 172.16.100.10 fa:16:3e:9f:84:ff 14a6a45a-acc2-4d3b-a0e3-c31412903300
snat 10.0.2.211 172.16.100.0/24
和 Non-Distributed FIP 相比,Distributed FIP 的流量必需透過Compute Node進出,而這裡的EXTERNAL_MAC
,就是用來讓從外部回來的封包,可以透過這個MAC找到要將封包送回給那一個compute node。將Compute Node上的br-int
的flow dump出來,可以看到將172.16.100.10
和 10.0.2.216
做 snat和dnat的flow. 和一般的FIP的DNAT不同的地方在於會多做一個mac src addr的修改 (mod_dl_src:fa:16:3e:9f:84:ff
)。之後packet回來後,會回給Compute Node處理,而不是由Network Node處理。
$ ovs-ofctl dump-flows br-int |grep "10.0.2.216" |grep nat
table=14, priority=100,ip,reg14=0x1,metadata=0x3,nw_dst=10.0.2.216 actions=ct(commit,table=15,zone=NXM_NX_REG11[0..15],nat(dst=172.16.100.10))
table=43, priority=161,ip,reg15=0x1,metadata=0x3,nw_src=172.16.100.10 actions=mod_dl_src:fa:16:3e:9f:84:ff,ct(commit,table=44,zone=NXM_NX_REG11[0..15],nat(src=10.0.2.216))
可以看到所有的Compute Node與Network Node都有相同的Bridge Mapping,所以FIP的封包可以直接使用Compute Node對外連線。
我們在Compute Node上抓封包,可以看到DNAT後的封包對外,表示在Distributed FIP的情境下,不會經過Network Node。
tcpdump -i eth0 icmp
02:10:57.573897 IP 10.0.2.216 > dns.google: ICMP echo request, id 16330, seq 1, length 64
02:10:57.584621 IP dns.google > 10.0.2.216: ICMP echo reply, id 16330, seq 1, length 64
這一步是驗證,由VM往Internet的封包,會由compute node直接送往Internet. 實際上,由Internet連到VM的封包,也會直接由Compute node送給VM。但是在我們這一個用VirtualBox建出來的實驗環境,如果是在compute node上直接連VM的Floating IP,因為是本機直接連VM,封包不會經過eth0,所以也抓不到封包。如果我們的三個VM的eth0是在同一個網路的話,就會查覺到,由別的VM連到Floating IP的封包,一定會直接送給compute node, 而不會經過network node。這是整個鐵人賽中,透過VirtualBox建立實驗環境,唯一一個無法完整驗證的實驗。
反之,如果將Floating IP由VM上拔掉,在compute node上不會發現ICMP封包,反而要在目前綁定的network node上才看得到。而且,這時候對外的IP是SNAT的外部IP。
02:14:31.287924 IP 10.0.2.211 > dns.google: ICMP echo request, id 19754, seq 1, length 64
02:14:31.294616 IP dns.google > 10.0.2.211: ICMP echo reply, id 19754, seq 1, length 64