转:https://www.aliyun.com/jiaocheng/518375.html

    • 摘要:容器近几年非常流行,有很多项目都考虑将容器与SDN结合。Kuryr就是其中一个项目。Kuryr项目在OpenStackbigtent下,目的是将容器网络与openstackNeutron对接。Kuryr给人的第一印象是:这又是一个在Neutron框架下的项目,能够通过Neutron统一的北向接口来控制容器网络的SDN项目。但是实际上,Kuryr是将Neutron作为南向接口,来与容器网络对接。Kuryr的北向是容器网络接口,南向是OpenStackNeutron。Kuryr背
    • 容器近几年非常流行,有很多项目都考虑将容器与SDN结合。Kuryr就是其中一个项目。Kuryr项目在OpenStackbig tent下,目的是将容器网络与openstackNeutron对接。Kuryr给人的第一印象是: 这又是一个在Neutron框架下的项目,能够通过Neutron统一的北向接口来控制容器网络的SDN项目。但是实际上,Kuryr是将Neutron作为南向接口,来与容器网络对接。Kuryr的北向是容器网络接口,南向是OpenStack Neutron。

      Kuryr背景介绍

      正式介绍前,先说下Kuryr这个单词。Kuryr是一个捷克语单词kurýr,对应英语里面是courier,对应的中文意思就是信使,送信的人。从这个名字能看出来,Kuryr不生产信息,只是网络世界的搬运工。这个从项目的图标也可以看出来。另外,由于都是拉丁语系,所以可以不负责任的说,Kuryr的发音应该是与courier类似。

      Kuryr最开始创立的时候,其目的是为了提供Docker与Neutron的连接。将Neutron的网络服务带给docker。随着容器的发展,容器网络的发展也出现了分歧。主要分为两派,一个是Docker原生的CNM(ContainerNetwork Model),另一个是兼容性更好的CNI(Container Network Interface)。Kuryr相应的也出现了两个分支,一个是kuryr-libnetwork(CNM),另一个是kuryr-kubernetes(CNI)。

      以上是Kuryr项目的背景介绍,下面看一下kuryr-libnetwork。

      Kuryr 在Libnetwork中如何工作

      kuryr-libnetwork是运行在Libnetwork框架下的一个plugin。要理解kuryr-libnetwork如何工作,首先要看一下Libnetwork。Libnetwork是从Docker Engine和libcontainer中将网络逻辑模块化之后独立出来的的项目,并且替代了原有的Docker Engine网络子系统。Libnetwork定义了一个灵活的模型,使用local或者remote driver来向container提供网络服务。kuryr-libnetwork就是Libnetwork的一个remote driver实现,现在已经成为Docker官网推荐的一个remote driver。

      Libnetwork的driver可以看是Docker的一个plugin,与Docker的其他plugin共用一套plugin管理框架。也就是说,Libnetwork的remote driver与Docker Engine中的其他plugin用一样的方式激活,并使用同样的协议。有关Libnetwork remote driver需要实现的接口在Libnetwork的Git上都有详细的描述。

      kuryr-libnetwork需要做的就是实现这些接口。可以从kuryr-libnetwork的代码中看出来。Libnetwork通过调用remote driver的Plugin.Activate接口,来查看remote driver实现了什么内容。从kuryr-libnetwork的代码中能看到,它实现了两个功能:NetworkDriver, IPAMDriver.

      @app.route('/Plugin.Activate', methods=['POST']) 
      def plugin_activate(): 
      """Returns the list of the implemented drivers. 
      This function returns the list of the implemented drivers defaults to 
      ``[NetworkDriver, IpamDriver]`` in the handshake of the remote driver, 
      which happens right before the first request against Kuryr. 
      See the following link for more details about the spec: 
      docker/libnetwork# noqa 
      """ 
      app.logger.debug("Received /Plugin.Activate") 
      return flask.jsonify(const.SCHEMA['PLUGIN_ACTIVATE'])

      Kuryr是怎么作为remote driver注册到Libnetwork中呢?这个问题应该这样看,Libnetwork是怎样发现Kuryr的?这要依赖于Docker的plugin discovery机制。当用户或者容器需要使用Docker的plugin的时候,他/它只需要指定plugin的名字。Docker会在相应的目录中查找与plugin名字相同的文件,文件中定义了如何连接该plugin。

      如果用devstack安装kuryr-libnetwork,devstack的脚本会在/usr/lib/docker/plugins/kuryr创建一个文件夹,里面的文件内容也很简单,默认是:http://127.0.0.1:23750。也就是说,kuryr-libnetwork实际上就起了一个http server,这个http server提供了Libnetwork所需的所有接口。Docker找到有这样的文件之后,就通过文件的内容与Kuryr进行通信。

      所以Libnetwork与Kuryr的交互是这样:

      Libnetwork:有人要用一个叫Kuryr的plugin,让我找找看。哦,Kuryr你好,你有什么功能? 
      Kuryr:我有NetworkDriver, IpamDriver这些功能,怎样,开心吗? Kuryr如何与Neutron连接

      上面讲的Kuryr如何与Docker Libnetwork连接。再来看看Kuryr如何与OpenStack Neutron对接。由于同是OpenStack阵营下的项目,并且都是Python语言开发的,所以,没有悬念,Kuryr用neutronclient与Neutron连接。所以总体来看,Kuryr的工作方式如下:

      由于Kuryr跟下面实际的L2实现中间还隔了个Neutron,所以Kuryr不是太依赖L2的实现。上图是Gal Sagie列出的Kuryr支持的一些Neutron L2实现方式。在此之外,我试过kuryr-libnetwork和Dragonflow的集成,并没有太多需要注意的地方,有机会可以专门说说这个。

      接下来看看Kuryr-libnetwork如何在Neutron和Docker中间做一个courier。由于北向是Libnetwork,南向是Neutron,所以可以想象,kuryr-libnetwork做的事情就是接收Libnetwork的资源模型,转化成Neutron的资源模型。先来看看Libnetwork的资源模型,也就前面说过的容器网络两派之一CNM。CNM由三个数据模型组成:

      Network Sandbox:定义了容器的网络配置 
      Endpoint:容器用来接入网络的网卡,存在于Sandbox中,一个Sandbox中可以有多个Endpoint 
      Network:相当于一个Switch,Endpoint接入在Network上。不同的Network之间是隔离的。

      对应Neutron,Endpoint是Neutron中的Port,而Network是Neutron中的Subnet。为什么Network对应的不是Neutron中的Network?可能是因为Libnetwork与Neutron的网络定义的区别的,不过至少在一个Neutron Network中只有一个Subnet时,两者在名字上是能对应的。

      除此之外,Kuryr还依赖OpenStack Neutron中的另一个特性:subnetpool。Subnetpool是Neutron里面的一个纯逻辑概念,它能够保证所有在subnetpool中的subnet,IP地址段不重合。Kuryr借助这个特性保证了由其提供的Docker Network,IP地址是唯一的。 Kuryr将Libnetwork发来的请求转换成相应的Neutron的请求,发送给Neutron。

      Kuryr连通容器网络与虚机网络

      但是实际网络的连通,没法通过Neutron的API来告诉Neutron怎么做,Neutron不知道容器的网络怎么接出来,也不提供这样的API。这部分需要Kuryr自己来完成,这也就是Kuryr的Magic所在(否则跟一个代理有什么区别)。最后来看看这部分吧。

      当Docker创建一个容器,并且需要创建Endpoint的时候,请求发送到了作为Libnetwork的remote driver---Kuryr上。Kuryr接到这个请求首先会创建Neutron port:

      neutron_port, subnets = _create_or_update_port( 
      neutron_network_id, endpoint_id, interface_cidrv4, 
      interface_cidrv6, interface_mac)

      之后会根据配置文件的内容,调用相应的driver,目前支持的driver有veth,用来连接主机容器网络,另一个是nested,用来连接虚机内的容器网络。当然,这里的主机,虚机都是相对OpenStack来说的,严格的说,OpenStack的主机也可以是一个虚机,例如我的开发环境。接下来以veth driver为例来说明。先看代码吧:

      try: 
      with ip.create(ifname=host_ifname, kind=KIND, 
      reuse=True, peer=container_ifname) as host_veth: 
      if not utils.is_up(host_veth): 
      host_veth.up() 
      with ip.interfaces[container_ifname] as container_veth: 
      utils._configure_container_iface( 
      container_veth, subnets, 
      fixed_ips=port.get(utils.FIXED_IP_KEY), 
      mtu=mtu, hwaddr=port[utils.MAC_ADDRESS_KEY].lower()) 
      except pyroute2.CreateException: 
      raise exceptions.VethCreationFailure( 
      'Virtual device creation failed.') 
      except pyroute2.CommitException: 
      raise exceptions.VethCreationFailure( 
      'Could not configure the container virtual device networking.') 
      try: 
      stdout, stderr = _configure_host_iface( 
      host_ifname, endpoint_id, port_id, 
      port['network_id'], port.get('project_id') or port['tenant_id'], 
      port[utils.MAC_ADDRESS_KEY], 
      kind=port.get(constants.VIF_TYPE_KEY), 
      details=port.get(constants.VIF_DETAILS_KEY)) 
      except Exception: 
      with excutils.save_and_reraise_exception(): 
      utils.remove_device(host_ifname)

      与Docker网络中的bridge模式类似,Driver首先创建了一个veth pair对,两个网卡,其中一块是container interface,用来接在容器的network namespace,并通过调用_configure_container_iface来进行配置;另一块是host interface,通过调用_configure_host_iface接入到Neutron的L2拓扑中。

      Host interface的处理方式是专门为OpenStack Neutron定制的。这里需要注意的是,不同的SDN底层的L2拓扑是不一样的,OpenVswitch,LinuxBridge,Midonet等等。Kuryr是怎么来支持不同的L2底层?首先,注意看OpenStack Neutron的port信息,可以发现有这么一个属性:binding:vif_type。这个属性表示了该port是处于什么样的L2底层。Kuryr针对不同的L2实现了一些shell脚本,用来将指定的网卡接入到Neutron的L2拓扑中,这些脚本位于/usr/libexec/kuryr目录下,它们与binding:vif_type的值一一对应。所以,Kuryr要做的就是读取Neutron port信息,找到对应的shell脚本,通过调用shell,将veth pair中的host interface接入到OpenStack Neutron的L2 拓扑中。接入之后,容器实际上与虚机处于一个L2网络,自然能与虚机通讯。另一方面,也可以使用Neutron提供的各种服务,Security group,QoS等等。

      目前kuryr支持的L2网络类型有:bridge iovisor midonet ovs tap unbound

      等等,这跟OpenStack Nova使用Neutron的方式是不是很像。Nova调用Neutron API创建port,Nova实际的创建网卡,绑定到虚机中。

