macvlan

macvlan的原理是在宿主机物理网卡上虚拟出多个子网卡,通过不同的MAC地址在数据链路层(Data Link Layer)进行网络数据转发的,它是比较新的网络虚拟化技术,需要较新的内核支持(Linux kernel v3.9–3.19 and 4.0+)。

准备实验环境

使用 node-1 和 host2 上单独的网卡ens38 创建 macvlan。为保证多个 MAC 地址的网络包都可以从 ens38通过,需要打开网卡的混杂模式

ip link set ens38 promisc on

确保 ens38 状态 UP 并且 promisc 模式已经生效。

创建macvlan网络

在 node-2 中也要执行相同的命令

root@node-2:~# docker network create  -d macvlan --subnet=172.16.86.0/24 --gateway=172.16.86.1  -o parent=ens38 mac_net1
fc9f85149d08638194aef4722d255e0cbda8a982653ad858d9a76fa96b00f43e
root@node-2:~#

-d macvlan 指定 driver 为 macvlan。

② macvlan 网络是 local 网络,为了保证跨主机能够通信,用户需要自己管理 IP subnet。

③ 与其他网络不同,docker 不会为 macvlan 创建网关,这里的网关应该是真实存在的,否则容器无法路由。

-o parent 指定使用的网络 interface。

在 node-1 中运行容器 bbox1 并连接到 mac_net1。

由于 node-1 中的 mac_net1 与 node-2 中的 mac_net1 本质上是独立的,为了避免自动分配造成 IP 冲突,需要通过 --ip 指定 bbox1 地址为 172.16.86.11。

在 node-2 中运行容器 bbox2,指定 IP 172.16.86.10。

验证 bbox1 和 bbox1 的连通性。

macvlan 网络结构分析

macvlan 不依赖 Linux bridge,brctl show 可以确认没有创建新的 bridge。

查看一下容器 bbox1 的网络设备:

除了 lo,容器只有一个 eth0,请注意 eth0 后面的 @if4,这表明该 interface 有一个对应的 interface,其全局的编号为 4。根据 macvlan 的原理,这个 interface 就是主机的 ens38,确认如下:

容器的 eth0 就是 ens38 通过 macvlan 虚拟出来的 interface。容器的 interface 直接与主机的网卡连接,这种方案使得容器无需通过 NAT 和端口映射就能与外网直接通信(只要有网关),在网络上与其他独立主机没有区别。当前网络结构如图所示:

用 sub-interface 实现多 macvlan 网络

macvlan 会独占主机的网卡,也就是说一个网卡只能创建一个 macvlan 网络,否则会报错:

macvlan 不仅可以连接到 interface(如 enp38),也可以连接到 sub-interface(如 ens38.xx)

VLAN 是现代网络常用的网络虚拟化技术,它可以将物理的二层网络划分成多达 4094 个逻辑网络,这些逻辑网络在二层上是隔离的,每个逻辑网络(即 VLAN)由 VLAN ID 区分,VLAN ID 的取值为 1-4094。

Linux 的网卡也能支持 VLAN(apt-get install vlan),同一个 interface 可以收发多个 VLAN 的数据包,不过前提是要创建 VLAN 的 sub-interface。

比如希望 ens38 同时支持 VLAN10 和 VLAN20,则需创建 sub-interface enp0s9.10 和 enp0s9.20。

在交换机上,如果某个 port 只能收发单个 VLAN 的数据,该 port 为 Access 模式,如果支持多 VLAN,则为 Trunk 模式,所以接下来实验的前提是:

enp38要接在交换机的 trunk 口上。如果用的是 VirtualBox 虚拟机,则不需要额外配置了。

在 ens38.10 和 ens38.20 上创建 macvlan 网络。

首先编辑 node-1和node-2 的 /etc/network/interfaces,配置 sub-auto ens38

然后启用 sub-interface:

ifup ens38.10

ifup ens38.20

创建 macvlan 网络:

docker network create -d macvlan --subnet=172.16.10.0/24 --gateway=172.16.10.1 -o parent=ens38.10 mac_net10

docker network create -d macvlan --subnet=172.16.20.0/24 --gateway=172.16.20.1 -o parent=ens38.20 mac_net20

在 node-1中运行容器:

docker run -itd --name bbox1 --ip=172.16.10.10 --network mac_net10 busybox

docker run -itd --name bbox2 --ip=172.16.20.10 --network mac_net20 busybox



在 node-2中运行容器:

docker run -itd --name bbox3 --ip=172.16.10.11 --network mac_net10 busybox

docker run -itd --name bbox4 --ip=172.16.20.11 --network mac_net20 busybox

当前网络结构如图所示

macvlan的网络隔离和联通

macvlan 之间的连通性

