Docker 网络详解

Posted 基层搬砖的Panda

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Docker 网络详解相关的知识,希望对你有一定的参考价值。

前置网络知识

OSI七层网络模型

从下到上依次为:物理层、数据链路层、网络层、传输层、会话层、表示层、应用层。

交换机:处在第二次,也就是数据链路层。作用:通过一个或者多个设备将不同子网连接在一起,相互通信;
路由器:处在网络层,实现信息的传送(简单描述:首先通过IP的网络地址定位到某个网络,期间可能经过多个网络,到达最终的网络后,再通过IP + 子网掩码 得到主机地址,用主机地址和PC的MAC地址映射关系找到最终的机器,再通过port定位到那个程序,对应的程序就能收到数据啦~)。每个路由器都有一张路由表,根据这张表寻找最终地址或者下一个转发的地址。

交换机

交换机工作于OSI参考模型的第二层,即数据链路层。交换机内部的CPU会在每个端口成功连接时,通过将MAC地址和端口对应,形成一张MAC表。在今后的通讯中,发往该MAC地址的数据包将仅送往其对应的端口,而不是所有的端口。

每个物理网卡对应一个唯一的MAC的地址(物理地址),这个地址是网卡在出场的时候就固定了的,保证不会重复。

交换机在同一时刻可进行多个端口对之间的数据传输。每一端口都可视为独立的物理网段(注:非IP网段),连接在其上的网络设备独自享有全部的带宽,无须同其他设备竞争使用。当节点A向节点D发送数据时,节点B可同时向节点C发送数据,而且这两个传输都享有网络的全部带宽,都有着自己的虚拟连接。假使这里使用的是10Mbps的以太网交换机,那么该交换机这时的总流通量就等于2×10Mbps=20Mbps。

总之,交换机是一种基于MAC地址识别,能完成封装转发数据帧功能的网络设备。

NAT(Network Address Translation)

NAT是指网络地址转换,1994年提出的。

当在专用网内部的一些主机本来已经分配到了本地IP地址(即仅在本专用网内使用的专用地址),但又想和因特网上的主机通信(并不需要加密)时,可使用NAT方法。这种通过使用少量的全球IP地址(公网IP地址)代表较多的私有IP地址的方式,将有助于减缓可用的IP地址空间的枯竭。

私有网络ip块

A 类:10.0.0.0~10.255.255.255
B 类:172.16.0.0~172.31.255.255
C 类:192.168.0.0~192.168.255.255

一、Docker网络命令

1.1 创建网络

docker network create net_name

1.2 删除网络

docker network rm net_name

1.3 查看网络列表

docker network ls

1.4 查看指定网络信息

docker network inspect net_name

1.5 连接一个容器到执行网络

docker network connect net_name container

1.6 将容器从指定网络断开

docker network disconnect

二、Docker网络连接

Docker默认提供了3种网络模式,生成容器时不指定网络模式下默认使用bridge桥接模式。
使用命令查看当前Docker所有的网络模式。

[root@VM-24-12-centos panda]# docker network ls
NETWORK ID     NAME         DRIVER    SCOPE
1837a1f4b464   bridge       bridge    local
b0363838038c   host         host      local
02040f0017d5   none         null      local
[root@VM-24-12-centos panda]#

2.1 bridge桥接

Docker默认的网络模式就是桥接,如果在启动容器时不使用–network 显式指定网络类型就会使用桥接模式。桥接,也叫网桥,指的是把物理网卡(eth0)当作交换机来用。

当Docker进程启动的时候,会在宿主机上创建一个docker0的虚拟网桥。每个启动的容器都会连接到这个网桥上。具体流程如下:容器在启动的时候,会从docker0子网中分配一个IP给容器(注意:该IP和物理网卡eth0不在同一个网段),同时将docker0的IP设置为容器的网关。接着,Docker会为该容器创建一对虚拟网卡设备veth pair,一个连接宿主机的docker0网桥,另一个连接该容器(veth0xxx)。

docker run -dit --name mynginx nginx
docker inspect mynginx

可以看到容器的IP地址为:172.17.0.3,网关:172.17.0.1(docker0的IP地址)

