如何構建一個簡單的CAAS系統

在CAAS系統出現前企業應用架構基本被IAAS/SAAS/PAAS等模式壟斷,直到docker的出現爲咱們打開了另外一個扇大門,廢話不說了,咱們直奔主題mysql

咱們先了解下一個簡單的CAAS系統是如何爲用戶提供服務的web

  • 企業用戶上傳它的應用代碼或其餘代碼託管方式,咱們生成用戶應用的鏡像,或者用戶直接上傳鏡像,或者用戶直接使用咱們提供的基礎服務鏡像redis

  • 用戶部署他的鏡像應用,啓動它的鏡像容器算法

  • 用戶訪問他的應用服務sql

OK,需求肯定了,該搬磚了docker

caas-docker

1. 用戶鏡像製做

既然是一個簡單的CAAS系統,咱們就不讓用戶上傳代碼或者使用第三方代碼託管了,直接讓他們製做鏡像後提交給咱們,爲此咱們須要搭建一個docker私服來讓用戶上傳鏡像,假設用戶上傳的鏡像遵循這種格式:
docker私服地址/{appId}:{version},這對用戶有必定要求,畢竟一些用戶可能連docker是啥都不知道就更別奢望讓他們編寫dockerfile製做鏡像交付給咱們了。固然若是咱們提供一些基礎服務鏡像(好比mysql服務,redis服務等)給用戶那最好了。數據庫

2. 啓動用戶鏡像

有了用戶製做的鏡像,該是啓動它的時候了後端

docker pull docker私服地址/{appId}:{version}
docker run -d docker私服地址/{appId}:{version}

啓動方式很簡單,但這並非咱們想要的,畢竟咱們是要讓用戶可以訪問到他部署的服務的,假如用戶的服務是一個web服務,那你得暴露出用戶的web服務端口,這須要咱們肯定容器的通訊方案:api

  • 跟宿主機共用一個網絡空間緩存

  • 發佈一個容器端口,讓docker隨機選擇一個未使用的高位端口

  • 發佈一個容器端口,並映射到宿主機上指定端口爲外部路由服務

  • 採用docker的'links'來容許容器間通訊。 若是一個新容器連接到一個已有容器,新容器將會經過環境變量得到已有容器的連接信息,一個關聯的容器將會得到它的對應鏈接信息,在它處理了那些變量後容許它自動鏈接。這樣就使得同一個宿主機上的容器不須要知道對應服務的端口和地址,就能夠直接進行通訊

咱們簡單的CAAS系統暫時還用不到容器間通訊,若是跟宿主機共用一個網絡空間即--net="host"模式啓動的話,那麼若是有多個用戶上傳了鏡像,他們的WEB服務端口都是8080,顯然宿主機上只能啓動一個8080端口,只能有一個用戶的容器啓動成功,其餘的由於端口已經被佔用致使啓動失敗,在這裏咱們選擇第三種模式,選擇指定的端口映射來發布容器,這也方便咱們後面管理宿主機上的端口資源。OK,啓動方式改爲下面:

docker run -d -p 25701:8080 docker私服地址/{appId}:{version}

爲了避免讓某個用戶的應用佔用過多資源致使影響到整個宿主機上其餘的應用,咱們稍微對用戶的資源進行下限制,好比限制用戶應用容器的使用內存和CPU權重

docker run -d -p 25701:8080 -m 512M -c 1024 docker私服地址/{appId}:{version}

爲了能作到水平擴展,容器服務最好是無狀態的的,這樣能更好的實現負載均衡和水平擴容。

應用啓動成功,咱們能夠經過在宿主機上訪問25701便可訪問容器的8080端口服務

在寫代碼的時候咱們經過Docker Remote API client libraries來啓動卸載容器,具體代碼實現就很少說了。

3. 服務發現

容器啓動成功後,用戶該如何訪問到他的容器服務呢,總不能提供宿主機IP給用戶直接訪問吧,這就須要咱們構建一個服務發現組件了

3.1 服務發現的工做方式:

  • 當每個服務啓動上線以後,他們經過發現工具來註冊自身信息

  • 服務的消費者可以在預設的終端查詢該服務的相關信息,而後它就能夠基於查到的信息與其須要的組件進行交互

