1 Docker原生网络
- Docker的镜像是最令人称道的地方,但是网络功能还是相对比较薄弱。
- Docker安装后会自动创建三种网络:bridge、host、none
docker network ls #查看docker网络
(1)Bridge模式
- bridge网络模式的示例:
docker在安装时会创建一个docker0的Linux Bridge,新建的容器会自动交接到这个接口
brctl show #查看当前主机上的网络桥接情况
docker run -d --name nginx nginx #创建一个名为nginx的容器
docker ps
brctl show #
ip addr show
注意:
我们可以发现在主机上运行一个容器后会增加一个网卡设备,并且桥接在docker0上,这个其实是一个虚拟网卡对,我们可以理解为它的一段桥接在docker0上,另一端连接在容器内的网络栈。
- Docker中bridge模式的详细分析
通过上面这个图,我们可以清晰的看到Docker中Bridge这种网络模式,所有的容器通过虚拟网络对,桥接到docker0上,然后通过Linux内核中的内核路由功能(即Linux内核相当于一个路由器),这样就能够与主机进行通信了。
-
Bridge模式的缺点:
- 容器没有一个公共的IP,只有在宿主机上能够查询到各个容器的IP,外部主机不但不能知道各个容器的IP,而且不能够知道docker0的IP,所以外部主机无法访问容器。
(2)host模式
host模式需要在创建容器时指定
docker run -d --network host nginx
brctl show
ip addr show
netstat -antlp
docker run --it --network host busybox
ip addr show #查看容器中的IP状况
总结:
- host模式可以说是bridge模式的一种补充,它弥补了bridge模式下,其他主机不能访问宿主机上创建的容器的短板。
- 但是host模式存在缺陷就是会消耗宿主机的资源,并且容器的网络缺少隔离性。
(3)none模式
- none模式是指禁用网络功能,只有lo,在容器创建时使用参数 --network none来进行指定。
docker run -it --network none busybox
ip addr show
- none模式用于创建集群中某些不需要IP的应用,比如加密应用等。
2 Docker自定义网络
-
Docker提供了三种自定义网络驱动:
- bridge
- overlay
- macvlan
-
我们可以使用命令 docker network create -d net-type name 来创建自定义网络
(1)bridge模式
- bridge驱动类似于默认的bridge网络模式,但是新增加了DNS解析功能
docker run -it --name demo busybox #使用默认的bridge来创建一个容器
ping demo #在容器内ping容器名称,看能否进行解析
docker network create -d bridge mynet1 #创建一个自定义网络模式bridge,名称为mynet1
docker network ls #查看当前docker中的网络模式
brctl show
ip addr
docker run -it --network mynet1 --name test busybox #通过自定义的网络模式创建一个名称为test的容器
ping test
- 还可以在创建自定义网络时指定,子网网段和网关等参数
docker network create -d bridge --subnet 192.168.1.0/24 --gateway 192.168.1.1 mynet2
ip addr
注意: 使用 --ip 参数可以指定容器的IP,但是必须是在自定义网桥上,默认的bridge模式不支持,同一网桥上的容器是可以互通的。
总结:
- 建议使用自定义的网络模型来创建容器,因为可以自动DNS解析容器名称到IP地址;
- 同样需要注意的是,使用相同的网络模型创建的容器相互之间可以进行通信,使用不同的网络模型创建的容器相互之间不能够进行通信(因为处于不同网段)。
docker network rm mynet1 #删除创建的自定义网络
(2)overlay、macvlan用于集群
- 创建跨主机网络,性能上macvlan更好用物理层链接,但overlay应用更广泛。
(3)如何使两个不同网桥的容器进行通信?
- 使用docker network connect命令为已经创建好的容器添加将要通信的容器的网卡
例如上图所示,vm1和vm3分别为两个容器,它们是通过不同的桥接来创建的,它们的容器IP不在一个网段,现在我们想让这两个容器能够进行通信,具体步骤就是,使用docker network connect 命令将容器vm1连接到my_net2上,相当于容器vm1具有双网卡,eth1桥接到了my_net2上,这样它就可以和创建在my_net2下的容器vm3进行通信了
docker network ls #查看当前docker中的网络
ip addr #查看两个桥接网络的子网网段
docker run -d --network mynet1 --name nginx nginx · #利用mynet1创建一个容器nginx
docker inspect nginx #查看nginx这个容器的IP地址
docker run -it --network mynet2 --name busyboxplus busyboxplus #利用mynet2创建一个容器busyboxplus
docker network connect mynet1 busyboxplus #让容器busyboxplus添加mynet1网络
3 Docker的容器通信
(1)DNS解析
-
容器之间除了使用IP通信外,还可以使用容器名称进行通信
- docker1.10开始,内嵌了一个DNS server
- DNS解析功能必须在自定义网络中使用
- 启动容器时使用 --name 参数来指定容器的名称
注:这个示例在文章前面自定义网络Bridge处已经做过
(2)Joined
- Joined容器一种较为特别的网络模式(类似于我们的host网络模式,只不过这里是共享已经运行的容器的网络)
- 在容器创建时使用 --network container:name指定(这里的name指的是运行的容器名称)
docker run -it --network container:busyboxplus --name busybox busybox
ip addr
- 处在这种模式下的Docker容器会共享一个网络栈,这样两个容器之间可以使用localhost高效快速通信
docker run -d --network mynet2 --name nginx nginx
docker inspect nginx
docker run -it --network container:nginx --name busyboxplus busyboxplus
ip addr
ping localhost:80
curl localhost:80
总结:这种Joined网络通信模式适用于一个业务中有多个容器,并且其中有两个容器有比较紧密的联系,那么就能够使用这种方式来进行容器的创建。
(3)link
-
link可以用来链接3两个容器
-
link的格式:
- –link< name or id >:alias
- name和id是源容器的name和id,alias是源容器的别名
-
link的作用是:当一个容器中的变量想被另外一个容器继承下来,那么就可以使用这种方式。
docker run -d --name vm1 nginx #创建一个名称为vm1的容器
docker exec -it vm1 bash #启动一个bash进入刚刚创建的容器vm1中
env #查看vm1容器中的变量
docker run -it --rm --link vm1:nginx busyboxplus #使用--link的方式连接到容器vm1,然后再创建爱你一个容器
env #查看新创建的容器中的变量
ping vm1
ping nginx
、
注意:这种使用–link创建的容器,它会带有解析功能,并且当源容器的IP发生变化后依旧能够进行解析;但是当源容器重新启动后获取到新的IP,其变量不会在当前容器中进行实时的更新,依旧是继承源容器第一次创建时的初始变量。
总结:在使用docker原生网络创建的容器中,如果想使用DNS解析功能,那么可以考虑使用–link这种方式来创建容器
(4)容器访问外网以及外部主机访问容器的过程分析
4 跨主机容器网络
-
跨主机网络通信方案
- Docker原生的overlay和macvlan
- 第三方的flannel、weave、calico
-
众多网络方案与Docker的集成
- CNM(Container Network Model)这个模型对容器网络进行了抽象
-
CNM分三类组件
- Sandbox:容器网络栈,包含容器接口、DNS、路由表
- Endpoint:作用是将Sandbox接入network(veth pair)
- Network:包含一组endpoint,同一network的endpoint可以通信
-
macvlan网络方案的实现:
- Linux kernel提供的一种网卡虚拟化技术;
- 无需Linux bridge,直接使用物理接口,性能极好。
-
搭建macvlan网络方案实验:
步骤一:在两台搭建好docker环境的主机上各添加一块网卡,并且打开网卡的混杂模式
ifup eth1
ip link set eth1 promisc on #添加混杂模式
步骤二:在两台docker主机上创建macvlan网络
docker network create -d macvlan --subnet 172.20.0.0/24 --gateway 172.20.0.1 -o parent=eth1 mynet1
docker network ls
步骤三:分别在两台docker主机上利用刚刚创建的自定义网络来创建一个容器,然后在新创建的容器内ping另外一台主机上创建的容器IP
#在server1上创建一个容器,指定其IP地址
docker run -it --name vm1 --rm --network mynet1 --ip 172.20.0.100 busyboxplus
ip addr show
#在server2上也创建一个容器,指定其IP地址
docker run -it --name vm2 --rm --network mynet1 --ip 172.20.0.200 busyboxplus
ip addr show
-
macvlan网络结构分析
- 没有新建Linux Bridge
- 容器借口直接与主机网卡相连,无需NAT或端口映射
- macvlan会独占主机网卡,但可以使用vlan子接口实现多macvlan网络
- vlan可以将物理二层网络划分为4094个逻辑网络,彼此隔离,vlan id 的取值为 1~4094
-
macvlan网络间的隔离和连通
- macvlan网络在二层上是隔离的,所以不同的macvlan网络的容器是不能通信的;
- 可以在三层上通过网关将macvlan网络连通起来;
- Docker本身不做任何限制,跟传统vlan网络那样管理。