Linux内核支持两种级别的设备模拟(纯软件):(1)链路层(二层)设备:每个网卡是成对出现的。一端在主机,一端在交换机上,linux原生支持模拟二层网桥设备交换机(工具bridge-utils);(2)网络层(三层)设备,OVS(Open VSwith),软件驱动的软硬件集中到一个软件上,统一调度。

安装 bridge-utils 工具
yum install -y bridge-utils

2.2 NAT 网络地址转换协议

如图,假设同一局域网中的两个容器helloA 和 helloB要通信:helloA的报文会先交给docker0网桥,宿主机判断报文的目标地址不是自己,通过查路由表发现是和机器115的helloB容器通信,就会通过eth0将报文发送到115机器,115再查找自己的路由表找到helloB容器。

但此时110机器是收不到115机器的回复的,为什么呢?因为helloA容器的报文的源IP是172.17.0.2,这个地址是私有的,115机器是看不到的;如果想收到115机器的回复,就需要把报文的源IP地址在出eth0物理网卡时,修改成192.168.10.110。这样115机器的回复报文会找到110机器,再通过查路由表就能知道是helloA容器了。

上面两个容器时彼此看不到对方的,helloA以为在和192.168.10.115通信,helloB以为在和192.168.10.110通信。这样效率不高,但是方便管理。如果不想和桥接一样暴露在外面,又不想藏在宿主机后面,怎么办呢?叠加网络应用而生。

2.3 host 模型

host模式可以让容器共享宿主机网络栈,这样的好处是外部主机与容器直接通信,但是容器的网络缺少隔离性。

2.4 none网络

none模式是指禁用网络功能,只有lo接口,在容器创建时使用 --network none指定

2.5 自定义网络类型

自定义网络模式,docker提供了三种自定义网络驱动: bridge overlay macvlan。建议使用自定义的网络来控制哪些容器可以相互通信。

在微服务部署的场景下,注册中心是使用服务名来唯一识别微服务的,而我们上线部署的时候微服务对应的IP地址可能会改动,所以我们需要使用容器名来配置容器间的网络连接。使用自定义网络创建容器后,相同网络下的容器,不管是通过容器IP还是容器名,都可以进行网络通信:

docker network --help
docker network create --help

2.5.1 创建网络并指定子网

docker network create --subnet=172.28.0.0/16 net_test_2

2.5.2 创建网络并指定子网、网关及ip范围
docker network create --subnet=172.38.0.0/16 --gateway=172.38.5.254 --ip-range=172.38.5.0/24 net_test_3


每创建一个网络就会在路由表中添加一条静态路由信息。

route -n 查看路由表

案例1

以nginx为例,我们启动三个容器,都接入 net_test_2 网络

docker run -d --network net_test_2 nginx
docker run -d --network net_test_2 nginx
docker run -d --network net_test_2 nginx

docker network inspect net_test_2 

可以看到,net_test_2 接了三个容器。


将 容器determined_chatelet连接到 net_test_1 网络,在查看determined_chatelet的详细信息,可以看到该容器连接了两个网络。

docker network connect net_test_1 determined_chatelet

docker inspect determined_chatelet


断开网路再次查看

docker network disconnect net_test_1 determined_chatelet
docker network disconnect net_test_2 determined_chatelet

实际案例二

不同网络的容器是无法通信的。需要加入同一个网络才能通信,并且只能访问同一个网络下的那个ip。


可以看到容器 magical_bartik的网络是net_test_1, IP地址是 172.19.0.2

docker inspect magical_bartik


可以看到容器 determined_chatelet 的网络是net_test_2, IP地址是 172.28.0.4

docker inspect determined_chatelet


进入到 determined_chatelet 容器

docker exec -it determined_chatelet bash

curl http://172.28.0.4 
curl http://172.19.0.2 

将上面两个容器同时连接到net_test_3 网络

docker network connect net_test_3 magical_bartik
docker network connect net_test_3 determined_chatelet 

docker inspect magical_bartik

再次进入到 determined_chatelet 容器

以上是关于Docker 网络详解的主要内容,如果未能解决你的问题,请参考以下文章

kubernetes之Docker网络详解

docker网络详解

Docker网络原理详解02

docker swarm网络模式

Docker 网络详解

云原生Docker09-Docker网络详解