bbox1 能 ping 通 bbox3,bbox2 能 ping 通 bbox4。即:同一 macvlan 网络能通信。

bbox1 无法 ping 通 bbox2 和 bbox4。即:不同 macvlan 网络之间不能通信。但更准确的说法应该是:不同 macvlan 网络不能 在二层上 通信。

在三层上可以通过网关将 macvlan 连通,新建虚拟机(192.168.113.5 )做路由

将192.168.113.5 配置成一个虚拟路由器,设置网关并转发 VLAN10 和 VLAN20 的流:首先确保操作系统 IP Forwarding 已经启用。

root@node-2:~# ifconfig enp0s8.10 172.16.10.1 netmask 255.255.255.0 up
root@node-2:~# ifconfig enp0s8.20 172.16.20.1 netmask 255.255.255.0 up

需要开启防火墙

然后执行sysctl -w net.ipv4.ip_forward=1

添加 iptables 规则,转发不同 VLAN 的数据包。

root@node-2:~# iptables -t nat -A POSTROUTING -o enp0s8.10 -j MASQUERADE
root@node-2:~# iptables -t nat -A POSTROUTING -o enp0s8.20 -j MASQUERADE
root@node-2:~# iptables -A FORWARD -i enp0s8.10 -o enp0s8.20 -m state --state RELATED,ESTABLISHED -j ACCEPT
root@node-2:~# iptables -A FORWARD -i enp0s8.20 -o enp0s8.10 -m state --state RELATED,ESTABLISHED -j ACCEPT
root@node-2:~# iptables -A FORWARD -i enp0s8.10 -o enp0s8.20 -j ACCEPT
root@node-2:~# iptables -A FORWARD -i enp0s8.20 -o enp0s8.10 -j ACCEPT

① 因为 bbox1 与 bbox4 在不同的 IP 网段,跟据 bbox1 的路由表:

root@node-1:~# docker exec bbox1 ip route
default via 172.16.10.1 dev eth0
172.16.10.0/24 dev eth0 scope link src 172.16.10.10
root@node-1:~#

数据包将发送到网关 172.16.10.1。

② 路由器从 eth2.10 收到数据包,发现目的地址是 172.16.20.11,查看自己的路由表:

于是将数据包从 eth2.20 转发出去。

③ 通过 ARP 记录的信息,路由器能够得知 172.16.20.11 在 host2 上,于是将数据包发送给 host2。

④ host2 根据目的地址和 VLAN 信息将数据包发送给 bbox4。

macvlan 网络的连通和隔离完全依赖 VLAN、IP subnet 和路由,docker 本身不做任何限制,用户可以像管理传统 VLAN 网络那样管理 macvlan。

docker_macvlan的更多相关文章

随机推荐

  1. [转帖]SAP一句话入门:Plant Maintenance

    SAP一句话入门:Plant Maintenance http://blog.vsharing.com/MilesForce/A618273.html PM就是Plant Maintenance(本文 ...

  2. CMake--常用指令

    1 . ADD_DEFINITIONS 向 C/C++ 编译器添加 -D 定义,比如 在CMakeList.txt文件中添加: ADD_DEFINITIONS(-DENABLE_DEBUG -DABC ...

  3. mac 中登陆mysql忘记密码解决办法

    1.打开终端,输入命令:cd /usr/local/mysql/bin 2.mysql -uroot -p,用这条命令登陆时报错信息: 报错:Enter password: ERROR 1045 (2 ...

  4. Centos6.8 安装git

    1.下载安装包 wget https://mirrors.edge.kernel.org/pub/software/scm/git/git-2.8.0.tar.gz 2.安装依赖 sudo yum - ...

  5. 解决mybatis generator警告Cannot obtain primary key information from the database, generated objects may be incomplete

    使用 mybatis generator 生成pojo.dao.mapper时 经常出现 Cannot obtain primary key information from the database ...

  6. jQuery AJAX获取JSON数据解析多种方式示例

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  7. 由 POST 400 错误拔出来的萝卜

    缘起 前段时间遇到扫描问题,好不容易拿到了扫描出来的数据,结果调用接口时弹了个 400(Bad request) 给我,匆匆找了点资料修补上线后,忐忑的心也可以安分点.然后,顺着这个 400 的萝卜, ...

  8. HTML 中的 href\src\url

    1. 2. -------from Stack Overflow <a><link>使用 href; <img><script>使用 src;

  9. 【python练习题】程序16

    #题目:输出指定格式的日期. import time print (time.strftime('%Y:%m:%d %X',time.localtime(time.time())))

  10. 【Python练习题】程序5

    #题目:输入三个整数x,y,z,请把这三个数由小到大输出. # a = input('请输入整数: \n') # # b = input('请输入整数: \n') # # c = input('请输入 ...