libnetwork插件化网络功能

Docker把网络跟存储这两部分的功能实现都以插件化形式剥离出来,允许用户通过指令来选择不同的后端实现。这也是Docker希望构建围绕着容器的强大生态系统的一些积极的尝试。剥离出来的独立容器网络项目叫libnetwork,从名字就能看出来,它希望将来为不同容器定义统一规范的网络层标准。

容器网络模型

libnetwork中容器网络模型(Container Networking Model,CNM)十分简洁,可以让上层使用网络的大量应用容器最大程度上不去关心底层实现。

容器网络模型的结构如图所示。

包括三种基本元素:

  1. Sandbox(沙盒):代表一个容器(准确地说,是其网络命名空间);
  2. Endpoint(接入点):代表网络上可以挂载容器的接口,会分配IP地址;
  3. Network可以连通多个接入点的一个子网。

对于使用CNM的容器管理系统来说,具体底下网络如何实现,不同子网彼此怎么隔离,有没有QoS,都可以不关心。只要插件能提供网络和接入点,只需把容器给接上或者拔下,剩下的都是插件驱动自己去实现。这样就解耦和容器和网络功能,十分灵活。

首先,是驱动注册自己到网络控制器,网络控制器使用驱动类型,来创建网络,然后在创建的网络上创建接口,最后把容器连接到接口上即可。销毁过程则正好相反,先把容器从接入口上卸载,然后删除接入口和网络即可。

CNM的典型生命周期如图所示:

目前CNM支持的驱动类型有四种:Null、Bridge、Overlay、Remote。简单介绍如下:

  1. Null:不提供网络服务,容器启动后无网络连接;
  2. Bridge:就是Docker传统上默认用Linux网桥和Iptables实现的单机网络;
  3. Overlay:是用vxlan隧道实现的跨主机容器网络;
  4. Remote:扩展类型,预留给其他外部实现的方案,比如有一套第三方的SDN方案(如OpenStack Neutron),就可以接进来。

从位置上看,libnetwork上面支持Docker,下面支持网络插件,自身处于十分关键的中间层。如果熟悉计算机网络协议模型的话,libnetwork就是最核心的TCP/IP层。目前,已有大量的网络方案开始支持libnetwork。包括OpenStack Kuryr项目,通过支持libnetwork,让Docker可以直接使用Neutron提供的网络功能。Calico等团队也编写了插件支持libnetwork,从而无缝地支持Docker网络功能。

Docker网络相关命令

在libnetwork支持下,Docker网络相关命令都作为network的子命令出现。

围绕着管理CNM的生命周期,主要包括以下命令:

  1. ls:列出所有的网络;
  2. create:创建一个网络;
  3. rm:删除一个网络;
  4. connect:把容器接入到网络;
  5. disconnect:把容器从网络卸载下来;
  6. inspect:查看网络的详细信息。

下面分别介绍这些命令。

1.列出网络

命令格式:docker network ls [OPTIONS]

支持参数包括:

-f:指定输出过滤器;

--no-trunc:不截断输出内容。

实际上,在不执行额外网络命令的情况下,用户执行docker network ls命令,一般情况下可以看到已创建的三个网络:

$ docker network ls

NETWORK ID          NAME                DRIVER
461e02c94370        bridge              bridge
e4d5886b2d2f        none                null
adbc1879bac5        host                host

分别为三种驱动的网络:null、host和bridge。

2.创建网络

命令格式:docker network create [OPTIONS] NETWORK

支持参数包括:

--aux-address value:辅助的IP地址;

-d,--driver string:网络驱动类型,如bridge或overlay;

--gateway value:网关地址;

--internal:禁止外部对创建网络的访问;

--ip-range value:分配IP地址范围;

--ipam-driver string:IP地址管理的插件类型;

--ipam-opt value:IP地址管理插件的选项;

--ipv6:支持IPv6地址;

--label value:为网络添加元标签信息;

-o,--opt value:网络驱动支持的选项;

