本文首发于我的公众号 Linux云计算网络(id: cloud_dev),专注于干货分享,号内有 10T 书籍和视频资源,后台回复「1024」即可领取,欢迎大家关注,二维码文末可以扫。

上一篇文章我们详细介绍了 macvlan 这种技术,macvlan 详解,由于它高效易配置的特性,被用在了 Docker 的网络方案设计中,这篇文章就来说说这个。

01 macvlan 用于 Docker 网络

在 Docker 中,macvlan 是众多 Docker 网络模型中的一种,并且是一种跨主机的网络模型,作为一种驱动(driver)启用(-d 参数指定),Docker macvlan 只支持 bridge 模式。

下面我们做两个实验,分别验证相同 macvlan 网络和不同 macvlan 网络的连通性。

1.1 相同 macvlan 网络之间的通信

首先准备两个主机节点的 Docker 环境,搭建如下拓扑图示:

1 首先使用 docker network create 分别在两台主机上创建两个 macvlan 网络:

root@ubuntu:~# docker network create -d macvlan --subnet=172.16.10.0/24 --gateway=172.16.10.1 -o parent=enp0s8 mac1

这条命令中,

  • -d 指定 Docker 网络 driver
  • --subnet 指定 macvlan 网络所在的网络
  • --gateway 指定网关
  • -o parent 指定用来分配 macvlan 网络的物理网卡

之后可以看到当前主机的网络环境,其中出现了 macvlan 网络:

root@ubuntu:~# docker network ls
NETWORK ID NAME DRIVER SCOPE
128956db798a bridge bridge local
19fb1af129e6 host host local
2509b3717813 mac1 macvlan local
d5b0798e725e none null local

2 在 host1 运行容器 c1,并指定使用 macvlan 网络:

root@ubuntu:~# docker run -itd --name c1 --ip=172.16.10.2 --network mac1 busybox

这条命令中,

  • --ip 指定容器 c1 使用的 IP,这样做的目的是防止自动分配,造成 IP 冲突
  • --network 指定 macvlan 网络

同样在 host2 中运行容器 c2:

root@ubuntu:~# docker run -itd --name c2 --ip=172.16.10.3 --network mac1 busybox

3 在 host1 c1 中 ping host2 c2:

root@ubuntu:~# docker exec c1 ping -c 2 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=0.641 ms
64 bytes from 172.16.10.3: seq=1 ttl=64 time=0.393 ms --- 172.16.10.3 ping statistics ---
2 packets transmitted, 2 packets received, 0% packet loss round-trip min/avg/max = 0.393/0.517/0.641 ms

注意:以上的实验都需要物理网卡 enp0s8 开启混杂模式,不然会 ping 不通。

1.2 不同 macvlan 网络之间的通信

接下来,我们来看看不同 macvlan 网络之间的连通性,搭建以下的拓扑环境:

由于 macvlan 网络会独占物理网卡,也就是说一张物理网卡只能创建一个 macvlan 网络,如果我们想创建多个 macvlan 网络就得用多张网卡,但主机的物理网卡是有限的,怎么办呢?

好在 macvlan 网络也是支持 VLAN 子接口的,所以,我们可以通过 VLAN 技术将一个网口划分出多个子网口,这样就可以基于子网口来创建 macvlan 网络了,下面是具体的创建过程。

1 首先分别在两台主机上将物理网口 enp0s8 创建出两个 VLAN 子接口。

# 使用 vconfig 命令在 eth0 配置两个 VLAN
root@ubuntu:~# vconfig add enp0s8 100
root@ubuntu:~# vconfig add enp0s8 200 # 设置 VLAN 的 REORDER_HDR 参数,默认就行了
root@ubuntu:~# vconfig set_flag enp0s8.100 1 1
root@ubuntu:~# vconfig set_flag enp0s8.200 1 1 # 启用接口
root@ubuntu:~# ifconfig enp0s8.100 up
root@ubuntu:~# ifconfig enp0s8.200 up

