雲端服務與經驗談 [3] 虛擬機器與應用程式部署 by qrtt1 | CodeData
top

雲端服務與經驗談 [3] 虛擬機器與應用程式部署

分享:

雲端服務與經驗談 [2] 雲端服務與架構演化 << 前情

在我使用過的 IaaS 服務中,以虛擬機器(Virtual Machine)服務最感興趣。透過雲端服務供應商(例如:Amazon 、Azure 或是國內的 MiCloud)提供的 API 可以自由地建立新機器,並且在不需要的時候透過 API 操作關閉並刪除它。這種新型態的使用模式,與在公司內部將實體機器轉成虛擬機器是完全不同的體驗。

近年流行的實體機器轉虛擬機器,主要是關係到公司內部機器管理的需求。合併多個實體機器在空間上可以節省,機器的數量少了,總用電量也能減少,同時虛擬機解決方案也多支援快照(Snapshot)工具,可以快速達到災後復原的目標。

IaaS 提供的虛擬機器服務同樣有上述的好處,同時有更重要的目標「Service」。基本的電力與網路供應之外,還需提供 API 以便透過程式操作。能透過程式操作就能製作各種管理工具,在適當的時候產生需要的「運算單位」,並且在不再需要這些運算資源時將其撤銷。概念上聽起來蠻容易的,但實行起來有些細節是需要多加思考的。

運算力的擴展

無論是否使用虛擬機器,隨著業務擴展導致伺服器服務總量的提昇,都需要考慮到擴展的問題。在不使用雲端虛擬機器服務的情況下,加入新的運算單位的方式,多為購入或租用實體機器並架構好所需的服務。持有硬體是固定的成本,運算能力也是固定的。以下圖為例:

雲端服務與經驗談 [3] 圖一

紅色的曲線是伺服器的不同日期的需求負載量。中間的虛線為目前伺服器可供給的負載量。多數的時間,實際的負載量能承載需求負載量,但因不同的時期需要面對超出合理負載量的風險。若屬輕微的情況,也許使用者只會感覺到「頓頓」的,較嚴重的情況是服務伺無法承受後崩潰無法服務。

這種需要面對突量大量負載的情況並不罕見,例如:每間大學期初選課都考驗著學校選課系統,每學期就只在那最初的一週會有突來的負載量。簡單的應對之策就是提昇整體的負載量,可能是加新的機器,或是將舊有的設備進行昇級。目標就是使得可供給負載量超出實際需求的負載量,如下圖所示:

雲端服務與經驗談 [3] 圖二

透過硬體升級提昇負載量的方法相當直觀,但它同時會讓負載量的利用率減低,多數時間都處於閒置的狀態,下圖標示黑點的部分即為閒置的負載量:

雲端服務與經驗談 [3] 圖三

閒置本身不是個嚴重的問題,問題在於總負載量擴充上去後伴隨增加的成本。以租用實體主機來說,原先租用一台不足以承受可預估的負載量,而多增加了二、三台主機一同服務使用者。那麼每個月的成本也就變成原本的二、三倍,或是一次性購入硬體的情況,那就是一次性的費用。以租賃的情況來說,可以在渡過服務尖峰時刻後退租,而購入實體機器就如同其他產財一般隨著時間折舊,特別在一年只有幾回集中的尖峰時刻的用量來說,其餘的日子可能會反覆思考這樣的採購行為是否合理?

回到我們的主題「虛擬機器」。有人可能會反問:那麼換上了雲端服務提供的虛擬機,就能解決這樣的問題嗎?單純將雲端服務商的虛擬機器取代一般主機商提供應的機器租賃服務是無法解決問題的,而且虛擬機器的運算能力往往比不上實體機器來得優異,既然在效能上無法獲得勝利,總要有可取之處才能吸引「消費者」選用。

我們先狹義地定義一下,雲端服務商提供的虛擬機器該有什麼樣的「服務」。它必需要能透過「規則」或「API」自動化管理使用者對於機器的需求。以 AWS EC2 為例,它本身有 API 可以讓你動態產生機器,你也可以設定 Auto Scaling 政策,監控一些機器的負載量或其它數據決定是一組服務下機器的數量。簡單地說,負載量高就多開新機器,負載量變低就減少服務的機器。這樣彈性面對負載量的策略才能讓雲端服務有別於一般主機商。

值得注意的是,你選用一個新的雲端服務商時,還是得確定如何使用它來達成自動管理機器的增減,不同服務商提供的功能可能與你過去經驗過的不同。例如:國內幾個剛起步的雲端服務商,有些甚至沒有公開的 API 讓你動態增減機器,更遑論要設定動態增減的策略。有些服務商的機器建立的時間較久,有時可能超過十至十五分鐘,若你的負載量恰好只有在這時間內暴衝,那應該是等不及它自動把機器生出來服務使用者,在請求增援的空窗期系統有機會因無法承受而崩潰。實際的情況得同時熟悉你的使用者與服務商能力來決定策略的細節。

應用程式部署問題

採用雲端虛擬機器(以下簡稱 VM)的優點是,它能非常動態地決定目前需要多少機器,並且能在不再需要使用時撤銷額外的資源。不過虛擬機建出來後該如何互相合作,又該如何將目前的狀態更新是需要注意的細節。

