深入Cloud Foundry

EMC中國研究院高級研究員  彭麟


引子

今年4月份,VMware突然發佈了業內第一個開源的PaaS——CloudFoundry。幾個關鍵字:開源、PaaS、VMware,如果你對雲計算感興趣,就衝着它的ApacheV2協議,如果不去GitHub拿它的代碼好好研讀一下,真有點對不起自己。筆者當時就是以這樣的心態去研究它的代碼,並把它部署在我們labs裏面。發佈至今的這幾個月裏,筆者一直關注它的演進,並從它的架構設計中獲益良多,覺得有必要寫出來與大家分享一下。由於個人知識、認知等原因,其中有些看法難免不成熟,大家可以直接批評、指教。

 

本文會分爲兩個部份:第一部份主要介紹CloudFoundry的架構設計,從它所包含的模塊介紹起,到各部份的消息流向,各模塊如何協調合作;第二部份會在第一部份的基礎上,以如何在你的數據中心裏面用CloudFoundry部署一個私有PaaS爲目標,把第一部分介紹到的架構知識使用起來。在本文,我不想簡單的介紹如何使用CloudFoundry,這方面的文章,在SpringSource的官方博客裏面有具體的介紹。如果需要這方面的介紹,筆者強烈建議到SpringSource或者CloudFoundry的官博找資料。另外,本文也不會具體介紹如何“貢獻”Cloud Foundry,例如添加自己的Runtime,添加第三方的Service,這將會是兩個很大的話題,以後我們會有專門的文章介紹,本文更多的算是入門級的架構介紹,可能會涉及到具體代碼,但是隻爲更好地理解架構而服務。在第二部份,會簡單介紹到如何用OrchestrationEngine來把CloudFoundry部署到IaaS上面,但是具體的實現方法將會放到介紹OrchestrationEngine的文章上面去,這裏更多的是一種思想和BestPractice的分享。

 

第一部份講的很多內容,會引用Pat在10月12日的VMwareCloud Forum上面關於CloudFoundry架構的演講。Pat是CloudFoundry Core的負責人,他的那次演講很值得一聽。如果你當時在場,並且理解他所說的內容,本部份可以選擇直接跳過。我除了會把說的內容講具體點外,不太可能可以講得比他好。

 

一、架構及模塊

從總體地看,CloudFoundry的架構如下:


 

 

這個架構圖以及下文所用到的各模塊架構圖均來自Pat的PPT。從上圖能夠看到CloudFoundry主要有以下幾大組件組成:


1、  Router:顧名思義,Router組件在CloudFoundry中是對所有進來的Request進行路由。進入Router的request主要有兩類:首先是來自VMCClient或者STS的,由CloudFoundry使用者發出的,管理型指令。例如:列出你所有apps的vmcapps,提交一個apps等等。這類request會被路由到AppLife Management組件,又叫CloudController組件去;第二類是外界對你所部署的apps訪問的request。這部份requests會被路由到Appexecution,又或者叫做DEAs的組件去。所有進入CloudFoundry系統的requests都會經過Router組件,看到這裏可能會有朋友會擔心Router成爲單點,從而成爲整個雲的瓶頸。但是CloudFoundry作爲雲系統,其設計的核心就是去單點依賴,組件平行擴充,且可替代的以保證擴展性,這是CloudFoundry,甚至所有云計算系統的設計原則,後文會討論CloudFoundry如何做到這點,目前只要知道,系統可以部署多個Routers共同處理進來的requests,但是Router上層的LoadBalance不在CloudFoundry的實現範圍,CloudFoundry只保證所有的request是無狀態的,這樣就使上層均衡附載選擇面非常非常大了,例如可以通過DNS做,也可以部署硬件的LoadBalancer,或者簡單點,弄臺ngnix作負載均衡器,都是可行的。

 

Router組件,目前版本是對nginx的一個簡單封裝。熟悉ngnix的朋友應該知道,它可以一個套接字文件(.sock文件)作爲輸入輸出。所有安裝CloudFoundry的Router組件服務器都會安裝一個nginx,其ngnix.conf文件有以下配置:

 

 

從整體的來看,Router組件的結構如下:


 

 

外界httprequest進入CloudFoundry服務器,nginx會首先接到request,nginx通過sock與router.rb進行交互,於是真正處理請求的是Router組件。router.rb裏面根據傳入的url,用戶名密碼等,進行邏輯判斷,到CloudController組件或者DEA組件取數據並且返通過與niginx連接的.sock文件返回。router.rb是對nginx進行了邏輯封裝。熟悉CloudFoundry的朋友肯定知道,CloudFoundry給每一個app分配了一個url訪問,如果直接使用VMware所託管的CloudFoundry.com的話,那你的app的url可能就是xxx.cloudfoundry.com,無論通過命令給你的app擴展了多少個instances,都是從這個url訪問的,這裏面的url轉換路由就是由router.rb實現的。


