Docker 一篇文章总结Docker的网络模式

Docker网络现状


为了解决容器网络性能低下、功能不足的问题,Docker启动了子项目“Libnetwork”。Libnetwork提出了新的容器网络模型(Container Network Model,简称CNM),定义了标准的API用于为容器配置网络,其底层可以适配各种网络驱动(如图Docker-network01所示)。CNM有三个:

  • 沙盒
    沙盒是一个隔离的网络运行环境,保存了容器网络栈的配置,包括了对网络接口、路由表和DNS配置的管理。在Linux平台上,沙盒是用Linux Network Namespace实现的,在其他平台上可能是不同的概念,如FreeBSD Jail。一个沙盒可以包括来自多个网络的多个Endpoint(端点)。

  • Endpoint
    Endpoint将沙盒加入一个网络,Endpoint的实现可以是一对veth pair或者OVS内部端口,当前的Libnetwork使用的是veth pair。一个Endpoint只能隶属于一个沙盒及一个网络。通过给沙盒增加多个Endpoint可以将一个沙盒加入多个网络。

  • 网络
    网络包括一组能互相通信的Endpoint。网络的实现可以是Linux bridge、vlan等。图Docker-network01 CNM概念模型

从CNM的概念角度讲,Libnetwork的出现使得Docker具备了跨主机多子网的能力,同一个子网内的不同容器可以运行在不同主机上。比如,同属于192.168.0.0/24子网IP地址分别为192.168.0.1和192.168.0.2的容器可以位于不同的主机上且可以直接通信,而持有IP 192.168.1.1的容器即使与IP为192.168.0.1的容器处于同一主机也不能互通。

Libnetwork已经实现了五种驱动(driver):

  • bridge
    Docker默认的容器网络驱动。Container通过一对veth pair连接到docker0网桥上,由Docker为容器动态分配IP及配置路由、防火墙规则等。

  • host
    容器与主机共享同一Network Namespace,共享同一套网络协议栈、路由表及iptables规则等。容器与主机看到的是相同的网络视图。

  • null
    容器内网络配置为空,需要用户手动为容器配置网络接口及路由等。

  • remote
    Docker网络插件的实现。Remote driver使得Libnetwork可以通过HTTP RESTful API对接第三方的网络方案,类似SocketPlane的SDN方案只要实现了约定的HTTP URL处理函数及底层的网络接口配置方法,就可以替换Docker原生的网络实现。

  • overlay
    Docker原生的跨主机多子网网络方案。主要通过使用Linux bridge和vxlan隧道实现,底层通过类似于etcd或consul的KV存储系统实现多机的信息同步。overlay驱动当前还未正式发布,但开发者可以通过编译实验版的Docker来尝试使用,Docker实验版同时提供了额外的network和service子命令来进行更灵活的网络操作,不过,需要内核版本>=3.16才可正常使用。

以上五种驱动已经随Docker 1.8一同发布。Docker的网络模块是可插拔式的,默认有五种网络模式可以选择,通过docker network ls这个命令来查看本机中所有的网络模式。 

[root@VM_0_14_centos ~]# docker network lsNETWORK ID          NAME                DRIVER              SCOPEc79756cf9cde        bridge              bridge              local204025a5abbc        host                host                local9b9024f5ac40        macvlan             macvlan             local6478888548d8        none                null                localp2e02u1zhn8x        overlay             overlay             swarm

bridge


Docker daemon启动时会在主机创建一个Linux网桥(默认为docker0,可通过-b参数手动指定)。容器启动时,Docker会创建一对veth pair(虚拟网络接口)设备,veth设备的特点是成对存在,从一端进入的数据会同时出现在另一端。Docker会将一端挂载到docker0网桥上,另一端放入容器的Network Namespace内,从而实现容器与主机通信的目的。bridge模式下的网络拓扑图如图docker-network02所示:

                                 图Docker-network02 bridge模式的网络拓扑图

在桥接模式下,Docker容器与Internet的通信,以及不同容器之间的通信,都是通过iptables规则控制的。总之,Docker网络的初始化动作包括:创建docker0网桥、为docker0网桥新建子网及路由、创建相应的iptables规则等。Bridge模式是Docker默认的容器运行模式,以bridge模式启动的容器,默认会从172.17.42.1/16子网内分配IP。

bridge模式是docker的默认网络模式,此模式会为每一个容器设置network namespace、ip地址等,在docker启动时候,就会在主机上创建一个名为docker0的虚拟网桥,在该主机上启动的docker容器都会连接到这个虚拟网桥上,这样就可以和同一宿主机上桥接模式的其它容器进行通信啦。

#运行一个名为box1的busybox容器,网络模式是bridge[root@VM_0_14_centos ~]# docker run -itd --name box1 busybox
24d88c0b3af9df06c367e9991c7628a2eaeb54e4f40a5326585fcf1274ea2f8f[root@VM_0_14_centos ~]# docker exec -it box1 sh
/ # ip addr show eth0
68: eth0@if69: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue
link/ether 02:42:ac:12:00:02 brd ff:ff:ff:ff:ff:ff
inet 172.18.0.2/16 brd 172.18.255.255 scope global eth0
valid_lft forever preferred_lft forever
#运行一个名为box2的busybox容器,网络模式是bridge       [root@VM_0_14_centos ~]# docker run -itd --name box2 busybox
f3980be667731ae36aa567910f4a7e80fcc877c33dec59b70f7dc6e49f8fe3f2[root@VM_0_14_centos ~]# docker exec -it box2 sh
/ # ping 172.18.0.2
PING 172.18.0.2 (172.18.0.2): 56 data bytes
64 bytes from 172.18.0.2: seq=0 ttl=64 time=0.146 ms
64 bytes from 172.18.0.2: seq=1 ttl=64 time=0.120 ms
...

