天天看點

零入門kubernetes網絡實戰-13->同一主控端上的兩個網絡命名空間通信方案

《零入門kubernetes網絡實戰》視訊專欄位址

https://www.ixigua.com/7193641905282875942

本篇文章視訊位址(稍後上傳)

本篇文章主要是想模拟一下,在同一個主控端上,多個網絡命名空間之間如何通信?

有哪些可以采取的方案。

可能存在的方案:

  • 方案一:使用一對veth pair将兩個命名空間直接連接配接起來,兩個命名空間處于同網段内
  • 方案二:為兩個命名空間分别設定自己的veth pair
    • 場景一:兩個命名空間處于同網段時的連結情況
    • 場景二:兩個命名空間處于非同網段時的連結情況
  • 方案三:使用虛拟網橋将兩個不同的命名空間連結起來

  • 方案一:使用價值并不是很大。
  • 方案二:具有一定的參考價值,為以後學期其他網絡模式奠定基礎
  • 方案三:使用價值最高。可以同時連接配接多個命名空間,使其通信。
1、方案一:使用一對veth pair将兩個命名空間直接連接配接起來,兩個命名空間處于同網段内
零入門kubernetes網絡實戰-13->同一主要端上的兩個網絡命名空間通信方案

模拟測試将veth pair的兩端分别加入兩個不同的網絡命名空間,測試一下連通性

ip link add veth1 type veth peer name veth2

ip netns add ns1
ip netns add ns2

ip link set veth1 netns ns1
ip link set veth2 netns ns2

ip netns exec ns1 ip addr add 10.244.1.2/24 dev veth1
ip netns exec ns2 ip addr add 10.244.1.3/24 dev veth2

ip netns exec ns1 ip link set veth1 up
ip netns exec ns2 ip link set veth2 up
           
ip netns exec ns1 ping -c 1 10.244.1.3
ip netns exec ns2 ping -c 1 10.244.1.2
           
零入門kubernetes網絡實戰-13->同一主要端上的兩個網絡命名空間通信方案
零入門kubernetes網絡實戰-13->同一主要端上的兩個網絡命名空間通信方案

在同一個主控端下,veth pair連結的兩個網絡命名空間可以通過veth pair進行互相通信

2、方案二:為兩個命名空間分别設定自己的veth pair
2.1、場景一:兩個命名空間處于同網段時的連結情況
零入門kubernetes網絡實戰-13->同一主要端上的兩個網絡命名空間通信方案
2.1.1、操作實戰
ip link add veth1a type veth peer name veth1b
ip link add veth2a type veth peer name veth2b

ip netns add ns1
ip netns add ns2

ip link set veth1a netns ns1
ip link set veth2a netns ns2

ip addr add 10.244.1.3 dev veth1b
ip addr add 10.244.1.4 dev veth2b
ip netns exec ns1 ip addr add 10.244.1.2/24 dev veth1a
ip netns exec ns2 ip addr add 10.244.1.5/24 dev veth2a

ip link set veth1b up
ip link set veth2b up
ip netns exec ns1 ip link set veth1a up
ip netns exec ns2 ip link set veth2a up
           
2.1.2、測試

在執行下面的測試指令前,最好先把抓包分析的指令執行一下,

因為肯定是ping不通的。先執行抓包指令,可以觀察到最初始的發包狀态。

ip netns exec ns1 ping 10.244.1.5
           
零入門kubernetes網絡實戰-13->同一主要端上的兩個網絡命名空間通信方案
2.1.3、抓包分析

分别對veth1a,veth1b, veth2a, veth2b進行抓包分析

2.1.3.1、在master節點上,進入ns1網絡命名空間對veth1a
ip netns exec ns1 tcpdump -nn -i veth1a
           
零入門kubernetes網絡實戰-13->同一主要端上的兩個網絡命名空間通信方案
2.1.3.2、在master節點上,進入ns2網絡命名空間對veth2a進行抓包
ip netns exec ns2 tcpdump -nn -i veth2a
           