2、  DEA(Droplet Execution Agency): 首先要解析下什麼叫做Droplet。Droplet在CloudFoundry的概念裏面是指一個把你提交的源代碼,以及CloudFoundry配套好的運行環境,再加上一些管理腳本,例如Start/Stop這些小腳本全部壓縮好在一起的tar包。還有一個概念,叫做Stagingapp,就是指製作上面描述這個包,然後把它存儲好的過程。CloudFoundry會自動保存這個Droplet,直到你start一個app的時候,一臺部署了DEA模塊的服務器會來拿一個Droplet的copy去運行。所以如果你擴展你的app到10個instances,那這個Droplet就被會複製十份,讓10個DEA服務器拿去運行。

 

下圖是DEA模塊的架構圖:


 

 

Cloud Controller模塊(下面會介紹)會發送start/stop等基本的apps管理請求給DEA,dea.rb接收這些請求,然後從NFS裏面找到合適的Droplet。前面說到Droplet其實是一個帶有運行腳本的,帶運行環境的tar包,DEA只需要把它拿過來解壓,並即行裏面的start腳本,就可以讓這個app跑起來。到此,app算是可以訪問,並start起來了,換句話說就是有這臺服務器的某一個端口已經在待命,只要有request從這個端口進來,這個app就可以接收並返回正確的信息。接着dea.rb要做些善後的工作:1、把這個信息告訴Router模塊。我們前面說到,所有進入CloudFoundry的requests都是由Router模塊處理並轉發的,包括用戶對app的訪問request,一個app起來後,需要告訴router,讓它根據loadbalance等原則,把合適的request轉進來,使這個app的instance能夠幹起活;2、一些統計性的工作,例如要把這個用戶又新部署了一個app告訴CloudController,以作quota控制等;3、把運行信息告訴HealthManager模塊,實時報告該app的instance運行情況。另外DEA還要負責部份對Droplet的查詢工作,譬如,如果用戶通過CloudController想查詢一個app的log信息,那DEA需要從該Droplet裏面取到log返回等等。


 

 

3、CloudController:CloudController是CloudFoundry的管理模塊。主要工作包括:


a) 對apps的增刪改讀;

b) 啓動、停止應用程序;

c) Staging apps(把apps打包成一個droplet);

d) 修改應用程序運行環境,包括instance、mem等等;

e) 管理service,包括service與app的綁定等;

f) Cloud環境的管理;

g) 修改Cloud的用戶信息;

h) 查看Cloud Foundry,以及每一個app的log信息。


 

 

這似乎有點複雜,但簡單的說,可以很簡單:就是與VMC和STS交互的服務器端。VMC和STS與CloudFoundry通信採用的是restful接口,另一方面CloudController是一個典型的Rubyon Rails項目,從VMC或者STS接到JSON格式的協議,然後寫入CloudController Database,併發消息到各模快去控制管理整個雲。和其他ROR項目一樣,CloudController的所有API可以從conf/routes.rb裏看到。開放的Restful接口好處在於第三方應用開發和集成,企業在用CloudFoundry部署私有云的時候,可以通過這些接口來自動化控制管理整個Cloud環境。這部份內容將在第二部份論述。

 

下圖是Cloud Controller的架構圖:


 

 

 

圖中Health Manager和DEA是外部模塊,CCDatabase就是CloudController Database,這個是整個CloudFoundry不能做HP的地方。CloudController Database的併發性不會很多,應用級別的數據庫訪問是由底下的Service模塊處理的,這個數據庫存的是Cloud的配置信息。讀操作主要來自DEA啓動,作爲初始化DEA的依據;以及healthmanager模塊會從這裏讀取預期的狀態信息,這部份數據會與從DEA得到的實際狀態信息進行比對。NFS是多個CloudController的共享存儲,CloudController其中一個重要工作就是StagingApps。Droplets的存儲是在集羣環境的唯一的。而CloudController是集羣運行,換言之,就是每一個控制Request可能由不同的CloudController處理,假設一個簡單的用戶場景:我們需要部署一個app到CloudFoundry中。我們在敲完那條簡單的push命令後,VMC開始工作,在做完一輪的用戶鑑權、查看所部署的apps數量是否超過預定數額,問了一堆相關app的問題後,需要發4個指令:


1.發一個POST到”apps”,創建一個app;

2.發一個PUT到”apps/:name/application”,上傳app;

3.發一個GET到”apps/:name/”,取得app狀態,看看是否已經啓動;

4.如果沒有啓動,發一個PUT到”apps/:name/”,使其啓動。


 