在先前分享的媒體偵測服務,它運行在 AWS EC2 主機上,同樣也需要處理部署的問題。在一開始,我們的方法單純開一個新的 VM,並在上面安裝需要的應用程式,與編譯後可執行的偵體偵測程式,大致的清單如下:

  • java-1.6.0-openjdk.x86_64 
  • java-1.6.0-openjdk-devel.x86_64 
  • git.x86_64 
  • make.x86_64
  • gcc.noarch 
  • openssl-devel.x86_64 
  • pkgconfig.x86_64
  • rtmpdump(使用原始碼版本編譯)
  • ffmpeg (使用原始碼編譯並加入一些需要的 patch)
  • 我們的程式(主體是 Java,需要時會外部呼叫 ffmpeg 提供判斷資訊)

標示為藍色的部分是可靜態部署的,因為他們是前置作業或執行環境的一部分(含 OS)。若沒有重大的 Bug 或安全性更新,實在不會有機會再動到它們。標示為綠色的部分是需動態部署的,但部署的方式需要改變。原先它是由原始碼版本編譯而成,需將它們預先編譯成可安裝檔在 VM 啟動時自行下載安裝(以使用 Amazon Linux AMI 的情況,就是打包成 RPM)。紅色部分即為主程式,由於解 Bug 或新增功能都會用到它,必需歸類在「動態」安裝的部分是必然的。

藍色區域可以簡單地歸入與 Image 一起更新的部分,而綠色區域就是可以討論的部分,主要的標準是它是否需要一直更新呢?若它更新的如紅色區域一樣地頻繁,那就應併入動態更新的區域。另一種考量是它更新的頻率沒有規律,那麼只好當作需動態更新處置。

主程式的更新我們試過三種方法:最初利用的是「版本控制系統」,再來是利用 AWS S3 上傳整包軟體,最後改成部分更新。

最初的「版本控制系統」更新,我們是利用 git 做更新。固定將要在 VM 上執行的程式 push 到名為 RELEASE 的 branch 上,當 VM 啟動後它會去 pull 最新的 RELEASE 原始碼,並執行 ant 編譯然後執行。

這設計很簡單,但需注意 branch 的管理,並且不能變更 RELEASE 的「舊」歷史,也要注意 pull 是否可能產生衝突的問題。另一個問題是 Image 上的 git 歷史是不會更新的,隨著 commit 的檔案與次數越多它可能會越來越慢,特別是有更新多份 JARs 的情況。由於考慮到放 JARs 不宜放在版本控制系統內,後來改採 gradle 管理 project,但 gradle 在 AWS EC2 的 micro instance 跑起來實在太慢了,迫使我們得放棄就地編譯的方式。若您的專案是以純文字檔組成為主的,像是 Python 這類的 Scripting Language,倒蠻適合利用版本控制系統更新策略。

就地編譯的策略不合用,那麼換個方向想。先在開發機上編譯好,上傳至 AWS S3 讓 VM 直接下載執行。這完全合用,只是將編譯的地點換成在開發機上做罷了。

不過,做了幾會發現新的困擾,那就是上傳至 AWS S3 的時間要很久,特別是明明只改了一個 Class 卻要整包上傳時,總是件奇怪的事。這種包山包海的更新策略用了幾回就沒耐心了。它需要有一些微調,若我們是用「同步」目錄的概念呢?將執行程式的目錄,同步至 S3 某個 prefix 之下,而 VM 則是將同個 prefix 對它的本地端同步,這樣只有變動的檔案需要上傳、下載。這個方法即能滿足預先編譯的需求,又能滿足只上傳變動的檔案,最終成為我們現在的部署、更新方案。

基礎建設部署

解決了日常更新問題後,我們回頭討論一下「基礎建設」的部分,也就是藍色區域的軟體清單。它值得討論的部分在於「久久裝一次,每次都忘記」不同的人裝起來可能會不太一致,漏了這個,忘了改某個設定。特別在多個 Data Center 間重建 Image 時,可能會出現不一致的情況。唯一的建議就是寫成 Install Script 並保存在版本控制系統內,它最好能自我滿足需要的設定內容。

以 Linux 機器為例,開了全新的 VM 後,只要設定好 SSH 無密碼登入,並使用 SSH 執行遠端指令呼叫 Install Script 等它完工即可,按下「Create Image」建出新的 Image。許多有提供公開 Image 的 Open Source 專案,都有在它們的版本控制系統上保存了建置 Image 用的 Install Script,例如 Apache Hadoop 專案,它不但有 Install Script 也在 Wiki 上寫下了設定的細節,是值得參考學習的範本。

當使用的是較著名的專案,多數的情況已經有人替它寫了雲端部署的工具。例如:Cassandra 或 Hadoop 都有許多工具能在網路上找到,例如 Apache Whir 試圖整合多個雲端供應商的部署問題。而依軟體生態系的不同,有各自偏好的工具。依 Linux 管理者來說,寫成 Shell Script 再理所當然不過。若您熟悉 Python 那麼試著使用 Fabric 撰寫自動化部署腳本一定能駕輕就熟。

無論最終您選擇的是什麼方案,請試著讓團隊的不便儘可能地減少。在開發、部署、更新三種角色間取得平衡。在這篇文章,我們由試誤的過程式分析部署的需求,它的手法是原始而直覺的。若環境能配合,可往更高階的 DevOps 工具遷移,例如:Chef 或 Puppet。

後續 >> 雲端服務與經驗談 [4] 架構與供應商相依問題

分享:
按讚!加入 CodeData Facebook 粉絲群

留言

留言請先。還沒帳號註冊也可以使用FacebookGoogle+登錄留言

關於作者

目前在一家網路應用軟體公司擔任開發工作,對多媒體處理與雲端應用充滿興趣,工作之餘亦常整理開發經驗分享於網路或於社群活動時進行分享。

熱門論壇文章

熱門技術文章