零入門kubernetes網絡實戰-13->同一主要端上的兩個網絡命名空間通信方案
2.1.4、在master節點上,對veth1b抓包
tcpdump -nn -i veth1b
           
零入門kubernetes網絡實戰-13->同一主要端上的兩個網絡命名空間通信方案
2.1.5、在master節點上,對veth2b抓包
tcpdump -nn -i veth2b
           
零入門kubernetes網絡實戰-13->同一主要端上的兩個網絡命名空間通信方案

從抓包情況來看,至少存在一個問題

從veth1a可以正常發送ARP資料包,并且将ARP資料包直接轉發到了veth1b網卡裡,

veth1b網卡也發送了同樣的資料包,但是,資料包從veth1b出來後,沒有對應的路由;

再檢視一下,目前的路由表

零入門kubernetes網絡實戰-13->同一主要端上的兩個網絡命名空間通信方案
2.1.6、設定目的路由

給去往10.244.1.2,10.244.1.5的資料包添加相關路由

ip route add 10.244.1.2 dev veth1b
ip route add 10.244.1.5 dev veth2b
route -n
           
零入門kubernetes網絡實戰-13->同一主要端上的兩個網絡命名空間通信方案

添加完路由後,抓包情況沒有發生變化,不再重複截圖了。

這個時候,需要關注一下核心參數proxy_arp了。

2.1.7、為什麼需要設定proxy_arp參數了?

下面純屬于個人了解:

如果你了解ARP的原理,就會發現:

當veth1a發起的ARP請求到達veth1b後,veth1b網卡進行解析ARP請求,發現目的IP并非自己。

是以,我不需要回複此APR請求。

是以,程式就卡在這裡了,veth1a不停的發送,Veth1b不停的丢棄。

是以,如果打破僵局的話,需要veth1b進行回複一下,代理别人回複一下。

就需要用到了proxy_arp參數了。

2.1.8、為veth1b設定一下proxy_arp參數
2.1.8.1、proxy_arp什麼意思呢?

是否開啟arp代理,開啟arp代理的話則會以自己的mac位址回複arp請求,0為不開啟,1則開啟。

可以參考一下,下面的網址

https://imliuda.com/post/1015

2.1.8.2、為veth1b網卡設定proxy_arp參數

在主控端上,執行下面的指令

echo 1 > /proc/sys/net/ipv4/conf/veth1b/proxy_arp
           

執行完,繼續觀察一下各網卡的發送情況

veth1a的抓包變化

零入門kubernetes網絡實戰-13->同一主要端上的兩個網絡命名空間通信方案
veth1b對veth1a的ARP請求,進行了回複。也就是替10.244.1.5進行了回複,

這種行為,稱為代理回複。
           

veth1b的抓包變化

零入門kubernetes網絡實戰-13->同一主要端上的兩個網絡命名空間通信方案
veth1a收到ARP的回複後,就立刻發起了icmp請求,并且将資料包轉發給了veht1b.
           

veth2b

零入門kubernetes網絡實戰-13->同一主要端上的兩個網絡命名空間通信方案
veth1b發起的資料包,經過路由判斷,将資料包發送給了veth2b
           
2.1.9、為veth2b設定proxy_arp參數
echo 1 > /proc/sys/net/ipv4/conf/veth2b/proxy_arp
           
零入門kubernetes網絡實戰-13->同一主要端上的兩個網絡命名空間通信方案
2.1.10、重新測試
ip netns exec ns1 ping 10.244.1.5
           
零入門kubernetes網絡實戰-13->同一主要端上的兩個網絡命名空間通信方案
2.1.11、下面提供一下,完整的建立指令
ip link add veth1a type veth peer name veth1b
ip link add veth2a type veth peer name veth2b

ip netns add ns1
ip netns add ns2

ip link set veth1a netns ns1
ip link set veth2a netns ns2

