容器的网络模式

容器网络概览

容器之间如何联通是个重要的问题。Docker官方文档 https://docs.docker.com/network/ 介绍了多种网络模式,本文加以阐述:

  • bridge
  • host
  • container
  • none
  • overlay
  • macvlan
  • netplugin
    一般网络选择none时,并不是不用网络而是使用自定义的网络模型,常见的自定义网络模型有overlay(vxlan),macvlan等,这些网络也常常以netplugin的即插件的方式出现。把常见的几种网络模式以表格的形式总结如下:
网络模式 配置 说明
bridge模式 --net=bridge 默认值,在Docker网桥docker0上为容器创建新的网络栈
host模式 --net=host 容器和宿主机共享network namespace即共享1号进程的网络
container模式 --net=container:name/id 容器和另外一个容器共享network namespace.k8s中的pod就是多个容器共享pause容器的网络,这个id常用pause容器的ID
none模式 --net=none 不配置网络,用户可以稍后进入容器,自行配置
用户自定义 --net=自定义网络 用户自定义网络,创建容器的时候可以指定为自定的网络。可以通过docker inspect 输出的NetworkMode来判断网络模式
使用如下命令查看容器的网络
# docker network list
NETWORK ID     NAME      DRIVER    SCOPE
7d7d6ca51d94   bridge    bridge    local
933f92ab7286   host      host      local
b08aa440b7df   none      null      local
其中,默认的容器网络是bridge网络,和名字一样它是一个linux bridge,可以用brctl查看。可以用docker inspect <network-id>或者docker network inspect <network-name/network-id>来查看该网络的详细信息,可以看到挂载到该网络的所有容器的信息。
# brctl show
bridge name     bridge id               STP enabled     interfaces
docker0         8000.0242db8d64e3       no              

默认的容器网络,bridge模式

如果你不给容器网络做任何设置,那么容器将会使用bridge网络模式。该模式下,Docker会为容器创建一个eth0端口,绑定在主机的docker0网桥上,并且给eth0分配一个和docker0同网段的IP地址。

docker run -d --net=bridge --name c1 busybox:01 sleep 60
进入容器查看网络,如下:
/ # ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
193: eth0@if194: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue 
    link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0
       valid_lft forever preferred_lft forever

如果新创建docker 网络,那么也是创建的bridge网络,并随着docker 网络的创建可以创建出一个新的bridge,绑定两个不同docker 网络也就是绑定两个不同的linux bridge,这样可以实现同一主机上的两个容器的网络隔离(ping不通)

# docker network create n1
# docker network create n2
# docker network list
#
# docker run -itd --network n1 --name c1 172.18.8.210:5000/library/net-nginx:v1.0 sleep 120
# docker run -itd --network n2 --name c2 172.18.8.210:5000/library/net-nginx:v1.0 sleep 120
容器c1和c2相互ping不通。

另外可以通过命令 docker network connect n1 10cd4efd7645, 把容器10cd4efd7645 连接到n1对应的网桥上,并分配n1网段的地址。

host网络

对于独立的容器,去掉容器和Docker主机之间的网络隔离,直接使用主机的网络。这种模式适用于系统组件。

docker run -d --net=host busybox:01 sleep 60

container网络

container 启动一个容器,会使用另外一个已经存在的容器的网络,它们会共享网络协议栈,它们的网络是一模一样的。

docker run -d --net=container:a56f9cc34ed0 busybox:01 sleep 60

这里指定网络要使用格式container:<name|id>.那么新创建出来的容器和原来的容器a56f9cc34ed0是一样的网络配置。

none网络

对于none网络模式的容器,禁用容器的所有网络。通常与自定义网络驱动程序一起使用。

docker run -d --net=none busybox:01 sleep 60

overlay网络

overlay网络和macvlan是docker原生的支持跨主机通信的网络模式。Overlay网络把多个Docker daemon连接起来并用swarm services通信。可以利用overlay网络来实现一个swarm service和一个单独容器的通信,或者实现分属于两个不同Docker daemons的单独容器的通信。该方法不需要在这些容器之间设置操作系统的路由。
其中如果要创建一个overlay网络必须要先使用 docker swarm init 将 Docker 守护进程初始化为 swarm manager,或者使用 docker swarm join 将其加入到现有的 swarm 中.然后可以用如下命令创建一个overlay网络:

$ docker network create -d overlay my-overlay

然后再创建容器使用此网络。因为不适用Swarm,所以这里暂不讨论这种网络。

macvlan网络

Macvlan网络允许你给容器分配一个MAC地址 使它看起来像网络上的一个物理设备。Docker守护进程通过容器的MAC地址将流量路由到容器。当希望直接连接到物理网络而不是通过 Docker 主机的网络栈进行路由时(特别是一些老的应用),使用 macvlan 网络是最佳选择。macvlan是linux操作系统内核提供的网络虚拟化方案之一,更准确的说法是网卡虚拟化方案。它可以为一张物理网卡设置多个mac地址,相当于物理网卡施展了影分身之术,由一个变多个,同时要求物理网卡打开混杂模式。针对每个mac地址,都可以设置IP地址,本来是一块物理网卡连接到交换机,现在是多块虚拟网卡连接到交换机。

1. 分别在两个主机上创建相同的macvlan: 
   docker network create -d macvlan   --subnet=172.16.86.0/24   --gateway=172.16.86.1   -o parent=bond0   macvlan-net
2. 然后使用该macvlan的IP分别在两台主机上创建容器,指定IP是为了防止IP冲突:
   docker run --name=host1container -d --net=my-macvlan-net --ip=172.16.86.2 busybox:01  sleep 100
   docker run --name=host2container -d --net=my-macvlan-net --ip=172.16.86.3 busybox:01  sleep 100
3. 尝试两台容器互ping

上面例子的macvlan的网络拓扑结构如下图所示:

netplugin

netplugin是网络插件模式, 您可以使用Docker安装和使用第三方网络插件。常用的网络插件有flannel、calico等。

几种网络模式的跨节点容器连通性

这里选几种我实际用过的,没用过的就不做文字搬运的工作了。主要有bridge模式,host模式,cni模式中的flannel和calico模式。如果后面实际工作学习中用到其他模式,我再更新文章。

bridge模式下的跨节点容器连通性

docker默认的bridge模式下不同节点之间的容器应该不能联通,如果要联通需要添加路由或者其他的方式。Flannel其实就是使用的bridge模式+路由的方式转发到外部节点。
例如,如下所示的flannel的路由:

192.168.1.0/24 via 192.168.1.0 dev flannel.1 onlink
192.168.2.0/24 via 192.168.2.0 dev flannel.1 onlink

其中flannel.1是一个vtep设备,flannel.1会绑定该节点的一块物理网卡,把数据包封装成vxlan包发送出去。

host模式下的跨节点容器连通性

host模式下的跨节点通信就简单很多,跟主机节点的联通性紧密相关。如果这两个主机可以联通,那么这两台主机上的容器也是可以联通的,否则不联通。

cni模式

cni模式下的跨节点通信一般都是可以的,例如使用overlay的flannel和使用纯路由模式的Calico都是可以实现跨节点通信的。它们一般都是第三方的较为成熟的方案,因此是支持跨节点通信的。只是它们还会有其他特性,需要用户根据场景来选择具体feature.

posted @ 2020-09-04 17:59  JaneySJ  阅读(706)  评论(1编辑  收藏  举报