如何在 docker 容器內使用 LTE 介面?
對於我的客戶,我必須在不同的機器上設置 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,你們都願意嫁給我嗎?