--subnet value:网络地址段。

3.删除网络

删除指定的网络。当网络上并不存在接入点时,删除成功。

命令格式:docker network rm NETWORK [NETWORK...]

4.接入容器

将一个容器连接到一个已存在的网络上。命令格式:docker network connect [OPTIONS] NETWORK CONTAINER

支持参数包括:

--alias value:为容器添加一个别名,此别名仅在所添加网络上可见;

--ip string:指定IP地址;

--ip6 string:指定IPv6地址;

--link value:添加链接到另外一个容器;

--link-local-ip value:为容器添加一个链接地址。

5.卸载容器

将一个连接到网络上的容器从网络上移除。命令格式:docker network disconnect [OPTIONS] NETWORK CONTAINER

支持参数包括-f、--force:强制把容器从网络上移除。

6.查看网络信息

查看已存在网络的具体信息。命令格式:docker network inspect [OPTIONS] NETWORK [NETWORK...]

支持参数包括-f、--format string:给定一个golang模板字符串,对输出结果进行格式化。

构建跨主机容器网络

使用libnetwork自带的Overlay类型驱动来轻松实现跨主机的网络通信。Overlay驱动默认采用VXLAN协议,在IP地址可以互相访问的多个主机上之间搭建隧道,让容器可以互相访问。

1.配置网络信息管理数据库

我们知道,在现实世界中,要连通不同的主机需要交换机或路由器(跨子网时需要)这样的互联设备。这些设备一方面是在物理上起到连接作用,但更重要的是起到了网络管理的功能。例如,主机位置在什么地方,地址是多少等信息,都需要网络管理平面来维护。

在libnetwork的网络方案中,要实现跨主机容器网络也需要类似的一个网络信息管理机制,只不过这个机制简单得多,只是一个键值数据库而已,如Consul、Etcd、ZooKeeper等工具都可以满足需求如图所示。

以Consul为例,启动一个progrium/consul容器,并映射服务到本地的8500端口,用如下命令即可:

$ docker run -d \

-p "8500:8500" \

-h "consul" \

progrium/consul -server -bootstrap

所在主机作为数据库节点。

2.配置Docker主机

启动两台Docker主机n1和n2,分别安装好最新的Docker-engine(1.7.0+)。确保这两台主机之间可以通过IP地址互相访问,另外,都能访问到数据库节点的8500端口。

配置主机的Docker服务启动选项如下所示:

DOCKER_OPTS="$DOCKER_OPTS --cluster-store=consul://<consul_node>:8500 --cluster-advertise=eth0:2376"

重新启动Docker服务如下所示:

$ sudo service docker restart

3.创建网络

分别在n1和n2上查看现有的Docker网络,包括三个默认网络:分别为bridge、host和none类型。

n1:$ docker network ls

n2:$ docker network ls

在任意节点上创建网络multi,例如在n1上执行如下命令即可完成对跨主机网络的创建:

n1:$ docker network create -d overlay multi

创建成功后,可以同时在n1和n2上查看到新的网络multi的信息:

n1:$ docker network ls

n2:$ docker network ls

NETWORK ID NAME DRIVER
dc581a3eab4c bridge bridge
ee21a768c6f6 host host
eadd374a1843 multi overlay
8d1ee747b894 none null

此时,还可以通过docker network inspect命令查看网络的具体信息:

$ docker network inspect multi

4.测试网络

在n1上启动一个容器c1,通过--net选项指定连接到multi网络上。查看网络信息,其中一个接口eth0已经连接到了multi网络上:

n1:$ docker run -it --name=c1 --net=multi busybox

/ # ip a

在n2上启动一个容器c2,同样连接到multi网络上。

通过ping c1进行测试,可以访问到另外一台主机n1上的容器c1:

n2:$ docker run -it --name=c2 --net=multi busybox

/ # ping c1

 

posted @ 2017-03-24 14:23  wade&luffy  阅读(846)  评论(0编辑  收藏  举报