爲了簡便,咱們使用zookeeper來做爲咱們的服務發現工具

首先在容器啓動成功後咱們將服務註冊到zookeeper中,存儲的path路徑以下:/caas/service/address/{appId}/{version},存儲的服務子節點爲{containerId}->{宿主機IP}:{服務端口}

例如用戶appId01和appId02分別部署了各自的應用版本容器containerId01和containerId02,對應的服務端口分別爲25701和25702,那麼zk裏存儲的註冊表信息爲下:

/caas/service/address/appId01/app01Version/containerId01 -> {宿主機IP}:25701
/caas/service/address/appId02/app02Version/containerId02 -> {宿主機IP}:25702

若是一個用戶部署了多個容器實例,對應的zk註冊表信息相似下面:

/caas/service/address/{appId}/{version}/containerId01 -> {宿主機IP}:25701
/caas/service/address/{appId}/{version}/containerId02 -> {宿主機IP}:25702
/caas/service/address/{appId}/{version}/containerId03 -> {宿主機IP}:25703
/caas/service/address/{appId}/{version}/containerId04 -> {宿主機IP}:25704

3.2 故障檢測

以上咱們完成了服務的註冊,註冊完服務後爲了實現應用的高可用,咱們應該還須要對容器進行故障檢測,故障檢測的方案一般有下面2種:

  • 組件主動請求服務發現心跳方式:組件能夠設置一個超時時間,並能按期去請求服務發現來重置超時時間,超時時間達到閥值更新註冊表

  • 服務發現主動請求組件心跳方式:服務發現按期的健康檢查組件以及當組件出現故障時更新註冊表

一般內部本身的服務可使用第一種方式讓組件主動請求服務發現,用戶本身寫的服務通常不可能費勁的去實現心跳來訪問服務發現組件,因此一般會要求用戶實現一個服務發現組件能訪問的心跳接口,讓服務發現組件去主動請求用戶的應用,一旦訪問失敗在重試必定次數後會認爲該應用已經出現故障沒法繼續提供服務,這時能夠根據策略來選擇直接中止刪除該用戶容器或者從新啓動。

好比服務發現的健康檢查組件能夠每隔必定時間來訪問用戶的心跳接口,相似{宿主機IP}:25701/_ping

3.3 註冊表安全訪問

基於安全方面考慮,一般狀況下咱們須要對服務發現作相應的訪問控制,以便對註冊表中的存儲信息實現安全訪問,可能有如下幾種方案可供參考:

  • 服務發現工具能夠採用SSL/TLS加密連接

  • 對寫入數據進行加密,使用者使用的信息必須用相應的密鑰解碼從服務發現中獲取

  • 服務發現實現訪問控制,將不一樣的鍵值切分到不一樣的分組中,根據訪問的須要來制定不一樣的祕鑰從而訪問相應的分組

這裏咱們就不說具體的安全方面的實現了,誰讓咱們是簡易版CAAS系統呢。

3.4 分佈式配置存儲和負載均衡

其實服務發現的註冊表存儲訪問地址只是其中的一個方面,你能夠用它來存其餘的信息,好比存應用的配置,你能夠經過配置動態的調整應用,也能夠存容器的相關指標,負載均衡就是一個很好的例子,它能夠經過查詢服務發現獲得各個後端節點承受的流量數,而後根據這個信息來調整配置。具體的負載均衡算法能夠根據需求來選擇,咱們就使用最簡單的round bobin算法,即輪詢方式訪問。這方面的實現涉及到CAAS系統的另外一個組件:路由網關,具體後面介紹。

上面咱們一直都是使用了zookeeper來做爲服務發現工具的,除了zk,咱們還可使用其餘的服務發現工具:etcd、consul、crypt、confd,你們有興趣能夠了解下,最重要的是能保證註冊表信息的數據一致性。

4. 調度編排

經過上面幾步你的CAAS系統基本小有所成了,但這還不夠。咱們在生產環境裏隨着用戶應用容器的數量增長鬚要增長宿主機來支撐避免資源不足,或者將某些用戶的實例單獨部署在指定的宿主機上,這就須要咱們實現一個調度器組件。