OpenStack容器网络项目Kuryr(libnetwork)的更多相关文章

  1. 灵雀云Kube-OVN进入CNCF沙箱,成为CNCF首个容器网络项目

    昨日,云原生计算基金会 (CNCF) 宣布由灵雀云开源的容器网络项目Kube-OVN 正式进入 CNCF 沙箱(Sandbox)托管.这是全球范围内首个被CNCF纳入托管的开源CNI网络项目,也是国内 ...

  2. Docker 0x07: Docke 容器网络

    目录 Docke 容器网络 Container Network Model (CNM) 具体项目中代码对象有哪些 Implementations实现的网络(直接英文版) Libnetwork incl ...

  3. 【Networking】容器网络大观 && SDN 资料汇总

    SDNLAB技术分享(十五):容器网络大观   SDNLAB君• 16-06-17 •2957 人围观 编者按:本文系SDNLAB技术分享系列,本次分享来自SDN撕X群(群主:大猫猫)群直播,我们希望 ...

  4. 容器网络——从CNI到Calico

    从容器诞生开始,存储和网络这两个话题就一直为大家津津乐道.我们今天这个环境下讲网络这个问题,其实是因为容器对网络的需求,和传统物理.虚拟环境对网络环境需求是有差别的,主要面临以下两个问题: 过去Iaa ...

  5. 理解Docker(6):若干企业生产环境中的容器网络方案

    本系列文章将介绍 Docker的相关知识: (1)Docker 安装及基本用法 (2)Docker 镜像 (3)Docker 容器的隔离性 - 使用 Linux namespace 隔离容器的运行环境 ...

  6. 从 Kubernetes 谈容器网络

    基本概念 在 Kubernetes 中.资源从管理粒度上分为三级:容器.Pod.Service. 容器 即 Docker 或者 Rocket 容器(1.0 中仅支持这两种容器). 容器是最低粒度的资源 ...

  7. 干货 | 博云基于OVS自研容器网络插件在金融企业的落地实践

    本文根据博云在dockerone社区微信群分享内容整理 过去几年博云在企业中落地容器云平台遇到了很多痛点,其中一个比较典型的痛点来自网络方面,今天很高兴跟大家聊聊这个话题并介绍下我们基于OVS自研的C ...

  8. 容器网络插件那么多,博云为什么基于OVS深度自研?

    背景 从2015年开始,博云开始基于Kubernetes和容器帮助客户交付应用管理平台.在开始阶段,博云选择了业界使用度非常广泛且成熟稳定的calico作为默认的网络方案并在calico方面积累了大量 ...

  9. 【转】理解Docker容器网络之Linux Network Namespace

    原文:理解Docker容器网络之Linux Network Namespace 由于2016年年中调换工作的原因,对容器网络的研究中断过一段时间.随着当前项目对Kubernetes应用的深入,我感觉之 ...

