Docker跨主機網絡——manual

1. Macvlan 簡介

在 Macvlan 出現之前,我們只能爲一塊以太網卡添加多個 IP 地址,卻不能添加多個 MAC 地址,因爲 MAC 地址正是通過其全球唯一性來標識一塊以太網卡的,即便你使用了創建 ethx:y 這樣的方式,你會發現所有這些“網卡”的 MAC 地址和 ethx 都是一樣的,本質上,它們還是一塊網卡,這將限制你做很多二層的操作。有了 Macvlan 技術,你可以這麼做了。

Macvlan 允許你在主機的一個網絡接口上配置多個虛擬的網絡接口,這些網絡 interface 有自己獨立的 MAC 地址,也可以配置上 IP 地址進行通信。Macvlan 下的虛擬機或者容器網絡和主機在同一個網段中,共享同一個廣播域。Macvlan 和 Bridge 比較相似,但因爲它省去了 Bridge 的存在,所以配置和調試起來比較簡單,而且效率也相對高。除此之外,Macvlan 自身也完美支持 VLAN。

同一 VLAN 間數據傳輸是通過二層互訪,即 MAC 地址實現的,不需要使用路由。不同 VLAN 的用戶單播默認不能直接通信,如果想要通信,還需要三層設備做路由,Macvlan 也是如此。用 Macvlan 技術虛擬出來的虛擬網卡,在邏輯上和物理網卡是對等的。物理網卡也就相當於一個交換機,記錄着對應的虛擬網卡和 MAC 地址,當物理網卡收到數據包後,會根據目的 MAC 地址判斷這個包屬於哪一個虛擬網卡。這也就意味着,只要是從 Macvlan 子接口發來的數據包(或者是發往 Macvlan 子接口的數據包),物理網卡只接收數據包,不處理數據包,所以這就引出了一個問題:本機 Macvlan 網卡上面的 IP 無法和物理網卡上面的 IP 通信!關於這個問題的解決方案我們下一節再討論。
Docker跨主機網絡——manual
簡單來說,Macvlan 虛擬網卡設備是寄生在物理網卡設備上的。發包時調用自己的發包函數,查找到寄生的物理設備,然後通過物理設備發包。收包時,通過註冊寄生的物理設備的 rx_handler 回調函數,處理數據包。

2.簡單介紹manual的流程

macvlan 就如它的名字一樣,是一種網卡虛擬化技術,它能夠將一個物理網卡虛擬出多個接口,每個接口都可以配置 MAC 地址,同樣每個接口也可以配自己的 IP,每個接口就像交換機的端口一樣,可以爲它劃分 VLAN。

macvlan 的做法其實就是將這些虛擬出來的接口與 Docker 容器直連來達到通信的目的。一個 macvlan 網絡對應一個接口,不同的 macvlan 網絡分配不同的子網,因此,相同的 macvlan 之間可以互相通信,不同的 macvlan 網絡之間在二層上不能通信,需要藉助三層的路由器才能完成通信,如下,顯示的就是兩個不同的 macvlan 網絡之間的通信流程。
Docker跨主機網絡——manual
我們用一個 Linux 主機,通過配置其路由表和 iptables,將其配成一個路由器(當然是虛擬的),就可以完成不同 macvlan 網絡之間的數據交換,當然用物理路由器也是沒毛病的。

3.Macvlan 的特點:

1.可讓使用者在同一張實體網卡上設定多個 MAC 地址。
2.承上,帶有上述設定的 MAC 地址的網卡稱爲子接口(sub interface);而實體網卡則稱爲父接口(parent interface)。
3.parent interface 可以是一個物理接口(eth0),可以是一個 802.1q 的子接口(eth0.10),也可以是 bonding 接口。
4.可在 parent/sub interface 上設定的不只是 MAC 地址,IP 地址同樣也可以被設定。
5.sub interface 無法直接與 parent interface 通訊 (帶有 sub interface 的 VM 或容器無法與 host 直接通訊)。
承上,若 VM 或容器需要與 host 通訊,那就必須額外建立一個 sub 6.interface 給 host 用。
7.sub interface 通常以 mac0@eth0 的形式來命名以方便區別。
用張圖來解釋一下設定 Macvlan 後的樣子:

