首页 > 代码库 > CloudFoundry基础知识学习
CloudFoundry基础知识学习
1 CloudFoundry简介
CloudFoundry是VMware旗下子公司Pivotal的一款开源PaaS产品,是一个由多个独立子系统组成的分布式系统,能偶支持多种运行时环境、开发语言、框架及服务,可以构建于IaaS平台之上,也可以直接部署于物理机器上,总共有两个版本分别是V1和V2,V2版本采用的更为成熟的架构思想,引入了如Buildpack、Warden等强大灵活的组件。
Cloud Foundry v1已于2013年1月底停止开发与维护,v2版本主要有以下变化:
1.v1中Router使用的是nginx+lua+ruby server的方式,v2使用了go语言gorouter,据称支持了websocket且极大提升了性能;
2.v2中Cloud Controller新增了quota、org、space等新的概念,更方便的进行权限和资源管理;
3.v1中为应用打包使用的是Stager组件,v2中移除了该组件,将打包功能加入到DEA中,另外完全重写了Health Manager;
4.v1里DEA可以独立运行,一个DEA负责的所有app都以子进程的形式挂在DEA主进程下,但v2之后DEA强依赖于Warden提供的安全容器来运行app了。
Cloudfoundry 的部分特色:
1、 基于消息的多组件架构是实现集群的简单、且有效方法。消息可以使集群节点间解耦,使自注册,自发现这些在大规模数据中心中很重要的功能得到实现;
2、 适当的抽象层,模板模式的使用,方便第三方可以方便在CloudFoundry开发扩展功能。CloudFoundry在DEA及Service层都做了抽象层处理,相对应地使开发者可以容易地为CloudFoundry开发Runtime和Service。例如,在CloudFoundry刚推出的时候,只支持Node.js, Java, Ruby,但第三方提供商、开源社区快速跟进,为CloudFoundry添加了PHP, Python的支持。这得益于CloudFoundry精巧的DEA架构设计。
2 Cloud Foundry v2的架构及流程示意图:
注:配合名词解释看架构图
3 CloudFoundry V2 主要名词解释
3.1 CloudController
CC即Could Controller,CloudFoundry V2版本中叫CC_ng,是CloudFoundry的管理模块,主要负责为cf、vmc、sts等客户端提供REST API接口,管理App的整个生命周期的状态及运行环境、日志等,是基于Fog组件规范的接口。
用户通过命令行工具cf与CloudFoundry Server打交道,实际主要就是和Cloud Controller交互。用户把app push给Cloud Controller,Cloud Controller将其存放在Blob Store,在数据库中为该app创建一条记录,存放其meta信息,并且指定一个DEA节点来完成打包动作,产出一个droplet(是一个包含Runtime的包,在任何dea节点都可以通过warden run起来),完成打包之后,droplet回传给Cloud Controller,仍然存放在Blob Store,然后Cloud Controller根据用户要求的实例数目,调度相应的DEA节点部署运行该droplet。另外,Cloud Controller还维护了用户组织关系org、space,以及服务、服务实例等等。
3.2 DEA
DEA组件全称Droplet Execution Agent,相当于部署App应用的容器,用于管理应用实例的整个生命周期,能够与CC组件通讯进行应用实例的启动和停止,在应用实例的整个生命周期中,DEA都会对其保持跟踪监控,并周期性地通过NATS消息组件将应用实例的状态信息进行广播(主要是被Health manager组件接收);最新版本的DEA组件(DEA_next)与老版本的DEA组件相比,优势在于新版本更具模块化,并且测试的覆盖面更广,而且还有一个非常大的改进:依赖Warden组件进行应用实例隔离;DEA中的还有个组件叫Director server,基于Go语言编写,当有请求发起时,DEA响应请求并重定向到director server,在DEA对该URL请求作出处理之前由director server验证其有效性。
DEA,部署在所有物理节点上,管理app实例,将状态信息广播出去。比如我们创建一个app,实例的创建命令最终会下发到DEA,DEA调用warden的接口创建container,如果用户要删除某个app,实例的销毁命令最终也会下发到DEA,DEA调用warden的接口销毁对应的container。
3.3 Warden
Warden是CloudFoundry的一个基础组件,用来在Unix系统环境中构建独立、完全隔离的资源环境,能够对CPU、内存、硬盘资源、网络资源进行控制。
当CloudFoundry刚刚推出的时候,Droplet包含了应用的启动、停止等简单命令。用户应用可以随意访问文件系统,也可以在内网畅通无阻,跑满CPU,占尽内存,写满磁盘,一切可以想到的破坏性操作都可以做到。CloudFoundry显然不会放任这样的情况太久,现在他们开发出了Warden,一个程序运行容器。这个容器提供了一个孤立的环境,Droplet只可以获得受限的CPU,内存,磁盘访问权限,网络权限,再没有办法搞破坏了。
Warden在Linux上的实现是将Linux内核的资源分成若干个namespace加以区分,底层的机制是CGROUP。这样的设计比虚拟机性能好,启动快,也能够获得足够的安全性。在网络方面,每一个Warden实例有一个虚拟网络接口,每个接口有一个IP,而DEA内有一个子网,这些网络接口就连在这个子网上。安全可以通过iptables来保证。在磁盘方面,每个warden实例有一个自己的filesystem。这些filesystem使用aufs实现的。Aufs可以共享warden之间的只读内容,区分只写的内容,提高了磁盘空间的利用率。因为aufs只能在固定大小的文件上读写,所以磁盘也没有出现写满的可能性。
LXC是另一个Linux Container。那为什么不使用它,而开发了Warden呢。因为LXC的实现是和Linux绑死的,CloudFoundry希望warden能运转在各个不同的平台,而不只是Linux。另外Warden提供了一个Daemon和若干Api来操作,LXC提供的是系统工具。还有最重要的一点是LXC过于庞大,Warden只需要其中的一点点功能就可以了,更少的代码便于调试。
3.4 Health Manager
Health Manager最初是用Ruby写的,后来用golang写了一版,称为HM9000,HM9000主要有四个核心功能:
· 监控app的实际运行状态(比如:running, stopped, crashed等等),版本,实例数目等信息。DEA会持续发送心跳包,汇报它所管辖的实例信息,如果某个实例挂了,会立马发送“droplet.exited”消息,HM9000据此更新app的实际运行数据;
· HM9000通过dump Cloud Controller数据库的方式,获取app的期望状态、版本、实例数目;
· HM9000持续比对app的实际运行状态和期望状态,如果发现app正在运行的实例数目少于要求的实例数目,就发命令给Cloud Controller,要求启动相应数目的实例。HM9000本身,不会要求DEA做些什么。它只是收集数据,比对,再收集数据,再比对;
· 用户通过cf命令行工具是可以控制app各个实例的启停状态的,如果app的状态发生变化,HM9000就会命令Cloud Controller做出相应调整;
HM9000就是保证app可用性的一个基础组件,app运行时超过了分配的quota,或者异常退出,或者DEA节点整个宕机,HM9000都会检测到,然后命令Cloud Controller做实例迁移。HM9000的代码在这里:https://github.com/cloudfoundry/hm9000
Health Manager模块目前还不是十分完善,但是Cloud Manage栈里面,自动化health管理、分析是一个很重要的领域,而这方面可以扩展的地方也很多,结合Orchestration Engine可以使云自管理、自预警;而与BI方面技术结合,可以统计运营情况,合理分配资源等,这方面CloudFoundry还在发展之中。
3.5 Buildpack
Buildpack通常是ruby工程,由若干ruby脚本和配置文件组成,包含了APP应用部署运行所需要的所有环境,包括语言框架和运行时环境,CloudFoundry原生支持Ruby、Java、Node.js及其主流框架,另外,Heroku等第三方的Buildpack也能部分支持,APP应用上传部署的过程中,CloudFoundry会检测APP配置以确定哪个buildpack能够适用,第三方的开源buildpack需要在部署的时候手动指定:cf push --buildpack URL。
举例来说,如果把一个php应用放置在某个路径下,然后将apache配置好,最后写一个启动脚本,然后将apache, php应用代码和启动脚本打成一个压缩包。在另外一台环境完全相同的机器上,你只需要下载这个压缩包,解压到对应目录下,然后启动脚本,应用就可以完美的复制到这台机器上。一个打好压缩包就是一个droplet,打压缩包的程序就叫buildpack,打包的过程叫staging。不同的应用类型对应的buildpack代码也不同。如果要增加一门cloudfoundry默认不支持的语言或者应用类型,就需要自定义buildpack。
当前版本默认支持的buildpack有java buildpack、ruby buildpack、nodejs buildpack三种,所以如果增加java、ruby、nodejs应用几乎不用上传这些应用需要的相关环境文件,只需要上传app应用就可以在dea上部署,如果新增的app需要的环境不是上述三种buildpack能够支持的,例如app需要的runtime是pyp,则需要新增一个自定的buildpack。
3.6 Router
V2版本的Router组件改为Gorouter,是基于Go语言编写的,用于CF平台到各组件(如CC,DEA等)的网络路由。Router通过定制实现了对所有连接到Router的网络连接的控制,从而能够更好地支持websocket和其他一些网络协议如HTTP等,所有的路由逻辑都有其独占的进程,减少一些不必要的网络延迟。Gorouter在CF平台上运行时,需要随时通过NATS消息进行更新,默认情况狂下,2分钟未接收到NATS消息,则该route将会被废弃,以释放资源,所以如果需要保存route激活状态的话,最起码得2分钟内对其进行一次更新操作。
Gorouter提供了两个HTTP接口进行监控管理:/varz和/healthz。/routes接口的返回结果是JSON格式的路由表信息,每个Route都有一个对应的接口信息数组。这些接口都要求身份认证,认证信息通过gorouter.yml文件进行配置,其中有端口、用户名、密码等配置项。
Router是整个平台的流量入口,负责分发所有的请求到对应的组件,包括来自外部用户对app的请求和平台内部的管理请求。它在内存中维护了一张路由表,记录了域名与实例的对应关系,所谓的实例自动迁移,靠得就是这张路由表,某实例宕掉了,就从路由表中剔除,新实例创建了,就加入路由表。
CloudFoundry1.0中的router是用nginx+lua嵌入脚本实现的,2.0用golang重写,更名为gorouter,性能有所提升,并声称试图解决websocket请求和tcp请求(虽然这在笔者看来是没用的),它的代码https://github.com/cloudfoundry/gorouter
3.7 UAA
UAA组件全称User Account and Authentication,是基于java语言进行开发,使用Maven进行包管理的一个子项目,主要用于CF平台的身份认证管理,事实上,它并不是CF平台的内部组件,而是一个基于OAuth2和OpenID通用身份认证规范的独立功能组件,可以用于CF平台的身份认证,也可以为其他项目提供SSO单点认证服务。
3.8 Droplet
Droplet---封装包(不好解释,暂且将其中文名称为封装包),是应用程序经过Staging(不好解释,暂且将其中文名称为封装)过程产生的一个可以执行运行的程序包,源于程序,封装后会留有一个端口用于监听HTTP请求,同时包含2个可执行动作:启动、停止,这个包里边会包含以下内容:
- 应用程序包(APP)
- 运行环境配置文件
- 管理控制脚本
3.9 Service Brokers
app在运行的时候通常需要依赖外部的一些服务,比如数据库服务、缓存服务、短信邮件服务等等。Service Broker就是app接入服务的一种方式。比如我们要接入MySQL服务,只要实现CloudFoundry要求的Service Broker API即可。但实际情况是在我们使用CloudFoundry之前,MySQL服务已经由DBA做了服务化、产品化,用起来已经很方便了。有必要实现其Service Broker API,按照CloudFoundry这套规则出牌么?笔者认为没有这个必要。app仍然按照之前访问MySQL服务的方式去做即可,没有任何问题。
3.10 Message Bus
NATS是一个分布式的消息发布和订阅系统,CloudFoundry的各组件之间的通信就是依赖NATS组件。
CloudFoundry使用NATS作为内部组件之间通信的媒介,NATS是一个轻量级的基于pub-sub机制的分布式消息队列系统,是整个系统可以松散耦合的基石。
我们以向router注册路由为例来说明NATS的作用。不管是外部用户对平台上的应用发起的请求,还是对内部组件(比如Cloud Controller、UAA)发起的请求,都是经由router做的转发,要能让router转发则首先需要向router注册路由。大体逻辑实现如下:
· router启动时,会订阅router.register这个channel,同时也会定时的向router.start这个channel发送数据
· 其他需要向router注册的组件,启动时会订阅router.start这个channel。一旦接收到消息,会立刻收集需要注册的信息(如ip、port等),然后向router.register这个channel发送消息。
· router接收到router.register消息后立即更新路由信息
· 以上过程不停循环,使router的状态时刻保持最新
3.11 Staging
Staging---封装(不好解释,暂且将其中文名称为封装),是DEA对上传完成的应用程序执行的一系列动作,DEA会按照buildpack中描述的具体要求,获取相关脚本或者其他依赖包,将其组装成为一个可以运行的封装包Droplet。
3.12 Flapping
应用程序(APP)部署或者运行的一种异常状态,表示该APP已经宕机多次无法正常运行或者根本就无法启动。
3.13 Authentication
这块包含两个组件,一个是Login Server,负责登录,一个是OAuth2 Server(UAA),UAA是个Java的项目,如果想找一个OAuth2开源方案,可以尝试一下UAA
3.14 Logging and Statistics
Metrics Collector会从各个模块收集监控数据,运维工程师可以据此来监控CloudFoundry,出了问题及时发现并处理。物理机的硬件监控则可以采用传统的一些监控系统来做,比如zabbix之类的。
Log这块是个大话题,CloudFoundry提供了Log Aggregator来收集app的log,我们也可以通过其他手段直接把log通过网络打出来,比如syslog、scribe之类的。
CloudFoundry基础知识学习