ip addr add 10.244.1.3 dev veth1b
ip addr add 10.244.1.4 dev veth2b
ip netns exec ns1 ip addr add 10.244.1.2/24 dev veth1a
ip netns exec ns2 ip addr add 10.244.1.5/24 dev veth2a

ip link set veth1b up
ip link set veth2b up
ip netns exec ns1 ip link set veth1a up
ip netns exec ns2 ip link set veth2a up

ip route add 10.244.1.2 dev veth1b
ip route add 10.244.1.5 dev veth2b

echo 1 > /proc/sys/net/ipv4/conf/veth1b/proxy_arp
echo 1 > /proc/sys/net/ipv4/conf/veth2b/proxy_arp

echo 1 > /proc/sys/net/ipv4/ip_forward
           

測試指令

ip netns exec ns1 ping 10.244.1.5
           

還可以進行日志追蹤設定

iptables -t raw -A PREROUTING -p icmp -j TRACE

iptables -t raw -A OUTPUT -p icmp -j TRACE
           

檢視日志

tail -f /var/log/messages
           

關于/proc/sys/net/ipv4/ip_forward

零入門kubernetes網絡實戰-13->同一主要端上的兩個網絡命名空間通信方案

你可以做一些測試,在上面測試正常的情況下,将ip_forward關閉,看看還能ping通不。

在稍微總結一下

直接看下面的圖

零入門kubernetes網絡實戰-13->同一主要端上的兩個網絡命名空間通信方案

個人了解:

是将ICMP資料包封裝到IP封包裡,然後,将IP封包封裝到以太網幀裡。

是以,veth2b其實,收到的應該是以太網幀。為了簡單,圖裡說的是IP封包。

veth2b收到IP封包後,對IP封包頭進行解析,獲得源IP是10.244.1.2,目的IP是10.244.1.5

veth2b第一次向veth2a進行轉發時,不知道Veth2a的MAC位址,

是以向veth2a發起了ARP請求。從上面對veth2b進行抓包分析裡,可以看出來。

veth2a收到ARP請求後,會進行回複

veth2b收到veth2a的回複後,會将IP封包發送給veth2a,

veth2a收到IP封包後,會進行解析,擷取ICMP資料包,并進行回報。

但是,veth2a并不知道10.244.1.2的Mac位址,是以,它也需要發起ARP請求。

是以,接下來,就是回複過程了,跟前面介紹原理一樣了。

協定的封裝過程,會在後面的tap章節進行介紹。
           

其實,這個解釋,可能經不起推敲的;因為在上面的測試用例中,當在ns1 ping主控端上的eth0網卡時,

隻添加了路由,并沒有為veth1設定proxy_arp參數;

2.1.12、請求過程,資料包的封包内容

下面是master節點上的

零入門kubernetes網絡實戰-13->同一主要端上的兩個網絡命名空間通信方案

上面是ns1網絡命名空間,下面是ns2網絡命名空間

下面的分析,僅供參考

  • 當veth1b網卡接收到veth1a發送的資料包後,對封包進行解析
  • 發現目的MAC是自己的,是以,需要接收此資料包,
  • 繼續解析,發現目的IP是10.244.1.5
  • 查詢路由,發現去往10.244.1.5,需要通過veth2b網卡發送
  • 交由veth2b網卡處理,veth2b網卡發現目的IP是10.244.1.5,需要發送ARP協定,擷取10.244.1.5IP對應的MAC位址
  • 擷取到MAC位址後,經由網絡協定棧重新封裝,建構新的以太網幀
  • 交由veth2b網卡發送出去。
(主要是網卡的具體功能,以及跟網絡協定棧調用順序,并不是非常了解。)
2.1.13、請求過程,都經曆了哪些iptables規則鍊

為了驗證測試,需要在master節點添加日志埋點;

此過程,需要使用到rsyslog服務

2.1.13.1、安裝rsyslog服務
2.1.13.1.1、安裝rsyslog服務
yum -y install rsyslog
           
2.1.13.1.2、更新配置檔案
echo "kern.*     /var/log/iptables.log" >> /etc/rsyslog.conf 
           
零入門kubernetes網絡實戰-13->同一主要端上的兩個網絡命名空間通信方案

.*,表示所有等級的消息都添加到iptables.log檔案裡

資訊等級的指定方式

  • .XXX,表示 大于XXX級别的資訊
  • .=XXX,表示等于XXX級别的資訊
    • 如,kern.=notice /var/log/iptables.log, 将notice以上的資訊添加到iptables.log裡
  • .!XXX, 表示在XXX之外的等級資訊
2.1.13.1.3、重新開機rsyslog服務
systemctl restart rsyslog

systemctl status  rsyslog
           
零入門kubernetes網絡實戰-13->同一主要端上的兩個網絡命名空間通信方案
2.1.13.2、在master節點上,添加日志埋點

将目前的日志統計清零

iptables -t nat -Z
iptables -t filter -Z
           

插入日志埋點前,先檢視一下,目前的現狀

iptables -t nat -nvL PREROUTING --line-number
iptables -t filter -nvL FORWARD --line-number
iptables -t nat -nvL POSTROUTING --line-number
           

插入日志埋點

iptables -t nat -A PREROUTING -p icmp -j LOG --log-prefix "Nat-PREROUTING-1-"
iptables -t filter -A FORWARD -p icmp -j LOG --log-prefix "Filter-FORWARD-1-"
iptables -t nat -A POSTROUTING -p icmp -j LOG --log-prefix "Nat-POSTROUTING-1-"
           

實時檢視日志

tail -f /var/log/iptables.log
           
2.1.13.3、重新發起請求
ip netns exec ns1 ping 10.244.1.5
           
零入門kubernetes網絡實戰-13->同一主要端上的兩個網絡命名空間通信方案

再次檢視日志

零入門kubernetes網絡實戰-13->同一主要端上的兩個網絡命名空間通信方案

看上面的圖,一共發送了5次請求

再看一下,iptables.log日志,一共有12條記錄。

  • 前4條記錄,是第1次請求和回報經過的規則鍊,請求經過了PREROUTING->FORWARD-POSTROUTING,回報經過了FORWARD鍊
  • 第5,6條記錄,是第2次請求和回報經過的規則鍊,請求和回報都隻經過FORWARD鍊
  • 第7,8條記錄,是第3次請求和回報經過的規則鍊,請求和回報都隻經過FORWARD鍊
  • 第9,10條記錄,是第4次請求和回報經過的規則鍊,請求和回報都隻經過FORWARD鍊
  • 第11,12條記錄,是第5次請求和回報經過的規則鍊,請求和回報都隻經過FORWARD鍊
2.1.13.4、經曆的iptables規則鍊
零入門kubernetes網絡實戰-13->同一主要端上的兩個網絡命名空間通信方案
2.2、場景二:兩個命名空間處于非同網段時的連結情況
2.2.1、網絡拓撲
零入門kubernetes網絡實戰-13->同一主要端上的兩個網絡命名空間通信方案

接下來,我們提供兩種方式來實作上面的網絡拓撲

2.2.2、操作實戰一(arp代理應答方案)
ip link add veth1a type veth peer name veth1b
ip link add veth2a type veth peer name veth2b

ip netns add ns1
ip netns add ns2

ip link set veth1a netns ns1
ip link set veth2a netns ns2

ip addr add 10.244.1.3 dev veth1b
ip addr add 10.244.2.2 dev veth2b
ip netns exec ns1 ip addr add 10.244.1.2/24 dev veth1a
ip netns exec ns2 ip addr add 10.244.2.3/24 dev veth2a

ip link set veth1b up
ip link set veth2b up
ip netns exec ns1 ip link set veth1a up
ip netns exec ns2 ip link set veth2a up

