Docker跨主機訪問
macvlan
創建macvlan網絡
打開網卡的混雜模式,並查看網卡狀態up且promisc模式已經生效
在兩個主機上創建macvlan網絡macvlan_net1
在另一台主機上執行相同的命令
-d macvlan指定driver為macvlan
macvlan網絡是local網絡,為了保證跨主機能夠通信,用戶需要自己管理IP subnet
與其他網絡不同,docker不會為macvlan創建網關,這里的網關應該是真實存在的,否則容器無法路由
-o parent指定使用的網絡接口
在第一台主機上運行容器test1並連接到macvlan_net1
由於兩台主機中的macvlan_net1本質上是獨立的,為了避免自動分配造成IP沖突,最好通過--ip指定test的地址
在第二台主機上運行容器test2,指定IP為172.16.86.11
驗證test1與test2的通信,由結果可以得出macvlan實現了跨主機訪問的功能
test2可以ping到test1的IP 172.16.86.10,但無法解析test1主機名,可見docker沒有為macvlan提供DNS服務
macvlan的網絡結構
查看容器test1的網絡設備
除了lo,容器只有一個eth0,eth0 后面的@if2表明該interface有一個對應的interface,其全局的編號為2。根據macvlan的原理,我們有理由猜測這個interface 就是主機的enp0s5,確認如下
可見,容器的eth0就是enp0s5通過macvlan虛擬出來的interface。容器的interface直接與主機的網卡連接,這種方案使得容器無需通過NAT和端口映射就能與外網直接通信(只要有網關),在網絡上與其他獨立主機沒有區別
用sub-interface 實現多macvlan 網絡
macvlan會獨占主機的網卡,也就是說一個網卡只能創建一個macvlan網絡,否則會報錯
但主機的網卡數量是有限的,如何支持更多的macvlan網絡呢?Linux 的網卡也能支持VLAN(apt-get install vlan),同一個interface可以收發多個VLAN的數據包,不過前提是要創建VLAN的sub-interface。比如希望enp0s5同時支持VLAN10和VLAN20,則需創建sub-interface enp0s5.10和enp0s5.20。
下面演示如何在enp0s5.10和enp0s5.20上創建macvlan 網絡。
(1)首先編輯兩台主機的/etc/network/interfaces,配置sub-
auto enp0s5 iface enp0s5 inet manual auto enp0s5.10 iface enp0s5.10 inet manual vlan-raw-device enp0s5 auto enp0s5.20 iface enp0s5.20 inet manual vlan-raw-device enp0s5
(2)然后啟用sub-interface
sudo ifup enp0s5.10 sudo ifup enp0s5.20
(3)創建macvlan 網絡
sudo docker network create -d macvlan --subnet=172.16.10.0/24 --gateway=172.16.10.1 -o parent=enp0s5.10 mac_net10 sudo docker network create -d macvlan --subnet=172.16.20.0/24 --gateway=172.16.20.1 -o parent=enp0s5.20 mac_net20
(4)在第一台主機上中運行容器
sudo docker run -itd --name test5 --ip=172.16.10.10 --network mac_net10 busybox sudo docker run -itd --name test6 --ip=172.16.20.10 --network mac_net20 busybox
(5)在第二台主機中運行容器
sudo docker run -itd --name test7 --ip=172.16.10.11 --network mac_net10 busybox sudo docker run -itd --name test8 --ip=172.16.20.11 --network mac_net20 busybox
驗證macvlan之間的連通性
為了方便驗證網絡的通信,先對所創建的容器進行相應的說明:test5與test7這兩個容器處於mac_net10下,IP分別為172.16.10.10和172.16.10.11;test6與test8處於mac_net20下,IP分別為172.16.20.10和172.16.20.11
讓處於同一macvlan網絡下的容器互ping,由結果可以看出同一macvlan網絡下的容器之間是可以通信的
讓處於不同macvlan網絡下的容器互ping
由結果可以看出不同macvlan之間不能通信。准確的說是不同macvlan網絡不能在二層上通信,在三層上可以通過網關將macvlan連通,下面我們就啟用網關。我們將第三台主機配置成一個虛擬路由器,設置網關並轉發VLAN10和VLAN20的流量,首先確保IP Forwarding已經啟用
輸出為1則表示啟用,如果為0可通過如下命令啟用
sudo sysctl -w net.ipv4.ip_forward=1
在 /etc/network/interfaces中配置vlan sub-interface
auto enp0s5 iface enp0s5 inet manual auto enp0s5.10 iface enp0s5.10 inet manual vlan-raw-device enp0s5 auto enp0s52.20 iface enp0s5.20 inet manual vlan-raw-device enp0s5
啟用sub-interface
sudo ifup enp0s5.10 sudo ifup enp0s5.20
將網關IP配置到sub-interface
sudo ifconfig enp0s5.10 172.16.10.1 netmask 255.255.255.0 up sudo ifconfig enp0s5.20 172.16.20.1 netmask 255.255.255.0 up
添加iptables規則,轉發不同VLAN的數據包
iptables -t nat -A POSTROUTING -o enp0s5.10 -j MASQUERADE iptables -t nat -A POSTROUTING -o enp0s5.20 -j MASQUERADE iptables -A FORWARD -i enp0s5.10 -o enp0s5.20 -m state --state RELATED,ESTABLISHED -j ACCEPT iptables -A FORWARD -i enp0s5.20 -o enp0s5.10 -m state --state RELATED,ESTABLISHED -j ACCEPT iptables -A FORWARD -i enp0s5.10 -o enp0s5.20 -j ACCEPT iptables -A FORWARD -i enp0s5.20 -o enp0s5.10 -j ACCEPT
現在第一台主機上位於mac_net10的test5已經可以與第二台主機上位於mac_net20的test8通信了
下面分析數據包是如何從test5(172.16.10.10)到達test8(172.16.20.11)的
(1)因為test5與test8在不同的IP網段,根據test5的路由表,數據包將發送到網段172.16.10.1
(2)路由器從enp0s5.10收到數據包,發現目的地址是172.16.20.11,查看自己的路由表,並將數據包從enp0s5.20轉發出去
(3)通過ARP記錄的信息,路由器能夠得知172.16.20.11在第二台主機上,於是將數據包發送給第二台主機
(4)第二台主機根據目的地址和VLAN信息將數據包發送給test8
macvlan網絡的連通性和隔離完全依賴VLAN、IP subnet和路由,docker本身不做任何限制,用戶可以像管理傳統VLAN網絡那樣管理macvlan