分享

开源 PaaS Cloud Foundry 深度解析

xioaxu790 发表于 2014-6-22 07:09:53 [显示全部楼层] 回帖奖励 阅读模式 关闭右栏 1 10195
问题导读:
1、什么是VCAP 存储库?
2、什么是云控制器、DEA、路由器,它们如何协调工作?




前言
您可能很想知道,Cloud Foundry 到底是怎样工作的,希望下面这些详细信息会告诉您 开源软件项目 Cloud Foundry 是如何工作的,它为什么可以工作,以及您如何使用它。

Cloud Foundry 位于 github 中,地址是:点击这里。VCAP 存储库是包含 PaaS 所有功能的分布式系统,所以是资源最丰富的部分,也称为 Cloud Foundry 的“内核”。 [译注:Cloud Foundry 在2012年4月启动了内核部分的重构工作,部分核心模块已经从vcap中移出] 我们已发布了 VCAP 安装脚本,它将帮助您获得运行 Cloud Foundry 实例的 Ubuntu 10.04 系统,该系统包括 VCAP 的所有组件,以及一些已建立并运行的服务(mysql、redis、mongodb),这样便于您在家里进行体验。

我们要围绕 Cloud Foundry 建立一个社区,因为目前对于开源项目来说这是最重要的。 可以想像有这样一个完整的“用户空间”工具生态系统,用户可以创建工具并将其插入 Cloud Foundry 内核以增加其价值,还可以针对任何特定情况进行自定义。 这个项目的范围非常广,因此我们只能截取其中的一部分,并在某种程度上与社区关联起来。我们认为这个内核足够每个人尽情使用,而且它已开始帮助我们规划云计算时代Linux的未来。

所以,应该如何构建这样的 PaaS(平台即服务)呢?它不仅能够在同一个部署和可伸缩性环境下运行多种语言,而且还能够在任何云或可运行 Ubuntu 的任何硬件上运行。 VCAP 是由我的同事 Derek Collison 做的架构设计,他可是真正的超级明星(这个家伙真是这样)。 这个设计非常优秀,它坚持“越接近系统的中心,代码就变得越傻瓜”的核心理念。 分布式系统从根本上说是硬骨头。 所以,共同构成整个系统的每个组件必须尽量简单,同时还要能够正确地各司其职。

VCAP 可分解为 5 个主要组件及 1 个消息总线:
云控制器(Cloud Controllor) 、Health Manager、路由器(Router)、DEA (Droplet Execution Agent) 和一组服务。 我们依次深入了解一下每个组件,看看它们是如何相互结合以构成完整的平台或云的。

NATS 是一个非常简单的发布/订阅消息系统,它是由 Derek Collison 编写的(这个家伙精通消息系统,相信我)。NATS 是所有内部组件进行通讯的系统。 虽然 NATS 非常适合这种类型的系统通讯,但您不会使用 NATS 进行应用层的消息传递。 VMWare 自己的 RabbitMQ 对于应用层消息传递来说很棒,我们计划在不久的将来让 Cloud Foundry 用户也能用上它。[译注:Cloud Foundry已经完成对RabbitMQ服务的集成]

在这里必须说明的是,该系统中的每个组件都是可水平扩展的,并具有自修复功能,这意味着您可以根据需要,每个组件都可以添加任意数量的实例,以便支持云上的负载。 由于所有组件都是解耦的,因此每个组件位于什么位置都无所谓,信息将在与其无关的环境中分布。(这真是太酷了 ;))


云控制器( Cloud Controller):
云控制器是系统的主要“大脑”。 这是一个异步 Rails3 应用程序,它使用 Ruby 1.9.2 、fibers以及eventmachine (一个ruby gem) 实现完全异步,这是最前沿的技术。 可以在这里获取控制器的代码: https://github.com/cloudfoundry/vcap/tree/master/cloud_controller。 该组件公开了与 CLI 工具“vmc”通讯的主要 REST 接口,以及用于 Eclipse 的 STS 插件。 如果您愿意,可以编写自己的客户端,来和云控制器公开的 REST 终端通讯,从而按您喜欢的任何方式与 VCAP 通讯。 但实际上没有必要这样做,因为“vmc”CLI 在编写时已具备了可脚本化功能。 如果您需要,它可以返回适当的退出代码以及 JSON,这样就可以使用 bash、ruby 或 python 等对其进行完整的脚本编写。