如果第2和第4步由不同的Cloud Controller來處理,而又無法保證他們能找到同一個Droplet,那第4步將會因爲找不到對應的Droplet而啓動失敗。如何保證這一連串指令過來所指向的Droplet都是同一個呢?使用NFS,使CloudController共享存儲是最簡單的方法。但是這個方法在安全性等方面並不完美。在10月12日的VMwareCloud Forum上,Pat告訴我們下一版本的CloudFoundry這裏將會有大調整,但是在那部份代碼公開前,我不方便在這評價太多。


 

4、  HealthManager: 做的事情不復雜,簡單的說是從各個DEA裏面拿到運行信息,然後進行統計分析,報告等。統計數據會與CloudController的設定指標進行比對,並提供Alert等。HealthManager模塊目前還不是十分完善,但是CloudManage棧裏面,自動化health管理、分析是一個很重要的領域,而這方面可以擴展的地方也很多,結合OrchestrationEngine可以使雲自管理、自預警;而與BI方面技術結合,可以統計運營情況,合理分配資源等。這方面CloudFoundry還在發展之中。


5、  Services:Cloud Foundry的Service模塊從源代碼控制上看就知道是一個獨立的、可Plugin的模塊,以方便第三方把自己的服務整合入CloudFoundry生態系統。在Github上看到service是與CloudFoundry Core項目vcap獨立的一個repository,爲vcap-service。Service模塊其中設計原則是方便第三方服務提供商提供服務。在這方面CloudFoundry做得很成功,從Github上看,已經有以下服務提供:a)MongoDB; b) mysql; c) neo4j; d) PostgreSql; e) RabbitMQ; f) Redis; g)vBlob。基類都是放在base文件夾中。 第三方如果需要自己開發CloudFoundry的服務,需要繼承改寫它裏面的兩個基礎類:Node和Gateway;而裏面一些操作,如:Provision,可以在base的provisioner.rb基礎上加入自己的邏輯,同樣的還有Service_Error和Service_Message等。關於如何寫自己的Service,ELC的博客會推出相應文章詳細論述,並不在本文的討論範圍裏面,從架構瞭解上來說,只要知道服務間的關係,知道個服務與base間透過繼承關係來橫向擴充,而CloudFoundry與apps調用Service是通過base來完成這一簡單的架構方法即可。


6、  NATS(Message bus): 從CloudFoundry的總架構圖看,位於各模塊中心位置的是一個叫nats的組件。NATS是由CloudFoundry的架構師Derek開發的一個輕量級的,支持發佈、訂閱機制的消息系統。Github開源地址是:https://github.com/derekcollison/nats。其核心基於EventMachine開發,代碼量不多,可以下載下來慢慢研究。CloudFoundry是一個多模塊的分佈式系統,支持模塊自發現,錯誤自檢,且模塊間低耦合。其核心原理就是基於消息發佈訂閱機制。每個臺服務器上的每個模塊會根據自己的消息類別,向MessageBus發佈多個消息主題;而同時也向自己需要交互的模塊,按照需要的信息內容的消息主題訂閱消息。譬如:一個DEA被加入CloudFoundry集羣中,它需要向大家吼一下,以表明它已經準備好服務了,它會發佈一個主題是”dea.start”的消息:


 

@ hello_message_json中包括DEA的UUID,ip, port, 版本信息等內容。


再例如,CloudController需要啓動一個Droplet的instance:

a)  首先一個DEA在啓動的時候,會首先會對自己UUID的消息主題進行訂閱。

  

其他模塊需要通過’’dea.#{uuid}.start”這個主題發送消息來使它啓動,一旦這個DEA接收到消息,就會觸發process_dea_start(msg)這個方法來處理啓動所需要的工作。


b)  Cloud Controller或者其他模塊發送消息,讓UUID爲xxx的DEA啓動。


 

 

c)  DEA模塊接收到消息後,就會觸發process_dea_start(msg)方法。msg是由其他模塊發送過來的消息內容,包括:droplet_id,instance_index, service, runtime等內容,process_dea_start會取得這些啓動DEA必須的信息,然後進行一系列操作,例如從NFS中取得Droplet,解壓,修改必要環境配置,運行啓動腳本等等。等一切都準備好後,然後需要給Router發個消息,告訴它這個Droplet已經隨時準備好報效國家,以後有相應的request記得讓它來處理。


 

 

d)  Router模塊在啓動時就已經訂閱”router.register”消息主題。

 

 

收到前面DEA發出的信息後,會觸發register_droplet方法,去綁定Droplet。到此啓動一個Droplet的instance工作完成。

 