Docker跨主機網絡——manual

4.實驗環境

docker01 docker02
192.168.1.11 192.168.1.13

關閉防火牆和禁用selinux,更改主機名

[root@localhost ~]# hostnamectl set-hostname docker01
[root@localhost ~]# su -
上一次登錄:二 12月 17 08:20:36 CST 2019從 192.168.1.1pts/0 上
[root@docker01 ~]# systemctl  stop firealld
Failed to stop firealld.service: Unit firealld.service not loaded.
[root@docker01 ~]# setenforce 0
setenforce: SELinux is disabled
[root@docker01 ~]# systemctl daemon-reload 
[root@docker01 ~]# systemctl restart docker

4.1 macvlan的單網絡通信

Docker跨主機網絡——manual
1) 打開網卡的混雜模式
//需要在docker01和docker02_上都進行操作。

[root@docker01 ~]# ip link show ens33
//查看網卡模式

Docker跨主機網絡——manual

[root@docker01 ~]# ip link set ens33 promisc on
//創建網卡模式爲混雜模式
[root@docker01 ~]# ip link show ens33
//查看網卡模式

Docker跨主機網絡——manual
2)在docker01.上創建macvlan網絡

[root@docker01 ~]# docker network create -d macvlan --subnet 172.22.16.0/24 --gateway 172.22.16.1  -o parent=ens33 mac_net1
// 創建一個macvlan模式的網絡
-o parent=綁定在哪張網卡之上
[root@docker01 ~]# docker network ls
//查看網卡信息

Docker跨主機網絡——manual

3)基於創建的macvlan網絡運行一個容器

[root@docker01 ~]# docker run -itd --name bbox1 --ip 172.22.16.10 --network mac_net1 busybox

4)在docker02.上創建macvlan網絡(要和docker01的macvlan一模一樣)

[root@docker02 ~]# docker network create -d macvlan  --subnet 172.22.16.0/24 --gateway 172.22.16.1  -o parent=ens33 mac_net1

[root@docker02 ~]# docker network ls

Docker跨主機網絡——manual

5)在docker02. 上,基於創建的macvlan網絡運行一個容器,驗證與docker01.上容器的通信。

[root@docker02 ~]# docker run -itd --name bbox2 --network mac_net1 --ip 172.22.16.20 busybox
//基於busybox創建一個容器
[root@docker02 ~]# docker exec -it bbox2 /bin/sh
//進入bbox2容器
/ # ping 172.22.16.10
//ping一下docker01的主機

Docker跨主機網絡——manual

4.2macvlan的多網絡通信

Docker跨主機網絡——manual

1) docker01和docker02驗證內核模塊8021q封裝
macvlan需要解決的問題:基於真實的ens33網卡,生產新的虛擬網卡。

[root@docker01 ~]# modinfo 8021q
//驗證內核模塊8021q封裝

Docker跨主機網絡——manual

[root@docker01 ~]# modprobe 8021q
//如果內核模塊沒有開啓,運行上邊的命令導入一下

2)docker01基於ens33創建虛擬網卡
修改ens33網卡配置文件

[root@docker01 ~]# cd /etc/sysconfig/network-scripts/
[root@docker01 network-scripts]# vim ifcfg-ens33  

Docker跨主機網絡——manual
手動添加虛擬網卡配置文件

[root@docker01 ~]# cd /etc/sysconfig/network-scripts/
[root@docker01 network-scripts]# cp -p ifcfg-ens33  ifcfg-ens33.10
//-p保留源文件或目錄的屬性
[root@docker01 network-scripts]# vim ifcfg-ens33.10
//修改ens33.10網卡配置文件
BOOTPROTO=none
NAME=ens33.10
DEVICE=ens33.10
ONBOOT=yes
IPADDR=192.168.10.10
PREFIX=24
GATEWAY=192.168.10.2
VLAN=yes

