實現Docker的跨主機網絡通訊的方案有不少,好比在以前博文中寫到的經過部署consul服務實現Docker容器跨主機通訊 ,而這篇博文將Macvlan寫下來docker
Macvlan工做原理:vim
- Macvlan是Linux內核支持的網絡接口。要求的Linux內部版本是v3.9–3.19和4.0+;
- 經過爲物理網卡建立Macvlan子接口,容許一塊物理網卡擁有多個獨立的MAC地址和IP地址。虛擬出來的子接口將直接暴露在相鄰物理網絡中。從外部看來,就像是把網線隔開多股,分別接受了不一樣的主機上同樣;
- 物理網卡收到包後,會根據收到包的目的MAC地址判斷這個包須要交給其中虛擬網卡。
當容器須要直連入物理網絡時,可使用Macvlan。Macvlan自己不建立網絡,本質上首先使宿主機物理網卡工做在‘混雜模式’,這樣物理網卡的MAC地址將會失效,全部二層網絡中的流量物理網卡都能收到。接下來就是在這張物理網卡上建立虛擬網卡,併爲虛擬網卡指定MAC地址,實現一卡多用,在物理網絡看來,每張虛擬網卡都是一個單獨的接口。centos
使用Macvlan有幾點須要注意:服務器
- 容器直接鏈接物理網絡,由物理網絡負責分配IP地址,可能的結果是物理網絡IP地址被耗盡,另外一個後果是網絡性能問題,物理網絡中接入的主機變多,廣播包占比快速升高而引發的網絡性能降低問題;
- 宿主機上的某張網上須要工做在‘混亂模式’下;
- 前面說到,工做在混亂模式下的物理網卡,其MAC地址會失效,因此,此模式中運行的容器並不能與外網進行通訊,可是不會影響宿主機與外網通訊;
- 從長遠來看bridge網絡與overlay網絡是更好的選擇,緣由就是虛擬網絡應該與物理網絡隔離而不是共享。
工做示意圖以下:網絡
實現效果:ide
- 兩臺centos 7.5,分別運行着docker服務;
- 兩臺docker服務器建立相同的一個MacVlan網絡,使docker服務器上的容器能夠實現跨主機通訊。
開始配置:
(1)第一臺docker服務器配置以下:性能
[root@docker ~]# ip link set ens33 promisc on #開啓ens33網卡的混雜模式。 #也就是開啓網卡的多個虛擬interface(接口) [root@docker ~]# ip link show ens33 #肯定查看的信息包含如下標紅的字樣 2: ens33: <BROADCAST,MULTICAST,'PROMISC',UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP mode DEFAULT qlen 1000 link/ether 00:0c:29:2f:89:cb brd ff:ff:ff:ff:ff:ff [root@docker ~]# docker network create -d macvlan --subnet 172.22.16.0/24 --gateway 172.22.16.1 -o parent=ens33 mac_net1 #建立macvlan網絡,指定網段、網關等信息,「-o」指定綁定在哪張網卡之上 [root@docker ~]# docker run -tid --name box1 --ip 172.22.16.10 --network mac_net1 busybox #基於新建立的macvlan網絡運行一個容器,並指定其IP。
確認運行的容器的IP地址:
(1)第二臺docker服務器配置以下(與第一臺docker服務器的配置基本類似):測試
[root@docker02 ~]# ip link set ens33 promisc on #開啓ens33網卡的混雜模式。 [root@docker02 ~]# ip link show ens33 #肯定查看的信息包含如下標紅的字樣 2: ens33: <BROADCAST,MULTICAST,'PROMISC',UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP mode DEFAULT qlen 1000 link/ether 00:0c:29:c6:57:bc brd ff:ff:ff:ff:ff:ff [root@docker02 ~]# docker network create -d macvlan --subnet 172.22.16.0/24 --gateway=172.22.16.1 -o parent=ens33 mac_net1 #建立一個與第一臺docker服務器的網段、網關相同的macvlan。並綁定到物理網卡上。 #爲了能夠直觀的看出其餘docker服務器上的macvlan和第這臺是在同一個網段的。 #因此,建議設置的網絡名稱同樣。 [root@docker02 ~]# docker run -tid --name box2 --ip 172.22.16.11 --network mac_net1 busybox #運行一個容器,並指定是基於macvlan網絡的 #注意,其IP地址不要與其餘docker服務器上的容器IP地址衝突
確認運行的容器的IP地址:code
使用第二臺docker服務器上的容器box2對第一臺docker服務器上的容器box1進行ping測試:blog
OK,跨主機的容器通訊就經過macvlan實現了。因爲使用混雜模式會形成物理網卡的MAC地址失效,因此容器並不能經過此模式進行與外網的通訊。
實現的效果以下:
- 兩臺centos 7.5,分別運行着docker服務;
- 每臺宿主機建立了兩個MacVlan網段供容器使用(172.10.16.0/24和172.20.16.0/24);
- 第一臺docker服務器上運行容器bbox1和bbox2,第二臺docker服務器運行容器bbox3和bbox4。
- 最終實現跨主機的同網段容器互相通訊。
開始配置:
(1)第一臺docker服務器配置以下:
[root@docker ~]# ip link set ens33 promisc on #開啓ens33網卡的混雜模式。 #也就是開啓網卡的多個虛擬interface(接口) [root@docker ~]# ip link show ens33 #肯定查看的信息包含如下標紅的字樣 2: ens33: <BROADCAST,MULTICAST,'PROMISC',UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP mode DEFAULT qlen 1000 link/ether 00:0c:29:2f:89:cb brd ff:ff:ff:ff:ff:ff [root@docker ~]# modinfo 8021q #查看是否加載8021q模塊,若是有信息返回,則表示該模塊已經加載
modinfo 8021q命令返回的信息以下:
[root@docker ~]# modprobe 8021q #若沒有加載8021q模塊,則執行此命令 [root@docker ~]# cd /etc/sysconfig/network-scripts/ [root@docker network-scripts]# vim ifcfg-ens33 #更改物理網卡配置 ...............#省略部份內容 BOOTPROTO=manual #將此配置項該爲「manual」,也是手動的意思 ...............#省略部份內容 #更改完成後,保存退出便可 [root@docker network-scripts]# cp -p ifcfg-ens33 ifcfg-ens33.10 #將網卡配置文件複製一份 # 「-p」表示保留文件本來的屬性 [root@docker network-scripts]# vim ifcfg-ens33.10 #更改複製出來的配置文件以下 BOOTPROTO=none NAME=ens33.10 #注意更更名稱 DEVICE=ens33.10 #注意更更名稱 ONBOOT=yes IPADDR=192.168.10.10 #給虛擬網卡設置一個IP PREFIX=24 GATEWAY=192.168.10.2 VLAN=yes #更改完成後,保存退出便可,注意,以上的IP與容器將要使用的IP並非同一網段 [root@docker network-scripts]# cp ifcfg-ens33.10 ifcfg-ens33.20 [root@docker network-scripts]# vim ifcfg-ens33.20 #編輯以下 BOOTPROTO=none NAME=ens33.20 #注意更更名稱 DEVICE=ens33.20 #注意更更名稱 ONBOOT=yes IPADDR=192.168.30.10 #注意,此處的IP與ens33.10並不在同一網段 PREFIX=24 GATEWAY=192.168.30.2 VLAN=yes #更改完成後,保存退出便可 [root@docker network-scripts]# ifdown ens33;ifup ens33 #重啓網卡,使更改生效 [root@docker network-scripts]# ifup ens33.10 #開啓ens33.10 [root@docker network-scripts]# ifup ens33.20 #開啓ens33.20 [root@docker ~]# docker network create -d macvlan --subnet 172.10.16.0/24 --gateway 172.10.16.1 -o parent=ens33.10 mac_net10 #建立一個macvlan網絡,給其定義一個網段、網關及綁定到ens33.10 [root@docker ~]# docker network create -d macvlan --subnet 172.20.16.0/24 --gateway 172.20.16.1 -o parent=ens33.20 mac_net20 #建立一個macvlan網絡,給其定義一個網段、網關及綁定到ens33.20 #接下來分別基於剛剛建立的macvlan網絡運行一個容器 [root@docker ~]# docker run -itd --name bbox1 --network mac_net10 --ip 172.10.16.10 busybox #基於網絡mac_net10運行一個容器,並指定其IP [root@docker ~]# docker run -itd --name bbox2 --network mac_net20 --ip 172.20.16.20 busybox #基於網絡mac_net10運行一個容器,並指定其IP
(2)第二臺docker服務器配置以下(基本與第一臺操做相似,只是要注意IP不要衝突):
[root@docker02 ~]# ip link set ens33 promisc on #開啓ens33網卡的混雜模式。 #也就是開啓網卡的多個虛擬interface(接口) [root@docker02 ~]# ip link show ens33 #肯定查看的信息包含如下標紅的字樣 2: ens33: <BROADCAST,MULTICAST,'PROMISC',UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP mode DEFAULT qlen 1000 link/ether 00:0c:29:2f:89:cb brd ff:ff:ff:ff:ff:ff [root@docker02 ~]# modinfo 8021q #查看是否加載8021q模塊,若是有信息返回,則表示該模塊已經加載
modinfo 8021q命令返回的信息以下:
[root@docker02 ~]# modprobe 8021q #若沒有加載8021q模塊,則執行此命令 [root@docker02 ~]# cd /etc/sysconfig/network-scripts/ [root@docker02 network-scripts]# vim ifcfg-ens33 #更改物理網卡配置 ...............#省略部份內容 BOOTPROTO=manual #將此配置項該爲「manual」,也是手動的意思 ...............#省略部份內容 #更改完成後,保存退出便可 [root@docker02 network-scripts]# scp root@192.168.20.7:/etc/sysconfig/network-scripts/ifcfg-ens33.* . #將第一臺docker服務器上的虛擬網卡配置文件複製過來 root@192.168.20.7 s password: #輸入第一臺docker服務器的用戶密碼 ifcfg-ens33.10 100% 117 0.1KB/s 00:00 ifcfg-ens33.20 100% 117 0.1KB/s 00:00 [root@docker02 network-scripts]# vim ifcfg-ens33.10 #只是更改其IP便可 BOOTPROTO=none NAME=ens33.10 DEVICE=ens33.10 ONBOOT=yes IPADDR=192.168.10.11 #更改IP是爲了避免要和第一臺docker服務器的虛接口IP衝突 PREFIX=24 GATEWAY=192.168.10.2 VLAN=yes [root@docker02 network-scripts]# vim ifcfg-ens33.20 #同上 BOOTPROTO=none NAME=ens33.20 DEVICE=ens33.20 ONBOOT=yes IPADDR=192.168.30.11 #更改其IP地址 PREFIX=24 GATEWAY=192.168.30.2 VLAN=yes [root@docker02 network-scripts]# ifdown ens33;ifup ens33 #重啓網卡,使更改生效 [root@docker02 network-scripts]# ifup ens33.10 #啓動ens33.10 [root@docker02 network-scripts]# ifup ens33.20 #啓動ens33.20 #接下來建立macvlan網絡,與第一臺docker服務器建立的網絡同樣 [root@docker02 ~]# docker network create -d macvlan --subnet 172.10.16.0/24 --gateway 172.10.16.1 -o parent=ens33.10 mac_net10 [root@docker02 ~]# docker network create -d macvlan --subnet 172.20.16.0/24 --gateway 172.20.16.1 -o parent=ens33.20 mac_net20 #接下來基於剛剛建立的網絡運行兩個容器 #基於mac_net10運行容器bbox3 [root@docker02 ~]# docker run -tid --name bbox3 --network mac_net10 --ip 172.10.16.11 busybox #基於mac_net20運行容器bbox4 [root@docker02 ~]# docker run -itd --name bbox4 --network mac_net20 --ip 172.20.16.21 busybox
配置至此,便可進行ping測試了,若是配置無誤,則bbox3應該和bbox1互通(由於其都是基於mac_net1010網絡);bbox4應該和bbox2互通(同理)。
但bbox3和bbox1不能和bbox4和bbox2互通(由於其不是基於同一個虛擬局域網)。
容器bbox3 ping 容器bbox1測試(注意:如果使用vmware虛擬機進行測試,因爲vmware的特性,需將其網絡適配器改成「橋接模式」,而不是NAT模式等。不然沒法通訊):
容器bbox4 ping 容器bbox2測試:
至此,跨主機網絡多網段已經實現,一樣,各個容器沒法與外網進行通訊。
docker網絡是一個比較複雜的概念,如有耐心,仍是建議閱讀docker官方文檔
———————— 本文至此結束,感謝閱讀 ————————