Docker网络解读

libnetwork

docker在1.9版本以后,引入了一套docker network子命令来管理docker网络。这容许用户能够根据他们应用的拓扑结构建立虚拟网络并将容器接入其所对应的网络。docker

具体来讲,docker网络是经过一个叫libnetwork的东西来进行管理的,用docker network命令对docker网络进行操做其实是与libnetwork Api进行交互。segmentfault

libnetwork内置有五种网络驱动,分别是:bridge驱动、host驱动、overlay驱动、remote驱动、null驱动。这些网络驱动为docker提供了多种网络模式。下面咱们简单说说各驱动的做用:网络

bridge驱动

bridge驱动即为一般说的桥接模式,此驱动为Docker的默认驱动,该驱动的做用为将Docker容器链接到docker默认建立的docker0网桥上面,若是未指定--network选项,建立的容器将默认指向docker0,该驱动即对应docker的bridge网络模式,经过NAT地址转换使容器和外界进行通讯。tcp

可以使用以下命令查看docker0网桥,该网桥会在docker安装后自动配置:性能

ip addr

图片描述

咱们能够看到默认的docker0网桥ip为172.17.0.1/16,在某些状况下假如咱们宿主机网段与docker0网段相同,咱们用bridge模式默认的docker0网桥会与宿主机产生网段冲突问题,这时候只须要更改docker0默认的网段或者使用docker容器的--network选项选择用户自定义的网桥便可解决。spa

host驱动

该驱动将docker容器与宿主机网络处于同一个network namespace下,docker容器将使用宿主机的网卡、ip和端口信息,故容器与外界不进行NAT地址转换,增长了网络性能,可是缺点是宿主机上已使用的端口docker容器不能再使用,该驱动对应docker的host网络模式。插件

overlay驱动

此驱动采用IETE标准的VXLAN方式,具体VXLAN实现方式这里暂不说明,该驱动主要用于建立容器的跨主机网络,对应docker的user-defined网络模式。code

remote驱动

这个驱动用于用户向libnetwork提供自定义的网络插件,并无实现任何网络功能。图片

null驱动

null驱动即为docker容器的none网络模式,该模式并为docker容器提供任何网络配置,只有docker容器自身的lo网卡,该模式通常用于一些特定的状况。ip

bridge网络模式的实现方式

咱们经常使用的docker网络模式通常都是bridge模式,下面咱们来分析docker是如何实现桥接网络的。

首先咱们能够经过以下命令查看docker0网关:

route -n

图片描述

从如上命令能够看出全部指向ip为172.17.0.0/16的数据包都从docker0网卡转发。

而后咱们用docker run命令启动一个容器名为demo,进入容器demo,一样用ip addr或ifconfig命令查看网卡,咱们能够看到以下两个网卡:
图片描述

lo网卡和eth0网卡。lo网卡即为容器自身的回环网卡,eth0网卡ip为172.17.0.3/16,和宿主机网卡docker0在同一网段,这时咱们用route -n命令查看demo容器的网关以下:
图片描述

能够看出demo的eth0网卡与宿主机的docker0网卡是相互连通的。

这时退出demo容器再来用ip addr查看宿主机的网络设备,会发现有一块以“veth”开头的网卡,如veth5653371,咱们能够猜想veth5653371与demo容器内的eth0网卡是一对veth设备(veth pair老是成对出现),veth设备的做用为用来链接两个不一样的network namespace,故docker0不是单纯的网卡而是网桥了,这就是docker的bridge网络模式的实现方式,经过链接docker0网桥来实现宿主机和容器的网络互通。

iptables规则实现端口映射

咱们知道了docker的bridge网络模式的网络互通方式,那么docker是如何实现宿主机和容器的端口映射的呢?这一切都靠配置iptables规则来实现,具体表现以下:

Docker安装完成后,将默认在宿主机系统上增长一些iptables规则,用iptables-save命令查看如下规则:

-A POSTROUTING -s 172.17.0.0/16 ! -o docker0 -j MASQUERADE

上面这条规则关系着Docker容器和外界的通讯,含义是:将源地址为172.17.0.0/16的数据包(即Docker容器发出的数据),当不是从docker0网卡发出时作SNAT。这样docker容器访问外部的流量会认为是宿主机发出的。

同理,docker容器和宿主机的端口映射也是经过iptalbes映射来实现的,假设咱们启动一个容器将其端口8080映射到宿主机端口8080上,咱们能够看到以下规则:

-A POSTROUTING -s 172.17.0.3/16 -d 172.17.0.3/16 -p tcp -m tcp --dport 8080 -j MASQUERADE
-A DOCKER -d 172.17.0.3/16 ! -i docker0 -o docker0 -p tcp -m tcp --dport 8080 -j ACCEPT

该规则将访问宿主机8080端口的流量转发到172.17.0.3/16(即demo容器的etho网卡)上,因此docker是经过配置iptalbes规则来实现端口映射的。

不一样宿主机容器网络互通

到目前为止,咱们所讲的docker网络环境仅仅是对单机而言的,要实现不一样宿主机的网络互一般常有多种方式,我这里选用的是flannel来实现不一样宿主机容器的网络互通,这也是kubernetes实现网络互通的方式,要想知道flannel是如何实现网络互通的,请查看个人下一篇博文:flannel解读

相关文章
相关标签/搜索