Linux

如何在 docker 容器內使用 LTE 介面?

  • April 23, 2021

對於我的客戶,我必須在不同的機器上設置 docker 容器,這些機器在各種物理鏈路上執行各種服務。

我不能對我的 docker 容器使用“主機”模式。

到目前為止,我已經愉快地使用 macvlan 驅動程序在我的容器中生成了新的網路介面。

例如:

networks:
 good_net:
   driver: macvlan
   driver_opts:
     parent: eno0
 slow_net:
   driver: macvlan
   driver_opts:
     parent: eno0
 high_latency_net:
   driver: macvlan
   driver_opts:
     parent: eno0

我在容器啟動時有一個腳本:

  • 給一個唯一的mac地址
  • 培養
  • dhcp 或靜態地址
  • 應用 tc 過濾器來調整每個網路的流量

工作正常:我可以在各個連結上執行 ping 和 iperf3 以測試它們是否按預期工作。

問題:現在真正的界面來了,它們破壞了我的設置。

其中一個連結現在是 LTE。

lte_net:
 driver: macvlan
 driver_opts:
   parent: lte0

在 PC1(主機,而不是容器)上:

4: lte0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UNKNOWN group default qlen 1000
  link/ether 7e:c4:d2:6a:e3:07 brd ff:ff:ff:ff:ff:ff
  inet 10.0.250.1/30 brd 10.0.250.3 scope global noprefixroute lte0
     valid_lft forever preferred_lft forever

在 PC2(主機,而不是容器)上:

4: lte0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UNKNOWN group default qlen 1000
  link/ether b6:30:cb:12:31:16 brd ff:ff:ff:ff:ff:ff
  inet 10.0.250.5/30 brd 10.0.250.7 scope global noprefixroute lte0
     valid_lft forever preferred_lft forever

主機可以通過 LTE 鏈路愉快地相互 ping 和 iperf3。

但是:在容器中,使用 macvlan 方法,它們不能:

  • 我為每個容器中的介面分配了同一子網中的 IP 地址:10.100.10.1/24 和 10.100.10.2/24
  • 我已經關閉了所有其他介面,所以只剩下一條路線:10.100.10.0/24 dev lte0 proto kernel scope link src 10.100.10.1
  • 從 pc1 上的容器,我嘗試在 pc2 上的容器中 ping 通 LTE 介面的 IP
  • 在主機上使用 tcpdump,我可以看到 lte 介面上的 ARP 數據包: 02:2d:6d:ad:63:62 (oui Unknown) > Broadcast, ethertype ARP (0x0806), length 42: Ethernet (len 6), IPv4 (len 4), Request who-has 10.100.10.2 tell 10.100.10.1, length 28

但是我看不到它們到達 pc2,甚至在主機級別也看不到。

原因很可能是來自 LTE 調製解調器無法辨識的 MAC 地址的數據包被丟棄。這類似於 WLAN 發生的情況。

所以我嘗試使用 ipvlan l2 代替,正如有時建議的那樣:

lte_net:
 driver: ipvlan
 driver_opts:
   ipvlan_mode: l2
   parent: lte0

容器中的 lte0 介面與其在主機上的父介面具有相同的 MAC 地址。但是沒有變化:仍然沒有跨越 LTE…

ipvlan l3 甚至沒有出現,但我認為這不是我需要的。

所以我的問題是:我做錯了什麼?如何正確訪問我的物理 LTE 作為 docker 容器中 IP 流量的網路介面?

對 3G 標記感到抱歉:我沒有足夠的聲譽來創建 LTE 標記…

謝謝 !

我終於找到了一個可行的解決方案……但是男孩我受苦了……並且學會了……

我現在有一個圍繞“docker-compose up -d”的包裝腳本和一個萬能的 docker-compose.yml,它從 4 個(我不需要更多)預設 docker 網路開始。

它看起來像這樣:

network:
 test_net0:
 test_net1:
 test_net2:
 test_net3:

啟動後,這將為每個 test_netX 創建:

  • 一個 veth 對:一個在容器命名空間中,一個在預設主機命名空間中
  • 一座橋:奴役了東道主的veth

對於主機上的標準 eth 介面,沒有問題:只需將其奴役到您選擇的網橋即可。我可以毫無問題地以同樣的方式奴役幾個 USB 乙太網適配器。這是在 bash 中完成的(現在我希望我們真的是在 python 中開始的)並且奴役是在使用 netns 的 iproute2 命令“up”之後完成的。

對於 LTE,事情變得複雜得多。首先,LTE 介面不會讓自己被正確地奴役。其次,雖然我們找不到關於它的文件,但經過大量實驗後,我們發現在 2 台主機上看到的 LTE 介面之間的某些東西做了很多丟棄:

  • 任何具有不在“LTE 網路”中的源或目標 IP 的數據包
  • (不確定但懷疑)任何具有與我們的 LTE 介面不同的源或目標 MAC 地址的數據包(順便說一下,這些似乎是由驅動程序動態分配的,讓事情變得更有趣)

基本上,我們的 LTE 設置只在 LTE 介面之間傳輸數據包。

所以我們有了一個絕妙的主意:讓我們通過 LTE 隧道傳輸我們的流量。我們從 ipip 隧道開始,但很快意識到我們邀請了一頭大象來野餐,因為我們需要通過 LTE 從容器到容器的多播,如果你有一百年的空閒時間,這可能是可行的……

然後,當我們在 LTE 鏈路上設置 GRETAP 而不是 ipip 隧道時,事情終於成功了。最大的優勢是 GRETAP 介面可以被奴役,並且它的行為類似於標準乙太網介面。

一旦我們在多播數據包上修復了太低的 TTL,我們的容器之間的所有類型的流量都可以通過 LTE 鏈路順利執行。

現在它看起來很容易和合乎邏輯……

Linux、iproute2、docker,你們都願意嫁給我嗎?

引用自:https://serverfault.com/questions/1052560