昨天我們已經建立了一個最基本的Logical Switch,並驗證二組veth pair是能透過logical switch連通。但細心的小夥伴應該有注意到,昨天的二個veth pair都在同一個節點上,二個veth pair會通好像沒什麼了不起的。所以,今天就來說說當二個veth pair在不同的節點上時,OVN是如何架構出這個邏輯網路吧。先來看一下今天要完成的實驗環境,和昨天的差異吧。今天的環境和昨天相比,唯一的差別就在於昨天是將二個veth pair都連在controller的br-int上;而今天則是controller和hypervisor的br-int,各自有一個veth pair接在其上。話不多說,先來動手試試吧。
和之前一樣,先用我整理好的bash function,理解下整個流程,再進一步細看這些指令做了什麼事情。
sudo su
cd /opt/iTHome-2023/day-03
source helper.sh
因為二個veth pair在不同的節點上,分別在二個節點上執行
# at controller
create-ns ns1 10.10.0.1
# at hypervisor
create-ns ns2 10.10.0.2
# at controller
create-ovn-ls-and-lsp ls0
細心的小夥伴如果有打開
create-ovn-ls-and-lsp
這個來研究,會注意到會從controller建立SSH連線至hypervisor。這一個動作只是要取得 hypervisor上 veth的mac address。取得後,仍要用ovn-nbctl進行設定,所以最重要的步驟還是在controller上執行。
# at controller
assign-iface-to-ovn-lsp ls0
# at hypervisor
assign-iface-to-ovn-lsp ls0
ovn-sbctl show
Chassis "1cea777a-68eb-4396-a5c2-6f3c875eb604"
hostname: controller
Encap geneve
ip: "192.168.33.10"
options: {csum="true"}
Port_Binding ls0-ns1
Chassis "a17b40ba-4668-40fc-9739-c9e72f0e2cab"
hostname: hypervisor
Encap geneve
ip: "192.168.33.20"
options: {csum="true"}
Port_Binding ls0-ns2
在這裡可以和昨天的ovn-sbctl的結果對比一下,因為昨天的veth都建立在controller上,所以做port 綁定時,都是將controller的interface綁至logical switch.而今天的例子,是分別將controller和hypervisor各別的interface綁至logical switch. 這些資訊都可透過ovn-sbctl得到驗證。
一旦將二個node上的veth pair放至logical switch後,我們就可以檢查二個namespace是否能連互相連通。在這裡我們是進入到controller的ns1 namespace對另一個namespace的IP執行Ping.
ip netns exec ns1 ping -c 4 10.10.0.2
PING 10.10.0.2 (10.10.0.2) 56(84) bytes of data.
64 bytes from 10.10.0.2: icmp_seq=1 ttl=64 time=1.11 ms
64 bytes from 10.10.0.2: icmp_seq=2 ttl=64 time=0.599 ms
64 bytes from 10.10.0.2: icmp_seq=3 ttl=64 time=0.552 ms
64 bytes from 10.10.0.2: icmp_seq=4 ttl=64 time=0.501 ms
--- 10.10.0.2 ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 3036ms
rtt min/avg/max/mdev = 0.501/0.689/1.105/0.242 ms
有了前二天的基礎,一路操作下來,今天的這個實驗,整個過程和昨天是不是完全相同呢。以邏輯網路角度來思考,二個namespace是在同一個logical switch上,能夠互相連通看似是非常直覺的一件事。但是深入的思考一下,二個在不同節點上的namespace, 到底是透過什麼原理進行通訊的阿?跨節點通訊的一切基礎,就是之前曾經提過的 GENEVE Overlay Network這個技術啦,到底GENEVE是一個什麼東西,Overlay Network又是什麼,讓我們趕快來了解一下。看完之後,你就懂了唷。
要了解為什麼在二個不同節點的二個namespace能夠通信,要先知道所謂的Overlay與 Underlay network。在圖中,Underlay Network一般指的就是真實網路,在我們的實驗環境就是eth0/eth1/eth2所使用的網路,正常的情況下,節點之間都是可以以透過Underlay Network連通;反之Overlay Network可以想像成是虛擬出來的虛擬網路,對應到我們之前的例子,就是一個實際上不存在而虛擬化出來的一個logical switch所連通的一10.10.0.0/24 的虛擬網路。
以虛擬網路(Overlay Network)的觀點來看,在圖中虛擬網路上的二台主機,10.10.0.1 與 10.10.0.2,因為在同一個logical swicth上,是透過灰色的箭頭直接通信。但是,虛擬網路(Overlay Network)裡並沒有任何的實體線路可以做到這件事,為了讓虛擬網路上的二台主機認為彼此正在通信,勢必要透過真實網路(Underlay Network)設備幫忙轉送。以實體網路(Underlay Network)的觀點來看,圖中,虛擬網路的灰色封包就如同一般應用層的payload,Underlay Network將這個應用層的payload,加上實體網路藍色的header,依照藍色的箭頭送到目的地後,再轉給虛擬網路處理,虛擬網路上的目的端就可收到封包。
了解Overlay network後,圖中將灰色的封包加上藍色的header,這個動作,就稱為Encapsulation。GENEVE的全名是 GEneric NEtwork Virtualization Encapsulation,就是一種可以執行圖中將黑色的封包裝至藍色封包的一種protocol。而OVN就是使用GENEVE進行封包的封裝,來實現在一個實體網路(或是Underlay Network)可以承載多個不同的邏輯網路(或是Overlay Network),達到網路虛擬化的功能。
由今天一開始的架構圖可以知道,從ns1出來的封包,會經過controller上不同的interface, 包含 veth-ns-br、ovn-a17b40-0、genev_sys_6081、eth1,我們在這些interface把封包抓出來看看吧。可以發現,除了eth1外之,其他的interface都是使用overlay network的IP。從eth1抓到的封包,就可以很清楚的看到,overlay network的IP是被封裝在underlay network的封包。
ovs-tcpdump -i veth-ns1-br icmp
06:45:40.919291 IP 10.10.0.1 > 10.10.0.2: ICMP echo request, id 13680, seq 1, length 64
06:45:40.920790 IP 10.10.0.2 > 10.10.0.1: ICMP echo reply, id 13680, seq 1, length 64
ovs-tcpdump -i ovn-2b1d48-0 icmp
06:45:40.919343 IP 10.10.0.1 > 10.10.0.2: ICMP echo request, id 13680, seq 1, length 64
06:45:40.920786 IP 10.10.0.2 > 10.10.0.1: ICMP echo reply, id 13680, seq 1, length 64
tcpdump -i genev_sys_6081 -vvnn icmp
06:45:40.919297 IP (tos 0x0, ttl 64, id 16541, offset 0, flags [DF], proto ICMP (1), length 84)
10.10.0.1 > 10.10.0.2: ICMP echo request, id 13680, seq 1, length 64
06:45:40.920401 IP (tos 0x0, ttl 64, id 38277, offset 0, flags [none], proto ICMP (1), length 84)
10.10.0.2 > 10.10.0.1: ICMP echo reply, id 13680, seq 1, length 64
tcpdump eth1 上的封包,dump出來的欄位有點多,實在有點難看,可以試著用視覺化的方式來閱讀這個封裝後的封包。
tcpdump -vvneei eth1 'udp port 6081'
06:45:40.919312 52:54:00:70:a8:ae > 52:54:00:3d:05:e8, ethertype IPv4 (0x0800), length 156: (tos 0x0, ttl 64, id 58271, offset 0, flags [DF], proto UDP (17), length 142)
192.168.33.10.46047 > 192.168.33.20.6081: [bad udp cksum 0xc3fa -> 0x9237!] Geneve, Flags [C], vni 0x3, proto TEB (0x6558), options [class Open Virtual Networking (OVN) (0x102) type 0x80(C) len 8 data 00010002]
ee:c7:25:6c:5e:89 > 92:be:a5:29:3f:6e, ethertype IPv4 (0x0800), length 98: (tos 0x0, ttl 64, id 16541, offset 0, flags [DF], proto ICMP (1), length 84)
10.10.0.1 > 10.10.0.2: ICMP echo request, id 13680, seq 1, length 64
06:45:40.920401 52:54:00:3d:05:e8 > 52:54:00:70:a8:ae, ethertype IPv4 (0x0800), length 156: (tos 0x0, ttl 64, id 27845, offset 0, flags [DF], proto UDP (17), length 142)
192.168.33.20.37856 > 192.168.33.10.6081: [bad udp cksum 0xc3fa -> 0xb236!] Geneve, Flags [C], vni 0x3, proto TEB (0x6558), options [class Open Virtual Networking (OVN) (0x102) type 0x80(C) len 8 data 00020001]
92:be:a5:29:3f:6e > ee:c7:25:6c:5e:89, ethertype IPv4 (0x0800), length 98: (tos 0x0, ttl 64, id 38277, offset 0, flags [none], proto ICMP (1), length 84)
10.10.0.2 > 10.10.0.1: ICMP echo reply, id 13680, seq 1, length 64
進一步把 eth1上的GENEVE的封包利用HPD 做視覺化的呈現後,可以看到外層的紫色的IPv4 header,是由192.168.33.10 在underlay network透過 UDP 送往 192.168.33.20;一旦這個封包被hypervisor收到後,將GENEVE的封裝解掉之後,在hypervisor上的ns2看到的則是由10.10.0.1送給10.10.0.2的ICMP封包。這樣是不是對所謂的封裝有比了解呢。
今天我們將昨天的實驗做了進一步的變動,讓相同logical switch,但實際在不同節點上的veth,可以透過GEVENE tunnel 做跨節點的傳輸。透過tcpdump和查看封裝後的封包內容,是不是對所謂的GENEVE overlay netwrok的行為有更具體的了解了呢.