我們可以看到整個CloudFoundry的核心就是一套消息系統,如果想了解CloudFoundry的來龍去脈,去跟蹤它裏面複雜的消息機制是非常好的方法。另一方面,CloudFoundry是一套基於消息的分佈式系統,面向消息的架構是它節點橫向擴展,組件自發現等雲特性的基礎。



 

 

 

Cloud Foundry的架構簡單介紹至此,其實作爲第一款開源的PaaS,CloudFoundry架構有很多可以學習借鑑的地方,很多細節上的處理是很精妙的,這些內容如果有可能會在後續文章繼續探討,本文題雖爲深入CloudFoundry,其實也只是淺嘗即止,把總體架構介紹一下,目標在於使我們有足夠的背景知識去用CloudFoundry搭建企業內部的私有PaaS。總結一下,筆者從CloudFoundry的結構中學到的東西:


1、  基於消息的多組件架構是實現集羣的簡單、且有效方法。消息可以使集羣節點間解耦,使自注冊,自發現這些在大規模數據中心中很重要的功能得到實現;

2、  適當的抽象層,模板模式的使用,方便第三方可以方便在CloudFoundry開發擴展功能。CloudFoundry在DEA及Service層都做了抽象層處理,相對應地使開發者可以容易地爲CloudFoundry開發Runtime和Service。例如,在CloudFoundry剛推出的時候,只支持Node.js,Java, Ruby,但第三方提供商、開源社區快速跟進,爲CloudFoundry添加了PHP,Python的支持。這得益於CloudFoundry精巧的DEA架構設計,如何開發新的Runtime支持,會在後續博文中有所論述.


 

二、源碼導讀


 

筆者一直覺得深入理解一個技術的最好方法就是讀它的源碼,而CloudFoundry是完全開源的PaaS平臺,而因爲剛發展起來,代碼量不多,主要作者們的代碼功力也相當不錯,讀起來很舒服,很適合研讀。而不得不再次表揚一下它完全基於消息機制的架構設計,對組件擴展性,第三方接入等方面做得很好,讀者可以從中學到不少思想性的東西。筆者很推薦大家去讀一下它的源代碼。你可以在Github上找到CloudFoundry的全部代碼:https://github.com/cloudfoundry,你會看到幾個不同的Repositories,它們分別是:

 

1、vcap: Cloud Foundry的Core,又或者稱作Kernel;

2、vcap-service: Cloud Foundry的Service組件。Cloud Foundry的service是作爲插件提供的,這出於它方便第三方開發service而設計的;

3、vmc: VMware Cloud CLI. 是一個Ruby應用,與Cloud Foundry的CLI交互。主要通過分析用戶輸入的CLI,向CloudFoundry發送Restful請求;

4、vcap-java: 如果你的app是用java開發,且需要與Cloud Foundry交互,例如取得當前serviceserver的ip地址等,你可能需要這個jar,裏面對我們Java開發常用框架有所支持,它底層也是對CloudFoundry的Restful請求的包裝;

5、vcap-java-client: Cloud Foundry的Restful API的Java封裝,與上面的項目不一樣,它只是個簡單的讀取CloudFoundry信息,並放如JavaBean中;

6、vcap-test: Cloud Foundry的test cases;

7、vcap-test-assets: Cloud Foundry一些apps示例。

 

續與回顧

本文第一部分介紹了CloudFoundry的整體架構,並在最後花了一點篇幅簡介CloudFoundry的代碼組織情況,以便於讀者自己去研究源代碼。筆者認爲開源項目最大的好處在於:當你讀懂源代碼、理解總體架構後,能夠成竹在胸,並吸收爲己用(有點類似武俠小說中的“北冥神功”)。“爲己用”就是本篇要說的內容:我們使用CloudFoundry搭建自己的私有PaaS平臺。

在介紹CloudFoundry之前,先說明一下,VMware在企業雲應用平臺的產品線上,有另外一款產品,叫做VMwarevFabric Cloud Application Platfor[1],這和Cloud Foundry屬於兩個產品,分別由兩批團隊開發。相比較來說,選擇vFabric會更令人省心省力,畢竟作爲商業產品,完善很多,而且發展已久,和STS[2]深度整合。如果企業以應用爲目的,不希望開發上面耗費太多人力物力,不妨考慮一下;如果選擇Hard模式,打算以CloudFoundry爲基礎搭建私有云,那就開始吧!

第二部份 基於CloudFoundry的私有云實踐 
 一、安裝配置CloudFoundry

本文內容所提到的CloudFoundry版本較早,,所以不可能一直緊跟着CloudFoundry的更新,造成有些內容並不是針對最新代碼庫,雖然我會比較新代碼庫來寫這篇文章,但是請一定不要把本文當作按部就班的安裝說明書。