4.1 宿主選擇

CAAS系統是一個分佈式系統,在多個宿主機的環境裏,咱們須要知道用戶的應用該部署在哪臺宿主機上,若是單機的話那就不須要選擇了,直接指定就行了。具體該如何調度須要考慮如下幾點:

  • 須要一個默認的調度策略,好比選擇可用內存最多的宿主機部署服務或選擇cpu最空閒的宿主機部署服務

  • 調度器須要提供覆蓋機制,好比2個容器必須部署在同一個宿主機上做爲一個單元來運行,好比同一個服務的2個實例容器必須部署在不一樣機器上來達到高可用

  • 調度器須要知足限制條件,好比給特定的宿主機打標籤,好比一些服務須要部署在集羣中的每一臺宿主機上

4.2 多容器部署調度

隨着業務的擴展,咱們可能須要提供分組容器管理,將一個集合的容器(一般是有相互依賴關係緊密關聯的組件)做爲一個單獨應用來處理,好比一個web服務容器再加上後端的數據庫服務容器組合成一個project來發布。這裏就很少作討論了,咱們的簡易版系統還沒考慮到這步。

4.3 供應

供應是指將一個新主機上線並完成基本配置使得它們可以工做的一個過程,一般在集羣管理裏用來自動擴展宿主機,管理工具來定義需求額外主機的過程以及自動觸發的條件,例如,若是你的應用的負載很高,你可能但願讓你的系統增長額外的機器並水平擴展容器以緩解負載,這裏咱們一樣不作實現,簡易版就直接手動增長宿主機就行了嘛。

咱們在這裏舉個實現調度器的相對簡陋的方案:

主要使用關係型數據庫如mysql來存儲宿主機信息,調度器查詢宿主機的相關指標信息根據調度算法選擇相應的宿主機來部署,利用樂觀鎖來保證併發操做時的數據一致性,利用事務來保證部署和卸載等操做的原子性。這裏面可能坑比較多,你們也可使用如今比較流行的調度器,經常使用的調度器有:fleet、marathon、Swarm、mesos、Kubernetes、compose,你們有興趣能夠了解下。

5. 網關

上面咱們在服務發現的負載均衡方面介紹到了網關,咱們把它做爲CAAS系統中重要的一個組件,他主要是負責用戶請求的轉發,舉個例子用戶部署了容器想要訪問它的容器服務,這個請求到達網關後網關根據策略選擇相應的後端容器服務而後轉發請求。根據用戶的設定,動態路由請求到對應容器實例,這至關於一個代理服務器。具體如何選擇容器實例服務轉發就須要實現負載均衡器,咱們能夠經過查詢服務發現組件來獲取相應容器信息來完成。既然是代理服務,咱們在中間能夠對用戶的請求作其餘處理,好比作黑名單過濾,作流量統計,作CNames路由等等

假設咱們的CAAS網關訪問域名是mycaas.gateway.cn,用戶在咱們後臺部署了一個WEB應用容器實例,調度器將他部署在了10.10.10.101宿主機上,容器服務端口映射爲25701,用戶請求mycaas.gateway.cn到達網關後,網關根據請求信息識別用戶查詢該用戶全部的應用容器信息,獲得全部的容器服務地址,根據負載均衡規則代理轉發到目標容器服務上。這個查詢服務發現的過程當中最好實現本地緩存,好比使用zookeeper的緩存減小和避免每次請求都訪問服務發現組件,同時代理轉發中儘可能使用鏈接池減小開銷。

6. 總結

至此咱們簡單的CAAS系統就架構設計好了,在整個系統中有服務發現/調度器/網關等多個組件協調配合。

caas


做者信息

做者來自力譜宿雲LeapCloud旗下MaxLeap團隊_雲服務研發成員:David Young
首發地址:https://blog.maxleap.cn/archi...

相關文章

基於PaaS和SaaS研發的商業雲平臺實戰
移動雲平臺的基礎架構之旅(二)- 雲代碼篇
微服務系統中的服務發現機制

歡迎關注微信訂閱號:MaxLeap_yidongyanfa

相關文章
相關標籤/搜索