openstart源码概述

来源:互联网 发布:梅西绝杀皇马 知乎 编辑:程序博客网 时间:2024/05/22 21:01

倘若对认知的技术很模糊,那么分解将是必不可少的梳理过程!统一性和基本型
—-致

openstack虚拟化部署方式:
1、libvirt驱动:libvirt提供了很好的python绑定,所以基于python的nova只要imput一个名为libvirt的python模块,就可以像c语言程序那样方便地调用libvirt的功能。
libvirt的python模块也提供了类似C库的python类:virConnect代表一个到VMM的连接,virConnect代表了一个虚拟机。
2、XenAPI驱动:比如XenAPI有”主机池”概念,是指一些共享存储的宿主机的集合,在主机池中进行动态迁移就没有必要迁移虚拟磁盘。这对Nova的实现十分重要(openstack与
虚拟化联系最紧密的是nova!)
http://www.alice.org/wp-content/uploads/2017/08/Alice3_unix_3_3_1_2.sh

openstack项目的架构:
1、openstack项目都是通过RESTful API向外提供服务。(RESTful—-互联网软件架构 >>>>> 此架构核心概念是”资源”。)
2、WSGI(web网关接口)则是python语言中定义的web服务器和web应用程序或架构之间的通用接口标准。也可把WSGI理解为服务端和应用端交互的一种包装,经过不同中间件的包装,便具有不同的功能,比如URL路由转发,在比如权限认证。这些不同中间件的组合便形成了WSGI的框架,比如paste。
3、openstack使用paste的deploy的组件来完成WSGI服务器和应用的构建,每个项目源码的etc目录下都有一个paste配置文件。
4、除了routers和paste deploy外,openstack中另一个与WSGI密切相关的是webob。webob通过对WSGI的请求与响应进行封装,来简化WSGI应用的编写。webob中两个重要的对象:
一是webob.request,对WSGI请求的environ参数进行封装;
一是webob.response,包含了标准WSGI响应的所有要素。
5、所有项目的源码目录都可以在/usr/lib/python2.7/site-packages/项目名称/下查到。比如:若为计算项目则把前句项目名称处改为nova,则进入可查看到nova源码!!

*单独说明(openstack模块源码简介):*

nova api的实现:
1、nova api请求路由:
nova api目录在:/usr/lib/python2.7/site-packages/nova/api,其目录下metadata文件夹是提供给所创建的虚拟机来获得一些配置信息的API。
nova api目录下:openstack文件夹下包含WSGI基础架构代码以及如何解析请求和分发请求的核心代码。
/usr/lib/python2.7/site-packages/nova/api/openstack/compute中可以找到对应每个API的入口点。
nova使用python paste作为工具来加载WSGI stack。WSGI stack通过文件/etc/nova/api-paste.ini配置。当解析每个URL请求的时候,可以通过URL映射找到API对应的resource object,目录文件/usr/lib/python2.7/site-packages/nova/wsgi.py。
2、nova API的实现:
/usr/lib/python2.7/site-packages/nova/api/openstack/compute此目录下打开keypairs类的文件是keypairs.py:(以下注解皆在配置文件内)
keypairs类描述了要注册的资源或者所要扩展的资源。
get_resourxes方法用来返回所要注册的资源,这里(见配置文件326–)注册了一个资源,名字为ALIAS所指定,此资源所对应的controller是keypairscontroller。
配置文件内除了添加新资源还可以扩展现有资源,扩展新资源见配置文件38–261。
其中多个声明代表对应不同版本的microversion,方法所对应的microversion通过decorator”wsgi.Controller_version”来指定。
分别对应配置文件中@wsgi.Controller.api_version后所代表的版本。
错误返回码在配置文件的@extensions.expected_errors((400, 403, 409)),代表拦截了所有未预期的错误。
@wsgi.response(201)则表示API请求正常返回码。
再然后通过方法的接口可以得到webob.request对象,从request对象中可以获取其他请求参数。除了这些标准的CURD方法,还可以添加action,从/usr/lib/python2.7/sitepackages/nova/api/openstack/compute/下的evacuate.py中可以看到如何注册evacuate action(配置文件中75—)。
3、版本升级(rolling upgrade的实现)之nova:
实现rolling upgrade需要的技术—RPC versioning、VersionedObject、Conductor
RPC versioning:保证了不同组件在不同版本的通信兼容性(RPC接口文件:/usr/lib/python2.7/site-packages/nova/compute/rpcapi.py)
VersionedObject:保证了组件通信对于复杂数据的兼容性
Conductor:帮助翻译这些数据,在整个nova中相当于组织者的角色(源码目录在:/usr/lib/python2.7/site-packages/nova/conductor)
conductor配置文件简介:
在目录下,rpcapi.py文件与RPC相关,其他服务奖这个模块导入就可以使用它提供的接口远程调用nova-conductor提供的服务,nova-conductor注册的RPC Server接受到RPC的请求后,再由manager.py文件中的类ComputeTaskManager和ConductorManager来完成任务的编排以及数据库访问的代理。此服务访问的特殊性,api.py文件中又对接口的调用做了一层封装,其他模块需要导入的是api模块,而不是rpcapi模块。
nova-compute所有访问数据库的动作都要通过Nova Objects交给nova-conductor来完成。所以出于安全性考虑,nova-conductor和nova-compute不能部署一服务器上
4、versioned object model:
nova数据库访问方式与对象构建过程的解耦:在object model支持远程数据库访问的同时,也能支持已有的本地直接访问数据库的功能。
object model代码位于/usr/lib/python2.7/site-packages/nova/objects目录,文件目录内的每一个类都对应数据库中的一个表,比如ComputeNode对应了数据库compute_nodes

