文档章节

OpenStack容器网络项目Kuryr(libnetwork)

n
 newlife111
发布于 2017/09/04 16:54
字数 2221
阅读 24
收藏 0

容器近几年非常流行,有很多项目都考虑将容器与SDN结合。Kuryr就是其中一个项目。Kuryr项目在OpenStack big tent下,目的是将容器网络与openstack Neutron对接。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(Container Network 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实际的创建网卡,绑定到虚机中。

下次再接着介绍一下kuryr-kubernetes吧。

本文转载自:https://zhuanlan.zhihu.com/p/24554386

共有 人打赏支持
n
粉丝 9
博文 34
码字总数 15927
作品 0
深圳
高级程序员
私信 提问
基于OpenStack和Kubernetes构建组合云平台——网络集成方案综述

一谈到云计算,大家都会自然想到三种云服务的模型:基础设施即服务(IaaS),平台即服务(PaaS)和软件即服务(SaaS)。OpenStack已经成为私有云IaaS的标准,而PaaS层虽然有很多可选技术,但...

msj0905
06/27
0
0
OpenStack Liberty 版本正式发布,实现新突破

美国时间10月15日,OpenStack基金会正式宣布推出OpenStack云软件的第12个版本 ,即Liberty版本(简称为L版本)。通过对主流数据中心技术的更广泛支持,OpenStack正在成为企业部署和交付云服务...

oschina
2015/10/16
6K
6
OpenStack推出最新版本Newton,显著提升单一云平台 对虚拟化、裸机和容器的管理

2016年10月10日-北京- OpenStack社区日前发布其命名为“Newton”的第14个版本。OpenStack是用于构建云的部署最广泛的开源软件。此次推出的新功能包括:Ironic裸机开通服务,Magnum容器编排集...

玄学酱
05/11
0
0
白皮书:OpenStack与容器的相遇相知(上)

导 读 本文由OpenStack基金会官方发布,来自基金会、用户、厂商的16位专家作者联合撰写,原文请访问:https://www.openstack.org/containers/whitepaper 想象一下,你的任务是从头开始构建整...

lq1ns259ej3okyvk4jf
05/28
0
0
开放基础架构新浪潮:互联网巨头背后的OpenStack

2018年5月21-24日,第十七届OpenStack峰会在温哥华盛大开幕,今年峰会的主题为“Open Infrastructure”。凸显出OpenStack基金会积极拥抱变化,主动求变的态度更加清晰,也是OpenStack基金会开...

云科技时代
05/25
0
0

没有更多内容

加载失败,请刷新页面

加载更多

自定义 Maven 的 repositories

有时,应用中需要一些比较新的依赖,而这些依赖并没有正式发布,还是处于milestone或者是snapshot阶段,并不能从中央仓库或者镜像站上下载到。此时,就需要 自定义Maven的<repositories>。 ...

waylau
54分钟前
1
0
徒手写一个es6代码库

mkdir democd demonpm initnpm install -g babelnpm install -g babel-clinpm install --save-dev babel-preset-es2015-node5 在项目目录创建两个文件夹 functional-playground ......

lilugirl
55分钟前
2
0
linux定位应用问题的一些常用命令,特别针对内存和线程分析的dump命令

1.jps找出进程号,找到对应的进程号后面才好继续操作 2.linux查看进程详细信息 ps -ef | grep 进程ID 3. dump内存信息 Jmap -dump:format=b,file=YYMMddhhmm.dump pid 4.top查看cpu占用信息 ...

noob_chr
55分钟前
1
0
Android TV开发-按键焦点

写在前面 按键焦点过程了解 2.1 dispatchKeyEvent 过程了解 2.2 焦点查找请求过程了解 1.2.1 第一次获取焦点 1.2.3 按键焦点 焦点控制 焦点记忆 应用场景 参考资料 [TOC] 1. 写在前面 工...

冰雪情缘l
55分钟前
1
0
java框架学习日志-3

这章主要是补充一些ioc创建对象的方式,ioc容器在写好<bean></bean>的时候就已经创建对象了。在之前的例子中,一直都是无参的构造方法。下面给出有参的构造方法的对象的创建,没有什么难点重...

白话
57分钟前
2
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部