千家信息网

OpenStack容器网络项目Kuryr的示例分析

发表于:2024-11-27 作者:千家信息网编辑
千家信息网最后更新 2024年11月27日,这篇文章给大家分享的是有关OpenStack容器网络项目Kuryr的示例分析的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。容器近几年非常流行,有很多项目都考虑将容器与SDN
千家信息网最后更新 2024年11月27日OpenStack容器网络项目Kuryr的示例分析

这篇文章给大家分享的是有关OpenStack容器网络项目Kuryr的示例分析的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。

容器近几年非常流行,有很多项目都考虑将容器与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 在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的示例分析"这篇文章就分享到这里了,希望以上内容可以对大家有一定的帮助,让大家可以学到更多知识,如果觉得文章不错,可以把它分享出去让更多的人看到吧!

网络 容器 项目 接口 文件 虚机 内容 实际 就是 接入 方式 模型 不同 名字 拓扑 网卡 脚本 支持 两个 主机 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 永康市明道网络技术有限公怎么样 企恩网络技术有限公司怎么样 支付宝网络安全管理人 东莞软件开发公司哪家好 软件开发行业的科目有哪些 tbc范克瑞斯服务器现状 软件开发工程师是工程师吗 羽末服务器 杭州凌程网络技术有限公司 咸宁专业的软件开发电话 北京软件开发联系人 税务局宣传网络安全知识 辽宁数据软件开发服务应用 宝山区品质软件开发服务生产厂家 呼市零基础app软件开发 软件开发做点什么创业项目好 mysql数据库实现方案 计算机网络技术主要学什 计算机三级网络技术知识点野 网络安全知答题 安信可云服务器 镇江营销软件开发培训学校 永康市明道网络技术有限公怎么样 维普资讯网具有的数据库 亚马逊服务器主动扣款 盛源网络技术服务有限公司 KTV网络技术员工资 鲲鹏数字服务器 数据库核心优势 网络安全法的颁布日期是什么时间
0