去年10月份開始,CloudFoundry的主代碼vcap裏面新增加了個目錄叫做dev_setup,Cloud Foundry大方地公開了他們的部署代碼,這樣大大簡化了我們把CloudFoundry部署在自建數據中心的難度。如之前Figo在VMwareCloud Forum提到的一樣,CloudFoundry官方用Chef[3]作爲部署工具 。Chef是OrchestrationEngine的一種,可以自動化管理、部署複雜的雲環境。工作過程大概就是我們需要寫一系列的“recipes”,這些“recipes”描述我們需要把我們的服務器部署成什麼(Apache,Mysql還是Hadoop?),然後Chef可以自己執行這些配置。現在數據中心變得越來越龐大,原來那種通過自己寫腳本完成自動部署的IT管理方式日漸不堪重負,幫助管理、部署數據中心服務器集羣的中間件變得越來越重要,我們統稱這類型工具爲OrchestrationEngine.

回到正題,如果使用了新版的CloudFoundry,可以參考dev_setup目錄和dev_setup/deployments目錄下面的兩個README文件。基本上使用提供的腳本來部署不同的CloudFoundry組件就是一條命令的事情。

但是既然我們命題爲深入CloudFoundry,那就必須深入地瞭解整個CloudFoundry的部署過程。 在這之前讓我們先回顧第一部分裏面的CloudFoundry總體架構圖:


Figure 1 CloudFoundry 總體架構圖

從圖1中可以看出兩點:

1、  CloudFoundry是完全模塊化的設計,每個模塊單獨存在、運轉。CloudFoundry是基於Ruby開發的,那每個部分可以認爲拿來即可運行,不存在編譯等過程;

2、  我們需要配置換的應該是圖中的箭頭部分。換句話說就是如何把每個模塊連接起來,使其成爲一個完整的、分佈式的系統。這點就是我們現在要做的事情。

如果你是用:

 

安裝的CloudFoundry,那你的系統裏面就應該包含了所有的子模塊。

 

DEA, Health_Manager, Router這三個模塊,代碼結構比較接近:都有一個bin目錄,毫無疑問裏面就是可執行文件,但是打開着個文件會發現它只是個簡單的link,真正的執行文件在lib下面,有對應的rb文件;而這幾個模塊的根目錄下面都有一個config目錄,裏面有以模塊命名的yml文件,這就是他們的配置文件。

而cloud_controller模塊,之前已經說過它是個典型的RoR項目,裏面的文件結構有點複雜,文件有點多,但是還是能找到config/cloud_controller.yml這個文件的;

 

接着就是service模塊,這裏會看到很多似曾相識的子目錄,比如mysql,redis, rabbit, mongodb。專業人士一看就知道是不同的服務,每個服務一個文件夾,點進這些目錄看,又看到熟悉的結構了,比如bin,config, lib,很簡單,和前面的DEA,Router等模塊的結構一樣。但是打開bin後,發現執行文件有點多,有個gateway,還有個node。(如果你是新的代碼庫,可能還看到個backup,顧名思義就是配置service備份工作的,不難理解,這裏就不敘述了)

 

我們來聊聊Service模塊的gateway和node。Gateway在一個servicenode裏面負責處理restfulapi的相關事情,負責讀入並初始化messagebus。Node是service的具體執行者,包括響應message,與底層service的交互等等。但是從配置文件來說,因爲gateway負責解析初始化messagebus,所以與messagebus相關的配置信息反而放在了xxx_gateway.yml裏面;而xxx_node.yml則是一些關於底層配置的信息,拿mysql_node.yml來說,就是一些max_long_query,max_long_tx這些信息。

 

如果我們要架構分佈式的雲環境,不應該選擇在一臺服務器裏面安裝所有的模塊,下面簡單介紹下做法:

 

通過研究源代碼,我們知道CloudFoundry的主安裝文件vcap_setup裏是可以選擇安裝哪些組件的。所以安裝全部組件應該是install這個腳本搞的鬼,我們去看看install[4]裏面做了什麼?

 

通過略讀install腳本,發現它不難理解,且每一個步驟都有一個echo來說明。它分別做了以下動作:

1、  檢測是否是Linux或者MacOS環境;

2、  安裝依賴包;

3、  安裝並啓動RVM;

4、  安裝Ruby;

5、  下載vcap;

6、  安裝配置vcap;

7、  重啓Nginx;

8、  安裝Bundler。

 

其中注意這一行命令:

這裏面的參數–a與-s。在vcap_setup的comments裏面有如下定義,

 

 

也就是說,install腳本爲了省去安裝時的提問過程,剝奪了我們的自主選擇權!那麼解決方法就簡單了——把這句改了,然後執行install,我們應該能看到安裝腳本詢問要不要安裝Router?要不要安裝CloudController?同樣的,因爲去掉了-s參數,所以在安裝過程中會提示需要安裝的Service類型。

