Docker网络

Posted 键盘歌唱家

tags:

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

一、简介

从其架构和运行流程来看,Docker是一个C/S模式的架构,后端是一个松耦合架构,众多模块各司其职。
docker运行的基本流程为:

1.用户是使用Docker Client和Docker Daemon建立通信,并发送请求给后者。
2.Docker Daemon作为docker架构中的主体部分,首先提供docker server的功能使其可以接受docker client的请求。
3.docker engine执行docker内部的一系列工作,每一项工作都是以一个Job的形式存在。
4.Job的运行过程中,当需要容器镜像时,则从docker registry中下载镜像,并通过镜像管理驱动Graph driver将下载的镜像以Graph的形式存储。
5.当需要为docker创建网络环境时,通过网络管理驱动Network driver创建并配置Docker容器网络环境
6.当需要限制docker容器运行资源或执行用户指令等操作时,则通过ExecDriver来完成。
7.LibContainer是一项独立的容器管理包,Network driver以及Exec Driver都是通过LibContainer来实现具体对容器进行的操作。

docker网络完全可以参考VM虚拟机的网络配置:

二、细节点和基本命令

docker启动后,发现虚拟机产生了一个docker0的虚拟网卡!

基本命令:

# 查看当前docker的所有网络
docker network ls
#创建网络
docker network create 网络名
# 删除网络
docker network rm 网络名
# 查看网络源数据
docker network inspect 网络名
# 帮助
docker network --help

三、网络模式



可以通过下面的案例来证明容器restar之后,ip是可能发生变化的:

docker run -it --name u1 ubuntu bash
docker run -it --name u2 ubuntu bash

# 发现 u2 ip是172.17.0.3
docker inspect u2 

#模拟u2宕机
docker stop u2
docker run -it --name u3 ubuntu bash
# 发现新启动的 u3 ip是172.17.0.3 占用了之前u2的ip
docker inspect u2 

3 .1brige模式

Docker服务默认会创建一个docker0的网桥(其上有个docker0内部和接口),该乔接网络的名称为docker0,它在内核层链接了其他物理或虚拟网卡,这就将所有容器和本地主机都放到同一个物理网络。Docker默认指定了docker0接口的IP地址和子网掩码,让主机和容器之间可以通过网桥相互通信。

1.整个宿主机的网桥模式都是docker0,类似一个交换机有一堆接口,每个接口都叫veth,在本地主机和容器内分别创建一个虚拟接口,并让他们彼此联通(这样一对接口叫做veth pair)
2.每个容器实例内部也有一块网卡,每个接口都叫eth0
3.docker0上面的每个veth匹配某个容器实例内部的eth0,两两配对,一一匹配。


veth pair的案例:

3.2Host模式

容器不会获得一个独立的Network Namespace,而是和宿主机共用一个Network Namespace,容器将不会虚拟出自己的网卡,而是用虚拟机的IP和端口。

比如下面的警告的意思是:docker启动指定了使用host模式,通过-p设置的参数将不会起到任何作用,端口会以主机端口号为主,重复则递增。

3.3None

在none模式下,并不为容器进行任何网络配置,也就是说这个容器没有网卡、IP、路由信息,只有一个lo,需要我们自己为docker容器添加网卡、配置IP等。
使用docker inspect none模式启动的容器,可以发现该容器是没有网关和IP信息的

并且只有lo这个网卡,显示着127.0.0.1这个本地回环地址

3.4Container

新建的容器和已经存在的一个容器共享一个网络Ip配置而不是和宿主机共享。新建立的容器不会创建自己的网卡,配置自己的ip,而是和一个指定的容器共享IP、端口范围等。同样,两个容器除了网络方面,其他的如文件系统、进程列表等还是隔离的。

下面的错误就是因为两个容器公用同一个ip同一个端口导致冲突了。

可以用下面的这个小巧但五脏俱全的linux镜像进行演示:

docker run -it --name alpine1 alpine /bin/sh
docker run -it --network container:alpine1 --name alpine1 alpine /bin/sh

3.5自定义网络

自定义网络的优势是解决默认brige模式由于容器宕机导致的ip变化的问题。因为在同一个自定义网络中的容器可以将容器名当作IP来访问彼此,下面是说明案例:

#启动测试容器
docker network create test
docker run -d -p 8081:8080 --network test --name tom1 billtgoo/tomcat8-jdk8
docker run -d -p 8082:8080 --network test --name tom1 billtgoo/tomcat8-jdk8