虽然我们很喜欢 git,但还是决定不将 VCAP 绑定到 git,我们需要支持所有源代码控制系统,但同时还要力求使 git 推送式部署简单易行,因此就选择了 vmc push。 但我们还要进行差异部署,也就是在您更新应用程序时推送版本间的差异部分。我们不想在每次远程部署时都推送整个应用程序的目录树,因为方便快捷对我们很重要。 我们的目标是与本地开发一样方便。

因此我们设计了一个系统,结合了本地开发和远程部署两者的优点。。 您作为用户,可以使用任何源代码控制系统,在您进行 vmc push 或 vmc 更新时,我们将检查您的应用程序目录树,并将“骨架指纹”(skeleton fingerprint)发送到云控制器。 这实际上是应用程序目录树中每个文件的指纹以及目录树的形状。 云控制器将这些信息存储在共享池中,可通过其指纹以及所看到的每个对象的大小进行访问。 然后,它向客户端返回一个文件清单,上面列出已经有的文件,以及需要客户端发送到云的文件,这样您的应用程序才完整。 这是一种清除重复的应用程序代码、框架、rubygem 代码和其他相关代码的操作。 您的客户端只发送云需要的对象,用以创建应用程序的完整“Droplet”(Droplet 是所有应用程序代码及其依赖内容的 tar 包,它们都打包在一个 Droplet 中,具有“开始”和“停止”按钮)。

当云控制器拥有组装应用程序所需的所有文件后,它会将应用程序推送到“暂存流水线”(staging pipeline)中。 暂存是将应用程序组装到一个 Droplet 中的过程,在此过程中,将获取构成应用程序及其依赖内容的所有对象,重写其配置文件来指向已绑定到应用程序的相应服务,然后使用启动和停止的两个封装脚本来创建 tar 包。


DEA:
源代码可在这里找到 Droplet Execution Agent:https://github.com/cloudfoundry/vcap/tree/master/dea。它是在实际运行应用程序的网格节点上的运行代理。因此,在任意特定的 Cloud Foundry 云构建中,常规设置情况下,DEA 节点比任何其他类型的节点都要多。每个 DEA 均可通过配置来公布不同的容量和不同的运行环境集,因此,DEA 节点无需大小均相同,也无需均可运行相同的应用程序。

下面,我们接着介绍云控制器。云控制器通过总线广播说自己有 Droplet 需要运行,寻求 Droplet 运行帮助。该 Droplet 附带了一些元数据,例如它需要哪种运行时,以及需要多少 RAM 等。运行环境是运行应用程序(如 ruby-1.8.7、ruby-1.9.2、java6 或 node.js)所需的基本组件。当 DEA 收到一条此类消息后,它会进行检查,确认自己能否满足相应的要求;如果它能够满足相应要求,则会答复云控制器,表示愿意提供帮助。

DEA 无需关心应用程序采用何种语言编写,因为它只能看到 Droplet。Droplet 是应用程序的简单打包程序,它通过一个输入(即端口号)来响应 HTTP 请求。此外,它还包含 2 个按钮:“启动”和“停止”。因此,DEA 视 Droplet 为黑匣子,当它接收到需要运行的新 Droplet 时,只需要告诉 Droplet 绑定到哪个端口和运行启动脚本。同时,Droplet 也是应用程序的一段 tar 格式源码,打包在启动/停止脚本中,包含您所有的配置文件,例如为了绑定至正确的数据库而重新编写的 database.yml。目前,我们还无法为所有类型的服务重新编写配置;因此,对于 Redis 或 Mongodb 之类的服务[译注:目前这两类服务已经支持自动配置],您还需要从环境变量 ENV['VCAP_SERVICES'] 中获取配置信息。

实际上,您应用程序容器的 ENV 中包含丰富的信息。如果您在笔记本电脑中创建一个目录,并在其中放置一个名为 env.rb 的文件,文件内容大致如下:
  1. $ mkdir env && cd env
  2. $ cat «EOF > envvars.rb
  3. require ‘sinatra’
  4. require ‘pp’
  5. get ‘/’ do
  6.   “<pre>#{ENV.pretty_inspect}</pre>”
  7. end
  8. EOF
  9. $ vmc push …
复制代码


这样会生成一个简单的应用程序,说明您的环境中有哪些资源,因此您就可以知道有哪些资源可以用来配置应用程序了。 如果您访问这个新应用程序,会看到类似以下内容的信息:


