Kubernetes网络自学系列 | 容器网络的第一个标准:CNM

Posted COCOgsta

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Kubernetes网络自学系列 | 容器网络的第一个标准:CNM相关的知识,希望对你有一定的参考价值。

素材来源:《Kubernetes网络权威指南》

一边学习一边整理内容,并与大家分享,侵权即删,谢谢支持!

附上汇总贴:Kubernetes网络自学系列 | 汇总_COCOgsta的博客-CSDN博客


2.4 容器网络的第一个标准:CNM

围绕Docker生态,目前有两种主流的网络接口方案,即Docker主导的Container Network Model(CNM)和Kubernetes社区主推的Container Network Interface(CNI),其中CNM相对CNI较早提出。下文将重点介绍Docker的CNM模型,CNI的介绍将放在后面的章节。

2.4.1 CNM标准

CNM模型如图2-3所示。

图2-3 CNM模型

从上图不难发现,CNM有3个主要概念:

·Network Sandbox:容器网络栈,包括网卡、路由表、DNS配置等。对应的技术实现有network namespace、FreeBSD Jail(类似于namespace的隔离技术)等。一个Sandbox可能包含来自多个网络(Network)的多个Endpoint;

·Endpoint:Endpoint作为Sandbox接入Network的介质,是Network Sandbox和Backend Network的中间桥梁。对应的技术实现有veth pair设备、tap/tun设备、OVS内部端口等;

·Backend Network:一组可以直接相互通信的Endpoint集合。对应的技术实现包括Linux bridge、VLAN等。如读者所见,一个Backend Network可以包含多个Endpoint。除此之外,CNM还需要依赖另外两个关键的对象来完成Docker的网络管理功能,它们分别是:

·Network Controller:对外提供分配及管理网络的APIs,Docker Libnetwork支持多个网络驱动,Network Controller允许绑定特定的驱动到指定的网络;

·Driver:网络驱动对用户而言是不直接交互的,它通过插件式的接入方式,提供最终网络功能的实现。Driver(包括IPAM)负责一个Network的管理,包括资源分配和回收。

有了这些关键的概念和对象,配合Docker的生命周期,通过API就能完成管理容器网络的功能。

最后,CNM还支持标签(label)。label是以key-value对定义的元数据,用户可以通过定义label这样的元数据自定义Libnetwork和驱动的行为。

2.4.2 体验CNM接口

CNM的接口较多,这里就不一一展开解释了,主要介绍几个常见的Docker daemon和CNM接口交互的过程。

1.Create Network

这一系列调用发生在使用docker network create的过程中。

(1)IpamDriver.RequestPool:创建subnetpool用于分配IP。

(2)IpamDriver.RequestAddress:为gateway获取IP。

(3)NetworkDriver.CreateNetwork:创建网络和子网。

2.Create Container

这一系列调用发生在使用docker run创建一个容器的过程中。当然,也可以通过docker network connect触发。

(1)IpamDriver.RequestAddress:为容器获取IP。

(2)NetworkDriver.CreateEndpoint:为容器创建网络接口。

(3)NetworkDriver.Join:为容器和外部网络驱动绑定。

(4)NetworkDriver.ProgramExternalConnectivity:使容器与外部进行网络连接。

(5)NetworkDriver.EndpointOperInfo:返回容器网络信息。

3.Delete Container

这一系列调用发生在使用docker delete删除一个容器的过程中。当然,也可以通过docker network disconnect触发。

(1)NetworkDriver.RevokeExternalConnectivity:撤销容器与外部网络的连接。

(2)NetworkDriver.Leave:容器与外部网络驱动解绑。

(3)NetworkDriver.DeleteEndpoint:删除容器内的网络设备。

(4)IpamDriver.ReleaseAddress:删除port并释放IP。

4.Delete Network

这一系列调用发生在使用docker network delete的过程中。

(1 )NetworkDriver.DeleteNetwork:删除Network。

(2)IpamDriver.ReleaseAddress:释放gateway的IP。

(3)IpamDriver.ReleasePool:删除subnetpool。

除了命令行,Docker还提供了CNM的remote plugin,即RESTful API。remote plugin监听一个指定的端口,Docker Daemon直接通过这个端口与remote plugin进行交互。这里不再赘述,感兴趣的读者可以自行查阅相关资料。

2.4.3 Libnetwork

上 文 多 次 提 到Libnetwork,接 下 来 我们就介 绍CNM的原生实现——Libnetwork。Libnetwork是Docker团队将Docker的网络功能从Docker核心代码中分离出去,用Go语言实现的一个独立库。Libnetwork通过插件的形式为Docker容器提供网络功能,用户可以根据自己的需求实现自己的网络驱动,以便提供不同的网络功能。

从架构上看,Libnetwork为Docker Daemon和网络驱动提供了接口。每次用户通过命令行或API提交的与网络相关的指令,都会先在Docker Daemon预处理,再根据驱动类型调用 Libnetwork模块的相应实现。因此,Libnetwork最主要的工作是联结底层驱动。