#测试命令
docker exec -it tom1 /bin/bash
# 在tom1容器中直接ping tom2
ping tom2

docker容器网络

参考技术A 利用Net Namespace可以为Docker容器创建隔离的网络环境,容器具有完全独立的网络栈,与宿主机隔离。也可以使Docker容器共享主机或者其他容器的网络命名空间,基本可以满足开发者在各种场景下的需要。

Docker支持 4种网络模式 :

1)host模式,--net=host指定,不支持多主机。

2)container模式,--net = container : name_or_id指定,不支持多主机。

3)none模式,--net=none指定,不支持多主机。

4)bridge模式,--net=bridge指定,默认设置,不支持多主机。

启动容器的时候使用Host模式,那么该容器与宿主机共用一个Network Namespace,因此容器将不会虚拟自己的网卡、配置自己的IP等,而是使用宿主机的IP和端口。

采用Host模式的容器,可以直接使用宿主机的IP地址与外界进行通信,无需额外进行NAT转换。由于容器通信时,不再需要通过Linux Bridge等方式转发或者数据包的拆封,性能上有很大优势。当然, Host模式有利也有弊 ,主要包括以下缺点:

1)容器没有隔离、独立的网络栈。容器因与宿主机共用网络栈而争抢网络资源,并且容器崩溃也可能导致宿主机崩溃,这在生产环境中是不允许发生的。

2)容器不再拥有所有的端口资源,因为一些端口已经被宿主机服务、Bridge模式的容器端口绑定等其他服务占用了。

需要补充说明的是,Host模式下的容器仅仅是网络命名空间与主机相同,但容器的文件系统、进程列表等还是和与宿主机隔离的。

Container模式是一种特殊的网络模式。该模式下的容器使用其他容器的网络命名空间,网络隔离性会处于Bridge模式与Host模式之间。当容器与其他容器共享网络命名空间时,这两个容器间不存在网络隔离,但它们与宿主机及其他容器又存在网络隔离。

在Kubernetes体系架构下引入Pod概念,Kubernetes为Pod创建一个基础设施容器, 同一Pod下的其他容器都以Container模式 共享这个基础设施容器的网络命名空间,相互之间以localhost访问,构成一个统一的整体。

与前两种不同,None模式的Docker容器拥有自己的Network Namespace,但并不为Docker容器进行网络配置。该Docker容器没有网卡、IP、路由等信息。需要用户为Docker容器添加网卡、配置IP等。

Bridge模式是Docker默认的网络模式,也是开发者最常使用的网络模式。在这种模式下,Docker为容器创建独立的网络栈,保证容器内的进程使用独立的网络环境,实现容器之间、容器与宿主机之间的网络栈隔离。同时,通过宿主机上的Docker0网桥,容器可以与宿主机乃至外界进行网络通信。

同一宿主机上,容器之间都是连接在Docker0这个网桥上,Docker0作为虚拟交换机使容器间相互通信 。但是, 由于宿主机的IP地址与容器veth pair的IP地址均不在同一个网段 ,故仅仅依靠 veth pair和NameSpace的技术 并不足以使宿主机以外的网络主动发现容器的存在。Docker采用了 端口绑定的方式(通过iptables的NAT) ,将宿主机上的端口流量转发到容器内的端口上,这样一来,外界就可以与容器中的进程进行通信。 iptables的介绍,请点我点我 。

创建容器,并将宿主机的3306端口绑定到容器的3306端口:docker run -tid --name db -p 3306:3306 mysql

在宿主机上,可以通过“iptables -t nat -L -n”,查到一条DNAT规则:DNAT tcp --0.0.0.0/0 0.0.0.0/0 tcp dpt:3306 to:172.17.0.5:3306

Bridge模式的容器与外界通信时,必定会占用宿主机上的端口,从而与宿主机竞争端口资源,这会造成对宿主机端口管理很复杂。同时,由于容器与外界通信是基于三层上iptables NAT,性能和效率损耗是显而易见的。

NAT将地址空间分段的做法引入了额外的复杂度。比如容器中应用所见的IP并不是对外暴露的IP, 因为网络隔离,容器中的应用实际上只能检测到容器的IP,但是需要对外宣称的则是宿主机的IP,这种信息的不对称将带来诸如破坏自注册机制等问题 。

摘抄自陆平的《基于Kubernetes的容器云平台实战》一书的第10章Kubernetes网络

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

容器化工具--------Docker的网络操作

容器化工具--------Docker的网络操作

Docker网络

云原生Docker09-Docker网络详解

docker — 容器网络

docker网络技术剖析