macvlan 本身是 linux kernel 模塊,其功能是允許在同一個物理網卡上配置多個 MAC 地址,即多個 interface,每個 interface 可以配置自己的 IP,macvlan 本質上是一種網卡虛擬化技術。
一、實驗環境
IP | 主機名 | 內核版本 |
---|---|---|
10.1.1.17 | master | kernel-5.2.11 |
10.1.1.13 | host1 | kernel-5.2.11 |
10.1.1.14 | host2 | kernel-5.2.11 |
二、創建macvlan網絡
在master、node1和node2上同時執行以下命令:
[root@master ~]# docker network create -d macvlan --subnet=172.16.10.0/24 --gateway=172.16.10.1 -o parent=ens33 mac1
476cfc5eb16c51647c02f87ff682452d4a76568b47d770a612996d0e09420e21
[root@master ~]# docker network ls
NETWORK ID NAME DRIVER SCOPE
7fd1d76008e3 bridge bridge local
af93f80d0ba6 host host local
476cfc5eb16c mac1 macvlan local
23d2bfb36bf0 none null local
node1:
[root@node1 ~]# docker network create -d macvlan --subnet=172.16.10.0/24 --gateway=172.16.10.1 -o parent=ens33 mac1
33e73b4f6637ce7064b4f6198a43125f07557e7bf824ad1ea39a276e910e11eb
[root@node1 ~]# docker network ls
NETWORK ID NAME DRIVER SCOPE
9986d9dda86f bridge bridge local
8611ebf969a6 host host local
33e73b4f6637 mac1 macvlan local
556e2a599b82 none null local
node2:
[root@node2 ~]# docker network create -d macvlan --subnet=172.16.10.0/24 --gateway=172.16.10.1 -o parent=ens33 mac1
14b860ca6be2458d3f210286be2f6a867177403f41d96985a5fcac60ec93fa78
[root@node2 ~]# docker network ls
NETWORK ID NAME DRIVER SCOPE
3891241149c3 bridge bridge local
a63bf958be9e host host local
14b860ca6be2 mac1 macvlan local
fb8797af5710 none null local
三、用macvlan網絡創建容器:
master:
[root@master ~]# docker run -itd --name c1 --ip=172.16.10.2 --network mac1 busybox
50f2d1b18bcf4301a13afa08c5eb780f1d37351e3e30617076c5a557e4eda512
node1:
[root@node1 ~]# docker run -itd --name c2 --ip=172.16.10.3 --network mac1 busybox
91ce7ad4a9f628417067a93df8c547199af438a8d0b1b20d616cbdc3742b655a
node2:
[root@node2 ~]# docker run -itd --name c3 --ip=172.16.10.4 --network mac1 busybox
02fa6f6be82c6c680f0e798662e3555bae204dddfa5b722d00b5f71ca80a7163
(4)三個容器的IP分別爲172.16.10.2\3\4,進入容器互相ping對方:
master:
[root@master ~]# docker attach c1
/ # ping -c 1 172.16.10.3
PING 172.16.10.3 (172.16.10.3): 56 data bytes
64 bytes from 172.16.10.3: seq=0 ttl=64 time=2.546 ms
--- 172.16.10.3 ping statistics ---
1 packets transmitted, 1 packets received, 0% packet loss
round-trip min/avg/max = 2.546/2.546/2.546 ms
/ # ping -c 1 172.16.10.4
PING 172.16.10.4 (172.16.10.4): 56 data bytes
64 bytes from 172.16.10.4: seq=0 ttl=64 time=1.240 ms
--- 172.16.10.4 ping statistics ---
1 packets transmitted, 1 packets received, 0% packet loss
round-trip min/avg/max = 1.240/1.240/1.240 ms
node1:
[root@node1 ~]# docker attach c2
/ # ping -c 1 172.16.10.2
PING 172.16.10.2 (172.16.10.2): 56 data bytes
64 bytes from 172.16.10.2: seq=0 ttl=64 time=0.510 ms
--- 172.16.10.2 ping statistics ---
1 packets transmitted, 1 packets received, 0% packet loss
round-trip min/avg/max = 0.510/0.510/0.510 ms
/ # ping -c 1 172.16.10.4
PING 172.16.10.4 (172.16.10.4): 56 data bytes
64 bytes from 172.16.10.4: seq=0 ttl=64 time=1.460 ms
--- 172.16.10.4 ping statistics ---
1 packets transmitted, 1 packets received, 0% packet loss
round-trip min/avg/max = 1.460/1.460/1.460 ms
node2:
[root@node2 ~]# docker attach c3
/ # ping -c 1 172.16.10.2
PING 172.16.10.2 (172.16.10.2): 56 data bytes
64 bytes from 172.16.10.2: seq=0 ttl=64 time=1.994 ms
--- 172.16.10.2 ping statistics ---
1 packets transmitted, 1 packets received, 0% packet loss
round-trip min/avg/max = 1.994/1.994/1.994 ms
/ # ping -c 1 172.16.10.3
PING 172.16.10.3 (172.16.10.3): 56 data bytes
64 bytes from 172.16.10.3: seq=0 ttl=64 time=1.213 ms
--- 172.16.10.3 ping statistics ---
1 packets transmitted, 1 packets received, 0% packet loss
round-trip min/avg/max = 1.213/1.213/1.213 ms
互相之間都是能夠ping通的。
四、網絡結構分析:
macvlan是不依賴Linux bridge的,創建好macvlan網絡之後,通過brctl show可以確認沒有創建新的網橋:
[root@master ~]# brctl show
bridge name bridge id STP enabled interfaces
docker0 8000.024276b03dbc no
查看c1容器的網絡:
[root@master ~]# docker exec c1 ip link
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
4: eth0@if2: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue
link/ether 02:42:ac:10:0a:02 brd ff:ff:ff:ff:ff:ff
除了lo,容器只有一個eth0,eth0後面有個if2,這說明該接口有個對應的interface,全局編號爲2,而在主機上執行 ip link可以看到,ens33的編號也是2:
[root@master ~]# ip link
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP mode DEFAULT group default qlen 1000
link/ether 00:0c:29:c9:32:dd brd ff:ff:ff:ff:ff:ff
3: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN mode DEFAULT group default
link/ether 02:42:76:b0:3d:bc brd ff:ff:ff:ff:ff:ff
所以,可以確定的是,容器抄底eth0就是ens33通過macvlan虛擬出來的interface。容器的interface直接與主機的網卡進行連接,這種方案使得容器無需通過NAT和端口映射就能與外網相通,在網絡上與其他獨立主機沒有區別。
五、不同 macvlan 網絡之間的通信
macvlan會獨佔主機的網卡,也就是說每個網卡只能創建一個macvlan網絡,否則會報錯。但主機的網卡是有限的,如何支持更多的macvlan網絡呢?好在macvlan不僅可以連接到interface,如ens33,還可以連接到sub-interface,如ens33.100,ens33.200。
Linux網卡支持VLAN技術,VLAN是現代常用的網絡虛擬化技術,同一個網卡(interface)可以支持多個VLAN的數據包,不過前提是要創建sub-interface。
比如希望ens33網卡支持VLAN10和VLAN20,則需要創建sub-interface ens33.10和ens33.20。在交換機上,如果某個口智能手法單個VLAN的數據,則port爲access模式;若要接受多個VLAN的數據,則爲trunk模式。所以ens33網卡對端要接在交換機的trunk口上。因爲我們是虛擬機,就不需要這樣操作了。下面開始創建基於VLAN的macvlan網絡。
首先兩臺主機上安裝vconfig工具:
[root@master ~]# wget https://mirrors.aliyun.com/centos/6.10/os/x86_64/Packages/vconfig-1.9-8.1.el6.x86_64.rpm
rpm -ivh vconfig-1.9-8.1.el6.x86_64.rpm
加載8021q模塊:
[root@master ~]# modprobe 8021q
開啓ens33網卡的混雜模式:
[root@master ~]# ifconfig ens33 promisc
確認混雜模式已經開啓:
ens33: flags=4419<UP,BROADCAST,RUNNING,PROMISC,MULTICAST> mtu 1500
inet 10.1.1.13 netmask 255.255.255.0 broadcast 10.1.1.255
inet6 fe80::55d8:65e5:d67d:8eaf prefixlen 64 scopeid 0x20<link>
ether 00:0c:29:5c:02:a3 txqueuelen 1000 (Ethernet)
RX packets 138 bytes 14859 (14.5 KiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 210 bytes 21630 (21.1 KiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
啓用IPV4. forwarding:
[root@master ~]# vim /etc/sysctl.conf
net.ipv4.ip_forward=1
然後重啓network。
[root@master ~]# systemctl restart network
現在三臺主機上分別基於ens33網卡創建兩個VLAN:
[root@master ~]# vconfig add ens33 100
[root@master ~]# vconfig add ens33 200
啓用VLAN:
[root@master ~]# ifconfig ens33.100 up
[root@master ~]# ifconfig ens33.200 up
基於兩個子接口分別創建mac10和mac20的macvlan網絡:
[root@master ~]# docker network create -d macvlan --subnet=172.16.10.0/24 --gateway=172.16.10.1 -o parent=ens33.100 mac10
[root@master ~]# docker network create -d macvlan --subnet=172.16.20.0/24 --gateway=172.16.20.1 -o parent=ens33.200 mac20
在node1上創建d1和d2兩個容器,分別基於mac10和mac20:
[root@master ~]# docker run -itd --name d1 --ip=172.16.10.10 --network mac10 busybox
[root@master ~]# docker run -itd --name d2 --ip=172.16.20.10 --network mac20 busybox
在node2上創建d3和d4兩個容器,分別基於mac10和mac20:
[root@master ~]# docker run -itd --name d3 --ip=172.16.10.11 --network mac10 busybox
[root@master ~]# docker run -itd --name d4 --ip=172.16.20.11 --network mac20 busybox
正常來講d1和d3屬於同一個網段,d2和d4屬於同一個網段,應該是能ping通的,目前我的實驗沒通,不知道是不是虛擬機本身不支持這個網絡。正在研究中。