2025年docker 四种网络模型(docker networkmode)

docker 四种网络模型(docker networkmode)nbsp 用一张图来说明 Docker 网络的基本概况 nbsp Docker 容器默认使用 bridge 模式的网络 其特点如下 使用一个 linux bridge 默认为 docker0 使用 veth 对 一头在容器的网络 namespace 中 一头在 docker0 上 该模式下 Docker Container 不具有一个公有 IP

大家好,我是讯享网,很高兴认识大家。



 

用一张图来说明 Docker 网络的基本概况:

docker 网络特性 docker的五种网络_docker 网络特性
讯享网

 

Docker 容器默认使用 bridge 模式的网络。其特点如下:

  • 使用一个 linux bridge,默认为 docker0
  • 使用 veth 对,一头在容器的网络 namespace 中,一头在 docker0 上
  • 该模式下Docker Container不具有一个公有IP,因为宿主机的IP地址与veth pair的 IP地址不在同一个网段内
  • Docker采用 NAT 方式,将容器内部的服务监听的端口与宿主机的某一个端口port 进行“绑定”,使得宿主机以外的世界可以主动将网络报文发送至容器内部
  • 外界访问容器内的服务时,需要访问宿主机的 IP 以及宿主机的端口 port
  • NAT 模式由于是在三层网络上的实现手段,故肯定会影响网络的传输效率。
  • 容器拥有独立、隔离的网络栈;让容器和宿主机以外的世界通过NAT建立通信

iptables 的 SNTA 规则,使得从容器离开去外界的网络包的源 IP 地址被转换为 Docker 主机的IP地址:

效果是这样的:

docker 网络特性 docker的五种网络_操作系统_02

示意图:

docker 网络特性 docker的五种网络_docker_03

定义:

Host 模式并没有为容器创建一个隔离的网络环境。而之所以称之为host模式,是因为该模式下的 Docker 容器会和 host 宿主机共享同一个网络 namespace,故 Docker Container可以和宿主机一样,使用宿主机的eth0,实现和外界的通信。换言之,Docker Container的 IP 地址即为宿主机 eth0 的 IP 地址。其特点包括:

  • 这种模式下的容器没有隔离的 network namespace
  • 容器的 IP 地址同 Docker host 的 IP 地址
  • 需要注意容器中服务的端口号不能与 Docker host 上已经使用的端口号相冲突
  • host 模式能够和其它模式共存

实验:

(1)启动一个 host 网络模式的容器

(2)检查其 network namespace,其中可以看到主机上的所有网络设备

示意图:

docker 网络特性 docker的五种网络_操作系统_04

定义:

 Container 网络模式是 Docker 中一种较为特别的网络的模式。处于这个模式下的 Docker 容器会共享其他容器的网络环境,因此,至少这两个容器之间不存在网络隔离,而这两个容器又与宿主机以及除此之外其他的容器存在网络隔离。  

实验:

(1)启动一个容器: 

docker run -d –name hostcs1 -p 5001:5001 training/webapp python app.py

(2)启动另一个容器,并使用第一个容器的 network namespace

docker run -d –name hostcs2 –network container:hostcs1  training/webapp python app.py

注意:因为此时两个容器要共享一个 network namespace,因此需要注意端口冲突情况,否则第二个容器将无法被启动。

示意图:

docker 网络特性 docker的五种网络_docker 网络特性_05

定义:

 网络模式为 none,即不为 Docker 容器构造任何网络环境。一旦Docker 容器采用了none 网络模式,那么容器内部就只能使用loopback网络设备,不会再有其他的网络资源。Docker Container的none网络模式意味着不给该容器创建任何网络环境,容器只能使用127.0.0.1的本机网络。

实验:

(1)创建并启动一个容器: docker run -d –name hostn1 –network none training/webapp python app.py

(2)检查其网络设备,除了 loopback 设备外没有其它设备

  Docker 多节点网络模式可以分为两类,一类是 Docker 在 1.19 版本中引入的基于 VxLAN 的对跨节点网络的原生支持;另一种是通过插件(plugin)方式引入的第三方实现方案,比如 Flannel,Calico 等等。

  Docker 1.19 版本中增加了对 overlay 网络的原生支持。Docker 支持 Consul, Etcd, 和 ZooKeeper 三种分布式key-value 存储。其中,etcd 是一个高可用的分布式 k/v存储系统,使用etcd的场景默认处理的数据都是控制数据,对于应用数据,只推荐数据量很小,但是更新访问频繁的情况。

3.1.1 安装配置

准备三个节点:

  • devstack 192.168.1.18
  • docker1 192.168.1.21
  • docker2 192.168.1.19

在 devstack 上使用Docker 启动 etcd 容器:

