您好,登錄后才能下訂單哦!
這篇文章給大家介紹Calico 網絡通信的原理是什么,內容非常詳細,感興趣的小伙伴們可以參考借鑒,希望對大家能有所幫助。
下面我們通過具體的例子來幫助大家理解 Calico 網絡的通信原理。任意選擇 k8s 集群中的一個節點作為實驗節點,進入容器 A,查看容器 A 的 IP 地址:
$ ip a 1: lo: <loopback,up,lower_up> mtu 65536 qdisc noqueue state UNKNOWN qlen 1000 link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 inet 127.0.0.1/8 scope host lo valid_lft forever preferred_lft forever 3: eth0@if771: <broadcast,multicast,up,lower_up,m-down> mtu 1440 qdisc noqueue state UP link/ether 66:fb:34:db:c9:b4 brd ff:ff:ff:ff:ff:ff inet 172.17.8.2/32 scope global eth0 valid_lft forever preferred_lft forever
這里容器獲取的是 /32 位主機地址,表示將容器 A 作為一個單點的局域網。
瞄一眼容器 A 的默認路由:
$ ip route default via 169.254.1.1 dev eth0 169.254.1.1 dev eth0 scope link
現在問題來了,從路由表可以知道 169.254.1.1
是容器的默認網關,但卻找不到任何一張網卡對應這個 IP 地址,這是個什么鬼?
莫慌,先回憶一下,當一個數據包的目的地址不是本機時,就會查詢路由表,從路由表中查到網關后,它首先會通過 ARP
獲得網關的 MAC 地址,然后在發出的網絡數據包中將目標 MAC 改為網關的 MAC,而網關的 IP 地址不會出現在任何網絡包頭中。也就是說,沒有人在乎這個 IP 地址究竟是什么,只要能找到對應的 MAC 地址,能響應 ARP 就行了。
想到這里,我們就可以繼續往下進行了,可以通過 ip neigh
命令查看一下本地的 ARP 緩存:
$ ip neigh 169.254.1.1 dev eth0 lladdr ee:ee:ee:ee:ee:ee REACHABLE
這個 MAC 地址應該是 Calico 硬塞進去的,而且還能響應 ARP。但它究竟是怎么實現的呢?
我們先來回想一下正常情況,內核會對外發送 ARP 請求,詢問整個二層網絡中誰擁有 169.254.1.1
這個 IP 地址,擁有這個 IP 地址的設備會將自己的 MAC 地址返回給對方。但現在的情況比較尷尬,容器和主機都沒有這個 IP 地址,甚至連主機上的端口 calicba2f87f6bb
,MAC 地址也是一個無用的 ee:ee:ee:ee:ee:ee
。按道理容器和主機網絡根本就無法通信才對呀!所以 Calico 是怎么做到的呢?
這里我就不繞彎子了,實際上 Calico 利用了網卡的代理 ARP 功能。代理 ARP 是 ARP 協議的一個變種,當 ARP 請求目標跨網段時,網關設備收到此 ARP 請求,會用自己的 MAC 地址返回給請求者,這便是代理 ARP(Proxy ARP)。舉個例子:
上面這張圖中,電腦發送 ARP 請求服務器 8.8.8.8 的 MAC 地址,路由器(網關)收到這個請求時會進行判斷,由于目標 8.8.8.8 不屬于本網段(即跨網段),此時便返回自己的接口 MAC 地址給 PC,后續電腦訪問服務器時,目標 MAC 直接封裝為 MAC254。
現在我們知道,Calico 本質上還是利用了代理 ARP 撒了一個“善意的謊言”,下面我們來確認一下。
查看宿主機的網卡信息和路由信息:
$ ip addr ... 771: calicba2f87f6bb@if4: <broadcast,multicast,up,lower_up> mtu 1440 qdisc noqueue state UP group default link/ether ee:ee:ee:ee:ee:ee brd ff:ff:ff:ff:ff:ff link-netnsid 14 inet6 fe80::ecee:eeff:feee:eeee/64 scope link valid_lft forever preferred_lft forever ... $ ip route ... 172.17.8.2 dev calicba2f87f6bb scope link ...
查看是否開啟代理 ARP:
$ cat /proc/sys/net/ipv4/conf/calicba2f87f6bb/proxy_arp 1
如果還不放心,可以通過 tcpdump 抓包驗證一下:
$ tcpdump -i calicba2f87f6bb -e -nn tcpdump: verbose output suppressed, use -v or -vv for full protocol decode listening on calicba2f87f6bb, link-type EN10MB (Ethernet), capture size 262144 bytes 14:27:13.565539 ee:ee:ee:ee:ee:ee > 0a:58:ac:1c:ce:12, ethertype IPv4 (0x0800), length 4191: 10.96.0.1.443 > 172.17.8.2.36180: Flags [P.], seq 403862039:403866164, ack 2023703985, win 990, options [nop,nop,TS val 331780572 ecr 603755526], length 4125 14:27:13.565613 0a:58:ac:1c:ce:12 > ee:ee:ee:ee:ee:ee, ethertype IPv4 (0x0800), length 66: 172.17.8.2.36180 > 10.96.0.1.443: Flags [.], ack 4125, win 2465, options [nop,nop,TS val 603758497 ecr 331780572], length 0
總結:
Calico 通過一個巧妙的方法將 workload 的所有流量引導到一個特殊的網關 169.254.1.1,從而引流到主機的 calixxx 網絡設備上,最終將二三層流量全部轉換成三層流量來轉發。
在主機上通過開啟代理 ARP 功能來實現 ARP 應答,使得 ARP 廣播被抑制在主機上,抑制了廣播風暴,也不會有 ARP 表膨脹的問題。
既然我們已經掌握了 Calico 的組網原理,接下來就可以手動模擬驗證了。架構如圖所示:
先在 Host0 上執行以下命令:
$ ip link add veth0 type veth peer name eth0 $ ip netns add ns0 $ ip link set eth0 netns ns0 $ ip netns exec ns0 ip a add 10.20.1.2/24 dev eth0 $ ip netns exec ns0 ip link set eth0 up $ ip netns exec ns0 ip route add 169.254.1.1 dev eth0 scope link $ ip netns exec ns0 ip route add default via 169.254.1.1 dev eth0 $ ip link set veth0 up $ ip route add 10.20.1.2 dev veth0 scope link $ ip route add 10.20.1.3 via 192.168.1.16 dev ens192 $ echo 1 > /proc/sys/net/ipv4/conf/veth0/proxy_arp
在 Host1 上執行以下命令:
$ ip link add veth0 type veth peer name eth0 $ ip netns add ns1 $ ip link set eth0 netns ns1 $ ip netns exec ns1 ip a add 10.20.1.3/24 dev eth0 $ ip netns exec ns1 ip link set eth0 up $ ip netns exec ns1 ip route add 169.254.1.1 dev eth0 scope link $ ip netns exec ns1 ip route add default via 169.254.1.1 dev eth0 $ ip link set veth0 up $ ip route add 10.20.1.3 dev veth0 scope link $ ip route add 10.20.1.2 via 192.168.1.32 dev ens192 $ echo 1 > /proc/sys/net/ipv4/conf/veth0/proxy_arp
網絡連通性測試:
# Host0 $ ip netns exec ns1 ping 10.20.1.3 PING 10.20.1.3 (10.20.1.3) 56(84) bytes of data. 64 bytes from 10.20.1.3: icmp_seq=1 ttl=62 time=0.303 ms 64 bytes from 10.20.1.3: icmp_seq=2 ttl=62 time=0.334 ms
實驗成功!
具體的轉發過程如下:
ns0 網絡空間的所有數據包都轉發到一個虛擬的 IP 地址 169.254.1.1,發送 ARP 請求。
Host0 的 veth 端收到 ARP 請求時通過開啟網卡的代理 ARP 功能直接把自己的 MAC 地址返回給 ns0。
ns0 發送目的地址為 ns1 的 IP 數據包。
因為使用了 169.254.1.1 這樣的地址,Host 判斷為三層路由轉發,查詢本地路由 10.20.1.3 via 192.168.1.16 dev ens192
發送給對端 Host1,如果配置了 BGP,這里就會看到 proto 協議為 BIRD。
當 Host1 收到 10.20.1.3 的數據包時,匹配本地的路由表 10.20.1.3 dev veth0 scope link
,將數據包轉發到對應的 veth0 端,從而到達 ns1。
回程類似
關于Calico 網絡通信的原理是什么就分享到這里了,希望以上內容可以對大家有一定的幫助,可以學到更多知識。如果覺得文章不錯,可以把它分享出去讓更多的人看到。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。