ENV 输出
这样 DEA 的职责差不多完成了,当它告诉 Droplet 应在哪个端口上侦听 HTTP 请求并运行其启动脚本,并且应用程序正确绑定到正确的端口后,它将通过总线广播新应用程序的位置,以便让路由器组件知道。 如果应用程序未成功启动,它将日志消息返回到尝试推送此应用程序的 vmc 客户端,告诉用户应用程序未启动的原因(希望是这样)。 现在我们来看看路由器组件在系统中必须完成的工作,说说路由器(鼓掌)。


路由器:
路由器是另一个基于ruby eventmachine精灵进程(daemon),顾名思义它完成它的本职工作,即路由请求。 在大型生产设置中,有一个路由器池,它们在 Nginx(或其他负载均衡器或 http cache/balancer)后进行负载均衡。 这些路由器在总线上侦听来自 DEA 的通知,如新应用程序上线,应用程序离线,等等。当获得实时更新时,它们将更新其内存中要查询的路由表,从而正确路由各请求。 因此,进入系统的请求将通过 Nginx 或其他 HTTP 终端终结点,然后在路由器池之间进行负载平衡。 其中一个路由器将负责答复请求,它将开始检查请求头(header),直到找到 Host: 头,这样就可以选出作为此请求的目标的应用程序名称。 然后,它将在路由表中执行基本的哈希查找,以查找代表此特定应用程序可能的后端列表。 信息内容大致如下:{‘foo.cloudfoundry.com’ => [‘10.10.42.1:5897’, ‘10.10.42.3:61378’, etc]}
在找到由“foo.cloudfoundry.com”表示的应用程序的实例列表时,它将选取一个随机后端实例作为请求的发送目标。 因此,路由器将选择一个后端实例,并将请求转发到该应用程序实例。 如果是诸如粘性会话(sticky session)这样的功能需要,还可以注入头级检查响应。

如果路由器选择的后端实例发生故障,它将重试其他后端实例,如果您拥有自己部署的 Cloud Foundry 实例,那么可使用多种方法对此行为进行自定义。 路由器在履行其职责以及所使用的方式方面非常直接。 它们基于饿,并在 ruby-1.9.2 上运行,因此速度较快,每个实例能够处理大量流量。与系统中的其他组件一样,它们可水平扩展,您可以根据需要添加更多路由器,以便向上扩展得越来越大。 系统以这样一种方式进行设计,甚至可以在运行的系统中完成这样的操作。


Health Manager:
Health Manager 是一个独立守护进程(daemon),它拥有与云控制器相同的数据模型副本,目前可以查看云控制器的数据库。

每隔一段时间,该守护进程会被唤醒并扫描云控制器的数据库,以了解整个云环境的状态应该是怎样的,然后进入该环境中检查真实状态,确保它是匹配的。 如果有不匹配的情况,它将消息发回云控制器以更正状态。 这是我们处理应用程序甚至是 DEA 节点丢失的情况的方式。 如果应用程序停止,Health Manager 将会注意到此情况,并通过向云控制器发出启动新实例的信号来快速修复该情况。 如果 DEA 节点完全失败,在该节点上运行的应用程序实例将被重新发回到其余的 DEA 节点网络中。


服务:
这些是应用程序可以选择使用并绑定的服务,目的是获取数据、传递消息、进行缓存和执行其他服务。 目前,redis 和 mysql 等在服务中运行,所有最终变为一个由 VMware 以及想要在我们的云中提供服务的所有用户提供的巨大的服务生态系统。 我要强调的是,您可以在部署到 VCAP 系统的不同应用程序之间共享服务实例。 也就是说,您可以有一个核心 Java Spring 应用程序,以及通过 redis 或 RabbitMQ 消息总线通讯的一堆 外围Sinatra 应用程序。

好啦,我的手指累了,肩膀也酸了,这第一篇算是完成了。 我打算经常写博客,也算是帮助将这个开源项目 Cloud Foundry 的社区组织起来。 说到这个项目,我希望你们和我一样感到兴奋,它实际上像是“框架、云和服务的机架”,而不仅仅是 Ruby 框架。 可在 3 个不同的轴上添加删除应用,并顺利进行测试和编码。 这真是太酷了,作为开发此技术的团队中的一员,我感到十分骄傲。

已有(1)人评论

跳转到指定楼层
ainubis 发表于 2015-3-27 16:26:56
学习啦(*^__^*) 嘻嘻……
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

关闭

推荐上一条 /2 下一条