使用 Docker 启动 etcd 请参考 https://coreos.com/etcd/docs/latest/docker_guide.html。不过,应该是因为制造镜像所使用的Dockerfile 原因,官网上的命令因为少了上面红色字体部分而会造成启动失败:

添加红色部分后,容器可以被正确创建:

在docker1 和 docker2 节点上修改 /etc/default/docker,添加:

然后分别重启 docker deamon。注意,要使用IP地址;要是使用 hostname 的话,docker 服务将启动失败:

3.1.2 使用 Docker overlay 网络

(1)在docker1上运行下面的命令创建一个 overlay 网络:

在 docker2 上你也会看到这个网络,说明通过 etcd,网络数据是分布式而不是本地的了。

(2)在网络中创建容器

在 docker2 上,运行 docker run -d –name over2 –network overlaynet1 training/webapp python app.py

在 docker1 上,运行 docker run -d –name over1 –network overlaynet1 training/webapp python app.py

进入容器 over2,发现它有两块网卡:

其中 eth1 的网络是一个内部的网段,其实它走的还是普通的 NAT 模式;而 eth0 是 overlay 网段上分配的IP地址,也就是它走的是 overlay 网络,它的 MTU 是 1450 而不是 1500.

进一步查看它的路由表,你会发现只有同一个 overlay 网络中的容器之间的通信才会通过 eth0,其它所有通信还是走 eth1.

先看此时的网络拓扑图:

docker 网络特性 docker的五种网络_运维_06

可见:

  • Docker 在每个节点上创建了两个 linux bridge,一个用于 overlay 网络(ov-000100-1de98),一个用于非 overlay 的 NAT 网络(docker_gwbridge)
  • 容器内的到overlay 网络的其它容器的网络流量走 overlay 网卡(eth0),其它网络流量走 NAT 网卡(eth1)
  • 当前 Docker 创建 vxlan 隧道的ID范围为 256~1000,因而最多可以创建745个网络,因此,本例中的这个 vxlan 隧道使用的 ID 是 256
  • Docker vxlan 驱动使用 4789 UDP 端口
  • overlay网络模型底层需要类似 consul 或 etcd 的 KV 存储系统进行消息同步
  • Docker overlay 不使用多播
  • Overlay 网络中的容器处于一个虚拟的大二层网络中

ov-000100-1de98 的初始情形:

这里很明显的一个问题是,vxlan dev vx-000100-1de98 的 fdb 表内容不全,导致从容器1 ping 容器2 不通。待选的解决方式不外乎下面几种:

  • 使用一个中央数据库,它保存所有容器的 IP 地址和所在节点的 IP 地址的映射关系
  • 使用多播
  • 使用比如 BGP 的特殊协议来广告(advertise)容器的 IP 和所在节点的 IP 的映射关系

Docker 从某种程度上利用了第一种和第三种方式的组合,首先Docker 利用 consul 以及 etcd 这样的分布式 key/value 存储来保存IP地址映射关系,另一方面个Docker 节点也通过某种协议来直接广告映射关系。

为了测试,中间重启了 docker1 节点,发现 over1 容器无法启动,报错如下:

回到容器之间无法ping通对方的问题,尚不知道根本原因是什么(想吐槽Docker目前的问题真不少)。要使得互相 ping 能工作,至少必须具备下面的条件:

在 docker1 上,

  • 为 vxlan dev 添加一条 fdb entry:02:42:14:00:00:03 dst 192.168.1.20 self
  • 在容器中添加一条 arp entry:ip netns exec over1 arp -s 20.0.0.3 02:42:14:00:00:03

在 docker 2 上,

  • 为 vxlan dev 添加一条 fdb entry:02:42:14:00:00:02 dst 192.168.1.21 self permanent
  • 在容器中添加一条 arp entry:ip netns exec over4 arp -s 20.0.0.2 02:42:14:00:00:02

使用 iperf 工具检查测试了一下性能并做对比:

 两台主机是同一个物理机上的两个虚机,因此,结果的绝对值其实没多少意义,相对值有一定的参考性。

文章 Testing Docker multi-host network performance 对比了多种网络模式下的性能,结果如下:

docker 网络特性 docker的五种网络_python_07

看起来这个表里面的数据和我的表里面的数据差不了太多。

  • Bridge 模式的性能损耗大概为10%
  • 原生 overlay 模式的性能损耗非常高,甚至达到了 56%,因此,在生产环境下使用这种模式需要非常谨慎。
  • 如果一定要使用 overlay 模式的话,可以考虑使用 Cisco 发起的  Calico 模式,它的性能和 bridge 相当。
  • Weave overlay 模式的性能数据非常可疑,按理说应该不可能这么差。

 

小讯
上一篇 2025-06-03 17:44
下一篇 2025-06-02 14:34

相关推荐

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请联系我们,一经查实,本站将立刻删除。
如需转载请保留出处:https://51itzy.com/kjqy/204434.html