2 分别在 host1 和 host2 上基于两个 VLAN 子接口创建 2 个 macvlan 网络,mac10 和 mac20。

root@ubuntu:~# docker network create -d macvlan --subnet=172.16.10.0/24 --gateway=172.16.10.1 -o parent=enp0s8.100 mac10
root@ubuntu:~# docker network create -d macvlan --subnet=172.16.20.0/24 --gateway=172.16.20.1 -o parent=enp0s8.200 mac20

3 分别在 host1 和 host2 上运行容器,并指定不同的 macvlan 网络。

# host1
root@ubuntu:~# docker run -itd --name d1 --ip=172.16.10.10 --network mac10 busybox
root@ubuntu:~# docker run -itd --name d2 --ip=172.16.20.10 --network mac20 busybox # host2
root@ubuntu:~# docker run -itd --name d3 --ip=172.16.10.11 --network mac10 busybox
root@ubuntu:~# docker run -itd --name d4 --ip=172.16.20.11 --network mac20 busybox

通过验证,d1 和 d3,d2 和 d4 在同一 macvlan 网络下,互相可以 ping 通,d1 和 d2,d1 和 d4 在不同的 macvlan 网络下,互相 ping 不通。

这个原因也很明确,不同 macvlan 网络处于不同的网络,而且通过 VLAN 隔离,自然 ping 不了。

但这也只是在二层上通不了,通过三层的路由是可以通的,我们这就来验证下。

重新找一台主机 host3,通过打开 ip_forward 把它改造成一台路由器(至于为什么可以这样,可以参考我之前的一篇文章),用来打通两个 macvlan 网络,大概的图示如下所示:

1 首先对 host3 执行 sysctl -w net.ipv4.ip_forward=1 打开路由开关。

2 然后创建两个 VLAN 子接口,一个作为 macvlan 网络 mac10 的网关,一个作为 mac20 的网关。

[root@localhost ~]# vconfig add enp0s8 100
[root@localhost ~]# vconfig add enp0s8 200
[root@localhost ~]# vconfig set_flag enp0s8.100 1 1
[root@localhost ~]# vconfig set_flag enp0s8.200 1 1 # 对 vlan 子接口配置网关 IP 并启用
[root@localhost ~]# ifconfig enp0s8.100 172.16.10.1 netmask 255.255.255.0 up
[root@localhost ~]# ifconfig enp0s8.200 172.16.20.1 netmask 255.255.255.0 up

3 这样之后再从 d1 ping d2 和 d4,就可以 ping 通了。

root@ubuntu:~# docker exec d1 ping -c 2 172.16.20.10
PING 172.16.20.10 (172.16.20.10): 56 data bytes
64 bytes from 172.16.20.10: seq=0 ttl=63 time=0.661 ms
64 bytes from 172.16.20.10: seq=1 ttl=63 time=0.717 ms --- 172.16.20.10 ping statistics ---
2 packets transmitted, 2 packets received, 0% packet loss
round-trip min/avg/max = 0.661/0.689/0.717 ms
root@ubuntu:~# docker exec d1 ping -c 2 172.16.20.11
PING 172.16.20.11 (172.16.20.11): 56 data bytes
64 bytes from 172.16.20.11: seq=0 ttl=63 time=0.548 ms
64 bytes from 172.16.20.11: seq=1 ttl=63 time=0.529 ms --- 172.16.20.11 ping statistics ---
2 packets transmitted, 2 packets received, 0% packet loss
round-trip min/avg/max = 0.529/0.538/0.548 ms

PS:可能有些系统做了安全限制,可能 ping 不通,这时候可以添加以下 iptables 规则,目的是让系统能够转发不通 VLAN 的数据包。

iptables -t nat -A POSTROUTING -o enp0s8.100 -j MASQUERADE

iptables -t nat -A POSTROUTING -oenp0s8.200 -j MASQUERADE

