Docker 的网络实现其实就是利用了 Linux 上的网络名字空间和虚拟网络设备(特别是 veth pair)。
Windows上查看IP地址是ipconfig, Linux上是ifconfig,但是Linux上还有一个命令叫 ip addr 可以查看IP地址。
ip addr除了 IP 地址,还可以查看网卡信息,
使用 ip addr 命令查看本机(阿里云Centos7)网卡信息:
可以看到机器执行 ip addr 命令后显示了三个网卡,lo,etho 和 docker0。
1、lo(loopback):是回环地址,经常被分配到127.0.0.1地址上,用于本机通信,经过内核处理后直接返回,不会在任何网络中出现。
2、eth0:主机网卡名,指阿里云Centos7内网地址,172.25.48.117,如果有多块网卡,会有多个eth (eth1,eth2)或其它名称
link/ether:MAC地址,是网卡的物理地址,唯一的,一块网卡一个MAC。
inet:IPV4地址,一块网卡可以绑定多个IPV4地址。
3、docker0:docker的网络接口(网桥),172.17.0.1,容器通过docker0网桥与本地主机或其他容器进行网络通信
veth是 Linux 中一种虚拟的网络设备,veth设备总是成对出现,所以一般也叫 veth-pair。
veth-pair中的两个 veth设备一端连着协议栈,一端彼此相连着。
veth的两端都直接连着网络协议栈,所以创建一个 veth-pair,主机上就会多2个网卡。
veth-pair 中一个设备收到协议栈的数据发送请求后,会将数据发送到另一个设备上去。
如果v-a和v-b是一对 veth 设备,v-a收到的数据会从v-b发出。相反,v-b收到的数据会从v-a发出。其实说白了,Veth就是一根“网线”,你从网线一端发数据,当然就从另一端收到数据了。网线的作用不就是这个么,veth也一样,把数据通过一端“复制”到另一端。
veth-pair常常充当着一个桥梁,连接着各种虚拟网络设备,典型的例子像“两个 namespace 之间的连接。
名字空间是 Linux 内核一个强大的特性。每个容器都有自己单独的名字空间,运行在其中的应用都像是在独立的操作系统中运行一样。名字空间保证了容器之间彼此互不影响。
namespace 是 Linux 2.6.x 内核版本之后支持的特性,主要用于资源的隔离。有了 namespace,一个 Linux 系统就可以抽象出多个网络子系统,各子系统间都有自己的网络设备,协议栈等,彼此之间互不影响。
如果各个 namespace 之间需要通信,怎么办呢,答案就是用 veth-pair 来做桥梁。
根据连接的方式和规模,可以分为“直接相连”,“bridge模式相连” 和 “通过 OVS 相连”。
bridge模式:docker默认的网络模式,为容器创建独立的网络命名空间,容器具有独立的网卡等所有单独的网络栈,是最常用的使用方式。
bridge是docker网络中最重要的一种网络模式。
两个 namespace 通过Bridge 相连模型图:
Docker 容器利用veth-pair这项技术,在本地主机和容器内分别创建一个虚拟接口,并让它们彼此连通。
Docker 创建一个容器的时候,会执行如下操作:
1、创建运行一个tomcat容器,取名为 tomcat01
docker run -d -P --name tomcat01 tomcat
2、查看容器内的网卡信息
docker exec -it tomcat01 ip addr
可以看到 tomcat01 容器的IPV4地址是 172.17.0.2
3、在主机上ping一下tomcat01,看本地能否ping通容器内部:
ping 172.17.0.2
可以看出是可以ping通容器内部。
4、查看本地主机和 tomcat01 容器的网卡:
容器内veth设备接口为 etho@if195,主机上的veth设备接口 veth6e6521b@if194
由于新创建了一个tomcat01容器,就会在linux本机产生一个网络命名空间,而且是成对出现,也就是容器里面还有一个接口和这个是一对进行连接的,上图两个蓝圈就是容器内的接口和主机上的接口,一个接口设备在容器内,另一个接口设备在本地主机上,并且主机上的接口桥接在docker0上。
证明:主机上的 veth6e6521b@if194 桥接在docker0上
1、先安装一个bridge-utils网桥工具包,在linux本机上执行以下命令
sudo yum install -y bridge-utils
在安装了bridge-utils工具后,我们就有了brctl的命令工具,
brctl 常规用法:
addbr 添加一个虚拟网桥
addif 为虚拟网桥添加物理端口
delbr 删除虚拟网桥,但是,在删除网桥的时候保证网桥是down的
delif 删除虚拟网桥上的一个物理接口
show 查看网桥的相关配置
stp 开启或关闭虚拟网桥的生成树功能
2、查看连docker0网桥上的设备
执行命令:
brctl show docker0
上图证明了接口veth6e6521b@if194是连接到了docker0这个网络上
因此,主机与容器之间的网络通信模型图可以参考:
bridge模式是docker默认的,也是开发者最常使用的网络模式。通过宿主机上的docker0网桥,容器可以与宿主机乃至外界进行网络通信。
在不指定网络模式的情况下,同一宿主机上,容器之间都是连接到docker0这个网桥上的,docker0可以作为虚拟交换机(或路由器)使容器可以相互通信。
容器与容器之间的网络通信模型图可以参考: