1.9 网络基本配置
1.8节介绍了Docker的存储配置,本节我们一起学习Docker的网络配置。通过本节的学习,我们就能知道容器如何连接互通了。
传统IT领域里的系统工程师和网络工程师各司其职,关联不多,但是云时代把他们结合在了一起。有些人因为没有太多网络技术基础,学习云计算虚拟化技术就比较吃力,加上网络虚拟化技术本身更迭速度就快,这让学习者更加头疼了。Docker作为轻量级的虚拟化技术,也离不开网络,特别是后期生产结合Kubernetes创建PaaS平台,不深入理解网络的话可能会遇到很多困难。
1.9.1 网络模型
1.Libnetwork项目
为了能更好地支持网络的各种功能,在Docker 1.7版本发布后,Docker官方创建了一个Libnetwork项目,通过这个项目统一容器的网络层标准。
2.CNM模型
Libnetwork项目是一个网络代码库,实现模型是CNM(Container Network Model)。CNM提供了用于开发的多种网络驱动,其架构如图1-56所示。
从图1-56中可以看出,Libnetwork作为一个网络代码库,向上对Docker Daemon守护进程提供了API接口,向下也提供了各种网络模式类型的接口和驱动,而这些具体的实现都是通过CNM完成的。
3.CNM的组成
CNM主要由3部分组成:沙盒(Sandbox)、接入端点(Endpoint)和网络(Network)。
(1)沙盒
沙盒可以有多个接入端点和网络。一个沙盒可以代表一个容器,里面包含了容器网络栈的所有信息,底层的技术实现就是Linux的Network Namespace。
图1-56 CNM架构
(2)接入端点
一个接入端点可以对接一个沙盒和一个网络,通过veth pair、ovs内部端口实现。一个接入端点只能存在于一个沙盒中,不能同时存在于多个沙盒中,其实就像交换机的接口,不能同时存在两个不同的交换机里。所以,我们给不同沙盒添加不同的接入端点,让沙盒接入不同的网络。
(3)网络
网络由一组互相连通的接入端点组成,技术实现可以是Linux bridge、vlan、vxlan等,一个网络可以包含多个接入端点。
CNM的组成及实现如图1-57所示。
图1-57 CNM的组成及实现
4.CNM的具体实现流程
首先,在网络控制器里注册CNM驱动,控制器根据类型创建网络;然后,网络控制器在创建好的网络上创建接入端点;最后,把容器连接到接入端点。如果是删除或销毁网络,以上步骤顺序反过来执行即可:首先把容器从接入端点拔出,然后删除接入端点,最后删除网络。
CNM的出现让容器的网络使用更加简单,我们不需要关心底层的具体实现。第三方网络插件要接入容器里,只需要提供网络和接入端点就能连通容器。有了CNM,容器本身和网络就解耦了,灵活性大大增强。
1.9.2 Docker原生的网络驱动
下面我们认识一下目前Docker Libnetwork原生的几种网络驱动模式。
1.网桥模式(bridge)
这是Docker默认的网络驱动模式。安装好Docker后,我们会发现自动创建了一个名为docker0的网桥,创建好的容器会默认使用这个网桥。单机环境可以直接使用网桥模式,如果容器要与外界通信,就要用到NAT转发。
2.主机模式(host)
该模式下容器与主机共享同一网络命名空间,里面的网络协议栈、路由表、iptables规则、网卡、IP、端口等都是共享的,容器跟宿主机在同一网络视图下。这个模式很好地解决了容器与外界通信地址转换的问题,可以直接使用宿主机的IP进行通信,这里的网络流量和压力都是经过宿主机的网卡,性能会比较高。不过这种模式有一定风险,因为容器跟宿主机共享一套网络机制,没有隔离,可能会引起网络资源与宿主机的竞争和冲突。规模小的场景可以使用这种模式。
3.overlay模式
这是Docker提供的跨主机多子网的原生网络驱动方案,实现机制是vxlan和Linux bridge,不过使用这种模式需要安装etcd、consul、zookeeper这样的键值,对数据存储系统提供信息同步支持。有了这个模式,Docker容器就能实现跨主机多子网互联了。
4.macvlan模式
macvlan模式和overlay模式一样,也是跨主机互联的网络驱动方案。macvlan本身是Linux内核模块,原理是在宿主机物理网卡上虚拟创建出多个子网卡(同一物理网卡上配置多个MAC地址,即多个接口),通过不同的MAC地址在数据链路层(Data Link Layer)进行网络数据转发,它是比较新的网络虚拟化技术,需要较新的内核支持(3.9~3.19和4.0以上)。
macvlan模式最大的优点是性能极好,macvlan模式不需要创建Linux bridge,而是直接通过以太接口连接到物理网络。另外,macvlan模式还支持802.1q trunk等更为复杂的网络拓扑结构。这里也要注意两点:第一,macvlan模式会独占主机的网卡,也就是说一个网卡只能创建一个macvlan网络,否则会报错;第二,同一个macvlan模式下的网络能通信,不同的macvlan网络之间不能通信。
总之,macvlan模式的连通性和隔离性完全依赖vlan、IP、subnet和路由,Docker本身不做任何限制,用户可以像管理传统vlan网络那样管理macvlan网络。
5.none模式
这是Docker提供的最简单的网络驱动模式。容器内的网络配置是空的,容器单独享用一个Network命名空间,因此是一个封闭的网络环境。容器启动后无任何网络连接,我们看到的是一个环回接口(loopback)。如果想让容器与外界互联,需要手动给容器配置网络接口、IP和路由。该模式灵活性最强。
以上5种网络驱动模式都是Docker原生的,如果都不能满足你的要求,那么可以接入第三方的驱动模式,比如flannel、pipework、Weave和Calico等,Docker是支持的。
1.9.3 Docker网络操作的基本命令
下面介绍几个比较基础的Docker网络操作命令。
$ docker network ls List networks # 查看容器网络列表 $ docker network create Create a network # 创建网桥模型网络 $ docker network connect Connect a container to a network # 让容器连接到指定网络 $ docker network disconnect Disconnect a container from a network # 让容器从某个网络中断开 $ docker network inspect Display detailed information on one or more networks # 查看网络的详细信息 $ docker network prune Remove all unused networks # 一键清理无用的网络列表 $ docker network rm Remove one or more networks # 删除网络
1.查看网络列表命令
我们直接执行docker network ls命令即可查看网络列表,如图1-58所示。
图1-58 查看Docker网络
2.创建网桥模型网络
执行docker network create network-name命令可以创建一个新的网桥模型网络,如图1-59所示。
图1-59 创建网桥模型网络
执行ifconfig命令可以查看网桥,如图1-60所示,图中br-842a5a8ed4a0就是新建的网桥,IP是172.18.0.1。
图1-60 查看网桥
如果想创建一个其他类型的网络,比如overlay,命令前加-d参数及类型即可。
$ docker network create -d overlay test-overlay-network
不过创建overlay类型的网络时要先准备好,比如搭建etcd kv的存储。
3.让容器连接到指定网络
前面创建好了网络,怎么让容器连接到这个网络呢?这里就要用到docker network connect命令了。我们通过一个实验来讲解这个命令。
先创建两个容器docker1和docker2。
$ docker run -itd --name=docker1 busybox $ docker run -itd --name=docker2 busybox
命令运行后的返回结果如图1-61所示。
图1-61 查看创建的容器
创建一个名为mynet的网络,网段是172.19.0.0/16。
$ docker network create -d bridge --subnet 172.19.0.0/16 mynet
命令运行后的返回结果如图1-62所示。
图1-62 创建并查看网络mynet
将容器docker2连接到网络mynet。
$ docker network connect mynet docker2
命令运行后的返回结果如图1-63所示。
图1-63 docker2连接到mynet网络
我们用docker network inspect mynet命令查看mynet网络,可以看到docker2在这个mynet网络下面了,IP是172.19.0.2。
创建最后一个容器docker3,连接的网络也是mynet。
$ docker run --net=mynet --ip=172.19.0.3 -itd --name=docker3 busybox
我们发现docker3的IP也在mynet里面了,并且docker2和docker3能相互通信,具体查看mynet详细信息,如图1-64所示。
4.让容器从某个网络中断开
执行docker network disconnect命令可以让容器从某个网络断开。
接着上面的实验环境,我们把docker3从mynet断开试试,只需要运行如下命令。
$ docker network disconnect mynet docker3
图1-64 docker3在mynet网络中的信息
命令运行后的返回结果如图1-65所示。
图1-65 docker3从mynet网络中断开
我们发现mynet里面已经没有docker3了,只剩下docker2。
5.查看网络的详细信息
通过docker network inspect+网络名即可查看网络的详细信息,比如查看mynet的详细信息,如图1-66所示。
图1-66 查看mynet网络详细信息
6.一键清理无用的网络列表
这里我们先用docker network create命令创建3个网络—test1、test2和test3,这3个网络都不挂载任何容器实例,如图1-67所示。
图1-67 创建test1、test2、test3网络
接着我们使用docker network prune命令一键清理这3个网络,看看是否能全部清除。
执行命令时发现有一个提示,问我们是否清除空闲的所有网络。我们输入y,然后就清理了这3个网络。该步骤如图1-68所示。
图1-68 清除空闲的网络
我们再执行docker network ls命令,发现test1、test2、test3以及之前创建的test-network都被清理了,如图1-69所示。
图1-69 查看网络信息
7.删除网络
如果只想删除某个网络,执行docker network rm+网络名即可。
建议删除之前确认一下这个网络是否有容器正在使用,如果有,可以先切断网络连接,然后再删除。
以上就是Docker网络的基本介绍,都是一些比较基础的概念,很容易掌握。容器网络离不开虚拟化网络技术,大家可以从容器网络启动过程、访问控制、flannel、Weave、OVS等方向再深入研究。了解清楚Docker相关概念,再学习Kubernetes网络,这样以后进行网络生产实践就会顺利许多。