随机推荐

  1. 修改BlackLowKey皮肤样式,增加占屏比

    页面定制CSS代码 #home { margin: 0 auto; width: 100%; } #sideBar { min-height: 200px; padding: 0 5px 0 5px; ...

  2. js 鼠标拖拽元素

    基础知识 event.clientX.event.clientY 鼠标相对于浏览器窗口可视区域的X,Y坐标(窗口坐标),可视区域不包括工具栏和滚动条.IE事件和标准事件都定义了这2个属性 event. ...

  3. C++读写TXT文件中的string或者int型数据以及string流的用法

    对文件的读写操作是我们在做项目时经常用到的,在网上看了很多博客,结合自身的项目经验总结了一下,因此写了这篇博客,有些地方可能直接从别的博客中复制过来,但是都会注明出处. 一.文件的输入输出 fstre ...

  4. 【Mysql sql inject】【入门篇】sqli-labs使用 part 3【15-17】

      Less-15- Blind- Boolian Based- String 1)工具用法: sqlmap -u --batch --technique BEST 2)手工注入 时间盲注放弃用手工了 ...

  5. JDK8 Lambda表达式对代码的简化

    只是举个例子: public class LambdaDemo { public static String findData( String name , LambdaInterface finde ...

  6. GPIO推挽输出和开漏输出详解

    open-drain与push-pull] GPIO的功能,简单说就是可以根据自己的需要去配置为输入或输出.但是在配置GPIO管脚的时候,常会见到两种模式:开漏(open-drain,漏极开路)和推挽 ...

  7. ES系列十三、Elasticsearch Suggester API(自动补全)

    1.概念 1.补全api主要分为四类 Term Suggester(纠错补全,输入错误的情况下补全正确的单词) Phrase Suggester(自动补全短语,输入一个单词补全整个短语) Comple ...

  8. tomcat下部署应用helloworld

    部署应用(简单)1.到Tomcat的安装目录的webapps目录,可以看到ROOT,examples, tomcat-docs之类Tomcat自带的的目录.2.在webapps目录下新建一个目录mya ...

  9. 安装cactiez v11对windows和linux系统进行监控

    日常运维中我们需要对服务器的流量.CPU占用.硬盘使用及内存.磁盘IP等进行监控和了解,cactiez是一款基于centos6.4定制安装了常用监控软件的系统,安装简单,功能强大很适合快速部署监控系统 ...

  10. Maven编译时,出现找不到符号

    解决办法: 如果使用的是聚合工程 1.执行project--clean(eclipse)或者build project(intellij),将项目清理一下. 2.执行聚合工程中的  Maven--cl ...