Docker 网络基础与实现

欢迎收藏作者个人网站

引言

什么是Docker?

Docker是应用容器引擎,它利用虚拟化技术打包应用及其依赖。

Docker解决什么问题?

Docker或者说虚拟化技术的出现,主要是为了解决应用能够快速构建、实施的问题。

  • 一方面, Docker技术帮助应用程序在不同的基础环境下快速实施部署。
    应用程序开发完成后,通常不会仅仅部署在一台特定的机器上,而是需要复制到不同环境、不同机器上实施,实施的基础环境很可能存在比较大的差异,如果在部署时才进行调试,部署效率低。Docker技术(或者说虚拟化技术)则可以用来帮助应用程序能够进行快速地实施、部署。
  • 另一方面,Docker技术可以让不同的应用程序在同一台机器上良好的运行,互不影响。
    比如我们想要在同一台机器上部署两个绑定了80端口的Web应用程序,如果没有Docker或虚拟化技术,就可能发生端口占用冲突。

说白了,Docker就是服务于应用的。

Docker的网络要解决什么问题?

Docker是服务于应用的,Docker网络就是解决容器中应用的网络通信问题,让容器中的应用就像在一台独立的主机上运行一般。

  • 当应用是部署在物理主机上时:
    应用发送的接收数据的流程如下图所示:
  •      

所有应用共享Linux系统网络协议栈,
socket 中存储了特定的四元组: 源ip+port,目的ip+port;

  • 当应用部署在虚拟机上时:

     ​​​​​​​

  • 当应用部署在Docker容器时:

 

Docker容器的本质是 共享内核,资源隔离、资源限制、文件系统rootfs


同一台宿主机上的Docker容器共享内核中传输 层和网络层的处理流程以及设备驱动,共享硬件资源,但是socket套接字和虚拟网络设备相互独立,需要进行隔离和限制。
Docker网络的实现主要就是如何在共享内核的基础上,实现socket的隔离,虚拟设备的隔离和通信.、

Docker的网络实现是站在巨人的肩膀上的,Docker主要是利用的操作系统的虚拟化技术,来实现不同容器的网络隔离和通信。

虚拟网络接口

Linux网络协议栈中,IP层不与物理网络设备(网络驱动)直接通信,而是和抽象的网络接口(lo、eth0、eth1等)交互。这为Docker不同容器中能够模拟网络环境提供的基础。

namespace

Docker是轻量级的虚拟化,他和虚拟机的一个主要区别是不同的Docker容器共享Linux内核。
共享内核就会存在资源可见性的问题。为此,Linux支持为不同资源设置不同的namespace,不同namespace的资源相互隔离、相互不可见。

namespace其实不单单用于Linux的网络模块(network)。Linux 支持一下六种类型的命名空间:Cgroup、IPC、Network、Mount、PID、Time、User、UTS。 这六种类型都是Docker虚拟化实现资源隔离的基础。

