1. docker网络
1.1 为什么要讲docker网络
要实现网络通信,机器需要至少一个网络接口(物理接口或虚拟接口)来收发数据包。如果不同子网之间要进行通信,需要路由机制。
Docker 中的网络接口默认都是虚拟接口,容器之间通过network namespace隔离,要实现容器与容器之间以及容器和外部网络打通,需要了解docker网络基本原理。
1.2 docker网络
安装好docker后,docker daemon会自动创建3个网络,如下:
[root@VM-16-3-centos ~]# docker network ls
NETWORK ID NAME DRIVER SCOPE
ea9575d62821 bridge bridge local
9f41557d1095 host host local
2a69923860ba none null local
docker 支持4中网络模式,分别是bridge, host, container和none。下面会一一介绍到。
1.2.1 什么是docker0网桥
docker启动后,会创建一个叫docker0的网络设备。它会在挂载到它的网口之间进行转发。同时,Docker 随机分配一个本地未占用的私有网段中的一个地址给 docker0
接口,此后启动的容器内的网口也会自动分配一个同一网段(172.17.0.0/16
)的地址。
[root@VM-16-3-centos ~]# ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
link/ether 52:54:00:03:49:e8 brd ff:ff:ff:ff:ff:ff
inet 10.0.16.3/22 brd 10.0.19.255 scope global eth0
valid_lft forever preferred_lft forever
inet6 fe80::5054:ff:fe03:49e8/64 scope link
valid_lft forever preferred_lft forever
3: br-92683e3909ef: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default
link/ether 02:42:89:79:e2:58 brd ff:ff:ff:ff:ff:ff
inet 172.18.0.1/16 brd 172.18.255.255 scope global br-92683e3909ef
valid_lft forever preferred_lft forever
4: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default
link/ether 02:42:c7:e4:6e:2e brd ff:ff:ff:ff:ff:ff
inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
valid_lft forever preferred_lft forever
docker0功效就像是一台虚拟交换机,负责交换不同网络的报文信息。
1.2.2 什么是veth pair
veth pair的全称是virtual ethernet,就是虚拟的以太网卡。veth pair是成对出现的一种虚拟网络设备接口,一端连着网络协议栈,一端彼此相连。如下图所:
创建一个 Docker 容器的时候,同时会创建了一对 veth pair
接口(当数据包发送到一个接口时,另外一个接口也可以收到相同的数据包)。这对接口一端在容器内,即 eth0
;另一端在本地并被挂载到 docker0
网桥,名称以 veth
开头。通过这种方式,主机可以跟容器通信,容器之间也可以相互通信。
1.2.3 容器网路互通原理
回顾一下主机之间数据包发送过程。
a向b发数据的前提:首先a需要b的ip地址(不讨论域名解析情况);其次,除非a和b在同一个局域网,否则a并不是直接向b发数据,而是向a的网关发数据。最后,a一定知道它自己的网关ip,因为是你自己设置的(或者dhcp自动分配的)
-
1)主机A首先在本局域网中广播发送一个ARP请求分组,其内容可以形象描述为:“我的IP地址是A,硬件地址是a,我想知道IP地址为B的主机硬件地址”。本局域网中的所有运行ARP的主机都会收到该ARP请求分组。
-
2)主机B收到该ARP请求分组后,发现其中询问的IP地址与自己的IP地址一致,则收下该分组,并且将主机A的硬件地址和IP地址信息写入自己的ARP高速缓存中,其他主机发现与ARP请求分组中询问的IP地址与自己收下的IP地址不一致,则丢弃该分组。
-
3)主机B收下ARP分组请求分组后,创建一个ARP响应分组,并将自己的硬件地址写入该响应分组。然后将这个分组直接发送给主机A;
-
4)主机A收到主机B的ARP响应分组后,将其中所携带的主机B的硬件地址写入ARP高速缓存中的地址映射表
所以docker网络中,会通过docker0网桥做路由寻址。
1.3 docker网络4中类型
可以在 docker run
的时候通过 --net
参数来指定容器的网络配置,有 4 个可选值:
--net=bridge
,这个是默认值,连接到默认的网桥。--net=host,
告诉 Docker 不要将容器网络放到隔离的命名空间中,容器的网络配置与 host 完全一样,其实容器共用主机的namespace。- 使用 host 网络好处就是性能,如果容器对网络传输效率有较高要求,则可以选择 host 网络。
- Docker host 的另一个用途是让容器可以直接配置 host 网路。比如某些跨 host 的网络解决方案,其本身也是以容器方式运行的,这些方案需要对网络进行配置,比如管理 iptables
- 不足之处就是:容器隔离性弱化,没有独立的网络栈。容器与主机竞争网络资源,比如要考虑端口冲突问题,Docker host 上已经使用的端口及其他容器映射到主机的端口,容器就不能再用了。
--net=container:NAME_or_ID
让 Docker 将新建容器的进程放到一个已存在容器的网络栈中,新容器进程有自己的文件系统、进程列表和资源限制,但会和已存在的容器共享 IP 地址和端口等网络资源,两者进程可以直接通过lo
环回接口通信。--net=none
让 Docker 将新容器放到隔离的网络栈中,但是不进行网络配置。之后,用户可以自己进行配置。
默认情况下,容器可以主动访问到外部网络的连接,但是外部网络无法访问到容器。想要允许外部访问容器,可以在 docker run
时候通过 -p
或 -P
参数来启用(可以多次使用 -p
标记来绑定多个端口)。
1.4 docker容器的CNI模型和CNM模型
1.4.1 CNI
Container Networking Interface(CNI)提供了一种linux的应用容器的插件化网络解决方案。CNI本身并不完全针对docker的容器,而是提供一种普适的容器网络解决方案。CNI模型涉及两个概念:
- 容器(container) : 容器是拥有独立linux网络命名空间的独立单元。比如rkt/docker创建出来的容器。
- 网络(network): 网络指代了可以相互联系的一组实体。这些实体拥有各自独立唯一的ip。这些实体可以是容器,是物理机,或者其他网络设备(比如路由器)等。
CNI的接口设计的非常简洁,只有两个接口ADD/DELETE。
1.4.2 CNM
CNM是docker公司力推的网络模型,
docker的CNM网络模型中三个部分,分别为:
- sandbox:
- 容器的网络栈,包括对容器接口、路由表以及DNS配置的管理。
- 一个sandbox可能包含多个endpoint。
- 简单来说就是linux的namespace
- endpoint:
- 一端属于网络一端属于sandbox
- 简单来说就是veth pair
- network:
- 一组能够相互通信的endpoint组成
- 可以通过linux bridge或者vxlan实现
CNM的接口相较于CNI模型更为复杂,但并非是完全不可调和的两个模型,二者可以进行转化。比如calico项目就是直接支持两种接口模型。
参考连接:
https://blog.csdn.net/gamer_gyt/article/details/54861970
https://blog.csdn.net/ANXIN997483092/article/details/81319146