欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  资讯频道

Neutron的软件架构

程序员文章站 2022-05-03 12:18:33
...
综述

众所周知,OpenStack 是目前开源界第二大的项目,参与的厂商之多可谓少见,实属发展的分布式系统软件大作,面对这么一个项目,我用自己在网络方面的经验与大家分享以 Neutron 为例的 OpenStack 软件设计。

Neutron 简介

Neutron是OpenStack 的虚拟网络组件,用洋气点的话说,就是一个 SDN 控制器。为什么我们需要虚拟网络?过去我们只给客户提供虚拟机,你花钱,我租你一台,想连接上就再买个公网 IP,就像很多人在 DigitalOcean 做得一样(当然 DigitalOcean 现在也有虚拟网络)。那有了虚拟网络可以干什么呢?我们来看一下 UnitedStack 控制面板里的一张图:

Neutron的软件架构

这是一个所见即所得网络架构!我们可以在上面随意的增加、修改和删除2、3层网络、路由器和虚拟机。而且通过虚拟网络,为用户提供自助式的安全组、VPN、负载均衡设备等高级服务也将方便许多。

此外,从软件设计角度来看 Neutron,它做到了 Unified API、Small Core、Pluggable Open Architecture 和Extensible,可以说是一个设计精良的系统。

架构
  • Neutron 的组件设计

作为一个分布式系统,我们需要在不同的节点上运行不同的组件,然后再将之组合起来,形成一个有机的整体,首先我给出 Neutron 在 OpenStack 中宏观的位置:

Neutron的软件架构

这个图是一个比较宏观的图,针对 Neutron 呢,它反映了一些事实:

1.需要借助 Keystone 完成认证服务

2.由 neutron-server 接受请求

3.组件间用消息中间件完成交流

4.消息会在 Server、Plugin 和 Agent 间传递

5.Agent 和 Plugin 与数据库交互

6.Agent 需要调用 Provider 完成功能

下面我们微观的看一下Neutron:

Neutron的软件架构

  • Neutron Server

在上面的图里我们可以看到,Neutron 的服务端是个很复杂的模块,他的复杂之处主要体现在它在”微内核“的基础上实现了 Plugin、Service Plugin、Extension 的插拔,及其与 DB 的交互。

先从请求的入口说起。简单的说,Neutron Server 就是一个 WSGI Application,WSGI 的好处相信不必我多说,它可以方便的增加或者抽取 Middleware,就像一个洋葱一样,把最核心的东西放在里面,别的各种类似Filter的东西一层一层叠在外面就好了。借用一个Pylon官方文档的图:

Neutron的软件架构

只说核心 App,APIRouter,顾名思义,它是用来路由 API 请求的,把 API 请求真正发往那些实现功能的函数,在这里 Neutron 会加载 core plugin 和 plugin extension,扩展它的 Resource map,针对每一个资源集合(比如 networks、subnets、ports 等)建立 Controller,以后 API 将被路由到 Controller 去,Controller 再去调用对应的 create、get、update、delete 方法。同时在这里还可以做一些通用的检查,比如权限、数据有效性、自动转化数据格式等等。

如何清晰的表达一个资源?首先要说明这是一个扩展的资源,而不是新的资源,然后它扩展的是 port,接着是否允许 post、put,需要怎么转换数据格式,用什么做数据验证,是否要做权限检查,默认值多少,在 get 资源时是否显示,就算不懂 Neutron 的人也能看懂这些语句的意思。这里体现了 Neutron/OpenStack 的代码框架设计的优雅高明的地方,节省了程序员写 dirty code 的时间,减少了初学者的学习门槛。
  • Core Plugin and Extensions

为什么在Middleware里要加 Extension 相关的 Filter?很简单,因为 Extension 扩展了 Resource Map,我们需要配置其相应的 URL,那么基础资源是哪些呢?在 Neutron 里,经过一些考虑后,我们把三类资源定义为核心资源,这三类资源分别是network、subnet、port。这三类资源的实现呢,对应的要求由 Core Plugin 来实现。