iptables -A FORWARD -i enp0s8.100 -o enp0s8.200 -m state --state RELATED,ESTABLISHED -j ACCEPT

iptables -A FORWARD -i enp0s8.200 -o enp0s8.100 -m state --state RELATED,ESTABLISHED -j ACCEPT

iptables -A FORWARD -i enp0s8.100 -o enp0s8.200 -j ACCEPT

iptables -A FORWARD -i enp0s8.200 -o enp0s8.100 -j ACCEPT

为什么配置 VLAN 子接口,配上 IP 就可以通了,我们可以看下路由表就知道了。

首先看容器 d1 的路由:

root@ubuntu:~# docker exec d1 ip route
default via 172.16.10.1 dev eth0
172.16.10.0/24 dev eth0 scope link src 172.16.10.10

我们在创建容器的时候指定了网关 172.16.10.1,所以数据包自然会被路由到 host3 的接口。再来看下 host3 的路由:

[root@localhost ~]# ip route
default via 192.168.108.1 dev enp0s3 proto dhcp metric 100
172.16.10.0/24 dev enp0s8.100 proto kernel scope link src 172.16.10.1
172.16.20.0/24 dev enp0s8.200 proto kernel scope link src 172.16.20.1
192.168.56.0/24 dev enp0s8 proto kernel scope link src 192.168.56.122 metric 101
192.168.108.0/24 dev enp0s3 proto kernel scope link src 192.168.108.2 metric 100

可以看到,去往 172.16.10.0/24 网段的数据包会从 enp0s8.100 出去,同理 172.16.20.0/24 网段也是,再加上 host3 的 ip_forward 打开,这就打通了两个 macvlan 网络之间的通路。

02 总结

macvlan 是一种网卡虚拟化技术,能够将一张网卡虚拟出多张网卡。

macvlan 的四种通信模式,常用模式是 bridge。

在 Docker 中,macvlan 只支持 bridge 模式。

相同 macvlan 可以通信,不同 macvlan 二层无法通信,可以借助三层路由完成通信。

思考一下:

  1. macvlan bridge 和 bridge 的异同点
  2. 还有一种类似的技术,多张虚拟网卡共享相同 MAC 地址,但有独立的 IP 地址,这是什么技术?

后台回复“加群”,带你进入高手如云交流群

我的公众号 「Linux云计算网络」(id: cloud_dev) ,号内有 10T 书籍和视频资源,后台回复 「1024」 即可领取,分享的内容包括但不限于 Linux、网络、云计算虚拟化、容器Docker、OpenStack、Kubernetes、工具、SDN、OVS、DPDK、Go、Python、C/C++编程技术等内容,欢迎大家关注。


参考:

https://www.cnblogs.com/CloudMan6/p/7400580.html

https://blog.csdn.net/dog250/article/details/45788279

https://www.hi-linux.com/posts/40904.html

