1. 程式人生 > >Flynn初探:基於Docker的PaaS平臺

Flynn初探:基於Docker的PaaS平臺

Flynn是一個開源的PaaS平臺,可自動構建部署任何應用到Docker容器叢集上執行,其功能特性與元件設計大量參考了傳統的PaaS平臺Heroku。本文旨在從使用動機、基本物件、層次架構、功能元件、基本工作流這幾個方面對Flynn做總體的介紹。

為什麼需要Flynn

為了便於理解Flynn的作用與功能,讓我們先來看看應用程式從開發到構建再到部署再到執行分別需要經歷的幾個實體狀態:

AppPhases

更具體一點,以一個Java程式為例來描述:

  • 原始碼:包括*.java、log4j.properties、pom.xml等檔案。

  • 釋出包:原始碼被編譯打包後生成一個JAR包,這個就是釋出包。

  • 部署配置:比如每個程序的啟動命令、環境變數、系統屬性等。通常,這些配置會寫在一個啟動腳本里面。

  • 程序:執行Java程式的實體。一個Java程式可以起多個程序,每個程序啟動不同的主類(實現了main()方法的類,一個JAR包可以包含多個主類)。

引入Docker後,釋出包變成封裝了JAR包與JDK環境的映象,程序變成在相互隔離的容器裡執行。但是,從原始碼到映象、從映象到執行容器這兩步轉換過程需要使用者人工的操作。尤其是後者的轉換,涉及到叢集資源排程、自動部署、配置管理、容器管控等一系列的複雜流程。更進一步,在執行階段還涉及擴縮容、日誌檢視、錯誤處理、執行監控等運維需求,如果全部人工操作將耗費巨大的工作量。

這時候類似Flynn這樣的PaaS出場了,基於Docker之上進一步封裝了整個構建、部署、執行工作流,使得使用者只需簡單地提交程式碼即可完成開發到執行的快速轉換:

  • 開發到構建:使用者通過git提交原始碼,由Flynn自動構建映象,並提供版本的管理——使用者可以建立新版本(提交新程式碼或修改部署配置)、回滾老版本等。

  • 部署到執行:Flynn自動選擇執行機器,為每個程序副本部署啟動單獨的容器,並提供程序的管理——使用者可以做擴縮容、檢視日誌、監控狀態等。


Flynn的基本物件

下面我們來看看釋出包、部署配置、程序這三個實體在Flynn中是如何抽象的。如下圖所示是其基本物件的關係描述:

FlynnObjects

  • App:表示一個應用,所有其他物件都是圍繞App而展開。

  • Artifact:表示應用的釋出包,實際上對應一個Docker映象。

  • Process:表示應用的程序。通過一個映象可以啟動多個不同的程序,每個程序執行在自己單獨的容器裡。

  • Release:是應用釋出態的抽象表示。它在Artifact的基礎上增加了一些不可變(immutable)的靜態配置,比如每個程序的啟動命令列、環境變數、繫結埠、等。要修改這些配置,需要生成一個新Release。Release這種不可變性是為了方便做Rollback,即應用隨時可以回退到之前的Release。

  • Formation: 是應用執行態的抽象表示。它在Release的基礎上增加了可變(mutable)的動態配置,即每個程序的副本(replica)個數。

  • Job: 是程序副本的抽象表示,每個Job對應一個執行容器。因此,在後文中可以看到,Job是資源排程的基本單元。


Flynn的層次架構

如下圖所示,Flynn的架構自下而上分為兩個層級——Layer 0和Layer 1。簡單地理解,可以認為Layer 1負責接受使用者請求,封裝成應用的執行指令,再由Layer 0解決在哪裡執行以什麼方式執行的問題。具體一點講,Layer 0面向的物件是Formation,負責將底層的叢集資源封裝成可執行Formation的一臺主機;Layer 1面向的物件是App,負責將App從原始碼構建成Artifact,進而封裝成Formation提交給Layer 0去執行。

這種分工明確的層次劃分,使整個系統非常靈活,相互鬆耦合,便於任意元件的替換(比如,甚至可以把Layer 0替換成不用容器去執行Formation)。


