云计算是一种按需付费的服务模式,虽然OpenStack前期在计量方面走了些“弯路”,但现在的ceilometer、gnocchi、aodh、panko项目的稳步并进算是让其峰回路转。然而,目前来看OpenStack的计费项目Cloudkitty并未柳暗花明,为此,借助本文向大家介绍Cloudkitty的架构、用户使用指导、开发以及社区方面的最新动态,希望可以吸引更多方面的关注、使用和社区参与。

当前upstream版本Cloudkitty可以完成虚拟机实例(compute)、云硬盘(volume)、镜像(image)、网络进出流量(network.bw.in, network.bw.out)、浮动IP(network.floating)的计费。得益于Cloudkitty的巧妙而优秀的设计,软件插件化思想更是体现的淋漓尽致,使得添加新的计费源异常容易,版本升级也十分方便。同样也能方便将Cloudkitty用于cloudstack、VMWare等环境中。
Cloudkitty主要依赖于遥测相关的项目,包括ceilometer和gnocchi,甚至是将要使用panko;计费策略和hashmap计费模型是其核心;模块插件化是其设计灵魂;接下来的三个部分内容将带您逐步探索。
第一部分:Cloudkitty架构详解本部分为理论架构篇,将会详细介绍当前Cloudkitty的整体架构,包括计费服务的对象获取(Tenant Fetcher)、计费数据源的收集(Collector)、计费引擎(Rating)的实现,计费费用数据的存储(Storage);另外将重点介绍hashmap计费模型。
 一、计费服务对象Tenant FetcherTenant Fetcher是用来获取合法的计费服务对象,即Cloudkitty要知道需要对谁的资源进行计费。当前具体实现了从csv文件中获取和keystone中获取两种方式,分别对应FakeFetcher类和KeystoneFetcher类,均实现了父类的get_tenants抽象方法。所以只要继承基类BaseFetcher实现get_tenants方法,并配置tenant_fetcher后端,就能处理xls文件完成从Excel文档中获取需要计费的租户信息。
Keystone是默认的获取计费租户的方式,同时支持V2和V3版本。具体逻辑是检查Cloudkitty用户是否在某个tenant内并拥有rating角色。所以在使用Cloudkitty时,一般对于想要计费的租户需要执行命令’keystone user-role-add --user cloudkitty --role rating --tenant demo’,将Cloudkitty用户加入租户并赋予rating角色。
 二、计费源数据收集Collector和统一化Transformer单纯从计费角度来看,计费源主要有两类,一类是静态资源,比如虚拟机实例、镜像、云硬盘、浮动IP;一类是动态资源,比如网络流量。对于静态资源一旦被创建,那么它的单价就固定,只需根据其生命周期按时间长短计费即可;对于动态资源需要统计计量情况进行计算费用。这就意味着计费的数据源应该包括event和measurement两部分,但当前Cloudkitty在计费数据收集方面没有加入事件分析能力。
这一步除了计费源数据的收集,还有一个十分重要的工作就是把这些数据转化为统一格式输入给计费引擎。Cloudkitty中的transformer模块将针对不同collector的不同类型的服务数据进行格式统一。这里需要特别说明的是transformer过程一般情况下分为两个阶段:

第一个阶段是将资源数据通过对应的CeilometerTransformer或者GnocchiTransformer进行转换。

第二阶段是使用CloudKittyFormatTransformer统一数据格式为data = [{'usage': {'service_type': [{'vol': {'unit': xx, 'qty': xxx}, 'desc': {'xxx': 'xxx',…, 'metadata': {‘xxx’: ’xxx’}}}]}, 'period': {'begin': xxxxx, 'end': xxxxx}}]交付给计费引擎。当然在不需要对资源数据进行转化的情况下,也可以直接使用CloudKittyFormatTransformer将数据转化为计费引擎所能识别的格式。

