上篇文章結尾提到 Linux
是支持 VXLAN
的,咱們可使用 Linux 搭建基於 VXLAN
的 overlay 網絡,以此來加深對 VXLAN 的理解,畢竟光說不練假把式。linux
先來看看最簡單的點對點 VXLAN
網絡,點對點 VXLAN
即兩臺主機構建的 VXLAN
網絡,每臺主機上有一個 VTEP
,VTEP
之間經過它們的 IP 地址進行通訊。點對點 VXLAN 網絡拓撲圖如圖所示:緩存
爲了避免影響主機的網絡環境,咱們可使用 Linux VRF
來隔離 root network namespace 的路由。VRF(Virtual Routing and Forwarding)是由路由表和一組網絡設備組成的路由實例,你能夠理解爲輕量級的 network namespace
,只虛擬了三層的網絡協議棧,而 network namespace
虛擬了整個網絡協議棧。詳情參看 Linux VRF(Virtual Routing Forwarding)的原理和實現。bash
Linux Kernel 版本大於
4.3
才支持 VRF,建議作本文實驗的同窗先升級內核。微信
固然了,若是你有專門用來作實驗的乾淨主機,能夠不用 VRF 來隔離。網絡
下面結合 VRF
來建立一個點對點 VXLAN 網絡。app
首先在 192.168.57.50
上建立 VXLAN 接口:ssh
$ ip link add vxlan0 type vxlan \
id 42 \
dstport 4789 \
remote 192.168.57.54 \
local 192.168.57.50 \
dev eth0
複製代碼
重要參數解釋:tcp
VNI
的值,有效值在 1 到 VTEP
通訊的端口,IANA 分配的端口是 4789。若是不指定,Linux 默認使用 8472
。VTEP
要使用的 IP 地址,即當前節點隧道口的 IP 地址。VTEP
通訊的設備,用來獲取 VTEP IP 地址。這個參數與 local 參數目的相同,二選一便可。查看 vxlan0
的詳細信息:分佈式
$ ip -d link show vxlan0
11: vxlan0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master vrf-test state UNKNOWN mode DEFAULT group default qlen 1000
link/ether 82:f3:76:95:ab:e1 brd ff:ff:ff:ff:ff:ff promiscuity 0
vxlan id 42 remote 192.168.57.54 local 192.168.57.50 srcport 0 0 dstport 4789 ageing 300 udpcsum noudp6zerocsumtx noudp6zerocsumrx
複製代碼
接下來建立一個 VRF,並將 vxlan0
綁定到該 VRF
中:post
$ ip link add vrf0 type vrf table 10
$ ip link set vrf0 up
$ ip link set vxlan0 master vrf0
複製代碼
再次查看 vxlan0
的信息:
$ ip -d link show vxlan0
13: vxlan0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master vrf0 state UNKNOWN mode DEFAULT group default qlen 1000
link/ether aa:4d:80:e3:75:e0 brd ff:ff:ff:ff:ff:ff promiscuity 0
vxlan id 42 remote 192.168.57.54 local 192.168.57.50 srcport 0 0 dstport 4789 ageing 300 udpcsum noudp6zerocsumtx noudp6zerocsumrx
vrf_slave table 10 addrgenmode eui64 numtxqueues 1 numrxqueues 1 gso_max_size 65536 gso_max_segs 65535
複製代碼
你會發現多了 VRF 的信息。
接下來爲 vxlan0 配置 IP 地址並啓用它:
$ ip addr add 172.18.1.2/24 dev vxlan0
$ ip link set vxlan0 up
複製代碼
執行成功後會發現 VRF 路由表項多了下面的內容,全部目的地址是 172.18.1.0/24
網絡包要經過 vxlan0 轉發:
$ ip route show vrf vrf0
172.18.1.0/24 dev vxlan0 proto kernel scope link src 172.18.1.2
複製代碼
同時也會增長一條 FDB
轉發表:
$ bridge fdb show
00:00:00:00:00:00 dev vxlan0 dst 192.168.57.54 self permanent
複製代碼
這個表項的意思是,默認的 VTEP
對端地址爲 192.168.57.54
。換句話說,原始報文通過 vxlan0
後會被內核添加上 VXLAN 頭部,而外部 UDP 頭的目的 IP 地址會被冠上 192.168.57.54
。
在另外一臺主機(192.168.57.54)上也進行相同的配置:
$ ip link add vxlan0 type vxlan id 42 dstport 4789 remote 192.168.57.50
$ ip link add vrf0 type vrf table 10
$ ip link set vrf0 up
$ ip link set vxlan0 master vrf0
$ ip addr add 172.18.1.3/24 dev vxlan0
$ ip link set vxlan0 up
複製代碼
一切大功告成以後,就能夠相互通訊了,在 192.168.57.50
上 ping 172.18.1.3
:
$ ping 172.18.1.3 -I vrf0
複製代碼
同時使用 wireshark
遠程抓包:
$ ssh root@192.168.57.54 'tcpdump -i any -s0 -c 10 -nn -w - port 4789' | /Applications/Wireshark.app/Contents/MacOS/Wireshark -k -i -
複製代碼
具體含義我就不解釋了,參考 Tcpdump 示例教程。
能夠看到 VXLAN
報文能夠分爲三塊:
ARP
請求),它們和經典網絡的通訊報文沒有任何區別,除了由於 MTU
致使有些報文比較小。VNI
確實是 42
。VTEP
所在主機的通訊報文頭部,目的 IP 地址爲對端 192.168.57.54
。下面來分析這個最簡單的模式下 vxlan 通訊的過程:
發送 ping 報文到 172.18.1.3
,查看路由表,報文會從 vxlan0
發出去。
內核發現 vxlan0
的 IP 是 172.18.1.2/24
,和目的 IP 在同一個網段,因此在同一個局域網,須要知道對方的 MAC 地址,所以會發送 ARP
報文查詢。
ARP
報文源 MAC 地址爲 vxlan0
的 MAC 地址,目的 MAC 地址爲全 1 的廣播地址(ff:ff:ff:ff:ff:ff)。
VXLAN
根據配置(VNI 42)添加上頭部。
對端的 VTEP
地址爲 192.168.57.54,將報文發送到該地址。
對端主機接收到這個報文,內核發現是 VXLAN 報文,會根據 VNI
發送給對應的 VTEP
。
VTEP
去掉 VXLAN 頭部,取出真正的 ARP
請求報文,同時,VTEP
會記錄源 MAC
地址和 IP 地址信息到 FDB
表中,這即是一次學習過程。而後生成 ARP
應答報文。
$ bridge fdb show
00:00:00:00:00:00 dev vxlan0 dst 192.168.57.50 self permanent
aa:4d:80:e3:75:e0 dev vxlan0 dst 192.168.57.50 self
複製代碼
應答報文目的 MAC 地址是發送方 VTEP
的 MAC 地址,目的 IP 是發送方 VTEP
的 IP 地址,直接發送給目的 VTEP。
應答報文經過 underlay 網絡直接返回給發送方主機,發送方主機根據 VNI
把報文轉發給 VTEP,VTEP 解包取出 ARP 應答報文,添加 ARP
緩存到內核,並根據報文學習到目的 VTEP
的 IP
地址和目的 MAC
地址,添加到 FDB
表中。
$ ip neigh show vrf vrf0
172.18.1.3 dev vxlan0 lladdr 76:06:5c:15:d9:78 STALE
$ bridge fdb show
00:00:00:00:00:00 dev vxlan0 dst 192.168.57.54 self permanent
fe:4a:7e:a2:b5:5d dev vxlan0 dst 192.168.57.54 self
複製代碼
VTEP
已經知道了通訊須要的全部信息,後續 ICMP 的 ping 報文都是在這條邏輯隧道中單播進行的,再也不須要發送 ARP
報文查詢。總結以上過程:一個 VXLAN 網絡的 ping 報文要經歷 ARP 尋址 + ICMP 響應 兩個過程,一旦 VTEP
設備學習到了對方 ARP 地址,後續通訊就能夠免去 ARP
尋址的過程。
上述的點對點 VXLAN
網絡通訊雙方只有一個 VTEP
,且只有一個通訊實體,而在實際生產中,每臺主機上都有幾十臺甚至上百臺虛擬機或容器須要通訊,所以須要一種機制將這些通訊實體組織起來,再經過隧道口 VTEP
轉發出去。
方案其實也很常見,Linux Bridge 就能夠將多塊虛擬網卡鏈接起來,所以能夠選擇使用 Bridge
將多個虛擬機或容器放到同一個 VXLAN 網絡中,網絡拓撲圖如圖所示:
和上面的模式相比,這裏只是多了一個 Bridge
,用來鏈接不一樣 network namespace 中的 veth pair
,同時 VXLAN
網卡也須要鏈接到該 Bridge
。
首先在 192.168.57.50
上建立 VXLAN 接口:
$ ip link add vxlan0 type vxlan \
id 42 \
dstport 4789 \
local 192.168.57.50 \
remote 192.168.57.54
複製代碼
而後建立網橋 bridge0
,把 VXLAN 網卡 vxlan0
綁定到上面,而後將 bridge0
綁定到 VRF
中,並啓動它們:
$ ip link add br0 type bridge
$ ip link set vxlan0 master br0
$ ip link add vrf0 type vrf table 10
$ ip link set br0 master vrf0
$ ip link set vxlan0 up
$ ip link set br0 up
$ ip link set vrf0 up
複製代碼
下面建立 network namespace
和一對 veth pair
,並把 veth pair 的其中一端綁定到網橋,而後把另外一端放到 network namespace 並綁定 IP 地址 172.18.1.2
:
$ ip netns add ns0
$ ip link add veth0 type veth peer name eth0 netns ns0
$ ip link set veth0 master br0
$ ip link set veth0 up
$ ip -n ns0 link set lo up
$ ip -n ns0 addr add 172.18.1.2/24 dev eth0
$ ip -n ns0 link set eth0 up
複製代碼
用一樣的方法在另外一臺主機上配置 VXLAN 網絡,綁定 172.18.1.3
到另一個 network namespace
中的 eth0:
$ ip link add vxlan0 type vxlan \
id 42 \
dstport 4789 \
local 192.168.57.54 \
remote 192.168.57.50
$ ip link add br0 type bridge
$ ip link set vxlan0 master br0
$ ip link add vrf0 type vrf table 10
$ ip link set br0 master vrf0
$ ip link set vxlan0 up
$ ip link set br0 up
$ ip link set vrf0 up
$ ip netns add ns0
$ ip link add veth0 type veth peer name eth0 netns ns0
$ ip link set veth0 master br0
$ ip link set veth0 up
$ ip -n ns0 link set lo up
$ ip -n ns0 addr add 172.18.1.3/24 dev eth0
$ ip -n ns0 link set eth0 up
複製代碼
從 172.18.1.2
ping 172.18.1.3
發現整個通訊過程和前面的實驗相似,只不過容器發出的 ARP
報文會先通過網橋,再轉發給 vxlan0
,而後在 vxlan0
處由 Linux 內核添加 VXLAN 頭部,最後發送給對端。
邏輯上,VXLAN 網絡下不一樣主機上的 network namespace
中的網卡都被鏈接到了同一個網橋上,這樣就能夠在同一個主機上建立同一 VXLAN
網絡下的多個容器,並相互通訊了。
上面兩種模式只能點對點鏈接,也就是說同一個 VXLAN 網絡中只能有兩個節點,這怎麼能忍。。。有沒有辦法讓同一個 VXLAN 網絡中容納多個節點呢?咱們先來回顧一下 VXLAN 通訊的兩個關鍵信息:
MAC
地址VTEP
的 IP 地址)跨主機的容器之間首次通訊時須要知道對方的 MAC
地址,所以會發送 ARP
報文查詢。若是有多個節點,就要把 ARP
查詢報文發送到全部節點,但傳統的 ARP
報文廣播是作不到的,由於 Underlay 和 Overlay 不在同一個二層網絡,默認狀況下 ARP
廣播是逃不出主機的。要想實現 Overlay 網絡的廣播,必需要把報文發送到全部 VTEP 所在的節點,爲了解決這個問題,大概有兩種思路:
MAC
地址和 VTEP IP
信息,直接把 ARP
和 FDB
信息告訴發送方 VTEP。通常是經過外部的分佈式控制中心來收集這些信息,收集到的信息會分發給同一個 VXLAN 網絡的全部節點。咱們先來看看多播是怎麼實現的,分佈式控制中心留到下一篇再講。
若是 VXLAN 要使用多播模式,須要底層的網絡支持多播功能,多播地址範圍爲
224.0.0.0~239.255.255.255
。
和上面的 點對點 VXLAN + Bridge 模式相比,這裏只是將對端的參數改爲 group
參數,其餘不變,命令以下:
# 在主機 192.168.57.50 上執行
$ ip link add vxlan0 type vxlan \
id 42 \
dstport 4789 \
local 192.168.57.50 \
group 224.1.1.1
$ ip link add br0 type bridge
$ ip link set vxlan0 master br0
$ ip link add vrf0 type vrf table 10
$ ip link set br0 master vrf0
$ ip link set vxlan0 up
$ ip link set br0 up
$ ip link set vrf0 up
$ ip netns add ns0
$ ip link add veth0 type veth peer name eth0 netns ns0
$ ip link set veth0 master br0
$ ip link set veth0 up
$ ip -n ns0 link set lo up
$ ip -n ns0 addr add 172.18.1.2/24 dev eth0
$ ip -n ns0 link set eth0 up
複製代碼
# 在主機 192.168.57.54 上執行
$ ip link add vxlan0 type vxlan \
id 42 \
dstport 4789 \
local 192.168.57.54 \
group 224.1.1.1
$ ip link add br0 type bridge
$ ip link set vxlan0 master br0
$ ip link add vrf0 type vrf table 10
$ ip link set br0 master vrf0
$ ip link set vxlan0 up
$ ip link set br0 up
$ ip link set vrf0 up
$ ip netns add ns0
$ ip link add veth0 type veth peer name eth0 netns ns0
$ ip link set veth0 master br0
$ ip link set veth0 up
$ ip -n ns0 link set lo up
$ ip -n ns0 addr add 172.18.1.3/24 dev eth0
$ ip -n ns0 link set eth0 up
複製代碼
和上面的實驗明顯有區別的是 FDB 表項的內容:
$ bridge fdb show
00:00:00:00:00:00 dev vxlan0 dst 224.1.1.1 self permanent
複製代碼
dst
字段的值變成了多播地址 224.1.1.1
,而不是以前對方的 VTEP 地址,VTEP 會經過 IGMP(Internet Group Management Protocol) 加入同一個多播組 224.1.1.1
。
咱們來分析下多播模式下 VXLAN
通訊的全過程:
172.18.1.3
,查看路由表,報文會從 vxlan0
發出去。vxlan0
的 IP 是 172.18.1.2/24
,和目的 IP 在同一個網段,因此在同一個局域網,須要知道對方的 MAC 地址,所以會發送 ARP
報文查詢。ARP
報文源 MAC 地址爲 vxlan0
的 MAC 地址,目的 MAC 地址爲全 1 的廣播地址(ff:ff:ff:ff:ff:ff)。VXLAN
根據配置(VNI 42)添加上頭部。VTEP
在哪臺主機,根據多播配置,VTEP
會往多播地址 224.1.1.1
發送多播報文。VXLAN
報文,就會根據 VNI
發送給相應的 VTEP
。VTEP
會去掉 VXLAN
的頭部,取出真正的 ARP
請求報文。同時,VTEP
會記錄源 MAC
地址和 IP 地址信息到 FDB
表中,這即是一次學習過程。若是發現 ARP
不是發送給本身的,就直接丟棄;若是是發送給本身的,則生成 ARP
應答報文。整個通訊過程和以前比較相似,只是 Underlay
採用組播的方式發送報文,對於多節點的 VXLAN
網絡來講比較簡單高效。但多播也是有它的問題的,並非全部網絡設備都支持多播(好比公有云),再加上多播方式帶來的報文浪費,在實際生成中不多被採用。下篇文章就着重介紹如何經過分佈式控制中心來自動發現 VTEP
和 MAC
地址等信息。
掃一掃下面的二維碼關注微信公衆號,在公衆號中回覆◉加羣◉便可加入咱們的雲原生交流羣,和孫宏亮、張館長、陽明等大佬一塊兒探討雲原生技術