从上面的示例可以看出,同一节点下的容器默认都是可以彼此交流哒~

       

host


host模式下,容器不会设置自己的network namespace、ip等,而是和宿主机共用,通过--network host可以将容器直接绑定在Docker主机的网络,没有网络隔离,但是其它方面,比如文件系统、进程列表还是与宿主机隔离的。外界也可以直接访问容器。

#运行一个名为box3的busybox容器,网络模式是host[root@VM_0_14_centos ~]# docker run -itd --network host --name box3 busybox

 

none


使用的none模式后,这个容器就是封闭的,不会去参与网络通信,这样就能够保证容器的安全性。

#启动一个名为box3的busybox容器,网络模式是none
[root@VM_0_14_centos ~]# docker run -itd --network none --name box3 busybox
f431bffbd88712f940aee745d7a1e6795f3ef545f79bb2151628f9198c9b1c1e[root@VM_0_14_centos ~]# docker exec -it box3 sh
/ # ifconfig
lo        Link encap:Local Loopback
          inet addr:127.0.0.1  Mask:255.0.0.0
          UP LOOPBACK RUNNING  MTU:65536  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)

 

macvlan


对于某一些应用程序,比如需要监视网络流量,期望直接连接到物理网络,这种情况下,可以使用macvlan的网络模式,docker会为容器的虚拟网络接口分配MAC地址。

创建一个macvlan网络


$ docker network create -d macvlan --subnet=172.16.86.0/24 --gateway=172.16.86.1 -o parent=eth0 macvlann

启动一个busybox容器,网络模式是macvlan

[root@VM_0_14_centos ~]# docker run -itd --network macvlann --name box busybox
77436b9c2c1638c498396ff765c27ffec885ff62d892c2064f41497460037156
[root@VM_0_14_centos ~]# docker exec box ip addr show eth0
67: eth0@if2: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue
    link/ether 02:42:ac:10:56:03 brd ff:ff:ff:ff:ff:ff
    inet 172.16.86.3/24 brd 172.16.86.255 scope global eth0
    valid_lft forever preferred_lft forever
[root@VM_0_14_centos ~]# docker exec box ip route\
default via 172.16.86.1 dev eth0
172.16.86.0/24 dev eth0 scope link  src 172.16.86.3

overlay


overlay网络是使用在swarm集群中,用于连接不同主机上的docker容器,允许不同宿主机上的容器相互通信。

#通过此命令我们可以创建集群中的manager,在输出信息中会包含一个token
[root@VM_0_14_centos ~]# docker swarm init

然后执行以下命令将工作节点加入集群

$ docker swarm join --token <token> <manager_host>:2377

新建一个overlay网络

[root@VM_0_14_centos ~]# docker network create --driver=overlay --attachable overlay
#列出docker swarm中所有节点,其中VM_0_14_centos这个节点是leader,其它两个节点是工作节点
[root@VM_0_14_centos ~]# docker node lsID                            HOSTNAME                  STATUS              AVAILABILITY        MANAGER STATUS      ENGINE VERSION
sa3m7r6m1lg4iz6dcfvyggr6s *   VM_0_14_centos             Ready               Active              Leader              19.03.11
azpq5fgozz5rd9y4lm11u69wq     VM_0_15_centos             Ready               Active                                  19.03.11
5mbf4l9k0y8zg69il7pk5ztxw     VM_0_16_centos             Ready               Active                                  19.03.7

分别在manager节点和work节点上启动一个busybox容器,并连接到overlay网络

$ docker run -it --network overlay --name box4 sh

然后我们在同一个overlay网络下的容器中互相去ping对方,是可以连接哒~

我们也可以利用overlay网络去创建一个集群服务,使用docker swarm去管理我们的集群服务。现在创建一个五副本的连接到overlay网络的nginx服务,暴露端口为80;

$ docker service create --name my-nginx --publish target=80,published=80 --replicas=5 --network overlay nginx

利用docker ps命令我们可以发现工作节点上也启动了nginx应用,这个就是通过overlay来实现不同主机中容器之间的通信。细心的小伙伴还会发现在任一节点结束一个副本,集群服务就会重启一个新的副本,会一直保持节点内的nginx副本数量为五个,有木有觉得还蛮有意思的!​​​​​​​

[root@VM_0_15_centos ~]# docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS               NAMES
1bf24ed438cf        nginx:latest        "/docker-entrypoint.…"   16 minutes ago      Up 16 minutes       80/tcp                 my-nginx.3.lcrhn4eelu1d5z4ln1ss9dczq

overlay网络模型在docker集群节点间的加入了一层虚拟网络,它有独立的虚拟网段,因此docker容器发送的内容,会先发送到虚拟子网,再由虚拟子网包装为宿主机的真实网址进行发送。 

                                                  

总 结


docker网络就介绍到这啦,通过上面的实践我们不难发现:

1、在需要多个docker容器在同一个宿主机上进行通信,最好就直接使用默认的bridge模式;

2、当多个应用程序需要组成集群提供高可用服务时候,overlay肯定是最佳的选择;

3、host模式对于优化性能以及在容器需要处理大量端口的情况下很有用,因为它不需要NAT,并且也不会为每个端口创建“ userland-proxy”。当想要容器对网络传输效率有较高要求,就可以选择host模式,但是要注意端口占用的问题哦~

猜你喜欢

转载自blog.csdn.net/qq_34556414/article/details/108228226