Libnetwork的网络控制器(Network Controller)负责将网络驱动和一个Docker网络进行对接。每个网络驱动负责为对接的网络提供服务,例如IPAM(IP地址管理)等。网络驱动可以按提供方被划分为原生驱动或远程驱动(第三方插件),原生驱动包括none、bridge、overlay和Macvlan。驱动也可以按照适用范围被划分为本地的和跨主机的。

Docker Daemon和Libnetwork的调用过程如图2-4所示。

图2-4 Docker Daemon和Libnetwork的调用过程

无论使用哪种网络类型,Docker Daemon与Libnetwok的交互流程都是一样的,它很好地对底层(驱动)实现进 行了抽象。如果需要实现自己的驱动,则开发者必须关注Libnetwork。

(1)Daemon创建网络控制器(Controller)实例,入参包括Docker层面的网络全局参数(genericOption),例如默认的bridge模式、kv store等。

(2)网络控制器创建容器网络,入参包括网络名、类型和对应驱动参数。从这里开始,会调用至真正的驱动实现。

(3)创建Endpoint,进行IP分配,准备网络设备接口。

(4)创建Sandbox,使用容器对应的网络命令空间,包含该容器的网络环境。

(5)已有的Endpoint加入Sandbox,完成容器与网络设备的对接。

结合CNM,Libnetwork所要达成的效果应该是:用户可以创建一个或多个网络(一个网络就是一个网桥或者一个VLAN),一个容器可以加入一个或多个网络。同一个网络中的容器可以通信,不同网络中的容器隔离。笔者认为这才是将网络从Docker分离出来的真正意义,即在创建容器之前,可以先创建网络(即创建容器与创建网络是分开的),然后决定让容器加入哪个网络。一个例子就是:

首先,创建两个overlay网络net1和net2,如下所示:

然后,运行一个容器net1c1,加入net1网络,如下所示:

最后,Libnetwork的架构如图2-5所示。

图2-5 Libnetwork的架构

2.4.4 Libnetwork扩展

前文提到,Libnetwork支持remote的网络驱动。Remote Driver提供了自定义网络的可能。远程驱动作为服务端,Libnetwork作为客户端,两者通过一系列带JSON格式的HTTP POST请求进行交互。这种形式对网络实现的可维护性、可扩展性有很大好处。对千差万别的网络实施方案而言,Docker算是解放了开发者的双手,让他们把更多精力放在自己擅长的容器方面,这一点和Kubernetes放手CNI plugin的思路非常像。远端的网络驱动,只要实现了以下接口,就能支持Docker容器网络的生命周期管理。

CNM总计10个接口,这么看,似乎CNI要实现的接口更少一点。

接下来,以思科的Contiv项目为例,演示Libnetwork扩展方法。

Contiv是思科主导开发的以远程插件的形式,基于OVS提供Docker容器网络的SDN能 力。功能上支持VLAN、VXLAN和QoS。要 想 使 用 Contiv 。首先需要在/var/run/docker/plugins/目录下注册socket文件,每次处理Libnetwork的RPC请求时,通过 ovsdbserver的管理接口执行修改ovs流表的操作,如图2-6所示。

图2-6 Docker集成Contiv插件的原理

2.4.5 小结

不管是CNM还是CNI,其最终目标都是以一致的编程接口,抽象网络实现。世界上有许多广泛的网络解决方案,它们适配不同的应用场景。然而,容器生态圈存在两个网络标准,对开发人员和运维人员而言绝对不是一个好消息,因为简单、自动化的网络配置是我们的最终诉求。笔者认为,对于已经失掉容器编排标准话语权的Docker而言,CNM也是“鸡肋”,虽然曾经被思科Contiv、Kuryr、Open Virtual Networking(OVN)、Project Calico、VMware、Weave等公司和项目采纳过,但其实更多只是“兼容”。未来的主流要看CNI!再加上2019年2月CNCF(Cloud Native Computing Foundation,云原生基金会)推出的CNF,将彻底统一云原生的网络技术标准。若读者已经采用CNM,也不必过分担心,因为CNI和CNM并非是完全不可调和的两个模型,二者是可以进行转化的。我们将在后面的章节详解CNI及如何和 CNM进行转换。

以上是关于Kubernetes网络自学系列 | 容器网络的第一个标准:CNM的主要内容,如果未能解决你的问题,请参考以下文章

Kubernetes网络自学系列 | 容器基础设施的代言人:Kubernetes

Kubernetes网络自学系列 | 主角登场:Linux容器

Kubernetes网络自学系列 | Pod的核心:pause容器

Kubernetes网络自学系列 | 如何做好技术选型:容器组网方案沙场点兵

Kubernetes网络自学系列 | 最常用的Docker网络技巧

Kubernetes网络自学系列 | iptables