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)。
兩種模式
ipvlan 有兩種不同的模式:L2 和 L3。一個父接口只能選擇一種模式,依附於它的所有虛擬接口都運行在這個模式下,不能混用模式。
L2 模式
ipvlan L2 模式和 macvlan bridge 模式工作原理很相似,父接口作為交換機來轉發子接口的數據。同一個網絡的子接口可以通過父接口來轉發數據,而如果想發送到其他網絡,報文則會通過父接口的路由轉發出去。
L3 模式
L3 模式下,ipvlan 有點像路由器的功能,它在各個虛擬網絡和主機網絡之間進行不同網絡報文的路由轉發工作。只要父接口相同,即使虛擬機/容器不在同一個網絡,也可以互相 ping 通對方,因為 ipvlan 會在中間做報文的轉發工作。
L3 模式下的虛擬接口不會接收到多播或者廣播的報文,為什么呢?這個模式下,所有的網絡都會發送給父接口,所有的 ARP 過程或者其他多播報文都是在底層的父接口完成的。需要注意的是:外部網絡默認情況下是不知道 ipvlan 虛擬出來的網絡的,如果不在外部路由器上配置好對應的路由規則,ipvlan 的網絡是不能被外部直接訪問的。
實驗
實驗環境:
➜ ~ uname -a Linux cizixs-ThinkPad-T450 4.4.0-57-generic #78-Ubuntu SMP Fri Dec 9 23:50:32 UTC 2016 x86_64 x86_64 x86_64 GNU/Linux ➜ ~ lsb_release -a No LSB modules are available. Distributor ID: Ubuntu Description: Ubuntu 16.04.2 LTS Release: 16.04 Codename: xenial
先創建兩個用做測試的 network namespace,關於 namespace 可參考之前的文章:
➜ ~ sudo ip netns add net1 ➜ ~ sudo ip netns add net2
然后創建出 ipvlan 的虛擬網卡接口,因為 L2 和 macvlan 功能相同,我們這里測試一下 L3 模式。創建 ipvlan 虛擬接口的命令和 macvlan 格式相同:
➜ ~ sudo ip link add ipv1 link eth0 type ipvlan mode l3 ➜ ~ sudo ip link add ipv2 link eth0 type ipvlan mode l3
把 ipvlan 接口放到前面創建好的 namespace 中:
➜ ~ sudo ip link set ipv1 netns net1 ➜ ~ sudo ip link set ipv2 netns net2 ➜ ~ sudo ip netns exec net1 ip link set ipv1 up ➜ ~ sudo ip netns exec net2 ip link set ipv2 up
給兩個虛擬網卡接口配置上不同網絡的 ip 地址,並配置好路由項:
➜ ~ sudo ip netns exec net1 ip addr add 10.0.1.10/24 dev ipv1 ➜ ~ sudo ip netns exec net2 ip addr add 192.168.1.10/24 dev ipv2 ➜ ~ sudo ip netns exec net1 ip route add default dev ipv1 ➜ ~ sudo ip netns exec net2 ip route add default dev ipv2
測試兩個網絡的連通性:
➜ ~ sudo ip netns exec net1 ping -c 3 192.168.1.10 PING 192.168.1.10 (192.168.1.10) 56(84) bytes of data. 64 bytes from 192.168.1.10: icmp_seq=1 ttl=64 time=0.053 ms 64 bytes from 192.168.1.10: icmp_seq=2 ttl=64 time=0.035 ms 64 bytes from 192.168.1.10: icmp_seq=3 ttl=64 time=0.036 ms --- 192.168.1.10 ping statistics --- 3 packets transmitted, 3 received, 0% packet loss, time 1998ms rtt min/avg/max/mdev = 0.035/0.041/0.053/0.009 ms
docker ipvlan 網絡
docker(v1.13) 也在開發對 ipvlan 的支持,不過目前只是 experiment 階段。你可以安裝最新版的 docker 來進行測試:
# 首先是創建 ipvlan 的網絡,這和 macvlan 網絡的操作基本一致,只是把 driver 修改成 `ipvlan`,然后選項中通過 `ipvlan_mode=l3` 設置 ipvlan 的工作模式: docker network create -d ipvlan \ --subnet=192.168.30.0/24 \ -o parent=eth0 \ -o ipvlan_mode=l3 ipvlan30 # 啟動兩個容器,可以發現在同一個 ipvlan 的兩個容器可以互相 ping 通 docker run --net=ipvlan30 -it --name ivlan_test3 --rm alpine /bin/sh docker run --net=ipvlan30 -it --name ivlan_test4 --rm alpine /bin/sh # 再創建另外一個 ipvlan 網絡,和前面的網絡不在同一個廣播域 docker network create -d ipvlan \ --subnet=192.168.110.0/24 \ -o parent=eth0 \ -o ipvlan_mode=l3 ipvlan110 # 在新建的網絡中運行容器,可以發現可以 ping 同前面網絡中的容器 docker run --net=ipvlan30 -it --name ivlan_test3 --rm alpine /bin/sh
這里只介紹了最基本的 ipvlan 在 docker 中的使用,更多可以參考 docker 官方文檔。
ipvlan 還是 macvlan?
ipvlan 和 macvlan 兩個虛擬網絡模型提供的功能,看起來差距並不大,那么什么時候需要用到 ipvlan 呢?要回答這個問題,我們先來看看 macvlan 存在的不足:
- 需要大量 mac 地址。每個虛擬接口都有自己的 mac 地址,而網絡接口和交換機支持的 mac 地址有支持的上限
- 無法和 802.11(wireless) 網絡一起工作
對應的,如果你遇到一下的情況,請考慮使用 ipvlan:
- 父接口對 mac 地址數目有限制,或者在 mac 地址過多的情況下會造成嚴重的性能損失
- 工作在無線網絡中
- 希望搭建比較復雜的網絡拓撲(不是簡單的二層網絡和 VLAN),比如要和 BGP 網絡一起工作
參考資料
- Configuring Macvlan and Ipvlan Linux Networking
- Linux Kernel ipvlan documentation
- Docker IPVlan Network Driver Doc
- ipvlan practice and implementation
- Macvlan and IPvlan basics
轉載: https://cizixs.com/2017/02/17/network-virtualization-ipvlan/