Docker 网络模型之 macvlan 详解,图解,实验完整的更多相关文章

  1. Docker Swarm 负载均衡详解 or 模式选择

    Docker Swarm 负载均衡详解 Swarm模式内置DNS组件,可以自动为集群中的每个服务分配DNS记录. Swarm manager使用内部负载均衡,根据服务的DNS名称在集群内的服务之间分发 ...

  2. Docker Swarm 高可用详解

    Docker Swarm 高可用详解 Manager管理节点宕机后其他管理节点仍然可以使用管理 intermal distributed state store:内部分布式状态存储同步共享到每个节点. ...

  3. 最佳实战Docker持续集成图文详解

    最佳实战Docker持续集成图文详解 这是一种真正的容器级的实现,这个带来的好处,不仅仅是效率的提升,更是一种变革:开发人员第一次真正为自己的代码负责——终于可以跳过运维和测试部门,自主维护运行环境( ...

  4. docker entrypoint入口文件详解

    docker entrypoint入口文件详解 pasting Dockerfile创建自定义Docker镜像以及CMD与ENTRYPOINT指令的比较 [k8s]args指令案例-彻底理解docke ...

  5. Docker:网络模式详解

    Docker作为目前最火的轻量级容器技术,牛逼的功能,如Docker的镜像管理,不足的地方网络方面. Docker自身的4种网络工作方式,和一些自定义网络模式 安装Docker时,它会自动创建三个网络 ...

  6. Docker基础 :网络配置详解

    本篇文章将讲述 Docker 的网络功能,包括使用端口映射机制来将容器内应用服务提供给外部网络,以及通过容器互联系统让多个容器之间进行快捷的网络通信,有兴趣的可以了解下. 大量的互联网应用服务包含多个 ...

  7. [P4基础]p4app的Docker镜像仓使用详解

    How to use the p4lang/p4app Docker image 本文参考 孙勇峰博客 和 p4app README 以及 p4app Dockerfile 结合自己的理解做一些记录, ...

  8. 网卡也能虚拟化?网卡虚拟化技术 macvlan 详解

    本文首发于我的公众号 Linux云计算网络(id: cloud_dev),专注于干货分享,号内有 10T 书籍和视频资源,后台回复「1024」即可领取,欢迎大家关注,二维码文末可以扫. 01 macv ...

  9. Docker Daemon 连接方式详解

    前言 在 Docker 常用详解指令 一文中粗粗提了一下, Docker 是分为客户端和服务端两部分的, 本文将介绍客户端是如何连接服务端的. 连接方式 1. UNIX域套接字 默认就是这种方式, 会 ...

随机推荐

  1. js怎么select 选中的值

    var obj = document.getElementById(”SelectID”); var index = obj.selectedIndex; // 选中索引var text = obj. ...

  2. openssl之BIO系列之20---缓冲(buffer)类型BIO

    缓冲(buffer)类型BIO ---依据openssl doc\crypto\bio_f_buffer.pod翻译和自己的理解写成 (作者:DragonKing, Mail: wzhah@263.n ...

  3. 8.JS数据类型

    ① 数据类型:字符串,数字,布尔,数组,对象,Null,Undefined ② JavaScript拥有动态类型.这意味着相同的变量可用作不同的类型: 实例 var x:   //x为undefine ...

  4. sam模板

    SAM模板 struct SAM{ * ; struct node{ node*nxt[],*fail; int len; }; node*root;int cnt; node no[maxn]; n ...

  5. MARA 附加结构(增强字段)

  6. 火狐浏览器使用firebug获取xpath和css path

    工作中,常常会用到网页元素的定位方式,常用的有xpath和css path两种定位方式. 现在简单介绍如何使用工具自动生成元素的定位字符串. 首先介绍在火狐浏览器上使用FireBug及其扩展FireP ...

  7. NSDate的具体使用(转载)

    NSDate的具体使用 时间与日期处理 主要有以下类: NSDate -- 表示一个绝对的时间点 NSTimeZone -- 时区信息 NSLocale -- 本地化信息 NSDateComponen ...

  8. Spring AOP-xml配置

    在spring AOP(一)中介绍了AOP的基本概念和几个术语,现在学习一下在XML中如何配置AOP. 在XML中AOP的配置元素有以下几种: AOP配置元素 描述 <aop:config> ...

  9. # <center>merge表不可用的问题</center>

    最近碰到了个很有意思的问题,值得一写 给merge表和基础表添加索引时发生了一个问题,不管是先给merge表加索引还是基础表加索引,如果表数据量大都会导致加索引期间对merge表的查询不可用,因为使用 ...

  10. Redis雪崩效应以及解决方案

    缓存雪崩产生的原因 缓存雪崩通俗简单的理解就是:由于原有缓存失效(或者数据未加载到缓存中),新缓存未到期间(缓存正常从Redis中获取,如下图)所有原本应该访问缓存的请求都去查询数据库了,而对数据库C ...