Swift体系结构:
1、作为对象存储的一种,Swift比较适合于存放静态数据。静态数据是指长期不更新数据或者更新频率低的数据,比如虚拟机的镜像、多媒体数据以及数据的备份。若需实时
更新数据,那么Cinder块存储较合适。
2、与其他openstack项目一样,Swift提供了RESTful API作为访问的入口,存储的每个对象都是一个RESTful资源拥有一个唯一的URL。
3、swift从架构上分为两个层次:访问层与存储层。

访问层的功能类似于网络设备中的Hub(多端口的转发器),主要包括两个部分,即Proxy Node(代理服务节点)和authenication(认证),分别负责RESTful请求的处理和用户身份认证。
Proxy Node上运行有Proxy Server来负责用户的RESTful请求,接受用户请求并进行身份验证。(转发给认证服务处理)
Proxy Server可以使用Memcached(高性能的分布式内存对象缓存系统)进行数据和对象的缓存。(减少数据库读取次数,提高用户访问速度)
存储层是由一系列的物理存储节点组成,负责对象数据的存储。存储层在物理层又分为:
Region:地理上隔绝的区域,也就是说不同的region通常在地理位置上被隔绝开来。
Zone:在每个region的内部又划分了不同的Zone来实现硬件上的隔绝。可以简单理解为Zone代表了一组独立的存储节点。
Storage Node:存储对象数据的物理节点,基于通用标准的硬件设备提供了不亚于专业存储设备的对象存储服务。(在此又在逻辑上分为三个层次:Account/Container/Object)
之上的逻辑性三个层次可以任意扩展。其中account在对象的存储过程中实现顶层的隔离,所代表的并不是个人账户而是租户。一个account可以被多个账户共同使用。
container代表了一组对象的封装,类似文件夹或目录,但是不能嵌套。
object则是具体的对象,由元数据和内容两部分组成。(故Swift要求一个对象必须存储在某个Container中,因此一个Account应该至少有一个container提供对象的存储)。
然后为了保证数据在某个存储硬件损坏的情况下也不会丢失,swift为每个对象都建立了一定数量的副本(replica,默认三个月),并且每个副本都存放在不同的Zone中,即便某个zone损坏,swift也可以通过其他Zone继续提供服务。
由于每个对象并不是只保存了一份,所以对象和副本之间的数据必须一致性,swift通过3中服务解决数据一致性的问题:
auditor:通过持续扫描磁盘来检查account、container、object的完整性,如果发现损坏,auditor会对文件进行隔离,通过replicator从其他对应副本恢复本地数据。
update:在创建一个container的时候需要对包含该container的account的信息进行更新,使得该account的数据库里面的container列表包含这个新创键的container。
replicator:负责检测各个节点上的数据及其副本是否一致。若不一致会更新为最新版本,并且负责将标记为删除的数据真正从物理介质上删除。
虽然对象最终仍以文件的形式存储在存储节点上,但是swift中并没有”路径”和”文件夹”这样的概念,所以引入了环(ring)的概念:
ring记录了存储对象与物理位置之间的映射关系,Account/Container/Object都有自己的ring。ring通过Zone、Device、Partition和Replica的概念来维护映射信息。

