介紹
macvlan 本身是 linxu kernel 模塊,其功能是允許在同一個物理網卡上配置多個 MAC 地址,即多個 interface,每個 interface 可以配置自己的 IP。macvlan 本質上是一種網卡虛擬化技術(最大優點是性能極好)
可以在linux命令行執行lsmod | grep macvlan
查看當前內核是否加載了該driver;如果沒有查看到,可以通過modprobe macvlan
來載入,然后重新查看。內核代碼路徑/drivers/net/macvlan.c
Macvlan 允許你在主機的一個網絡接口上配置多個虛擬的網絡接口,這些網絡 interface
有自己獨立的 MAC 地址,也可以配置上 IP 地址進行通信。Macvlan 下的虛擬機或者容器網絡和主機在同一個網段中,共享同一個廣播域。Macvlan 和 Bridge
比較相似,但因為它省去了 Bridge 的存在,所以配置和調試起來比較簡單,而且效率也相對高。除此之外,Macvlan 自身也完美支持 VLAN
。
工作模式(Bridge VS MACVlan)
Bridge Mode
Bridge 是二層設備,僅用來處理二層的通訊。
Bridge 使用 MAC 地址表來決定怎么轉發幀(
Frame
)。Bridge 會從 host 之間的通訊數據包中學習 MAC 地址。
可以是硬件設備,也可以是純軟件實現(例如:
Linux Bridge
)。
提示:
Bridge 有可能會遇到二層環路,如有需要,可以開啟 STP 來防止出現環路。
MACVlan Mode
可讓使用者在同一張實體網卡上設定多個 MAC 地址。
上述設定的 MAC 地址的網卡稱為子接口(
sub interface
);而實體網卡則稱為父接口(parent interface
)。parent interface
可以是一個物理接口(eth0),可以是一個 802.1q 的子接口(eth0.10),也可以是bonding
接口。可在 parent/sub interface 上設定的不只是 MAC 地址,IP 地址同樣也可以被設定。
sub interface
無法直接與parent interface
通訊 (帶有 sub interface 的 VM 或容器無法與 host 直接通訊)。若 VM 或容器需要與 host 通訊,那就必須額外建立一個
sub interface
給 host 用。sub interface 通常以
mac0@eth0
的形式來命名以方便區別。
MACVlan模式
- Bridge:屬於同一個parent接口的macvlan接口之間掛到同一個bridge上,可以二層互通(macvlan接口都無法與parent 接口互通)。
- VPEA(Virtual Ethernet Port Aggregator):所有接口的流量都需要到外部switch才能夠到達其他接口。
Private:接口只接受發送給自己MAC地址的報文。
Passthru: 父接口和相應的MacVLAN接口捆綁在一起,這種模式每個父接口只能和一個 Macvlan 虛擬網卡接口進行捆綁,並且 Macvlan 虛擬網卡接口繼承父接口的 MAC 地址。
前三種模式示意圖:
實驗
Bridge Mode:創建了兩個macvlan接口,分別放到兩個netns中;然后驗證這兩個macvlan口之間客戶互通。
設置網卡混雜模式(PROMISC網卡混雜標志):
[root@localhost ~]#ifconfig ens224 promisc
[root@localhost ~]# ifconfig ens224
ens224: flags=4419<UP,BROADCAST,RUNNING,PROMISC,MULTICAST> mtu 1500
………………
創建兩個macvlan接口,其parent接口都是ens224
[root@localhost ~]# ip link add link ens224 name macv1 type macvlan mode bridge
[root@localhost ~]# ip link add link ens224 name macv2 type macvlan mode bridge
查看接口狀態:
創建namespace
[root@localhost ~]# ip netns add net1
[root@localhost ~]# ip netns add net2
將macvlan接口插入到namespace
[root@localhost ~]# ip link set macv1 netns net1
[root@localhost ~]# ip link set macv2 netns net2
設置網卡IP,設置網卡UP狀態
ip netns exec net1 ip addr add 52.1.1.151/24 dev macv1
ip netns exec net2 ip addr add 52.1.1.152/24 dev macv2
設置網卡IP,設置網卡UP狀態
[root@localhost ~]#ip netns exec net1 ip addr add 52.1.1.151/24 dev macv1
[root@localhost ~]#ip netns exec net2 ip addr add 52.1.1.152/24 dev macv2
[root@localhost ~]#ip netns exec net1 ip link set macv1 up
[root@localhost ~]#ip netns exec net2 ip link set macv2 up
查看網卡狀態
[root@localhost ~]# ip netns exec net1 ip a
1: lo: <LOOPBACK> mtu 65536 qdisc noop state DOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
4: macv1@if3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UNKNOWN group default qlen 1000
link/ether 4e:a1:51:a9:3f:ef brd ff:ff:ff:ff:ff:ff link-netnsid 0
inet 52.1.1.151/24 scope global eth0
valid_lft forever preferred_lft forever
[root@localhost ~]# ip netns exec net2 ip a
1: lo: <LOOPBACK> mtu 65536 qdisc noop state DOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
5: macv2@if3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UNKNOWN group default qlen 1000
link/ether fe:b5:85:c1:77:c1 brd ff:ff:ff:ff:ff:ff link-netnsid 0
inet 52.1.1.152/24 scope global macv2
valid_lft forever preferred_lft forever
ping測試結果:
net1和net2無法ping通宿主機,ping自己也不通.2個容器互相ping沒有問題
更改容器內網卡名字
ip netns exec net1 ip link set mac1 name eth0
ipvlan
IPVlan 和 macvlan 類似,都是從一個主機接口虛擬出多個虛擬網絡接口。一個重要的區別就是所有的虛擬接口都有相同的 macv 地址,而擁有不同的 ip 地址。因為所有的虛擬接口要共享 mac 地址,所有有些需要注意的地方:
- DHCP 協議分配 ip 的時候一般會用 mac 地址作為機器的標識。這個情況下,客戶端動態獲取 ip 的時候需要配置唯一的 ClientID 字段,並且 DHCP server 也要正確配置使用該字段作為機器標識,而不是使用 mac 地址
Ipvlan 是 linux kernel 比較新的特性,linux kernel 3.19 開始支持 ipvlan,但是比較穩定推薦的版本是 >=4.2(因為 docker 對之前版本的支持有 bug),具體代碼見內核目錄:
/drivers/net/ipvlan/
ipvlan模式
L2:
ipvlan L2 模式和 macvlan bridge 模式工作原理很相似,父接口作為交換機來轉發子接口的數據。同一個網絡的子接口可以通過父接口來轉發數據,而如果想發送到其他網絡,報文則會通過父接口的路由轉發出去。
L3:
ipvlan 有點像路由器的功能,它在各個虛擬網絡和主機網絡之間進行不同網絡報文的路由轉發工作。只要父接口相同,即使虛擬機/容器不在同一個網絡,也可以互相 ping 通對方,因為 ipvlan 會在中間做報文的轉發工作。
模式架構圖:
實驗
創建IPVlan L3模式
[root@localhost ~]#ip link add link ens224 ipvlan1 type ipvlan mode l3
[root@localhost ~]#ip link add link ens224 ipvlan2 type ipvlan mode l3
注意看ipvlan1 和ipvlan2 的MAC地址跟ens224的一樣
[root@localhost ~]# 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: ens192: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP mode DEFAULT group default qlen 1000
link/ether 00:0c:29:05:18:ac brd ff:ff:ff:ff:ff:ff
3: ens224: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP mode DEFAULT group default qlen 1000
link/ether 00:0c:29:05:18:b6 brd ff:ff:ff:ff:ff:ff
4: ipvlan1@enp0s3: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN group default qlen 1000
link/ether 00:0c:29:05:18:b6 brd ff:ff:ff:ff:ff:ff
5: ipvlan2@enp0s3: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN group default qlen 1000
link/ether 00:0c:29:05:18:b6 brd ff:ff:ff:ff:ff:ff
創建ns綁定接口
[root@localhost ~]#ip net add net-1
[root@localhost ~]#ip net add net-2
[root@localhost ~]#ip link set ipvlan1 netns net-1
[root@localhost ~]#ip link set ipvlan2 netns net-2
配置IP
[root@localhost ~]#ip net exec net-1 ip addr add 10.0.2.18/24 dev ipvlan1
[root@localhost ~]#ip net exec net-2 ip addr add 10.0.3.19/24 dev ipvlan2
[root@localhost ~]#ip net exec net-1 ip link set ipvlan1 up
[root@localhost ~]#ip net exec net-2 ip link set ipvlan2 up
增加路由
[root@localhost ~]#ip net exec net-1 route add default dev ipvlan1
[root@localhost ~]#ip net exec net-2 route add default dev ipvlan2
ping測試
2個ns可以正常互相ping通,無法ping通宿主機IP
抓取ARP報文,結果無法在L3模式中抓到ARP,說明二層廣播和組播都不處理,工作在L3.(這就是和L2模式的區別)
[root@localhost ~]#ip net exec net-1 tcpdump -ni ipvlan1 -p arp
創建L2模式,其余操作跟L3一樣
ip link add link enp0s3 ipvlan1 type ipvlan mode l2
ip link add link enp0s3 ipvlan2 type ipvlan mode l2
區別在於L2可以在2個ns中抓取到ARP報文
總結:
ipvlan L3模式中外部網絡默認情況下是不知道 ipvlan 虛擬出來的網絡的,如果不在外部路由器上配置好對應的路由規則,ipvlan 的網絡是不能被外部直接訪問的。