在 Macvlan 出現以前,咱們只能爲一塊以太網卡添加多個 IP 地址,卻不能添加多個 MAC 地址,由於 MAC 地址正是經過其全球惟一性來標識一塊以太網卡的,即使你使用了建立 ethx:y 這樣的方式,你會發現全部這些「網卡」的 MAC 地址和 ethx 都是同樣的,本質上,它們仍是一塊網卡,這將限制你作不少二層的操做。有了 Macvlan 技術,你能夠這麼作了。linux
Macvlan 容許你在主機的一個網絡接口上配置多個虛擬的網絡接口,這些網絡 interface 有本身獨立的 MAC 地址,也能夠配置上 IP 地址進行通訊。Macvlan 下的虛擬機或者容器網絡和主機在同一個網段中,共享同一個廣播域。Macvlan 和 Bridge 比較類似,但由於它省去了 Bridge 的存在,因此配置和調試起來比較簡單,並且效率也相對高。除此以外,Macvlan 自身也完美支持 VLAN。docker
同一 VLAN 間數據傳輸是經過二層互訪,即 MAC 地址實現的,不須要使用路由。不一樣 VLAN 的用戶單播默認不能直接通訊,若是想要通訊,還須要三層設備作路由,Macvlan 也是如此。用 Macvlan 技術虛擬出來的虛擬網卡,在邏輯上和物理網卡是對等的。物理網卡也就至關於一個交換機,記錄着對應的虛擬網卡和 MAC 地址,當物理網卡收到數據包後,會根據目的 MAC 地址判斷這個包屬於哪個虛擬網卡。這也就意味着,只要是從 Macvlan 子接口發來的數據包(或者是發往 Macvlan 子接口的數據包),物理網卡只接收數據包,不處理數據包,因此這就引出了一個問題:本機 Macvlan 網卡上面的 IP 沒法和物理網卡上面的 IP 通訊!關於這個問題的解決方案咱們下一節再討論。
簡單來講,Macvlan 虛擬網卡設備是寄生在物理網卡設備上的。發包時調用本身的發包函數,查找到寄生的物理設備,而後經過物理設備發包。收包時,經過註冊寄生的物理設備的 rx_handler 回調函數,處理數據包。vim
macvlan 就如它的名字同樣,是一種網卡虛擬化技術,它可以將一個物理網卡虛擬出多個接口,每一個接口均可以配置 MAC 地址,一樣每一個接口也能夠配本身的 IP,每一個接口就像交換機的端口同樣,能夠爲它劃分 VLAN。網絡
macvlan 的作法其實就是將這些虛擬出來的接口與 Docker 容器直連來達到通訊的目的。一個 macvlan 網絡對應一個接口,不一樣的 macvlan 網絡分配不一樣的子網,所以,相同的 macvlan 之間能夠互相通訊,不一樣的 macvlan 網絡之間在二層上不能通訊,須要藉助三層的路由器才能完成通訊,以下,顯示的就是兩個不一樣的 macvlan 網絡之間的通訊流程。
咱們用一個 Linux 主機,經過配置其路由表和 iptables,將其配成一個路由器(固然是虛擬的),就能夠完成不一樣 macvlan 網絡之間的數據交換,固然用物理路由器也是沒毛病的。ide
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 後的樣子:函數
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
1) 打開網卡的混雜模式
//須要在docker01和docker02_上都進行操做。測試
[root@docker01 ~]# ip link show ens33 //查看網卡模式
[root@docker01 ~]# ip link set ens33 promisc on //建立網卡模式爲混雜模式 [root@docker01 ~]# ip link show ens33 //查看網卡模式
2)在docker01.上建立macvlan網絡3d
[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 //查看網卡信息
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
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的主機
1) docker01和docker02驗證內核模塊8021q封裝
macvlan須要解決的問題:基於真實的ens33網卡,生產新的虛擬網卡。
[root@docker01 ~]# modinfo 8021q //驗證內核模塊8021q封裝
[root@docker01 ~]# modprobe 8021q //若是內核模塊沒有開啓,運行上邊的命令導入一下
2)docker01基於ens33建立虛擬網卡
修改ens33網卡配置文件
[root@docker01 ~]# cd /etc/sysconfig/network-scripts/ [root@docker01 network-scripts]# vim ifcfg-ens33
手動添加虛擬網卡配置文件
[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
3)docker02基於ens33建立虛擬網卡
修改ens33網卡配置文件
[root@docker02 ~]# cd /etc/sysconfig/network-scripts/ [root@docker02 network-scripts]# vim ifcfg-ens33
手動添加虛擬網卡配置文件
[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
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
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的網絡模式設置爲橋接模式
測試一下相同網卡的主機是否能ping通
[root@docker01 ~]# docker exec -it bbox10 /bin/sh / # ping 172.16.20.20
[root@docker02 ~]# docker exec -it bbox20 /bin/sh / # ping 172.16.20.20
Macvlan 是將 VM 或容器經過二層鏈接到物理網絡的近乎理想的方案,但它也有一些侷限性:
1.Linux 主機鏈接的交換機可能會限制同一個物理端口上的 MAC 地址數量。雖然你可讓網絡管理員更改這些策略,但有時這種方法是沒法實行的(好比你要去給客戶作一個快速的 PoC 演示)。
2.許多 NIC 也會對該物理網卡上的 MAC地址數量有限制。超過這個限制就會影響到系統的性能。
3.IEEE 802.11 不喜歡同一個客戶端上有多個 MAC 地址,這意味着你的 Macvlan 子接口在無線網卡或 AP 中都沒法通訊。能夠經過複雜的辦法來突破這種限制,但還有一種更簡單的辦法,那就是使用 Ipvlan,感興趣能夠本身查閱相關資料。
macvlan是一種網卡虛擬化技術,可以將一張網卡虛擬出多張網卡。
macvlan的特定通訊模式,經常使用模式是bridge。
在Docker中,macvlan只支持bridge模式。
相同的macvlan能夠通訊,不一樣的macvlan二層沒法通訊,能夠經過三層路由完成通訊。
思考一下:
macvlan bridge和bridge的異同點還有一種相似的技術,多張虛擬網卡共享相同MAC地址,但有獨立的IP地址,這是什麼技術?