collector和transformer模块分别有多种实现,collector实现了ceilometer,fake,gnocchi和 meta四种方式,transformer实现了CeilometerTransformer,GnocchiTransformer以及通用的CloudKittyFormatTransformer三种方式。所以这两个模块分别提供了get_collector和get_transformers方法,根据后端配置动态选择对应的插件,具体是使用stevedore模块的driver方式和extension方式加载实现的。
每种collector的实现最终都会通过retrieve函数将归一化的数据发送给计费引擎。对于ceilometer和fake,这个retrieve函数会根据不同的服务调用get_compute,get_image,get_volume,get_network_bw_in,get_network_bw_out,get_network_floating,这六个方法就分别对应着cloudkitty的计费服务compute, image, volume, network.bw.in, network.bw.out, network.floating。而每个方法获得相关服务数据后会做transformer处理返回给计费引擎,最终计费引擎根据计费模型计算出具体费用再将费用数据存储起来便完成了整个计费流程。

对于gnocchi,它的retrieve函数则有所不同,gnocchi直接使用自己的metric.get_measures和resource.search方法获得相关资源数据。这恰恰也体现了cloudkitty collector模块的插件化,并且实现上非常灵活,意味着如果想为CloudStack,Eucalyptus,OpenNebula等IaaS平台添加collector插件也是件愉快而轻松的事。

 三、计费引擎RatingOrchestrator类是Cloudkitty计费引擎的具体实现,支持多线程,支持多种计费模型同时运行,并能指定优先级。在计费策略上Cloudkitty采用的是周期轮询计费的方式,默认是每一小时对云环境中所需计费的资源进行费用核算,并将费用数据持久化存储起来。还有一个大周期是当月内,如果rated_data_frames表中的数据是空的时候,每次启动cloudkitty-processor就会重新计算当月内每小时的费用(这对调试Cloudkitty也很有帮助)。
Cloudkitty当前的计费模型有三个,分别是noop,hashmap和pyscripts。
1、noop模型为空,仅作为测试用;2、hashmap是当前Cloudkitty实用价值最高,最容易使用,最接近实际案例的计费模型,后文将单独做详细介绍;3、pyscripts计费模型提供了使用python代码定制计费的接口,用户可以直接将含有计费逻辑的python脚本上传给cloudkitty实现定制化的计费,所以pyscripts计费模型使用门槛较高。 计费模型的设计和实现相对比较复杂,首先计费模型要具有enabled和priority属性并能设置,借助stevedore作为插件注册到cloudkitty.rating.processors命名空间内;其次要实现抽象方法process执行具体的费用计算逻辑;最后还需要借助pecan提供对外使用的Rest API接口。但是hashmap计费模型目前能完成绝大部分实际场景需求的计费工作,后文将对它做详细介绍。关于大家关心的按秒计费,需要加入event分析后才比较容易实现,这块内容将在第三部分提到,也是我接下来的主要计划。
 四、费用数据的存储Storage前面提到Cloudkitty的计费引擎是周期性计算资源费用的,而这个周期可以根据实际情况修改,只要能在一个计费周期内完成所有资源的费用计算即可。对应一项资源的服务默认在一个小时的计费周期下,一个月内就会有720条的费用数据生成,如果将计费周期调得更小,云环境中的需要计费的资源更多,那么将会对费用数据的存储带来挑战,它会直接影响到数据的使用效果,因此费用数据的存储也是一个重要的环节。 Cloudkitty的storage目前支持sqlalchemy和gnocchi_hybrid两种方式存放费用数据,因为它们都是通过插件方式实现的,所以具体采用哪种可以通过配置文件指定,再通过get_storage方法获得具体storage实例,十分灵活方便。 Storage的具体实现过程包括:(1)通过抽象方法get_time_frame从存储后端中的数据来确定下一个时间范围。(2)通过append方法将费用数据记入提交缓存,期间可能会通过get_tenants函数和_dispatch函数做预处理或加工。(3)通过commit函数将费用数据写入到后端存储持久化。这个过程会做_pre_commit,_commit,_post_commit一系列的工作确保数据被可靠地存储。(4)对外提供get_total方法,返回费用情况。 sqlalchemy和gnocchi_hybrid的数据格式或者说表的结构都包括begin, end, unit, qty, res_type, rate, tenant_id和对资源描述相关的字段。实际上两种后端存储都是基于SQL实现的,所以随着时间的推移和云环境中需要计费资源的增加,费用数据的增加同样会出现之前类似ceilometer用SQL存储measurement数据带来性能瓶颈的问题。所以将费用数据存储在gnocchi中是必须的,详见https://review.openstack.org/#/c/319425/
 五、hashmap计费模型Hashmap计费模型是Cloudkitty的核心,其数据结构如下图所示,接着是hashmap计费模型中的几个元素及核心概念。

  • Hashmap Group:一个Group表示一组计费规则,例如你可以创建多个计费规则,将它们分成两组来分别为instance和volume计费,避免计费规则混乱。

  • Hashmap Service:一个Service将计费规则映射到具体的数据collector,例如compute,volume,image,network.bw.in,network.bw.out,network.floating。

  • Hashmap Field:一个Field通常是指某个资源元数据metadata字典中的一个字段。例如对于instance,可以指定Field为flavor,availability_zone等;对于volume可以指定Field为volume_type,availability_zone和status等。既可以为Field指定mapping类型的计费规则也能指定Threshold类型的计费规则。

  • Hashmap Mapping: 一个Mapping是指某个最终的计费规则,mapping这类计费规则可以为某个服务指定价格,也可以为Field指定价格。例如你可以指定compute服务的基础价格Flat=10$,这会适用于所有的云主机;同时你也能具体指定flavor name,value=m1.tiny,Rate=1.2,则flavor为m1.tiny的云主机价格就为10$*1.2=12$,value=m1.medium,Flat=20$,则flavor为m1.medium的云主机价格就是20$;再例如指定volume的基础单价为2$,选定Field为volume_type,SATA类型打九五折value=sata,Rate=0.95,则sata盘的单价就是2$*0.95=1.9$;SAS为标准云硬盘不打折,则不用设定,单价依然为2$;SSD为高速硬盘应加价0.2倍value=ssd,Rate=1.2,则ssd盘的单价就是2$*1.2=2.4$。

  • Hashmap Threshold:Threshold是另外一种最终计费规则,threshold这类计费规则更适用于基于level的Rate价格。例如云硬盘基础单价为2$(可用mapping设定),如果用户购买超过50GB,可以打九折Level=50,Rate=0.9,此时单价为2$*0.9=1.8$;超过100GB打八折Level=100,Rate=0.8,此时单价为2$*0.8=1.6$。