這裏注意,IP要和ens33網段做一個區分, 保證網關和網段IP的一致性,設備名稱和配置文件的-致性,並且打開VLAN支持模式。

創建第二個虛擬網卡配置文件

[root@docker01 network-scripts]# cp -p ifcfg-ens33.10 ifcfg-ens33.20
[root@docker01 network-scripts]# vim ifcfg-ens33.20
//修改ens33.20網卡配置文件
BOOTPROTO=none
NAME=ens33.20
DEVICE=ens33.20
ONBOOT=yes
IPADDR=192.168.20.20
PREFIX=24
GATEWAY=192.168.20.2
VLAN=yes

docker01上的操作,啓用創建的虛擬網卡:

[root@docker01 network-scripts]# ifup ifcfg-ens33.10 
[root@docker01 network-scripts]# ifup ifcfg-ens33.20
[root@docker01 network-scripts]# ifconfig
//查看IP

Docker跨主機網絡——manual

3)docker02基於ens33創建虛擬網卡
修改ens33網卡配置文件

[root@docker02 ~]# cd /etc/sysconfig/network-scripts/
[root@docker02 network-scripts]# vim ifcfg-ens33  

Docker跨主機網絡——manual
手動添加虛擬網卡配置文件

[root@docker02 ~]# cd /etc/sysconfig/network-scripts/
[root@docker02 network-scripts]# cp -p ifcfg-ens33  ifcfg-ens33.10
//-p保留源文件或目錄的屬性
[root@docker02 network-scripts]# vim ifcfg-ens33.10
//修改ens33.10網卡配置文件
BOOTPROTO=none
NAME=ens33.10
DEVICE=ens33.10
ONBOOT=yes
IPADDR=192.168.10.11
PREFIX=24
GATEWAY=192.168.10.2
VLAN=yes

這裏注意,IP要和ens33網段做一個區分, 保證網關和網段IP的一致性,設備名稱和配置文件的-致性,並且打開VLAN支持模式。

創建第二個虛擬網卡配置文件

[root@docker02 network-scripts]# cp -p ifcfg-ens33.10 ifcfg-ens33.20
[root@docker02 network-scripts]# vim ifcfg-ens33.20
//修改ens33.20網卡配置文件
BOOTPROTO=none
NAME=ens33.20
DEVICE=ens33.20
ONBOOT=yes
IPADDR=192.168.20.21
PREFIX=24
GATEWAY=192.168.20.2
VLAN=yes

docker02上的操作,啓用創建的虛擬網卡:

[root@docker02 network-scripts]# systemctl restart network
[root@docker02 network-scripts]# ifup ifcfg-ens33.10 
[root@docker02 network-scripts]# ifup ifcfg-ens33.20
[root@docker02 network-scripts]# ifconfig
//查看IP

Docker跨主機網絡——manual
4)docekr01和docker02基於虛擬網卡,創建macvlan網絡

[root@docker02 network-scripts]# docker network create -d macvlan --subnet 172.16.10.0/24 --gateway 172.16.10.1  -o parent=ens33.10 mac_net10
//創建一個新的網卡基於ens33.10
[root@docker02 network-scripts]# docker network create -d macvlan --subnet 172.16.20.0/24 --gateway 172.16.20.1  -o parent=ens33.20 mac_net20
//創建一個新的網卡基於ens33.20

5)Docker01部署一個私有倉庫
Docker01

   72  docker pull registry
//下載registry鏡像
   73  docker run -itd --name registry -p 5000:5000  --restart=always registry:latest 
//基於registry鏡像,啓動一臺容器
   76  docker tag busybox:latest  192.168.1.11:5000/busybox:v1 
//把容器重命名一個標籤
   77  docker ps

Docker跨主機網絡——manual

   78  vim /usr/lib/systemd/system/docker.service #13行修改
