• 【NetDevOps】新一代网工需要了解的那点事儿(八)---MacVLAN


    8 MacVLAN

      前面的章节介绍了几种 Linux 虚拟网络设备:tap/tun、veth-pair、bridge等它们本质上是Linux内核提供的网络虚拟化解决方案,本章节要讲的MacVLAN也是其中的一种,准确说这是一种网卡虚拟化的解决方案。因为MacVLAN这种技术能将 一块物理网卡虚拟成多块虚拟网卡 ,由一个变多个(前提是网卡要打开混杂模式)。针对每一个虚拟网卡都可以分配一个独立的MAC地址和IP地址,这就相当于多个虚拟网卡通过一块物理网卡连接到物理网络中。

    8.1 基本原理

      macvlan是 Linux内核支持的一项特性,支持的版本有 v3.9-3.19 和 4.0+,推荐比较稳定的版本4.0+。它一般是以内核模块的形式存在,我们可以通过以下方法判断当前系统是否支持:

    [root@d1 ~]# modprobe macvlan
    [root@d1 ~]# lsmod | grep macvlan
    macvlan                19239  0
    

      如果以上命令报错或者没有回显,那么说明您的系统暂时不支持macvlan。对于网工肯定纠结macvlan和vlan有啥区别,其实只是长得有点像实现机制是真心不一样啊。通过macvlan虚拟出来的子接口和原来的物理接口是完全独立的,这些macvlan虚拟接口可以单独配置MAC地址和IP地址,而vlan子接口和主接口需共用相同的MAC地址。vlan主要用来划分广播域,而 macvlan本身就是在同一个广播域中。macvlan通过不同的子接口来做到流量的隔离,一般通过收到报文的目的MAC来判断这个包需要交给哪个虚拟网卡转发,虚拟网卡再将数据包交给上层协议栈来处理。

                        +------------------------------------------------------------------------+
                        |                                                                        |
                        |                                           +-------------------------+  |
                        |                                  Eth0     |     Network Stack       |  |
                        |                              +------------+                         |  |
                        |                              |            +----------------+---+--+-+  |
                        |                              |                             |   |  |    |
                        |Physical Network              |                             |   |  |    |
                        |       +                      |                             |   |  |    |
                        |       |                      |       AA   +------------+   |   |  |    |
                        |       |                      |   +--------+  Macvlan A +---+   |  |    |
                        |       |                      |   |        +------------+       |  |    |
                        |       |                      |   |                             |  |    |
                        |  +----+----+                 |   |                             |  |    |
                        |  |         |         +-------+---+   BB   +-------------+      |  |    |
                        |  |  Eth 0  +--------+if dst mac is+-------+  Macvlan B  +------+  |    |
                        |  |         |         +-----------+        +-------------+         |    |
                        |  +---------+                     |                                |    |
                        |                                  |                                |    |
                        |                                  |   CC   +-------------+         |    |
                        |                                  +--------+  Macvlan C  +---------+    |
                        |                                           +-------------+              |
                        |                                                           By:[F0rGeEk] |
                        +------------------------------------------------------------------------+
    

    8.2 工作模式

      macvlan子接口之间的通信模式,macvlan分为以下四种网络模式。其中最常用的是bridge模式。

    • 1. privite
        在private模式下,同一主接口下的子接口之间彼此隔离不能通信。即使从外部的物理网络引流,也不能互相通信。
    • 2. vepa
        在vepa模式下,子接口之间的通信流量需要引流到外部支持802.1Qbg/VPEA功能的交换机上(可以是物理的或者虚拟的交换机),经由外部交换机转发再绕回来。这里所说的支持802.1Qbg/VPEA功能的交换机是指支持"端口回流"功能或者叫"支持hairpin模式",也就是说数据包从一个端口收到后还能通过这个端口再转发出去。
    • 3. bridge
        这bridge式下,主要是模拟Linux bridge的功能,但比bridge要好的一点的是每个接口的MAC地址是已知的,不用学习。所以在这种模式下,子接口之间默认就可以互相通信。
    • 4. passthru
        这种模式只允许单个子接口连接主接口,且必须设置成混杂模式,一般用于子接口桥接和创建 VLAN 子接口的场景。

    8.3 MacVLAN实践

      这里我们也分两部分来进行实践,一种实在普通的Linux网络环境下,另一种实在Docker容器环境中实践。在Docker网络环境中还可以分为两种,一种是相同macvlan之间的通信还有一种是不同macvlan之间的通信。其中不同vlan之间的通信类似数通中的单臂路由,因为二层是不通的所以需要借助三层网络通信,这里就需要通过一台路由设备(也可以是开启ip_forward的Linux主机)来进行路由转发。本文就介绍最基础最底层的实践方式,不同macvlan之间的通信相信对于网工的你来说简直easy的不要不要的。

    • MacVLAN连接连个不同的NS
                               +-------------------------------------+
                               |   +-------+             +-------+   |
                               |   |  NS1  |             |  NS2  |   |
                               |   +---+---+             +---+---+   |
                               |       |                     |       |
                               |       |       XXXXXXX       |       |
                               |       |     XX       XX     |       |
                               |       +---+X  MacVLAN  X+---+       |
                               |             XX       XX             |
                               |               XXXXXXX               |
                               |               +     +               |
                               |               |     |               |
                               |         +-----+--+--+-----+         |
                               | 12.1.1.1|  Mac1  |  Mac2  |12.1.1.2 |
                               |         +--------+--------+         |
                               |         |      ens33      |         |
                               |         +-----------------+         |
                               |                        By:[F0rGeEk] |
                               +-------------------------------------+
    

      这里我们的实验环境是将两个不同的Name Space之间通过macvlan连通,如上图所示为物理接口ens33创建两个macvlan子接口,使用bridge模式,并配置IP地址然后将它们分别加入到两个不同的NS中,最后测试连通性。具体过程如下:

     # 创建两个macvlan子接口
    [root@d1 ~]# ip link add link ens33 dev mac1 type macvlan mode bridge
    [root@d1 ~]# ip link add link ens33 dev mac2 type macvlan mode bridge
     # 创建两个NS
    [root@d1 ~]# ip netns add ns1
    [root@d1 ~]# ip netns add ns2
     # 将两个macvlan子接口分别加入ns1和ns2
    [root@d1 ~]# ip link set mac1 netns ns1
    [root@d1 ~]# ip link set mac2 netns ns2
     # 为两个macvlan子接口配置IP地址并激活
    [root@d1 ~]# ip netns exec ns1 ip addr add 12.1.1.1/24 dev mac1
    [root@d1 ~]# ip netns exec ns1 ip link set mac1 up
    [root@d1 ~]# ip netns exec ns2 ip addr add 12.1.1.2/24 dev mac2
    [root@d1 ~]# ip netns exec ns2 ip link set mac2 up
     # 查看两个ns中的macvlan子接口配置信息
    [root@d1 ~]# ip netns exec ns1 ip -d link show mac1
    3: mac1@if2: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UNKNOWN mode DEFAULT group default qlen 1000
        link/ether 42:e3:dc:fc:32:54 brd ff:ff:ff:ff:ff:ff link-netnsid 0 promiscuity 0
        macvlan mode bridge addrgenmode eui64 numtxqueues 1 numrxqueues 1 gso_max_size 65536 gso_max_segs 65535
    [root@d1 ~]# ip netns exec ns2 ip -d link show mac2
    4: mac2@if2: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UNKNOWN mode DEFAULT group default qlen 1000
        link/ether fa:9e:76:06:1a:dd brd ff:ff:ff:ff:ff:ff link-netnsid 0 promiscuity 0
        macvlan mode bridge addrgenmode eui64 numtxqueues 1 numrxqueues 1 gso_max_size 65536 gso_max_segs 65535
     [root@d1 ~]# ip netns exec ns1 ip addr show mac1
    3: mac1@if2: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UNKNOWN group default qlen 1000
        link/ether 42:e3:dc:fc:32:54 brd ff:ff:ff:ff:ff:ff link-netnsid 0
        inet 12.1.1.1/24 scope global mac1
           valid_lft forever preferred_lft forever
        inet6 fe80::40e3:dcff:fefc:3254/64 scope link
           valid_lft forever preferred_lft forever
    [root@d1 ~]# ip netns exec ns2 ip addr show mac2
    4: mac2@if2: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UNKNOWN group default qlen 1000
        link/ether fa:9e:76:06:1a:dd brd ff:ff:ff:ff:ff:ff link-netnsid 0
        inet 12.1.1.2/24 scope global mac2
           valid_lft forever preferred_lft forever
        inet6 fe80::f89e:76ff:fe06:1add/64 scope link
           valid_lft forever preferred_lft forever
     # 测试连通性
    [root@d1 ~]# ip netns exec ns1 ping 12.1.1.2 -c 3
    PING 12.1.1.2 (12.1.1.2) 56(84) bytes of data.
    64 bytes from 12.1.1.2: icmp_seq=1 ttl=64 time=0.035 ms
    64 bytes from 12.1.1.2: icmp_seq=2 ttl=64 time=0.037 ms
    64 bytes from 12.1.1.2: icmp_seq=3 ttl=64 time=0.037 ms
    
    --- 12.1.1.2 ping statistics ---
    3 packets transmitted, 3 received, 0% packet loss, time 2000ms
    rtt min/avg/max/mdev = 0.035/0.036/0.037/0.005 ms
    

    抓包分析 ICMP 报文

    [root@d1 ~]# tcpdump -i ens33 -w macvlan.pcap
    tcpdump: listening on ens33, link-type EN10MB (Ethernet), capture size 262144 bytes
    ^C18 packets captured
    19 packets received by filter
    0 packets dropped by kernel
    [root@d1 ~]# sz macvlan.pcap A
    
    • 容器网络环境中相同macvlan之间
        在docker容器网络环境中,macvlan也是一种非常常见且重要的跨主机网络模型。下面我们就针对容器网络进行相同macvlan在不同主机之间通信的实践。实验环境为两台server:Server A和Server B;分别启用一个自定义网络172.33.1.0/24名称为mac1和mac2;分别创建两个容器并指定IP地址;最后测试两个容器之间的网络连通性。
                             +------------------------------------------------------------------------+
                             |                                                                        |
                             |   +-------------------+                        +-------------------+   |
                             |   |Server A           |                        |Server B           |   |
                             |   |    +---------+    |                        |    +---------+    |   |
                             |   |    | Docker A|    |                        |    | Docker B|    |   |
                             |   |    +---------+    |                        |    +---------+    |   |
                             |   |    172.33.1.11    |                        |    172.33.1.12    |   |
                             |   |         |         |                        |         |         |   |
                             |   |  +------+------+  |                        |  +------+------+  |   |
                             |   |  |    Mac 1    |  |                        |  |    Mac 2    |  |   |
                             |   |  +------+------+  |                        |  +------+------+  |   |
                             |   |         |         |                        |         |         |   |
                             |   |    +----+----+    |                        |    +----+----+    |   |
                             |   |    |  ens33  |    |                        |    |  ens33  |    |   |
                             |   +----+---------+----+                        +----+---------+----+   |
                             |     172.16.116.131/24                            172.16.116.132/24     |
                             |             |                                            |             |
                             |             +--------------------------------------------+             |
                             |                                                           By:[F0rGeEk] |
                             +------------------------------------------------------------------------+
    

    具体实践过程如下:

     # 启动docker服务
    [root@d1 ~]# service docker start
    Redirecting to /bin/systemctl start docker.service
     # 创建docker自定义网络
    [root@d1 ~]# docker network create -d macvlan --subnet=172.33.1.0/24 --gateway=172.33.1.1 -o parent=ens33 mac1
    [root@d2 ~]# docker network create -d macvlan --subnet=172.33.1.0/24 --gateway=172.33.1.1 -o parent=ens33 mac2
     # 检查自定义网络是否创建成功
    [root@d1 ~]# docker network ls
    NETWORK ID         NAME            DRIVER            SCOPE
    f8a5e7ba5015        bridge             bridge              local
    a96c8a04be60        host                host                 local
    e179ce74baa4        mac1              macvlan           local
    8f8172bcf173        none                null                  local
    [root@d2 ~]# docker network ls
    NETWORK ID         NAME             DRIVER           SCOPE
    68199147d7fe        bridge              bridge              local
    eb0d0e219eb8        host                host                 local
    9c2b18b8a08a        mac2               macvlan           local
    b7ac4a61fcce        none                 null                  local
     #创建并启用容器
    [root@d1 ~]# docker run -itd --name DockerA --ip=172.33.1.11 --network mac1 busybox
    00dda3a8691564dce5e062a2c4ea89cb5c9640373102d587eb2c83e122642a67
    [root@d1 ~]# docker ps
    CONTAINER ID        IMAGE      COMMAND             CREATED             STATUS              PORTS               NAMES
    00dda3a86915        busybox             "sh"                4 seconds ago       Up 2 seconds                            DockerA
    [root@d2 ~]# docker run -itd --name DockerB --ip=172.33.1.12 --network mac2 busybox
    debe59d38ece790d1ffd3d2dc17240a15812b73025fd89b23d9d394f53fa7dc8
    [root@d2 ~]# docker ps
    CONTAINER ID        IMAGE      COMMAND             CREATED             STATUS              PORTS               NAMES
    debe59d38ece        busybox             "sh"                2 seconds ago       Up 2 seconds                            DockerB
     # 验证不同宿主机上的容器网络连通性
    [root@d1 ~]# docker exec -it DockerA sh
    / # ifconfig
    eth0      Link encap:Ethernet  HWaddr 02:42:AC:21:01:0B
              inet addr:172.33.1.11  Bcast:172.33.1.255  Mask:255.255.255.0
              UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
              RX packets:28 errors:0 dropped:0 overruns:0 frame:0
              TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
              collisions:0 txqueuelen:0
              RX bytes:2544 (2.4 KiB)  TX bytes:0 (0.0 B)
    
    lo        Link encap:Local Loopback
              inet addr:127.0.0.1  Mask:255.0.0.0
              UP LOOPBACK RUNNING  MTU:65536  Metric:1
              RX packets:0 errors:0 dropped:0 overruns:0 frame:0
              TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
              collisions:0 txqueuelen:1000
              RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)
    / # ping 172.33.1.12 -c 3
    PING 172.33.1.12 (172.33.1.12): 56 data bytes
    64 bytes from 172.33.1.12: seq=0 ttl=64 time=0.405 ms
    64 bytes from 172.33.1.12: seq=1 ttl=64 time=0.361 ms
    64 bytes from 172.33.1.12: seq=2 ttl=64 time=0.310 ms
    
    --- 172.33.1.12 ping statistics ---
    3 packets transmitted, 3 packets received, 0% packet loss
    round-trip min/avg/max = 0.310/0.358/0.405 ms
    

    抓包分析 ICMP 报文

    [root@d2 ~]# tcpdump -i ens33 -w macvlan.pcap
    tcpdump: listening on ens33, link-type EN10MB (Ethernet), capture size 262144 bytes
    ^C25 packets captured
    26 packets received by filter
    0 packets dropped by kernel
    [root@d2 ~]# sz macvlan.pcap
    
      从以上抓包分析中可以看出docker网络环境中,通过macvlan的方式连通两个不同宿主机上同一个网段的容器时,数据包没有进行二次封装转发的都是原始数据包,这说明使用这种方式更为节能高效。
  • 相关阅读:
    Oracle 删除重复数据的几种方法
    12.25模拟赛T3
    java实现第五届蓝桥杯圆周率
    java实现第五届蓝桥杯武功秘籍
    Oracle 审计初步使用
    [CERC2017]Intrinsic Interval——扫描线+转化思想+线段树
    ORA-12012 Error on auto execute of job "SYS"."ORA$AT_OS_OPT_SY_<NN> in 12.2.0 Database
    12.25模拟赛T2
    java实现第五届蓝桥杯写日志
    java实现第五届蓝桥杯李白打酒
  • 原文地址:https://www.cnblogs.com/4geek/p/12611134.html
Copyright © 2020-2023  润新知