用户将可以在配置文件里*的设置 Plugin,然后再由NeutronManager加载。其结构也很清晰,CommonDbMixin完成基础的 DB 操作,比如在查询时增加 hook,设置 filter 等,NeutronDbPluginV2做与 Core Plugin 相关的数据库操作,最后 Core Plugin 继承NeutronDbPluginV2以及扩展的类。那么_supported_extension_aliases是做什么的呢,我们前边说 Server 有一层 Filter 去加载 Extension 的 Resource Map,它在查找 Extension 时呢,是先根据目录进行查找的,查找 extensions 目录下的所有 Python 文件,然后每个 extension 都会有一个 alias 名字,extension manager 再去查我们当前加载的 Core Plugin 是否支持这个 Extension,如果支持则加载,否则在日志里记录一下这个"extension not supported by plugin"。
  • Service Plugin

刚才只提到了加载 Core Plugin 和 Extensions,其实加载 Core Plugin 之后就加载 Service Plugin 了,而且因为 Core Plugin 和 Service Plugin 有很多相似的地方,所以 Core Plugin 很多地方也都按照 Service Plugin 去处理,就比如说 Resource Map,我们核心资源是写在RESOURCE_ATTRIBUTE_MAP里的,Plugin Extension 由 Extension Manager 加载,那 Service Plugin 呢?刚才我们说 Extension Manager,并没有区分什么 Plugin Extension Manager 或者 Service Extension Manager,就是因为这两个确实是不做区分的,而且很重要的一点是我们统一的只由 Extension 去扩展资源,就如前面 Filter 只有 Extension 但没有别的,所以如果你需要扩展 Resource Map,那么写一个扩展,然后把它加在你的 Service Plugin 的 supported_extension 里,Server 就可以接受相应的请求并路由了。
  • Agent

把服务端做得优雅,微内核之后,我们就要将调用发到 Agent 端去干活了,首先我们要解决的是 RPC 远程调用的问题。为了简化设计,多应用已成熟的东西,Neutron 或者别的 OpenStack 组件都是使用现有的 MessageQueue 服务完成的,而且 MessageQqueue 的调用有单独抽象出来一个模块叫做 Oslo.Messaging,于是对于 Neutron、Nova 这些服务它们也就不需要去考虑底层的 MQ 支持哪些,该如何调用这些问题了。目前 Oslo.Messaging 支持的 MQ 组件有 RabbitMQ、ZeroMQ 和 Qpid。我们平时用的比较多的 MQ Backend 主要是 RabbitMQ,其对Topic类型消息的处理过程大概如图所示:

Neutron的软件架构

OK,现在消息能发能收了,但可以通讯还不够,我们需要实现远程过程调用,俗称 RPC,在 Neutron 里这主要涉及到两个类:

Neutron的软件架构

右边的Rpcroxy是服务端联系 Agent 用的,而RpcCallback是 Agent 联系服务端用的。在无论消息段还是服务端,都会运行来自oslo.messaging的MessageHandlingServer或类似的类,也就是一个个用绿色线程启的Rpcorker,当RpcWoker收到任务时会去执行相应的调用,在一些 Agent (比如 L3 Agent)里还实现了优先队列,以保证高优先级的任务被首先执行。

总结

将分散在全世界的数百名来自不同厂家,专注不同业务的工程师集合起来,完成一个目前没有成熟标准和现成学习者的软件,不得不说开源社区的力量很强大,它既要保证代码的优秀、自然,还要兼顾不同厂商的利益与差异,能在 3 年多的时间完成一个现在我们已经敢把它部署在 UnitedStack 线上,同时运营着共有云和托管云,支撑数千名客户的稳定高效使用的虚拟网络组件已经表现不俗。在此希望所有对网络虚拟化感兴趣的同学加入进UnitedStack,我们并肩打造一个更加优秀的云计算平台!

来自:王为 UnitedStack
相关标签: Neutron 架构