一些swift文件
/usr/bin/swift-proxy-server:代理服务(proxy server)进程
/usr/bin/swift-account-auditor:对应Account
/usr/bin/swift-container-auditor:对应Container
/usr/bin/swift-object-auditor:对应Object的Auditor(审计)进程

Swift中所谓的Ring就是基于一致性Hash所构造的环,数据结构包含三种:
设备表:设备表中的每一项都对应一个Device(设备),其中记录了Device的具体位置信息,包括Device ID、所在的Region、Zone、IP地址以及端口号,以及用户的权重(Weight)。
设备查新表:存储Partition的各个副本(默认是3个)与具体Device的映射信息。
partition移位值:表示在Hash之后将Object名字二进制移位的位数。
构建Ring:Swift使用swift-ring-builder工具构建一个ring。(也就是构建一个设备查询表)
通过源码让我们了解构建Ring的过程:

源码说明:
swift-ring-builder工具源码位于/usr/bin/swift-ring-builder脚本。这个脚本只是对swift.cli.ringbuilder模块的封装,直接调用了swift.cli.ringbuilder的main函数。
完成一定的参数解析等工作后,最终使用swift.cli.ringbuilder.Commands类的create()函数去完成ring的创建。此函数逻辑:
主要是创建一个swift.common.ring.builder.RingBuider类的实例,然后将初始化信息保存到Ring的builder文件和备份文件里。
源码文件:/usr/lib/python2.7/site-packages/swift/common/ring/builder.py(59—)。
若构建Ring的步骤完成,需执行swift-ring-bilder的add命令添加设备到Ring中,和create命令类似,add命令由swift.cli.ringbuilder.Commands类的add()函数完成。
源码文件:/usr/lib/python2.7/site-packages/swift/cli/ringbuilder.py
最终使用swift.common.ring.builder.RingBuider类的实例的add_dev()函数完成设备的添加(builder.py源码,326—)。
对于之上步骤的详细解说
一、HTTP请求到WSGI Application(Proxy Server的配置文件/usr/bin/swift-proxy-server):
1、首先run_wsgi函数会启动Proxy Server监听用户的HTTP请求,Paste Deploy会在这个WSGI Server创建时参与进来,然后通过Paste配置文件(/etc/swift/proxy-server.conf)去加载特定的WSGI Application。
配置文件解释:配置文件中的pipeline(17—)定义的除了最后一个proxy-server,其他app都是作为filter的角色。
配置文件解释:其中”egg:swift#proxy”(29–)表示使用swift包中的proxy模块。
配置文件解释:其中”[filter:slo]”定义中的”egg:swift#slo”(79–)表示使用swift包中的slo模块。
二、WSGI Application到对应的Controller
proxy-server根据请求的信息调用相应的Controller中的函数。与3个对象相对应分别为:AccountController、ContainerConntroller、ObjectController。相应的目录则在/usr/lib/python2.7/site-packages/swift/proxy/controllers目录
三、存储节点上的Account Server、Container Server、Object Server
Account Server:配置文件位于/etc/swift/
container server:使用swift.container.server模块的app_factory()函数加载Container Server的WSGI Application。
Object Server:使用swift.obj.server模块的app_factory()函数加载Object Server的WSGI Application。
认证:
1、swift支持外部和内部两种认证方式:
外部是指Keystone服务认证。
内部是指通过swift的WSGI中间件Tempauth来认证用户。
2、具体使用何种方式认证在Proxy Server的Paste Deploy配置文件/etc/swift/proxy-server.conf(17–)中进行设置。
如果使用Tempauth,需要在配置文件tempauth部分(35–)定义用户的信息。格式为:user__ = [group] [group] […] [storage_url]
key就是密码。group有两种,一种是.reseller_admin,具有对任何Account操作的权限;另一种是.admin,只能对所在Account进行操作。最后的storage_url用于在认证之后向用户返回swift的URL。(具体例子可在配置文件内查看)