ExecStart=/usr/bin/dockerd --insecure-registry 192.168.1.11:5000  

   80  systemctl daemon-reload 
   81  systemctl restart docker.service 
//重啓docker
  100  docker push 192.168.1.11:5000/busybox:v1
//上傳容器到私有倉庫 
  101  docker images

Docker02

78  vim /usr/lib/systemd/system/docker.service #13行修改
ExecStart=/usr/bin/dockerd --insecure-registry 192.168.1.11:5000  

   80  systemctl daemon-reload 
   81  systemctl restart docker.service 
     //重啓docker
   99  docker pull 192.168.1.11/busybox:v1 
     //下載剛剛上傳的鏡像

6)docker01和docker02基於busybox:v1鏡像和網卡mac_net10,mac_net20,創建容器。
Docker01

[root@docker01 ~]# docker run -itd --name bbox10 --network mac_net10 --ip 172.16.10.10 192.168.1.11:5000/busybox:v1
[root@docker01 ~]# docker run -itd --name bbox20 --network mac_net20 --ip 172.16.20.20 192.168.1.11:5000/busybox:v1
**Docker02**
[root@docker02 ~]# docker run -itd --name bbox10 --network mac_net10 --ip 172.16.10.10 192.168.1.11:5000/busybox:v1
[root@docker02 ~]# docker run -itd --name bbox20 --network mac_net20 --ip 172.16.20.20 192.168.1.11:5000/busybox:v1

***這裏只需注意,我們在這裏的操作跟在docker01和上面的操作是一模一樣的,操作順序大致爲:
驗證8021q內核封裝
基於ens33網卡創建新的虛擬網卡,ens33.10和ens33.20 (注意和docker01. 上的ens33.10和ens33.20必須是在同一-網段,且IP不能衝突)基於此網絡運行容器。(注意和docker01 上的容器,都是基於剛剛創建的macvlan網絡,但IP地址不能衝突)


7)驗證
在docker01.上進入容器bbox10和docker02.上的bbox11進行通信。
在docker01.上進入容器bbox20和docker02.上的bbox21進行通信。
注意: VMware的網絡必須設置爲Bridge模式。

現在把docker01和docker02的網絡模式設置爲橋接模式

Docker跨主機網絡——manual
測試一下相同網卡的主機是否能ping通

[root@docker01 ~]# docker exec -it bbox10  /bin/sh
/ # ping 172.16.20.20

Docker跨主機網絡——manual

[root@docker02 ~]# docker exec -it bbox20  /bin/sh
/ # ping 172.16.20.20

Docker跨主機網絡——manual

5.Macvlan 的侷限性

Macvlan 是將 VM 或容器通過二層連接到物理網絡的近乎理想的方案,但它也有一些侷限性:

1.Linux 主機連接的交換機可能會限制同一個物理端口上的 MAC 地址數量。雖然你可以讓網絡管理員更改這些策略,但有時這種方法是無法實行的(比如你要去給客戶做一個快速的 PoC 演示)。
2.許多 NIC 也會對該物理網卡上的 MAC地址數量有限制。超過這個限制就會影響到系統的性能。
3.IEEE 802.11 不喜歡同一個客戶端上有多個 MAC 地址,這意味着你的 Macvlan 子接口在無線網卡或 AP 中都無法通信。可以通過複雜的辦法來突破這種限制,但還有一種更簡單的辦法,那就是使用 Ipvlan,感興趣可以自己查閱相關資料。

6.總結

macvlan是一種網卡虛擬化技術,能夠將一張網卡虛擬出多張網卡。

macvlan的特定通信模式,常用模式是bridge。

在Docker中,macvlan只支持bridge模式。

相同的macvlan可以通信,不同的macvlan二層無法通信,可以通過三層路由完成通信。

思考一下:

macvlan bridge和bridge的異同點
還有一種類似的技術,多張虛擬網卡共享相同MAC地址,但有獨立的IP地址,這是什麼技術?

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章