Docker 网络部分执行流分析(Libnetwork源码解读)

【编者的话】Libnetwork作为Docker网络部分的依赖库,在Docker 1.9中正式脱离实验阶段,进入主分支正式投入生产使用阶段。有了新的Networking我们可以创建虚拟网络,然后将container加入到虚拟网络中,以获得最适合所部署应用的网络拓扑结构。本文将借助于对Docker网络部分的源码分析,以对Libnetwork做一个详尽的介绍和使用及开发的样例。

Libnetwork作为Docker网络部分的依赖库,在Docker1.9中正式脱离实验阶段,进入主分支正式投入生产使用阶段。有了新的Networking我们可以创建虚拟网络,然后将container加入到虚拟网络中,以获得最适合所部署应用的网络拓扑结构。

1 组件的标准化

为了标准化网络驱动的开发步骤和支持多种网络驱动,Docker公司在Libnetwork中实现了CNM(Container Network Model)。CNM主要建立在如下三个组件上。


沙盒(Sandbox):一个沙盒包含了一个容器网络栈的信息。沙盒可以对容器的接口,路由和DNS设置等进行管理。沙盒的实现可以是Linux Network Namespace, FreeBSD Jail或者类似的机制。一个沙盒可以有多个端点(Endpoint)和多个网络(Network)。


端点(Endpoint):一个端点可以加入一个沙盒和一个网络。端点的实现可以是veth pair, Open vSwitch内部端口或者相似的设备。一个端点只可以属于一个网络并且只属于一个沙盒。


网络(Network):一个网络是一组可以直接互相联通的端点。网络的实现可以是Linux bridge,VLAN等等。一个网络可以包含多个端点。



2 CNM对象详细介绍

介绍了CNM中三个主要的组件之后,下面对CNM中的各个对象做一个详细的介绍。


NetworkController:NetworkController通过暴露给用户创建和管理网络的API,以便用户对libnetwork进行调用。Libnetwork支持多种驱动,其中包括内置的bridge,host,container和overlay,也对远程驱动进行了支持(即支持用户使用自定义的网络驱动)。


Driver:Driver不直接暴露给用户接口,但是driver是真正实现了网络功能的对象。NetworkController可以对特定driver提供特定的配置选项,其选项对libnetwork透明。为了满足用户使用需求和开发需求,driver既可以是内置的类型,也可以是用户指定的远程插件。每一种驱动可以创建自己独特类型的network,并对其进行管理。在未来可以会对不同插件的管理功能进行整合,以求做到方便管理不同类型的网络。


Network:Network对象是CNM的一种实现。NetworkController通过提供API对Network对象进行创建和管理。NetworkController当需要创建或者更新Network的时候,它所对应的Driver会得到通知。Libnetwork通过抽象层面对同属于一个网络的各个endpoint提供通信支持,同时将其与其他endpoint进行隔离。这种通信支持可以是同一主机的,也可以是跨主机的。


Endpoint:Endpoint代表了服务端点。它可以提供不同网络中容器的互联。Endpoint由创建对应Sandbox的驱动进行创建。


Sandbox:Sandbox代表了一个容器中诸如ip地址,mac地址,routes,DNS等信息的配置。Sandbox在用户要求在一个Network创建Endpoint的时候进行创建并分配对应的网络资源。Libnetwork会用特定的操作系统机制(例如:linux的netns)去填充sandbox对应的容器中的网络配置。一个sandbox中可以有多个连接到不同网络的endpoint。



3 Libnetwork工作执行流简介

下面对libnetwork的工作流做一个梗概。



4 Docker使用libnetwork内置驱动的执行流详解

在介绍介绍Docker使用libnetwork内置驱动的执行流之前,我们先来看一下Dorker的默认网络模式(bridge模式)中,各个设备和容器之间的关系。其简要关系如图2所示。

02.jpg


图2 bridge模式中各个设备与容器关系

上图中container1和container2是两个Docker容器,veth0和veth1,veth2和veth3是两对veth pair(veth pair可以用于不同netns之间的通信),docker0是网桥(docker0可以连接不同的网络),eth0是宿主机的物理网卡。

图中的container1和container2都拥有不同的netns。以container1为例,veth pair中的veth0被加入到container1的netns中,并且被配置ip地址等基本信息,则veth0就成为了container1的一块网卡,与veth0所对应的的veth1被连接到docker0网桥上。Docker0网桥上还连接了宿主机的物理网卡eth0。这样container1就可以利用veth0与Internet进行通信了。类似的container2也连接到了docker0网桥上,显然container1与container2之间也是可以进行通信的。

结合上面提到的CNM中的概念来,我们可以知道docker0网桥就是CNM中的network组件,它可以代表一个网络。Container所拥有的netns就是CNM中的一个sandbox,它是一个独立的网络栈。Veth pair则是CNM中的endpoint,它的一个端点可以通过加入一个网桥来加入一个network,另一个端点可以加入一个sandbox,这样就将这个sandbox所对应的容器加入到了这个network中。

在了解了各个设备和容器之间的关系和各种设备和CNM各种组件的对应关系后,我们来看一下Docker是如何与libnetwork和libcontainer进行协作交互,并且为各个容器创建和配置网络的。Docker中使用默认模式(bridge模式)为容器创建和配置网络的过程如图3所示。

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/c03b70033ab9651c421f6ed8bce318a6.html