FlynnComponents

Flynn的功能元件

下面總結一下組成兩個層級的各個元件及其功能(所有元件自身都可以執行在容器裡):


Layer 0

  • Scheduler: 資源排程器,定期從Layer 1獲取Formation的更新,再根據每個Formation的部署配置生成一個個的Job,最後從叢集中選擇合適的機器去執行這些Job。

  • Host Service: 執行在叢集每臺機器上的agent,負責管控執行在本機的容器,並收集執行狀態資訊。

  • Host Leader:一個特殊的Host Service,做為"cluster leader",負責維護整個叢集的狀態資訊(比如有哪些機器、每臺機器上執行的Job等),並提供給Scheduler用於資源排程。

  • Discoverd:基於etcd的服務發現模組,提供容器間的發現機制。實際上,Flynn自身的元件間通訊也是通過Discoverd來相互發現的。

Layer 1

  • CLI:提供給使用者使用的命令列工具。

  • Controller:為Flynn系統的入口,封裝了核心物件(比如app/artifact/release/job)的增刪改查操作,以RESTFul介面方式提供給外部客戶和內部元件呼叫。它維護的REST物件將持久化到postgre資料庫。Layer 0的Scheduler就是通過Controller的介面來獲取Formation更新的。

  • GitReceiver:接受使用者git push原始碼的SSH伺服器。接受到git push後將觸發Receiver。

  • Receiver:基於buildpack機制,利用SlugBuilder從原始碼包構建slug包。buildpack和slug都是從Heroku借鑑過來的概念。簡單地理解,buildpack是一組用於構建原始碼的指令碼,buildpack可以多種多樣,每個buildpack可構建某種型別的原始碼,這種型別可以是不同的語言(比如Java、PHP)、不同的構建方式(比如maven、gradle);而slug則是buildpack構建生成的部署包,包含了編譯輸出檔案、依賴庫檔案等執行環境。

  • BlobStore: HTTP檔案伺服器,用於上傳/下載slug包。

  • SlugBuilder:接受原始碼包,基於某種buildpack構建生成slug包。選擇哪一種buildpack可以顯式地指定,也可以由SlugBuilder根據原始檔自動匹配。

  • SlugRunner:執行slug包,會從BlobStore下載應用的slug包。


Flynn的工作流

下面通過一個例子來展示Flynn各個元件的工作流。使用Flynn來構建部署應用最基本的流程是以下三步:

使用者建立app

flynn create myapp

FlynnCreateApp

使用者提交app程式碼

git push flynn master

FlynnGitPush

使用者擴容app的程序

flynn scale web=2

FlynnScaleApp


對比Kubernetes

Kubernetes是Google開源的Docker容器叢集管理系統,為容器化的應用提供資源排程、部署執行、服務發現、擴容縮容等整一套功能,更詳細地介紹請參考作者的另一篇文章《Kubernetes初探:原理及實踐應用》

在應用的抽象上,Flynn與Kubernetes有本質的區別:Flynn的應用管理單元是App,只對應一個Docker映象,但可以由這個映象來啟動多個程序,並且每個程序可以單獨擴縮容;而Kubernetes的應用管理單元是Pod,可對應多個不同的Docker映象,並且Pod內的各個容器保證會執行在相同的機器上,整個Pod作為擴縮容的基本單位。

另外一個根本的區別是Kubernetes不提供映象構建與版本管理的功能。因此,Kubernetes只能看成是面向容器而不是面向應用的系統。當然,我們可以在Kubernetes之上擴充這些功能。


對比Deis

與Flynn類似,Deis也是受到Heroku的啟發,基於Docker之上構建的PaaS平臺。因此,從功能特性到應用抽象,兩者是大同小異。

至於兩者的差異,瞭解不是很多,這裡提三點:第一,Deis是用Python開發的,而Flynn是Go;第二,Deis依賴於CoreOS,而Flynn因為所有元件都可執行在容器裡,沒有OS的依賴;第三,Deis在構建階段,除了buildpack方式構建外,還支援Dockerfile與映象直接上傳兩種方式,相對Flynn更為靈活。