有了namespace的概念,不同容器虚拟出独立的网络环境就变为可行。(比如我们可以在不同的容器中创建网络接口eth0.

 

veth

namespace用于实现网络资源的隔离,但是Docker容器与宿主机经常需要进行通信,这就需要Linux系统中veth-pair技术的支持。

veth是虚拟网络设备接口,它总是成对出现,用于连通两个namespace。从其中一个端口发出的数据包,可以直接出现在与它对应的另一个端口上。

 

 

bridge

veth-pair解决了不同命名空间两两通信的问题(容器与容器、容器与宿主机),但是一台宿主机上可以启动大量的容器,这些容器的数据包需要汇聚到同一个网络接口才能与宿主机以外的设备通信。如果仅仅是基于veth-pair来进行数据转发配置,就过于繁琐。

Linux网络内核引入网桥bridge来实现多个网络接口之间的通信,可以将一台机器上的若干接口连通起来。在OSI网络模型中,网桥属于数据链路层。

 

路由表

Linux网络内核通过路由表来指定数据包的转发路径。
一台Linux主机里可能有多个虚拟网络接口、多个物理网络设备,在TCP/IP协议中,IP数据包里包含了目的地址,但是并不知道如何到达目标地址。路由表则用于指示要抵达目的地址,数据包下一条应该先到哪里去。
路由表示例:

[root@VM_16_35_centos ~]# route -n

Kernel IP routing table

Destination Gateway Genmask Flags Metric Ref Use Iface

0.0.0.0 172.16.16.1 0.0.0.0 UG 0 0 0 eth1

169.254.0.0 0.0.0.0 255.255.0.0 U 1002 0 0 eth1

172.16.16.0 0.0.0.0 255.255.240.0 U 0 0 0 eth1

Docker网络实现

对Linux的虚拟化支持有一定了解后,我们就可以来看下Docker的网络实现了。

Docker的几种网络模型

  • bridge: Docker容器有自己的Network-Namesapce,通过veth-pair和Linux-Bridge技术实现容器与宿主机的网络通信。brige模式是Docker的默认网络模式。
  • host: Docker容器与宿主机共享网络,容器不会有自己的Network-Namesapce,与宿主机不进行网络隔离。
  • overlay: 将多个Docker Daemon连接到一起。
  • IPvlan: 用户可以完全控制IPv4和IPv6寻址。支持对二层VLAN tag和三层网络路由的完全控制。
  • macvlan: 支持为容器设置mac地址,让Docker daemon能够基于Mac地址路由流量。
  • none: 这种模式下的容器禁用所有网络。
  • Network plugins: 安装使用第三方的Docker网络插件。

这里我们主要介绍下bridge网络模式。

Docker网络实现

创建bridge

在Docker-Daemon启动是会在宿主机创建一个bridge:docker0.

[root@VM_52_29_centos ~]# ip link show

1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT

link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00

2: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP mode DEFAULT qlen 1000

link/ether 52:54:00:bb:18:70 brd ff:ff:ff:ff:ff:ff

3: br-703d0323a265: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN mode DEFAULT

link/ether 02:42:80:e4:57:84 brd ff:ff:ff:ff:ff:ff

4: docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP mode DEFAULT

link/ether 02:42:40:84:e0:47 brd ff:ff:ff:ff:ff:ff

[root@VM_52_29_centos ~]# ifconfig docker0

docker0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500

inet 192.168.10.1 netmask 255.255.255.0 broadcast 192.168.10.255

ether 02:42:40:84:e0:47 txqueuelen 0 (Ethernet)

RX packets 12788 bytes 588170 (574.3 KiB)

RX errors 0 dropped 0 overruns 0 frame 0

TX packets 42200 bytes 59457226 (56.7 MiB)

TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0

[root@VM_52_29_centos ~]#

 

容器网络

启动容器时,Docker会为容器新增一个network-namespace,并创建veth-pair与宿主机相连。

[root@VM_52_29_centos ~]# docker ps

CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES

fea48be1f2d1 alpine:3.15.4 "/bin/sh" 9 minutes ago Up 9 minutes friendly_tereshkova

fd21e950935d mysql:5.7 "/bin/bash" 2 years ago Up 8 weeks tencenthealth

此处启动了两个容器。

查看当前的网络接口:

[root@VM_52_29_centos ~]# ip link show

1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT

link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00

2: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP mode DEFAULT qlen 1000

link/ether 52:54:00:bb:18:70 brd ff:ff:ff:ff:ff:ff

3: br-703d0323a265: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN mode DEFAULT

link/ether 02:42:80:e4:57:84 brd ff:ff:ff:ff:ff:ff

4: docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP mode DEFAULT

link/ether 02:42:40:84:e0:47 brd ff:ff:ff:ff:ff:ff

6: vethf077bca: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP mode DEFAULT

link/ether a2:72:5a:9a:24:60 brd ff:ff:ff:ff:ff:ff

226: vethbf84100: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP mode DEFAULT

link/ether 36:bf:28:65:73:86 brd ff:ff:ff:ff:ff:ff

可以看到新增了两个veth接口vethf077bcavethbf84100, 他们分别与两个容器中的eth0形成veth-pair。

再看网桥的连接

[root@VM_52_29_centos ~]# bridge link

6: vethf077bca state UP : <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 master docker0 state forwarding priority 32 cost 2

226: vethbf84100 state UP : <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 master docker0 state forwarding priority 32 cost 2

可以看到两个veth-pair在宿主机这一端都和docker0关联。

 

路由表与流量转发

bridge、namespace、虚拟网络接口、veth-pair都准备好后,流量如何转发呢,这就需要用到路由表了。

在分析路由表前,我们需要先看下各个虚拟网络接口关联的IP。
宿主机上的网络接口:

[root@VM_52_29_centos ~]# ifconfig

br-703d0323a265: flags=4099<UP,BROADCAST,MULTICAST> mtu 1500

inet 172.25.0.1 netmask 255.255.0.0 broadcast 172.25.255.255

ether 02:42:80:e4:57:84 txqueuelen 0 (Ethernet)

RX packets 0 bytes 0 (0.0 B)

RX errors 0 dropped 0 overruns 0 frame 0

TX packets 0 bytes 0 (0.0 B)

TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0

docker0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500

inet 192.168.10.1 netmask 255.255.255.0 broadcast 192.168.10.255

ether 02:42:40:84:e0:47 txqueuelen 0 (Ethernet)

RX packets 12788 bytes 588170 (574.3 KiB)

RX errors 0 dropped 0 overruns 0 frame 0

TX packets 42200 bytes 59457226 (56.7 MiB)

TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0

eth1: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500

inet 9.134.52.29 netmask 255.255.252.0 broadcast 9.134.55.255

ether 52:54:00:bb:18:70 txqueuelen 1000 (Ethernet)

RX packets 22843799 bytes 4344974378 (4.0 GiB)

RX errors 0 dropped 0 overruns 0 frame 0

TX packets 23575652 bytes 5537180006 (5.1 GiB)

TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0

lo: flags=73<UP,LOOPBACK,RUNNING> mtu 65536

inet 127.0.0.1 netmask 255.0.0.0

loop txqueuelen 0 (Local Loopback)

RX packets 4483879 bytes 3456236895 (3.2 GiB)

RX errors 0 dropped 0 overruns 0 frame 0

TX packets 4483879 bytes 3456236895 (3.2 GiB)

TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0

vethbf84100: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500

ether 36:bf:28:65:73:86 txqueuelen 0 (Ethernet)

RX packets 0 bytes 0 (0.0 B)

RX errors 0 dropped 0 overruns 0 frame 0

TX packets 0 bytes 0 (0.0 B)

TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0

vethf077bca: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500

ether a2:72:5a:9a:24:60 txqueuelen 0 (Ethernet)

RX packets 0 bytes 0 (0.0 B)

RX errors 0 dropped 0 overruns 0 frame 0

TX packets 92 bytes 4094 (3.9 KiB)

TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0

可以看到,宿主机自身的网络接口lo、eth0分别绑定了IP:127.0.0.1, 9.134.52.29.
网桥Docker0也绑定了IP: 192.168.10.1。
而veth设备vethbf84100、vethf077bca并没有IP,因为他们并不与外界直接通信,而是通过Docker0来转发流量。Docker0与vethbf84100、vethf077bca流量互通。

容器中的网络接口:

[root@VM_52_29_centos ~]# docker exec -it fd21e950935d /bin/bash

eth1: error fetching interface information: Device not found

[root@fd21e950935d /]# ifconfig

eth0 Link encap:Ethernet HWaddr 02:42:C0:A8:0A:02

inet addr:192.168.10.2 Bcast:192.168.10.255 Mask:255.255.255.0

UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1

RX packets:92 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:4094 (3.9 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:0

RX bytes:0 (0.0 b) TX bytes:0 (0.0 b)

[root@fd21e950935d /]#

可以看到容器中的eth0与宿主机的docker0在同一个网段。

接下来看下路由表
宿主机上的路由表:

[root@VM_52_29_centos ~]# route -n

Kernel IP routing table

Destination Gateway Genmask Flags Metric Ref Use Iface

0.0.0.0 9.134.52.1 0.0.0.0 UG 0 0 0 eth1

9.0.0.0 9.134.52.1 255.0.0.0 UG 0 0 0 eth1

9.134.52.0 0.0.0.0 255.255.252.0 U 0 0 0 eth1

10.0.0.0 9.134.52.1 255.0.0.0 UG 0 0 0 eth1

100.64.0.0 9.134.52.1 255.192.0.0 UG 0 0 0 eth1

169.254.0.0 0.0.0.0 255.255.0.0 U 1002 0 0 eth1

172.16.0.0 9.134.52.1 255.240.0.0 UG 0 0 0 eth1

172.25.0.0 0.0.0.0 255.255.0.0 U 0 0 0 br-703d0323a265

192.168.0.0 9.134.52.1 255.255.0.0 UG 0 0 0 eth1

192.168.10.0 0.0.0.0 255.255.255.0 U 0 0 0 docker0

[root@VM_52_29_centos ~]#

当docker0上的包,目的地址不是192.168.10.0/24时,表示目的地址在相同网段,不需要经过网关,Flags=U(不含G)。
其他网络接口上的包按普通流程处理。

在看下容器内的路由表:

[root@fd21e950935d /]# route -n

Kernel IP routing table

Destination Gateway Genmask Flags Metric Ref Use Iface

0.0.0.0 192.168.10.1 0.0.0.0 UG 0 0 0 eth0

192.168.10.0 0.0.0.0 255.255.255.0 U 0 0 0 eth0

[root@fd21e950935d /]#

当目的地址为192.168.10.0/24时,目的地址在相同网段,不需要经过网关。Flags=U(不含G)
当目的地址为其他地址时,流量转发需要经过网关,Flags=UG。

参考文章

Networking overview

理解 Linux 网络栈(1):Linux 网络协议栈简单总结

linux 路由表设置 之 route 指令详解

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
Docker网络原理是Docker容器之间以及容器和主机之间进行通信的基础Docker使用了一种称为"docker0"的虚拟网络桥接器来实现容器网络连接。 当你在主机上启动Docker容器时,Docker会为每个容器创建一个虚拟网卡,并将这些虚拟网卡连接到"docker0"桥接器上。"docker0"桥接器是一个虚拟以太网桥,它充当了主机与容器之间的交换机。 每个容器都有一个唯一的IP地址,由Docker引擎自动分配。这个IP地址是在Docker守护进程启动时从私有IP地址段中动态分配的。容器通过这个IP地址与其他容器或主机进行通信。 此外,Docker还提供了多种网络驱动程序来扩展网络功能,例如: 1. 桥接网络驱动程序(Bridge):这是Docker默认的网络驱动程序。它使用"docker0"桥接器,将容器连接到主机上的网络。 2. 主机网络驱动程序(Host):使用主机网络驱动程序时,容器将直接使用主机的网络栈,与主机共享IP地址。 3. Overlay网络驱动程序(Overlay):Overlay网络允许在跨多个Docker主机上创建多个容器,并通过虚拟网络进行通信。 4. MACVLAN网络驱动程序(MACVLAN):MACVLAN网络允许每个容器使用主机上的物理网络接口的MAC地址,使容器看起来像是直接连接到物理网络上。 这些网络驱动程序可以根据需要进行配置和使用,以满足特定的网络需求。总之,Docker网络原理通过虚拟网络桥接器和网络驱动程序的组合,实现容器之间和容器与主机之间的网络通信。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值