ip route add 10.244.1.2 dev veth1b
ip route add 10.244.2.3 dev veth2b
ip netns exec ns1 route add -net 10.244.2.0/24 dev veth1a
ip netns exec ns2 route add -net 10.244.1.0/24 dev veth2a

echo 1 > /proc/sys/net/ipv4/conf/veth1b/proxy_arp
echo 1 > /proc/sys/net/ipv4/conf/veth2b/proxy_arp

echo 1 > /proc/sys/net/ipv4/ip_forward
           

該方式,完全跟同網段是一樣的。

從ns1裡ping ns2

ip netns exec ns1 ping 10.244.2.3
           
零入門kubernetes網絡實戰-13->同一主要端上的兩個網絡命名空間通信方案

從ns2裡ping ns1也是可以的

ip netns exec ns2 ping 10.244.1.2
           
2.2.3、操作實戰二(可以認為是路由方案)
ip link add veth1a type veth peer name veth1b
ip link add veth2a type veth peer name veth2b

ip netns add ns1
ip netns add ns2

ip link set veth1a netns ns1
ip link set veth2a netns ns2

ip addr add 10.244.1.3 dev veth1b
ip addr add 10.244.2.2 dev veth2b
ip netns exec ns1 ip addr add 10.244.1.2/24 dev veth1a
ip netns exec ns2 ip addr add 10.244.2.3/24 dev veth2a

ip link set veth1b up
ip link set veth2b up
ip netns exec ns1 ip link set veth1a up
ip netns exec ns2 ip link set veth2a up

ip route add 10.244.1.0/24 dev veth1b
ip route add 10.244.2.0/24 dev veth2b
ip netns exec ns1 route add -net 10.244.2.0/24 gw 10.244.1.3 dev veth1a
ip netns exec ns2 route add -net 10.244.1.0/24 gw 10.244.2.2 dev veth2a

echo 1 > /proc/sys/net/ipv4/ip_forward
           

将主控端作為路由器來使用。

零入門kubernetes網絡實戰-13->同一主要端上的兩個網絡命名空間通信方案

測試,如下:

ip netns exec ns1 ping 10.244.2.3
           
2.3、方案三:使用虛拟網橋将兩個不同的命名空間連結起來

本方案,可以參考後續的網橋相關文章

3、總結
  • 如果你已經看過<<基于veth pair+snat技術實作内部網絡通路本區域網路的其他主控端>>的文章後,可以思考一下,為什麼在這篇文章裡,沒有使用proxy_arp代理轉發參數呢?同樣,在場景二裡的操作實戰二中也沒有使用proxy_arp代理轉發參數?
    • 本篇文章裡使用了proxy_arp代理轉發參數,是因為?
      • snat文章裡,設定預設路由,并指定了網關位址,将veth1b網卡設定為網關了,當資料包去往10.211.55.0/24路由時,都會将資料包發送給網關,通過ARP是可以擷取網關的MAC位址的。
      • 而本篇文章裡沒有在ns1網絡命名空間裡設定預設路由,是以,當veth1a發送ARP協定擷取10.244.1.5IP對應的MAC位址時,veth1b網卡雖然收到了ARP資料包,發現目的IP并非是自己,就丢棄了;是以,需要讓veth1b代理回答一下arp協定。
  • 本測試用例,實際中,就是同一個節點上容器之間如何通信
可以重點關注幾個事情?
是否跨網段了,是否設定了路由,指定了網關,通過哪個網卡發送出去的?
ARP協定用來幹什麼的?
proxy_arp代理轉發?什麼時候使用代理轉發
網橋不用設定代理轉發,應該是預設支援的。
網卡之間資料包轉發時,經過了哪些鍊?第一次,跟第二次,,,,,經過的鍊是否一樣?
當然,一開始,總結不好,等時間長了,做了很多練習,就會發現。
好像,來來回回,就這些東西。
隻是,一開始,比較亂而已。
點選 下面 傳回 專欄目錄

<<零入門kubernetes網絡實戰>>技術專欄之文章目錄

繼續閱讀