linux虚拟网络
虚拟机的网络功能由虚拟网卡(vNIC)提供,Hypervisor(拟机的生成与管理)可以为每个虚拟机创建一个或多个vNIC,在虚拟机的角度,这些vNIC等同于物理的网卡。为了实现与传统物理网络等同的网络结构,与NIC(网卡)一样Switch(交换机)也被虚拟化为虚拟交换机(vSwitch),各个vNIC连接在vSwitch的端口上,最后这些vSwitch通过物理Server的物理网卡访问外部的物理网络。
由此可见,对于一个虚拟的二层网络结构来说,主要是完成两种网络设备的虚拟化:NIC硬件和交换设备。网络虚拟化的形式有以下几种,neutron也是基于这些完成私有虚拟网络network的构建。

TAP/TUN/VETH:
TAP/TUN是linux内核实现的一对虚拟网络设备,TAP工作在二层,TUN工作在三层,linux内核通过这两个设备向绑定该设备空间的用户空间程序发送数据,反之亦然。
基于TAP驱动,即可以实现虚拟网卡的功能,虚拟机的每个vNIC都与Hypervisor中的一个设备相连。当一个TAP设备歘创建时,在linux设备文件目录下将会生成一个。
对应的字符设备文件,用户程序可以像打开普通文件一样打开文件进行续写。
VETH设备成对出现,送到一端请求发送的数据总是从另一端以接受的形式出现。

linux Bridge(网桥):
工作于二层的虚拟网络设备,功能类似于物理的交换机。Bridge可以绑定其他linux网络设备作为从设备,并将这些从设备虚拟化为端口,当一个从设备被绑定到Bridg。
上时,就相当于真实网络中的交换机端口插入一个连接终端的网线。
比如:Bridge设备br0绑定了实际设备eth0与虚拟设备tap0/tap1,此时,对于Hypervisor的网络协议栈上层来说,只看到br0,并不会关心桥接细节。当这些设备接受到。
数据包时,会将其提交给br0决定数据包的去向,br0会根据MAC地址与端口的映射关系进行转发。因此只需为br0设置IP,比如10.0.1.0/24。此时,eth0、tap0/1均通过br0处于此网。
对于虚拟网络来说,交换设备的虚拟化是很关键的一环,vSwitch负责连接vNIC与物理网卡,同时也桥接同一物理Server内的各个vNIC。

