CloudFoundry是一个标杆项目,在其架构设计上有很多值得借鉴的地方。我们从CloudFoundry官网上截了一张图,我们以此来分析各个组件的作用。RouterRouter是整个平台的流量入口,负责将所有请求分发到相应的组件,包括外部用户对app的请求和平台内部的管理请求。路由器是PaaS平台中的一个重要组件。它在内存中维护了一张路由表,记录了域名和实例的对应关系。所谓实例的自动迁移,就是靠这张路由表。当一个实例宕机时,如果被发现,它会被从路由表中移除,当一个新的实例被创建时,它会被添加到路由表中。CloudFoundry1.0中的router是用nginx+lua内嵌脚本实现的,2.0用golang重写,更名为gorouter,性能有所提升,号称尝试解决websocket请求和tcp请求(虽然这个在我看来没什么用),它的代码在https://github.com/cloudfoundry/gorouter,大家可以研究一下。Authentication由两个组件组成,一个是LoginServer,负责登录,另一个是OAuth2Server(UAA)。UAA是一个Java项目。如果你想找一个OAuth2开源方案,可以试试UAACloudControllerCloudController负责管理app周期的整个生命周期。用户通过命令行工具cf与CloudFoundryServer打交道,主要是与CloudController进行交互。用户将应用推送到CloudController,CloudController将其存储在BlobStore中,在数据库中为该应用创建一条记录,存储其元信息,并指定一个DEA节点完成打包动作,并产生一个droplet(包含Runtime包的droplet可以通过wardenrun在任意dea节点上运行),打包完成后将droplet发送回CloudController,仍然保存在BlobStore中,然后CloudController根据用户需要的实例数调度相应的DEA节点部署运行Droplet。此外,CloudController还维护了用户组织关系org、space、services、serviceinstances等。HealthManagerHealthManager最初是用Ruby写的,后来用golang写了一个版本,叫HM9000,HM9000有四个核心功能:监控app的实际运行状态(如:running、stopped、crashed等)、version、实例数等信息。DEA会持续发送心跳包,上报其管辖的实例信息。如果一个实例挂了,它会立即发送一个“droplet.exited”消息,HM9000会相应地更新应用程序的实际运行数据。HM9000将转储云控制器数据库。获取应用程序的预期状态、版本和实例数。HM9000不断比较应用程序的实际运行状态和预期状态。如果发现app运行的实例数小于要求的实例数,则向CloudController发送命令,启动相应数量的实例。实例。HM9000本身不会要求DEA做任何事情。它只是收集数据,比较,收集数据,再比较。用户可以通过cf命令行工具控制app各个实例的启动和关闭状态。如果应用的状态发生变化,HM9000会命令CloudController做出相应的调整HM9000归根结底是保证应用可用性的基础组件。当应用程序运行超出分配的配额,或异常退出,或整个DEA节点宕机时,HM9000会检测到,然后命令CloudController迁移实例。HM9000的代码在这里:https://github.com/cloudfoundry/hm9000,有兴趣的同学可以研究ApplicationExecution(DEA)DEA,即DropletExecutionAgent,部署在所有物理节点上,管理app实例,以及信息被广播。比如我们创建一个app,实例创建命令会发给DEA,DEA会调用warden接口创建容器。如果用户要删除一个app,实例销毁命令最终会发给DEA,DEA会调用warden接口。销毁相应的容器。CloudFoundry刚推出时,Droplets包含启动和停止应用程序等简单命令。用户应用程序可以随意访问文件系统,也可以在内网畅通无阻,跑满CPU、内存、磁盘。凡是你能想到的破坏性操作都能做到,太可怕了。CloudFoundry显然不会让这种情况持续太久,现在他们开发了Warden,一个运行容器的程序。这个容器提供了一个隔离的环境,Droplet只能得到有限的CPU、内存、磁盘访问权限、网络权限,没有办法破坏它。Warden在Linux上的实现是将Linux内核的资源划分成几个namespace来区分。底层机制是CGROUP。这样的设计比虚拟机性能更好,启动速度更快,安全性也足够。在网络方面,每个Warden实例都有一个虚拟网络接口,每个接口都有一个IP,在DEA中有一个子网,这些网络接口都连接到这个子网。通过iptables可以保证安全。在磁盘方面,每个warden实例都有自己的文件系统。这些文件系统是使用aufs实现的。Aufs可以在wardens之间共享只读内容,区分只写内容,提高磁盘空间利用率。因为aufs只能对固定大小的文件进行读写,所以不存在磁盘满的可能。LXC是另一个Linux容器。那么为什么不使用它,而是开发Warden。因为LXC的实现是和Linux捆绑在一起的,CloudFoundry希望warden可以在各种平台上运行,而不仅仅是Linux。另外Warden提供了一个Daemon和几个API来操作,LXC提供了系统工具。最重要的一点是LXC太大了,而Warden只需要它的一点点功能,代码少容易调试。ServiceBrokersapp在运行时通常需要依赖一些外部服务,比如数据库服务、缓存服务、短信邮件服务等等。ServiceBroker是应用程序访问服务的一种方式。比如我们要访问MySQL服务,只需要实现CloudFoundry需要的ServiceBrokerAPI即可。但实际情况是,在我们使用CloudFoundry之前,MySQL服务已经被DBA服务化和产品化了,使用起来非常方便。是否有必要实现其ServiceBrokerAPI并遵循CloudFoundry的规则?作者认为没有这个必要。APP还是可以按照之前访问MySQL服务的方式进行,没有任何问题。消息总线CloudFoundry使用NATS作为内部组件之间的通信媒介。NATS是一个基于pub-sub机制的轻量级分布式消息队列系统,是整个系统松耦合的基石。下面以向router注册路由为例来说明NATS的作用。无论是外部用户对平台上的应用程序的请求,还是对内部组件(如CloudController、UAA)的请求,都由路由器转发。要让路由器转发,首先需要向路由器注册一条路由。大致的实现逻辑如下:路由器启动时,会订阅router.register通道,同时也会定时向router.start通道发送数据。其他需要向路由器注册的组件在启动时会订阅router.start频道。一旦收到消息,它会立即收集需要注册的信息(如ip、端口等),然后向router.register通道发送消息。路由器收到router.register消息后立即更新路由信息。以上过程不断循环,使路由器的状态保持最新。LoggingandStatisticsMetricsCollector会收集各个模块的监控数据,运维工程师可以据此对CloudFoundry进行监控。如果出现问题及时发现并处理。物理机的硬件监控可以用一些传统的监控系统来完成,比如zabbix之类的。日志是一个很大的话题,CloudFoundry提供了LogAggregator来收集应用日志。我们也可以通过其他方式直接通过网络打印日志,比如syslog,scribe之类的。参考《CloudFoundry社区文档》http://docs.cloudfoundry.org/《limengyun’s blog》http://limengyun.com/《新版CloudFoundry揭秘》http://qing.blog.sina.com.cn/2294942122/88ca09aa33001753.html本文来自来自:http://blog.ulricqin.com/article/cloudfoundry-component
