您好,登錄后才能下訂單哦!
這篇文章給大家分享的是有關(guān)OpenStack容器網(wǎng)絡(luò)項(xiàng)目Kuryr的示例分析的內(nèi)容。小編覺(jué)得挺實(shí)用的,因此分享給大家做個(gè)參考,一起跟隨小編過(guò)來(lái)看看吧。
容器近幾年非常流行,有很多項(xiàng)目都考慮將容器與SDN結(jié)合。Kuryr就是其中一個(gè)項(xiàng)目。Kuryr項(xiàng)目在OpenStack big tent下,目的是將容器網(wǎng)絡(luò)與openstack Neutron對(duì)接。Kuryr給人的第一印象是: 這又是一個(gè)在Neutron框架下的項(xiàng)目,能夠通過(guò)Neutron統(tǒng)一的北向接口來(lái)控制容器網(wǎng)絡(luò)的SDN項(xiàng)目。但是實(shí)際上,Kuryr是將Neutron作為南向接口,來(lái)與容器網(wǎng)絡(luò)對(duì)接。Kuryr的北向是容器網(wǎng)絡(luò)接口,南向是OpenStack Neutron。
正式介紹前,先說(shuō)下Kuryr這個(gè)單詞。Kuryr是一個(gè)捷克語(yǔ)單詞kuryr,對(duì)應(yīng)英語(yǔ)里面是courier,對(duì)應(yīng)的中文意思就是信使,送信的人。從這個(gè)名字能看出來(lái),Kuryr不生產(chǎn)信息,只是網(wǎng)絡(luò)世界的搬運(yùn)工。這個(gè)從項(xiàng)目的圖標(biāo)也可以看出來(lái)。另外,由于都是拉丁語(yǔ)系,所以可以不負(fù)責(zé)任的說(shuō),Kuryr的發(fā)音應(yīng)該是與courier類似。
Kuryr最開(kāi)始創(chuàng)立的時(shí)候,其目的是為了提供Docker與Neutron的連接。將Neutron的網(wǎng)絡(luò)服務(wù)帶給docker。隨著容器的發(fā)展,容器網(wǎng)絡(luò)的發(fā)展也出現(xiàn)了分歧。主要分為兩派,一個(gè)是Docker原生的CNM(Container Network Model),另一個(gè)是兼容性更好的CNI(Container Network Interface)。Kuryr相應(yīng)的也出現(xiàn)了兩個(gè)分支,一個(gè)是kuryr-libnetwork(CNM),另一個(gè)是kuryr-kubernetes(CNI)。
kuryr-libnetwork是運(yùn)行在Libnetwork框架下的一個(gè)plugin。要理解kuryr-libnetwork如何工作,首先要看一下Libnetwork。Libnetwork是從Docker Engine和libcontainer中將網(wǎng)絡(luò)邏輯模塊化之后獨(dú)立出來(lái)的的項(xiàng)目,并且替代了原有的Docker Engine網(wǎng)絡(luò)子系統(tǒng)。Libnetwork定義了一個(gè)靈活的模型,使用local或者remote driver來(lái)向container提供網(wǎng)絡(luò)服務(wù)。kuryr-libnetwork就是Libnetwork的一個(gè)remote driver實(shí)現(xiàn),現(xiàn)在已經(jīng)成為Docker官網(wǎng)推薦的一個(gè)remote driver。
Libnetwork的driver可以看是Docker的一個(gè)plugin,與Docker的其他plugin共用一套plugin管理框架。也就是說(shuō),Libnetwork的remote driver與Docker Engine中的其他plugin用一樣的方式激活,并使用同樣的協(xié)議。有關(guān)Libnetwork remote driver需要實(shí)現(xiàn)的接口在Libnetwork的Git上都有詳細(xì)的描述。
kuryr-libnetwork需要做的就是實(shí)現(xiàn)這些接口??梢詮膋uryr-libnetwork的代碼中看出來(lái)。Libnetwork通過(guò)調(diào)用remote driver的Plugin.Activate接口,來(lái)查看remote driver實(shí)現(xiàn)了什么內(nèi)容。從kuryr-libnetwork的代碼中能看到,它實(shí)現(xiàn)了兩個(gè)功能: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注冊(cè)到Libnetwork中呢?這個(gè)問(wèn)題應(yīng)該這樣看,Libnetwork是怎樣發(fā)現(xiàn)Kuryr的?這要依賴于Docker的plugin discovery機(jī)制。當(dāng)用戶或者容器需要使用Docker的plugin的時(shí)候,他/它只需要指定plugin的名字。Docker會(huì)在相應(yīng)的目錄中查找與plugin名字相同的文件,文件中定義了如何連接該plugin。
如果用devstack安裝kuryr-libnetwork,devstack的腳本會(huì)在/usr/lib/docker/plugins/kuryr創(chuàng)建一個(gè)文件夾,里面的文件內(nèi)容也很簡(jiǎn)單,默認(rèn)是:http://127.0.0.1:23750。也就是說(shuō),kuryr-libnetwork實(shí)際上就起了一個(gè)http server,這個(gè)http server提供了Libnetwork所需的所有接口。Docker找到有這樣的文件之后,就通過(guò)文件的內(nèi)容與Kuryr進(jìn)行通信。
所以Libnetwork與Kuryr的交互是這樣:
Libnetwork:有人要用一個(gè)叫Kuryr的plugin,讓我找找看。哦,Kuryr你好,你有什么功能?
Kuryr:我有NetworkDriver, IpamDriver這些功能,怎樣,開(kāi)心嗎?
上面講的Kuryr如何與Docker Libnetwork連接。再來(lái)看看Kuryr如何與OpenStack Neutron對(duì)接。由于同是OpenStack陣營(yíng)下的項(xiàng)目,并且都是Python語(yǔ)言開(kāi)發(fā)的,所以,沒(méi)有懸念,Kuryr用neutronclient與Neutron連接。所以總體來(lái)看,Kuryr的工作方式如下:
由于Kuryr跟下面實(shí)際的L2實(shí)現(xiàn)中間還隔了個(gè)Neutron,所以Kuryr不是太依賴L2的實(shí)現(xiàn)。上圖是Gal Sagie列出的Kuryr支持的一些Neutron L2實(shí)現(xiàn)方式。在此之外,我試過(guò)kuryr-libnetwork和Dragonflow的集成,并沒(méi)有太多需要注意的地方,有機(jī)會(huì)可以專門(mén)說(shuō)說(shuō)這個(gè)。
接下來(lái)看看Kuryr-libnetwork如何在Neutron和Docker中間做一個(gè)courier。由于北向是Libnetwork,南向是Neutron,所以可以想象,kuryr-libnetwork做的事情就是接收Libnetwork的資源模型,轉(zhuǎn)化成Neutron的資源模型。先來(lái)看看Libnetwork的資源模型,也就前面說(shuō)過(guò)的容器網(wǎng)絡(luò)兩派之一CNM。CNM由三個(gè)數(shù)據(jù)模型組成:
Network Sandbox:定義了容器的網(wǎng)絡(luò)配置
Endpoint:容器用來(lái)接入網(wǎng)絡(luò)的網(wǎng)卡,存在于Sandbox中,一個(gè)Sandbox中可以有多個(gè)Endpoint
Network:相當(dāng)于一個(gè)Switch,Endpoint接入在Network上。不同的Network之間是隔離的。
對(duì)應(yīng)Neutron,Endpoint是Neutron中的Port,而Network是Neutron中的Subnet。為什么Network對(duì)應(yīng)的不是Neutron中的Network?可能是因?yàn)長(zhǎng)ibnetwork與Neutron的網(wǎng)絡(luò)定義的區(qū)別的,不過(guò)至少在一個(gè)Neutron Network中只有一個(gè)Subnet時(shí),兩者在名字上是能對(duì)應(yīng)的。
除此之外,Kuryr還依賴OpenStack Neutron中的另一個(gè)特性:subnetpool。Subnetpool是Neutron里面的一個(gè)純邏輯概念,它能夠保證所有在subnetpool中的subnet,IP地址段不重合。Kuryr借助這個(gè)特性保證了由其提供的Docker Network,IP地址是唯一的。
Kuryr將Libnetwork發(fā)來(lái)的請(qǐng)求轉(zhuǎn)換成相應(yīng)的Neutron的請(qǐng)求,發(fā)送給Neutron。
但是實(shí)際網(wǎng)絡(luò)的連通,沒(méi)法通過(guò)Neutron的API來(lái)告訴Neutron怎么做,Neutron不知道容器的網(wǎng)絡(luò)怎么接出來(lái),也不提供這樣的API。這部分需要Kuryr自己來(lái)完成,這也就是Kuryr的Magic所在(否則跟一個(gè)代理有什么區(qū)別)。最后來(lái)看看這部分吧。
當(dāng)Docker創(chuàng)建一個(gè)容器,并且需要?jiǎng)?chuàng)建Endpoint的時(shí)候,請(qǐng)求發(fā)送到了作為L(zhǎng)ibnetwork的remote driver---Kuryr上。Kuryr接到這個(gè)請(qǐng)求首先會(huì)創(chuàng)建Neutron port:
neutron_port, subnets = _create_or_update_port( neutron_network_id, endpoint_id, interface_cidrv4, interface_cidrv6, interface_mac)
之后會(huì)根據(jù)配置文件的內(nèi)容,調(diào)用相應(yīng)的driver,目前支持的driver有veth,用來(lái)連接主機(jī)容器網(wǎng)絡(luò),另一個(gè)是nested,用來(lái)連接虛機(jī)內(nèi)的容器網(wǎng)絡(luò)。當(dāng)然,這里的主機(jī),虛機(jī)都是相對(duì)OpenStack來(lái)說(shuō)的,嚴(yán)格的說(shuō),OpenStack的主機(jī)也可以是一個(gè)虛機(jī),例如我的開(kāi)發(fā)環(huán)境。接下來(lái)以veth driver為例來(lái)說(shuō)明。先看代碼吧:
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網(wǎng)絡(luò)中的bridge模式類似,Driver首先創(chuàng)建了一個(gè)veth pair對(duì),兩個(gè)網(wǎng)卡,其中一塊是container interface,用來(lái)接在容器的network namespace,并通過(guò)調(diào)用_configure_container_iface來(lái)進(jìn)行配置;另一塊是host interface,通過(guò)調(diào)用_configure_host_iface接入到Neutron的L2拓?fù)渲小?/p>
Host interface的處理方式是專門(mén)為OpenStack Neutron定制的。這里需要注意的是,不同的SDN底層的L2拓?fù)涫遣灰粯拥?,OpenVswitch,LinuxBridge,Midonet等等。Kuryr是怎么來(lái)支持不同的L2底層?首先,注意看OpenStack Neutron的port信息,可以發(fā)現(xiàn)有這么一個(gè)屬性:binding:vif_type。這個(gè)屬性表示了該port是處于什么樣的L2底層。Kuryr針對(duì)不同的L2實(shí)現(xiàn)了一些shell腳本,用來(lái)將指定的網(wǎng)卡接入到Neutron的L2拓?fù)渲?,這些腳本位于/usr/libexec/kuryr目錄下,它們與binding:vif_type的值一一對(duì)應(yīng)。所以,Kuryr要做的就是讀取Neutron port信息,找到對(duì)應(yīng)的shell腳本,通過(guò)調(diào)用shell,將veth pair中的host interface接入到OpenStack Neutron的L2 拓?fù)渲?。接入之后,容器?shí)際上與虛機(jī)處于一個(gè)L2網(wǎng)絡(luò),自然能與虛機(jī)通訊。另一方面,也可以使用Neutron提供的各種服務(wù),Security group,QoS等等。
目前kuryr支持的L2網(wǎng)絡(luò)類型有:bridge iovisor midonet ovs tap unbound
等等,這跟OpenStack Nova使用Neutron的方式是不是很像。Nova調(diào)用Neutron API創(chuàng)建port,Nova實(shí)際的創(chuàng)建網(wǎng)卡,綁定到虛機(jī)中。
感謝各位的閱讀!關(guān)于“OpenStack容器網(wǎng)絡(luò)項(xiàng)目Kuryr的示例分析”這篇文章就分享到這里了,希望以上內(nèi)容可以對(duì)大家有一定的幫助,讓大家可以學(xué)到更多知識(shí),如果覺(jué)得文章不錯(cuò),可以把它分享出去讓更多的人看到吧!
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。