下面是我們實驗室中服務器的具體配置圖,

 

Figure 2 Cloud Foundry 在ELC 實驗室中的部署圖

 

首先,我們手上沒有硬件LoadBalancer,而且爲了節約ip資源,我們決定只用一個外部ip,使用橋接,然後用Ngnix來做loadbalancer,所有的requests會轉向4臺Router。

 

我建議Router宜多一點,因爲CloudFoundry當前的設計,Router的資源會很緊張,但是如第一部分說到那樣,這問題會在以後的版本改善。目前還是多加點Router服務器吧。

 

然後CloudController我們用了3臺,並且這三臺也同時兼了Health_Manager的功能,因爲CloudController主管的是控制流,資源佔用不會太大。我一開始也覺得CloudController會很耗資源,因爲從上一部分的工作描述來看,它負責的工作還是比較多的,但實際應用下來,結果和筆者想的相差很遠。這部分需要的資源其實並不多,可能因爲我們不是經常需要啓動/關閉/刪除instance。

 

後面是一個單獨的數據庫服務器。在生產環境裏用的是postgresql,用其他也是可以的,在cloud_controller.yml裏面修改就好。這是整套系統的單點,我也一度擔心過,但據說CloudFoundry.com用的也是單點數據庫,沒存在太大問題。據說CloudFoundry在設計的時候已經注意到這裏的數據流量問題。

 

接着是5臺服務器用於Health-Manger,其中3臺與CloudController公用。因爲我希望多檢測一點數據,用於後面的管理,所以在這裏狠下了心。

 

DEA模塊,也是5臺服務器。這裏算是app的主場,建議根據資源需求動態增加,CloudFoundry有很好的擴展性設計,如果某一模塊吃不消了,都可以動態添加。

 

Service模塊,同樣給了5臺。我們目前只用到Mysql,Postgresql和MongoDB。同樣按照項目需要來加。其他Service暫時還沒用上。

 

接着就是貫穿這套系統的MessageBus模塊。CloudFoundry的所有模塊都需要指定到這個MessageBus。它是基於NATS的,輕量級,很好用,但是有個問題是不支持HA/HP集羣,也就是說無法配成多臺Messagebus hosts。這部份據說正在開發,而既然CloudFoundry.com都能應付得了,我們私有云,一臺server,應該足矣!

 

後面我們選幾個模塊看看具體的配置修改:

1. /etc/nginx/nginx.conf

前面說到,我們用一臺nginx來作爲loadbalancer。我們整個服務器集羣用的是虛擬機,這臺虛擬機配雙網卡,分別設爲privatenetwork和vmnetwork,兩網卡間採用橋接。這臺服務器有雙ip:10.32.105.165和192.168.1.178。我們進入這臺機器,選擇Nginx的一個原因是,只要安裝CloudFoundry,因爲Router組件是基於Nginx的,所以都會安裝這個HttpServer,減少了我的工作。配置Nginx沒什麼特殊之處,我用了最簡單的方法,設置一個upstream,採用RR來均衡負載。

 
然後設置location的proxy_pass到這個upstream:
 
 
Ngnix用作loadbalancer的做法很多,而且可以引入權重算法等,大家按需使用。
2. Router.yml

Load balancer出來的request就會流到Router組件,Router.yml的配置相當簡單:

 

唯一需要改的只有mbus,就是把mbus指到我們的mbus服務器去。

3. cloud_controller.yml

Cloud_controller.yml看起來相當複雜,我們可以選擇需要的配置修改:

 
這三行屬於api的URI信息。external_uri比較重要,請在DNS裏面綁定這個域名到LoadBalancer的外部ip地址(如果沒有的話,需要訪問的client要配置hosts文件,綁定LoadBalancer和這個域名)。我們的配置是在DNS綁定好api.elc.com和10.32.105.165。

 

按照配置文件裏面的介紹,說這個可以不修改,默認爲nil,我配置成了CloudController的ServerIp,用起來沒出問題。

 

接着有兩個重要的配置:

 

這兩個目錄是關於用戶上傳的apps(在Cloud Foundry裏叫做Droplets),以及相關資源的目錄。上一部分說到,在CloudController的當前實現,是採用一個NFS來存儲這些Droplets,使它全局唯一。所以我們在此之前,需要建立一個NFS,並且每個安裝Cloud_Controller的服務器把這個NFSmount到/var/vcap/shared下。這點非常非常重要,否則會出現上文說的啓動失敗問題!

 

接下去,我們需要配一個,所有CloudFoundry組件都要配置的內容,mbus:

 

 