Open vSwitch:
在云环境中,仅凭物理交换机的支持,管理员无法区分被桥接的物理网卡上流淌的数据包属于哪个VM、OS以及用户。Open vSwitch的引入则使云环境中虚拟网络的管理以及对网络状态和流量的监控变得容易。
比如,我们可以像配置物理交换机一样,将接入到Open vSwitch上的各个VM分配到不同VLAN中实现网络隔离。我们也可以在Open vSwitch端口上为VM配置Qos(Qos是网络的一种安全机制),同时Open vSwitch也支持包括NetFlow(数据交换方式及数据流的统计信息)、sFlow(一种网络监测技术很多标准的管理接口和协议。
Open vSwitch在云环境中的各种虚拟化平台上(如Xen和KVM)实现了分布式的虚拟交换机,一个物理Server上的vSwitch可以透明的与另一Server上的vSwitch上的vSwitch连接在一起。

neutron网络抽象
我们知道neutron通过L3的抽象router提供路由器的功能,通过L2的抽象network/subnet完成对真实二层物理网络的映射,并且network有linux bridge、open vswitch等实现方式。除此之外,在L2中,neutron还提供了一个重要的抽象port,代表了虚拟交换机上的一个虚拟交换端口,记录其属于哪个网络以及对应的IP等信息。
neutron主要实现了以下几种网络类型:
·flat:flat类型的网络不支持VLAN,因此不支持二层隔离,所有虚拟机都在一个广播域。
·VLAN:与flat相比,VLAN类型的网络自然会提供VLAN的支持。
·NVGRE:是点对点的IP隧道技术,可以用于虚拟网络互联。NVGRE容许在CRE内传输以太网帧,而CRE key拆成两部分,前24位作为tenant ID,后8位作为entropy用于区分隧道两端连接的不同虚拟网络。
·VxLAN:技术的本质是将L2层的数据帧头重新定义后通过L4层的UDP进行传输。相较于采用物理VLAN实现的网络虚拟化,VXLAN是UDP隧道,可以穿越IP网络,使得两个虚拟VLAN可以实现二层联通。

neutron架构
1、neutron API:
类似于nova对API资源的管理方式,neutron也将基于各种网络抽象得到的API资源分为核心资源(Core API)与扩展资源(extension API)两种,core API只对应L2层的network/
subnet/port3中抽象,其余的各层抽象都含盖在extension API的范围。neutron API实现的主要代码位于/usr/lib/python2.7/site-packages/neutron/api:
api_common.py:一些API实现通用的类和方法;
extensions.py:neutron API extension接口定义;
目录内的rpc目录:
·agentnotifiers:非核心资源的agent(L3/DHCP等)的rpc接口;
·callbacks:neutron实现的注册回调机制;
·handlers:plugin对agent的rpc接口(非核心);
v2目录:
attributes.py:核心资源的API属性定义及相关函数;
base.py:WSGI controller的基类;
resource.py:WSGI resource的基类;
resource_helper.py:resource的辅助性函数;
router.py:API router;
versions.py:用户请求是版本号时,使用这个模块进行处理;
2、ML2 Plugin
ML2解耦了网络拓扑类型与底层的虚拟网络实现机制,并分别通过driver的形式进行扩展,其中,不同的网络拓扑类型对应着type driver,由type manager管理,不同的网络实现机制对应着mechanism driver,由mechanism manager管理。
ML2 Plugin的源码结构:
config.py:一些配置选项定义
driver_api.py:定义typedriver/mechanismdriver的基类
drivers:各种typedriver/mechanismdriver的实现
managers.py:定义typedriver/mechanismdriver的类
rpc.py:与agent进行RPC交互
plugin.py:类Ml2Plugin实现(Ml2Plugin类配置文件99—) ☟☟☟
这里写图片描述
我们看到它是通过继承众多的Mixin,能够支持许多功能。由于具体设备的操作由Agent来完成,ML2 Plugin本身实际上大都是在完成基于数据的一些操作,致力于正确有效地管理network/port/subnet这些资源及其相互关系,同时正确地与Agent交互从而完成虚拟网络部署。
ML2也支持许多扩展的资源,同样Ml2Plugin里有定义,详情见配置文件127—
这里写图片描述
比如执行neutron的客户端命令创建网络,并开启debug模式,这容许我们直接直接地看到传递给Plugin的各个参数的生成过程:
通过Router模块的路由,这个命令最终由Plugin的create_network()函数来完成(见配置文件772—)
这里写图片描述
port binding扩展:
有两种扩展方式:一种是为network/port/subnet增加属性;另一种就是增加一些新的资源,比如VPNaas。
externtion API的定义都位于/usr/share/openstack-dashboard/openstack_dashboard/dashboards/project/networks/ports/extensions,它们的基类以及一些公用的代码则位于/usr/lib/python2.7/site-packages/neutron/api/extensions.py文件,添加新的资源需要实现get_resources()方法,而扩展则需实现get_extended_resources()方法。
port binding只是对port的扩展并不引入新的资源,只需要实现get_extended_resources()方法(见:/usr/lib/python2.7/site-packages/neutron/extensions/portbindings.py)。

注:书籍参考《openstack设计与实现》、《openstack最佳实践—测试与CI/CD》等

原创粉丝点击