通过以上介绍和具体举例,说明hashmap计费模型具有较广泛的使用范围,能满足实际需求中较复杂的计费场景。总结一下hashmap计费模型,它可以直接为资源或者服务设定价格(Flat或者Rate);也能根据资源的Field设定mapping和threshold类型的价格(Flat或者Rate);还能根据资源某字段的Level设定价格(Rate为主)。

OpenStack计费项目Cloudkitty系列详解(一)的更多相关文章

  1. TortoiseGit学习系列之TortoiseGit基本操作拉取项目(图文详解)

    前面博客 TortoiseGit学习系列之TortoiseGit基本操作克隆项目(图文详解) TortoiseGit学习系列之TortoiseGit基本操作修改提交项目(图文详解) TortoiseG ...

  2. TortoiseGit学习系列之TortoiseGit基本操作修改提交项目(图文详解)

    前面博客 TortoiseGit学习系列之TortoiseGit基本操作克隆项目(图文详解) TortoiseGit基本操作修改提交项目 项目克隆完成后(可以将克隆 clone 理解为 下载,检出 c ...

  3. Git学习系列之Git基本操作拉取项目(图文详解)

    前面博客 Git学习系列之Git基本操作推送项目(图文详解) 当然,如果多人协作,或者多个客户端进行修改,那么我们还要拉取(Pull ... )别人推送到在线仓库的内容下来. 大神们是不推荐使用 pu ...

  4. Git学习系列之Git基本操作推送项目(图文详解)

    前面博客 Git学习系列之Git基本操作提交项目(图文详解) 如果完成到一定程度,那么可以推送到远端在线仓库. 推送之前,请确保你已经设置了全局的 user.name 和 user.email, 如果 ...

  5. Git学习系列之Git基本操作提交项目(图文详解)

    前面博客 Git学习系列之Git基本操作克隆项目(图文详解) 然后可以 cd 切换到 LispGentleIntro 目录, 新增或者修改某些文件.这里只是模拟一下操作, 实际情况可能是 使用 Ecl ...

  6. QAction系列详解

    QAction系列详解 一.QAction类详解 [详细描述] QAction类提供了抽象的用户界面action,这些action可以被放置在窗口部件中.        应用程序可以通过菜单,工具栏按 ...

  7. MySQL系列详解八:MySQL多线程复制演示-技术流ken

    前言 Mysql 采用多线程进行复制是从 Mysql 5.6 开始支持的内容,但是 5.6 版本下有缺陷,虽然支持多线程,但是每个数据库只能一个线程,也就是说如果我们只有一个数据库,则主从复制时也只有 ...

  8. Angular-cli新建项目目录结构详解

    Angular-cli新建项目目录结构详解 在上一篇博客中我们已经通过Angular CLI命令行工具创建出来一个全新的Angular项目,要想写项目,首先我们要先搞清楚项目的目录结构是怎样的,每个文 ...

  9. vue-cli3.0 脚手架搭建项目的过程详解

    1.安装vue-cli 3.0 ? 1 2 3 npm install -g @vue/cli # or yarn global add @vue/cli 安装成功后查看版本:vue -V(大写的V) ...

随机推荐

  1. HDU 1069 Monkey and Banana(最长递减子序列)

    题目链接 题意:摞长方体,给定长方体的长宽高,个数无限制,可随意翻转,要求下面的长方体的长和宽都大于上面的,都不能相等,问最多能摞多高. 题解:个数无限,其实每种形态最多就用一次,把每种形态都单独算一 ...

  2. c++的类型转换(转)

    类型转换机制可以分为:隐式类型转换 和 显示类型转换(强制类型转换) C中的类型转换: 事情要从头说起,这个头就是C语言.我们已经习惯了使用C-like类型转换,因为它强大而且简单. 主要有以下两种形 ...

  3. JVM性能调优监控工具详解

    现实企业级Java开发中,有时候我们会碰到下面这些问题: OutOfMemoryError,内存不足 内存泄露 线程死锁 锁争用(Lock Contention) Java进程消耗CPU过高 .... ...

  4. 【驱动】USB驱动实例·串口驱动·键盘驱动【转】

    转自:http://www.cnblogs.com/lcw/p/3159370.html Preface USB体系支持多种类型的设备. 在 Linux内核,所有的USB设备都使用 usb_drive ...

  5. python3中内建函数map()与reduce()的使用方法

    map()的使用    map()的使用方法形如map(f(x),Itera).对,它有两个参数,第一个参数为某个函数,第二个为可迭代对象.如果不懂什么是函数,不懂什么是可迭代对象没关系,记住下面的例 ...

  6. js中图片获取src的正则

    链接: JavaScript 正则表达式:http://www.runoob.com/js/js-regexp.html js正则匹配出所有图片及图片地址src的方法:http://www.jb51. ...

  7. 如何同步删除svn管理的package包目录

    转:https://blog.csdn.net/shiwodecuo/article/details/51754598 eclipse在实际的开发中,当我们的项目由svn进行管理时,若想删除选中的整个 ...

  8. 四、Springboot Debug调试

    描述: 在使用maven插件执行spring-boot:run进行启动的时候,如果设置的断点进不去,要进行以下的设置. 1.添加jvm参数配置 在spring-boot的maven插件加上jvmArg ...

  9. Python_oldboy_自动化运维之路(四)

    本节内容 集合 字符编码与转码 函数语法及基本特性 函数参数与局部变量 返回值和嵌套函数 递归 匿名函数 高阶函数 1.集合 集合是一个无序的,不重复的数据组合,它的主要作用如下: 去重,把一个列表变 ...

  10. git —— 多人协作(远程库操作)

    1.查看远程库信息 $ git remote 2.查看详细远程库信息 $ git remote -v 3.推送分支 $ git push origin 分支名 4.抓取分支 $ git checkou ...