後面有很長的一段是關於Rails的環境配置,這裏就不囉嗦這些內容了。再往後,有一些單個賬戶資源限制問題,可以留意一下:

 
這裏如果對於內部使用可以適當放寬一下。配置文件裏的其他內容,可以根據自己的需要來訂製修改。

 

4. health_manager.yml

接下去就該配置health_manager.yml。一開始看到的就是兩個所有模塊都要修改的內容,local_route和mbus:

 

 

Local_route還是填本機的ip,mbus填的都一樣,就是mbus服務器的ip和端口。

然後,從本文第一部分所描述的health_manager的職責可知道,該模塊和CloudController數據庫有交互,所以需要配置database_enviroment信息。這部份需要和CloudController吻合。

 

health_manager.yml還有一些關於healthcheck頻率等的配置,這部份可以選擇不用修改。如果需要具體定製,可以參考yml文件中的comments。

5. DEA.yml

一如既往地需要修改local_route和mbus。

 

這裏有一個配置需要注意一下:

 

DEA模塊會自己host一個thin服務器用來處理髮送到以下URL的請求,讓用戶可以直接訪問到app的files。

 

 

換句話說,如果需要自己開發一些應用對app進行文件級管理的話,可以通過上面這個URL。另外,這個URL也是我們訪問app文件的一個選擇。或者我們可以從CloudContorller的API進入也是可以的,後面關於如何管理我們搭建的私有云時,會討論到這個話題:

 

除此之外,其它配置如果沒有特殊要求,可以保持默認。

6. Service層配置

在Service層,每種service的配置都略有不同,但是大同小異,需要修改的地方也不多。在這裏,我舉Mysql爲例子。和所有的Service一樣,mysql分爲了兩個配置文件(最新版本會多一個backup,共三個):mysql_gateway.yml和mysql_node.yml。

 

對於mysql_gateway.yml,需要改的,只有:

host: 192.168.1.193

mbus: nats:// 192.168.1.177:4222

 

對於mysql_node.yml,這裏比較多的是mysql調優參數,按照需要修改。但同樣有兩處需要修改:

Ip_route: 192.168.1.193

mbus: nats:// 192.168.1.177:4222

 

到此爲止,所有的安裝配置完成。如果一切順利的話,重新啓動component後,CloudFoundry應該就可以用了。再強調一次,這篇博客並不是一個可按部就班的安裝指南。CloudFoundry在一直髮展,代碼變動很大。如果不指定某一版本,很難保證所寫就一定適合。我覺得更多的應該是在通讀本文第一部分後,對CloudFoundry的整體架構有個瞭解,然後前面的描述可以看作是一些可具體理解CloudFoundry的切入點。通過去修改配置文件,保證系統如第一部份描述那樣來運轉。

 

CloudFoundry的架構並不複雜,其主要思想就是messagebus的配置,使異構的、分佈式的組件可以互相通信合作。我瀏覽了下CloudFoundry的最新代碼,很多新增配置配置是控制component如何運轉的配置,保持默認狀態即可。如果大家在配置過程中有什麼問題,很歡迎直接@我的微博(@Layne_Peng)進行討論,我會盡量幫忙。

二、下一步?

要搭建一個完整的私有云系統,還有很多缺少的地方,譬如下層的IaaS如何集成?如果CloudFoundry一個組件負載過高,應該如何擴容?能否做到自動化?如何檢測、管理CloudFoundry的服務器集羣?這些都是需要解決的問題。

 

首先,CloudFoundry是與底層IaaS無關的,我們可以用vSphere或者OpenStack來作爲IaaS方案。爲了實現雲計算的可伸縮性,IaaS層需要提供如下兩個功能:

1、  當CloudFoundry某些組件的發出性能警報,或者到達我們設定的某些指標時,我們需要用IaaS創建部署該組件的虛擬機,並把它啓動加入CloudFoundry集羣中(由OrchestrationEngine來做);

2、  當某些組件有大量資源盈餘,而物理資源出現緊張情況的時候,IaaS需要刪除虛擬機,把計算資源歸還到資源庫;

3、  IaaS需要提供虛擬機的註冊、存儲、查找、導入、啓動等功能。

而OrchestrationEngine在我們Lab中負責把由IaaS導入並已經啓動的虛擬機,按照前面章節介紹的“安裝配置CloudFoundry”配置好,以保證新加入的虛擬機資源可以被CloudFoundry使用。

 

我們的私有云有了IaaS和PaaS,有了自動化管理工具(也就是OrchestrationEngine),但中間還缺少監控管理工具。有了監控管理工具,我們纔可以知道現在CloudFoundry每個服務器的資源使用情況,纔可以向IaaS請求計算資源。這一塊要做得非常完善並不容易,但是我們可以按照我們的需要,去做一些必需的。實現自己的監管工具,第一件要做的事就是認識CloudFoundry提供的API,以便我們獲得PaaS的運行信息。

 

前面多次提及,CloudFoundry的管理是由CloudController負責,並對外提供RestfulAPI,供VMC和STS使用。另外,CloudController是典型的RoR項目,所以我們需要的一切API都可以在vcap/cloud_controller/Router.rb文件找到。

 

打開Router.rb文件,我們可以發現這裏基本可以得到部署在CloudFoundry上apps和services所有信息,包括app的統計信息、app的crashlogs、service node所提供的服務、servicenode的資源情況等等。再配合Linux本身的一些基本命令,我們可以知道服務器節點的資源情況。

 

另外,我們在Router.rb還能發現以下API,

 

通過它們,我們可以拿到每個apps的所有file文件。也就是說,我們可以拿到Webserver(假設是Java的instance,那WebServer就是Tomcat)的logfiles。通過分析這些logfiles,我們可以得到目前部署在我們PaaS上的app運行情況。

 

這裏面的話題很多,可以發揮的地方也很大。我是先分析Router.rb可以提供哪些信息,然後覺得哪些比較有價值,可以聯繫到我們業務的哪些需要,來設計的。分析這些API的比較好辦法就是直接Query這些API,然後看看返回數據。

 

我用的是Chrome瀏覽器,只需要裝個AdvancedREST client插件,我們就可以直接訪問這些RestAPI了。訪問大部份CloudFoundry的RestfulAPI,都首先需要拿到授權Token,我這裏直接用http://api.cloudfoundry.com爲例。

 

我們用VMC的時候,先需要把Target設定爲http://api.cloudfoundry.com,這一步其實就是給VMC設定了Restful的訪問BaseURL,屬於本地操作。

 

第二步就是執行login,並輸入email和password,我們可以通過研究VMC的源代碼,或者直接看VCap源代碼,得知,這個login其實是發向:

 

post   'users/*email/tokens'       => 'user_tokens#create',   :as => :create_token

 

所以,我們可以用AdvancedREST client往上面的URL發送POST請求,並把email和password的JSON格式放到Body裏面,

 

 

從服務器返回了一串Token,這就是我們需要拿到的授權Token,後面的所有操作都需要用到。

 

接着我們就可以慢慢嘗試CloudController能爲我們提供什麼信息了。舉個最簡單的例子,我想看當前email賬戶下的所有apps列表,只需要把以上的Token放到請求的header裏面,並把name設爲AUTHORIZATION,然後GET  http:// api.cloudfoundry.com/apps:

 

返回信息就是該賬戶下所有的apps列表:

  

從這裏可以得到這個用戶的apps的一些基本情況,包括appname、url、所使用的技術、instance數目、資源情況等等。

 

再舉一個簡單的例子,如果我想做一個Portal列出部署在我的PaaS裏面的所有應用,這個API或許可以派上用場。

 

開發一個完善的PaaS不是我們研究院的主要任務,而且搭建一個私有云需要大量的開發量,我只是簡單實現了一小部分。如果真打算搭建私有云平臺,要做的工作還有很多。譬如ActiveState就基於CloudFoundry,做了一個商業版的PaaS,叫做Stackato[5],它們也是在Monitor和Manage上面做了很多工作,值得參考一下。

結束語

上下兩部分的深入CloudFoundry到這裏就寫完了。雖然命名爲深入,其實很多地方只是簡單帶過,對CloudFoundry的分析也只到架構一層,還有很多內容可以挖掘,譬如開發自己的Runtime,嵌入新的Service等等,以後如果必要,我可以再寫文章聊聊相關內容。第二部分簡單介紹了CloudFoundry的安裝,以及我們實驗室裏面的使用,希望對大家有幫助。

 

Cloud Foundry作爲業內第一個開源的PaaS,我覺得它給我們打開了一扇研究雲計算環境下平臺架構設計的窗戶,我相信圍繞它的周邊開發會有一片很大的空間可以讓開源界進入,這篇文章只不過是拋磚引玉。

 

關於作者

 

彭麟,EMC中國研究院高級研究員,關注雲計算平臺架構設計、分佈式計算原理等領域。

微博:http://www.weibo.com/laynepeng

 

Reference:

[1]http://www.vmware.com/products/vfabric

[2]SpringSource Tool Suite: http://www.springsource.com/developer/sts

[3]http://www.opscode.com/chef

[4]https://raw.github.com/CloudFoundry/vcap/master/setup/install

[5]http://www.activestate.com/cloud


原文:http://qing.weibo.com/2294942122/88ca09aa330004r8.html  http://qing.weibo.com/2294942122/88ca09aa33000975.html 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章