在 Google Cloud Platform 上建置可擴充且有彈性的網路應用程式

建立兼具彈性與擴充性的應用程式,是所有應用程式架構的核心要素。一個設計精良的應用程式應能隨著需求的增減靈活調度資源,並且具備足夠的彈性來承受一或多個運算資源損失的情形。

本說明文件適合熟悉 Compute Engine 的系統作業專家閱讀。在本文中,您將學習如何使用廣泛應用於各種網路應用程式的模式和做法,透過 Google Cloud Platform 建置可擴充且富有彈性的應用程式架構。本文件的範例是以 Redmine 這套建構在 Ruby on Rails 應用程式上的熱門開放原始碼專案管理工具來進行部署;透過這個部署範例,您將瞭解這些原則如何應用於實際的使用情況中。在本文後段的部署範例解決方案一節中,您還有機會親自部署應用程式,並且下載所有原始碼做為參考。

GCP 可讓您以具成本效益的方式,輕鬆建置及運作可擴充且富有彈性的網路應用程式。您可以透過 Compute Engine、自動配置器等服務,根據需求輕鬆調整應用程式的資源。Compute Engine 的以秒計費模式讓您用多少就付多少,而且您可以透過續用折扣自動獲得最優惠價格,免除您面對五花八門的容量或預留方案而難以抉擇的困擾。

如要概略瞭解 GCP 提供的網路託管服務選項,請參閱服務網站

事前準備

定義擴充性和彈性

在介紹範例應用程式架構之前,讓我們先來談談「擴充性」和「彈性」這兩個詞的涵義。

擴充性:因應需求調整容量的能力

一個可擴充的網路應用程式不論使用者多寡,即使是 1 或 1,000,000 個使用者都能應付自如,並能從容應對流量的高峰期和低谷期。透過適時增減虛擬機器,可擴充的應用程式只會耗用因應需求所需的資源。

下圖顯示可擴充的應用程式如何因應需求的增減變化。

顯示資源如何因應需求擴充的圖表。

請留意,應用程式會隨著需求的變動而調整容量。這種設計上的佈局有時也稱為彈性,能確保您僅針對應用程式在特定時刻所需的運算資源付費。

彈性:承受非預期狀況的能力

一個高可用性或高彈性的網路應用程式,在遇到系統元件故障的狀況時,不論是預期或非預期情況都能繼續運作如常。如果單個執行個體故障或整個區域出現問題,具彈性的應用程式依然會保有容錯能力,且會繼續持續運作,並在必要時自行修復。由於狀態資訊未儲存在任何一個執行個體上,因此損失單個執行個體 (或即使是整個區域) 並不會影響應用程式的效能。

要設計一個真正具有彈性的應用程式,必須從軟體開發及應用程式架構的層級進行規劃。本文主要從應用程式架構的層級進行探討。

高彈性應用程式的架構設計通常涉及下列幾個面向:

  • 利用負載平衡器監控伺服器,並將流量分配到最適合處理要求的伺服器
  • 將虛擬機器放到不同的地區中託管
  • 設定強大的儲存空間解決方案

Google Cloud Platform:彈性靈活且經濟實惠

傳統上能夠支援擴充性及彈性的架構,通常必須在資源方面挹注大量的投資。對內部部署解決方案而言,擴充性通常意味著您必須在兩種情形之間做抉擇:為了處理高峰用量而在伺服器容量上花大錢;或是購買僅足以應付平均需求的容量,承擔流量暴增時應用程式效能不彰或使用者體驗欠佳的風險。然而,彈性講求的不只是伺服器容量而已,地點也同樣重要。為減緩暴風或地震等實際事件的影響,您必須考慮將作業伺服器架設在不同的實體位置,但這會使成本大增。

GCP 為您提供替代的方案:一套可讓您以靈活方式增添架構擴充性和彈性的雲端服務組合。此外,GCP 還提供一種能夠讓您輕鬆掌控成本的服務定價方式。

使用 Google Cloud Platform 打造具彈性且可擴充的架構

下表顯示建置高擴充性與高彈性應用程式的關鍵必要需求與不同 GCP 服務之間的對應關係。

架構需求 Google Cloud Platform 服務
負載平衡 HTTP 負載平衡
伺服器託管 Compute Engine地區與區域
伺服器管理 執行個體範本代管執行個體群組自動配置器
資料儲存空間 Cloud SQLCloud Storage

下圖顯示這些 GCP 元件如何協同運作,共同建置一個兼具擴充性和彈性的網路應用程式。我們將在下節詳細說明各個元件所扮演的角色。

顯示可擴充且具有彈性的網路應用程式的圖表。

元件總覽

範例應用程式架構中的每個元件在確保應用程式的擴充性及彈性方面都發揮了各自的作用。本節將概略介紹各個元件服務,並在後續章節中說明這些元件如何互相搭配運作。

HTTP 負載平衡器

HTTP 負載平衡器提供一個讓客戶用於存取應用程式的公開 IP 位址。此 IP 位址可與 DNS A 記錄 (如 example.com) 或 CNAME (如 www.example.com) 建立關聯。傳入的要求會根據每個群組的容量,分配至各區域的每個執行個體群組。在同個區域內,要求會平均分配給群組中的執行個體。雖然 HTTP 負載平衡器能平衡不同地區之間的流量,但本範例解決方案僅在具有多個區域的單一地區使用這項元件。

區域

區域是某個地區內的獨立位置。同一地區中的各個區域會以高頻寬且低延遲的網路相互連線。Google 建議將應用程式部署在同個地區內的不同區域。

執行個體

執行個體是指 Google 基礎架構所託管的虛擬機器。您可以如同實體伺服器一般地安裝及設定這些執行個體。在範例部署中,您會使用開機指令碼和 Chef 來設定具有應用程式伺服器的執行個體及網路應用程式的程式碼。

執行個體範本

執行個體範本定義了機器類型、映像檔、區域、標籤及其他執行個體屬性,並可用於建立代管執行個體群組

代管執行個體群組

代管執行個體群組是以執行個體範本為基礎的一組性質相同的執行個體。HTTP 負載平衡器會以代管執行個體群組為目標,將工作負載分配給群組中的執行個體。代管執行個體群組有對應的執行個體群組管理員資源,負責為群組新增及移除執行個體。

自動配置器

Compute Engine 自動配置器會透過群組管理員,將 Compute Engine 執行個體新增或移除至代管執行個體群組,以回應流量、CPU 使用率或其他信號。在範例解決方案中,自動配置器回應了 HTTP 負載平衡器的每秒要求數 (RPS) 指標。自動配置器是為代管執行個體群組自動調整資源配置的必要工具。

Cloud SQL

Cloud SQL 是一項支援 MySQL 和 PostgreSQL 的全代管資料庫服務。包括複製、加密、修補程式和備份等作業全都交由 Google 代管。Cloud SQL 執行個體會部署在單一區域,而其資料會自動複製到其他區域。此範例中使用的 Redmine 應用程式與 MySQL 相容,並且能與 Cloud SQL 完美搭配運作。

Cloud Storage

Cloud Storage 使物件 (通常是檔案) 能夠透過簡單且可擴充的介面進行儲存及擷取。此解決方案使用 Cloud Storage 值區將私人 SSL 金鑰發佈到可擴充的 Compute Engine 執行個體,並且用來儲存所有上傳至 Redmine 應用程式的檔案。也就是說,執行個體的磁碟中不會存放任何狀態資訊。

彈性

對於本範例架構而言,所謂的彈性是指此架構必須能夠自動替換已經故障或變得無法使用的執行個體。當任何新執行個體上線時,此架構應能夠:

  • 瞭解其在系統中的角色
  • 自動完成設定
  • 探索其依附元件
  • 自動開始處理要求

如要自動替換故障的執行個體,您可以同時搭配多個 Compute Engine 元件:

開機指令碼會在執行個體啟動或重新啟動時執行。這些指令碼可用來安裝軟體和更新,以確保服務能夠在虛擬機器中運作,或甚至可用來安裝 Chef、Puppet、Ansible 或 Salt 等設定管理工具。

此解決方案使用開機指令碼安裝 Chef Solo,並且進而用來設定與應用程式搭配的執行個體。如要瞭解如何使用開機指令碼和 Chef Solo 自動設定執行個體,請參閱本主題結尾的附錄:新增執行個體

除了開機指令碼之外,您還需要定義一些項目才能啟動 Compute Engine 執行個體。例如,您需要指定其機器類型、要使用的作業系統映像檔及要掛載的磁碟。您可以使用執行個體範本來定義這些選項。

執行個體範本和開機指令碼可一起用來定義要如何啟動 Compute Engine 執行個體,以及要如何在該執行個體上設定軟體,使其能夠在您的應用程式架構中發揮特定的作用。

顯示開機指令碼、執行個體範本和執行個體如何協同運作的圖表。

無庸置疑地,執行個體範本就只是範本而已。為讓這個範本發揮作用,您需要用一種方法將範本套用至新上線的 Compute Engine 執行個體。為此,您需要建立一個代管執行個體群組。您可以決定您要在任何特定時間執行的執行個體數量,以及您要將哪個執行個體範本套用至這些執行個體。接著,執行個體群組管理員會負責視需要啟動及設定這些執行個體。

下圖顯示這些元件如何協同運作:

  • 開機指令碼
  • 執行個體範本
  • 執行個體群組管理員
  • 代管執行個體群組
顯示開機指令碼、執行個體範本、執行個體群組管理員和代管執行個體群組如何協同運作的圖表。

代管執行個體群組及其對應的執行個體群組管理員可以是「特定區域」或「地區性」的資源。執行個體範本是專案層級的資源,可在任何區域及地區中的多個代管執行個體群組中重複使用;不過,您可以在執行個體範本中指定一些區域資源,藉此將範本的使用範圍限制在這些區域資源所在的區域。

透過使用開機指令碼、執行個體範本和代管執行個體群組,您目前所建構的系統可將健康狀態不良的執行個體替換為新的執行個體。在下一節中,您將看到一種可用來定義及偵測健康狀態不良的執行個體的方法。

健康狀態檢查

此時,範例應用程式差不多已具備打造彈性所需的一切工具。但還缺少了某個要素,那就是可用來識別健康狀態不良的執行個體的方法,如此一來才能知道哪些執行個體應該進行替換。

這個應用程式的設計旨在透過 HTTP 負載平衡器,將使用者連線到適當的健康執行個體。此架構可讓您使用兩種服務來識別能夠為要求提供服務的執行個體:

  • 健康狀態檢查。HTTP 健康狀態檢查可指定要在每個執行個體上執行健康狀態檢查的通訊埠和路徑。健康狀態檢查預期收到的回應是 200 OK (代表執行個體的狀態是健康的)。
  • 後端服務。後端服務可定義應自負載平衡器接收流量的一或多個執行個體群組。後端服務可指定執行個體要公開的通訊埠和通訊協定 (如 HTTP 通訊埠 80),以及要對執行個體群組中的執行個體進行的 HTTP 健康狀態檢查。

下圖顯示這種應用程式架構,以及後端服務和 HTTP 健康狀態檢查與負載平衡器和執行個體群組之間的關係。

顯示健康狀態檢查和後端服務的圖表。

利用 Cloud SQL 實現資料彈性

網路、運算及儲存是應用程式架構的三大核心要素。這裡所描述的應用程式架構已涵蓋網路及運算這兩大要素,但還缺少一個要素,那就是儲存。

此範例解決方案使用 Cloud SQL 第一代執行個體來提供全代管的 MySQL 資料庫。在 Cloud SQL 的輔助下,Google 可自動進行複製、加密、修補程式管理及備份等作業。

Cloud SQL 資料庫是一種地區級的資料庫,因為其資料會被複製到地區內的所有區域。這等同於當資料有任何更新時,就會立刻為其備份。因此,即使發生區域大當機的狀況 (儘管發生機率極低),資料也會受到保留。

Cloud SQL 提供兩種複製模式供您選擇:

  • 同步複製。選用同步複製模式時,更新會先複製到多個區域,然後再傳回用戶端。在發生重大事件時,這可以確保資料的可靠性及可用性,只是寫入速度會比較慢。
  • 非同步複製。選用非同步複製模式時,為了提高寫入總處理量,在資料快取到本機後便會確認寫入作業,然後再將資料複製到其他位置。由於非同步複製不需要等到複製作業完成後才確認寫入,因此可提高資料寫入資料庫的速度。但是,如果在資料庫更新後的幾秒鐘內,資料中心突然發生故障事件,您可能會失去最新的更新資料。

這項解決方案中的 Redmine 應用程式就採用同步複製模式,因為工作負載的寫入作業不是很密集。您應該根據特定應用程式的具體寫入效能及資料耐用性需求,選擇使用同步複製模式或非同步複製模式。

擴充性

上文說明了範例應用程式如何使用 GCP 建立具彈性的應用程式。但光有彈性還不夠,擴充性也同樣重要。不論使用者數是 1 個還是 1,000,000 個,應用程式都應穩定有效地運作,並隨著使用者數量的多寡而增減資源,以達到成本效益。

若要使應用程式的資源隨著需求變化增減,則必須具備以下工具:

  • 一個可讓您為服務增加或移除執行個體的工具。您還需要一個用來決定何時需要增加及何時應該移除執行個體的方法。GCP 的自動配置器就是用來解決這項問題的工具。
  • 一個儲存狀態資料的工具。由於執行個體會來來去去,因此不建議將狀態資料儲存在這些執行個體上。應用程式架構透過將關聯性資料儲存在單獨的 Cloud SQL 執行個體來解決此問題,只是這還需要容納使用者上傳的檔案。Cloud Storage 可以滿足這些要求。

以下各節說明如何使用自動配置器來調度執行 Redmine 應用程式的基礎架構資源,以及如何利用 Cloud Storage 來上傳檔案。

使用自動配置器調度資源

由於應用程式的使用量時有消長,因此應用程式必須能夠針對所需資源進行動態調整。您可以使用 Compute Engine 自動配置器來克服這項挑戰。

當流量或負載升高時,自動配置器會增加資源來處理額外的活動,並且會在流量或負載降低時,將資源移除以節省成本。自動配置器會根據您定義的資源調度規則來自動執行這些動作,完全無需後續的人為介入。

自動配置器可帶來雙重效益:

  1. 使用者可獲得更優異的應用程式使用體驗,因為隨時都有足夠的資源可以應付需求。
  2. 您可以更有效地控管成本,因為自動配置器會在需求降到特定門檻以下時移除執行個體。

自動配置器可根據 CPU 使用率、服務容量或 Stackdriver Monitoring 指標調整虛擬機器的數量。此解決方案使用服務容量指標,根據執行個體從負載平衡器收到的每秒要求數 (RPS) 來新增或移除 Compute Engine 執行個體。詳情請參閱使用 Compute Engine 自動配置器進行批次處理

每秒要求數 (RPS)

前述各節所介紹的單一後端服務,可用來辨識應自負載平衡器接收流量的執行個體群組。此範例解決方案還針對與後端服務關聯的每個執行個體群組做了 balancingMode=RATE 的設定。這個屬性會指示負載平衡器根據在 maxRatePerInstance 屬性中所定義的 RPS (本例設為 100) 來調度資源。此設定值表示負載平衡器會嘗試將每個執行個體的 RPS 保持在 100 或 100 以下。如要進一步瞭解後端服務的設定屬性,請參閱後端服務說明文件

如要調整 RPS 的數值,您需要為每個需要自動調度資源的執行個體群組都建立一個自動配置器。在此範例中,執行個體群組被規劃為區域級的資源,因此您必須在每個區域中都建立一個自動配置器。

顯示自動配置器如何融入應用程式架構的圖表。

每個自動配置器都包含 utilizationTarget 屬性;該屬性定義了自動配置器應將負載平衡器的最大服務容量維持在多少百分比。此範例將每個自動配置器的 utilizationTarget 設為 80%,即後端服務的每個執行個體最高速率 100 RPS 的八成。這表示自動配置器將於 RPS 超過每個執行個體最高速率的 80% (即 80 RPS) 時進行擴增。自動配置器將在 RPS 降至該門檻值以下時進行縮減。

顯示自動配置器如何確定是否新增或移除執行個體的流程圖。

此外,每個自動配置器也會定義各自不可逾越的執行個體數量上下限。

請注意,只有代管執行個體群組能提供這種自動配置功能。詳情請參閱執行個體群組自動調度執行個體群組資源

處理檔案上傳

Redmine 應用程式的其中一項功能是可讓使用者在登入後進行檔案上傳及儲存。Redmine 和許多其他類似的網路應用程式都會預設將這些檔案儲存在本機磁碟上。如果您只有一部備份機制完善的伺服器,這確實是不錯的方法。但是,當負載平衡器背後有多個可自動擴充的 Compute Engine 執行個體時,這就不是理想的做法。因為在使用者上傳檔案後,系統並無法保證下一個要求也會送到儲存檔案的機器上。此做法也無法保證自動配置器不會終止已不需要但仍存有檔案的執行個體。

較佳的做法是使用 Cloud Storage,因為這項服務提供了一個集中的位置,非常適合用於儲存及存取從眾多自動擴充網路伺服器上傳的檔案。Cloud Storage 還提供一個可與 Amazon S3 用戶端互通的 API,因此無需進行任何修改即可與現有的 S3 應用程式外掛程式相容,包括 Redmine S3 外掛程式。許多第三方和開放原始碼應用程式都有外掛程式可以支援類似 Cloud Storage 的物件儲存空間。若您想要建置自己的應用程式,您可以直接使用 Cloud Storage API 來支援儲存檔案。

以下為使用 Redmine 和 Cloud Storage 上傳 (藍色箭頭) 及擷取 (綠色箭頭) 檔案的流程圖:

顯示要求如何在 Redmine 應用程式中傳遞的流程圖。

圖中顯示的程序如下:

  1. 使用者從網路瀏覽器「張貼」檔案。
  2. 負載平衡器選擇用於處理要求的執行個體。
  3. 執行個體將檔案儲存於 Cloud Storage。
  4. 執行個體將檔案中繼資料 (如名稱、擁有者及其在 Cloud Storage 中的位置) 儲存於 Cloud SQL 資料庫。
  5. 當使用者要求檔案時,檔案會從 Cloud Storage 串流至執行個體。
  6. 執行個體透過負載平衡器傳遞串流。
  7. 檔案送達使用者。

儲存空間容量

除了能從 Compute Engine 執行個體移除狀態檔案上傳並使其動態調度資源之外,Cloud Storage 還提供一個可長期儲存無限量上傳檔案的備援空間。這可說是一項兼具彈性、擴充性與成本效益的儲存解決方案。您只需針對使用的儲存空間付費而不必費心規劃容量,而且資料會自動分散儲存於多個區域,以達到備援的目的。

費用

到目前為止,我們已利用本文的應用程式架構,介紹了如何使用 GCP 建置一個兼具彈性與擴充性的應用程式。但光是懂得如何建構應用程式還不夠,您還應該知道如何用最具成本效益的方法來完成這項工作。

本節將為您說明此應用程式架構除了兼具彈性與擴充性的優點之外,成本效益也非常高。首先,我們要對應用程式的負載程度及使用頻率做出一些基本假設,然後再將這些假設換算為基本的費用預估。請記住,這些純粹只是假設而已。您可以依需要自由調整這些數據,以建立更符合您自己的應用程式用途的費用預估。

計算

在考量應用程式架構時,保持伺服器運作順暢需要花多少費用是基本的思考重點。此處的費用分析使用以下假設:

指標
每月平均網頁瀏覽量 20,000,000
每月平均 HTTP 要求數量 120,000,000
用量高峰時段 (90% 或以上) 週一至週五上午 7 點至下午 6 點
每個網頁瀏覽的資料傳輸量 100KB
每月高峰時數 220
高峰時段的要求頻率 每秒 127 個要求 (RPS)
離峰時段的要求頻率 每秒 6 個要求 (RPS)

根據這些假設,您將可算出每個月應用程式在高峰時段 (週一至週五上午 7 點至下午 6 點) 所收到的網頁瀏覽量:

20,000,000 (瀏覽量/月) * 6 (要求數/瀏覽) * 90% (發生於高峰時段) = 108,000,000

每個月平均有 22 個工作日。如果每個工作日有 11 個高峰小時,那麼您需要提供足以應付每月 242 個高峰小時的運算資源。

接下來,您需要確定哪種類型的 Compute Engine 執行個體能夠處理此類流量。此應用程式架構使用 gatling.io 進行基本負載測試。測試結果顯示 4 個 n1-standard-1 類型的 Compute Engine 執行個體就足夠應付流量。

在非高峰時段,此解決方案會至少保持兩個 n1-standard-1 執行個體運作。

如要瞭解運作這些執行個體需要多少費用,請使用 Google Cloud Platform Pricing Calculator 查詢最新的價格估算。在實際查詢後,您會發現兩種案例的執行個體都自動符合續用折扣資格。

負載平衡與資料傳輸

此應用程式佈建了一個設有單一轉送規則的負載平衡器;該規則是提供給使用者連線的公開 IP 位址。該轉送規則按小時計費。

在進行資料傳輸預估時,請先考慮最壞的情況。負載平衡器會按照處理的輸入資料量收費,從負載平衡器傳出的流量則按照一般輸出費率計費。假設 120,000,000 個 HTTP 要求中,有 99.5% 都是使用者載入 Redmine 專案頁面的要求。載入頁面算 1 個 HTTP GET 要求,而它又會連帶產生 5 個載入其他資產 (CSS、映像檔和 jQuery) 的 HTTP GET 要求。因此,載入整個頁面總共需要 6 個 HTTP 要求。這可得出以下的結果:

  • 每月約載入 20,000,000 個完整頁面
  • 每頁約需處理 10 KB 的輸入資料及產生 450 KB 的資料傳輸量
  • 負載平衡器每月約需處理總共 214 GB 的資料量,並產生 9,091 GB 的輸出流量。

20,000,000 個 HTTP 要求中的另外 0.5% 是 HTTP POST 要求,用於上傳平均大小約為 0.5 MB 的檔案,每個月處理 500 GB 的額外資料量。

根據 Google Cloud Platform Pricing Calculator 的估算,此案例應支付的費用包括負載平衡器的 714 GB 資料傳輸處理費,加上 9,091 GB 的輸出流量計費。

資料傳輸量是按照最壞的情況估算,因為它算入了應要求由 Compute Engine 執行個體透過負載平衡器提供的所有內容 (包括靜態資產) 的費用,並未計入快取技術或內容傳遞聯播網 (CDN) 可節省的流量。在每個頁面載入產生的 450 KB 酬載中 (試想此解決方案每月的頁面載入量超過 20M),有 333 KB 必須載入 jQuery。只要更新一行應用程式,從 Google 託管程式庫載入 jQuery,您就能節省 73% 的資料傳輸費用。

使用新的方法估算後,您就可以知道轉換到 Google 託管程式庫能幫您節省多少資料傳輸費用。

儲存空間

此解決方案使用 Cloud Storage 儲存所有透過 Redmine 應用程式上傳的檔案。如上一節所述,大約 0.5% 的資料傳輸量是上傳檔案所產生的,並且檔案的平均大小為 0.5MB。這表示您每個月估計可以看見 1,000,000 個新上傳的檔案,也等於您每個月需要 500GB 的新儲存空間。此解決方案還假設每月需要用 1,000,000 個 HTTP PUT 作業來儲存新檔案,這些將按照 A 級作業費率收費。

使用 Google Cloud Platform Pricing Calculator 進行價格估算,將可得出 Cloud Storage 的使用成本。

此處的架構使用 Cloud SQL 來儲存應用程式的所有關聯性資料。根據前文提及的範例指標,容量為 1024MB RAM 的 D2 資料庫應該就具有足夠的容量來應付應用程式的工作負載,並讓應用程式維持每週 7 天、每天 24 小時的運作。由於此資料庫的使用率應該相當頻繁,因此請在計算器中為 I/O 作業勾選「繁重」選項。我們對範例架構進行了插入 100,000 個文件的測試,結果顯示 50GB 的磁碟可支援儲存超過 100,000,000 個文件,也就是說資料庫可透過上述費率使用長達 8 年以上。

使用 Google Cloud Platform Pricing Calculator 估算可得出此部分架構的預估費用。

部署範例解決方案

如要部署此解決方案中描述的範例應用程式,請前往 GitHub 存放區,查看在 Google Cloud Platform 上建構可擴充且具彈性的網路應用程式相關說明。

附錄:新增執行個體

為了打造有彈性且可擴充的應用程式架構,您需要考量許多因素,其中包括決定如何新增執行個體。具體而言,您需要決定如何自動設定新上線的執行個體。

本節中將為您介紹一些可用的選項。

開機載入軟體安裝

為了服務使用者的網路要求,除了基本的作業系統之外,每個執行個體還需要安裝一些額外的軟體,並且載入設定資料,其中包括資料庫連線資訊及儲存檔案的 Cloud Storage 值區名稱等等。如果將這些元件想像成一層層的結構,就能把每個執行個體上的整個堆疊組合轉化為如下的視覺圖像:

顯示軟體如何在執行個體上堆疊的圖表。

此應用程式使用執行個體範本;該範本指定了執行個體在啟動時使用的 Compute Engine 映像檔。具體來說,此解決方案使用的是由 Canonical 開發及支援的 Ubuntu 14.10 映像檔。由於這是基本作業系統映像檔,所以並未包含應用程式必須用到的特定軟體或設定。

若要在新執行個體上線時自動安裝堆疊的其餘部分,您可以使用 Compute Engine 開機指令碼搭配 Chef Solo 來執行開機載入作業。您可以透過將 startup-script 中繼資料屬性項目新增至執行個體範本的方式來指定開機指令碼。開機指令碼會在執行個體開機時執行。

此開機指令碼將會:

  1. 安裝 Chef 用戶端。
  2. 下載一個名為 node.json 的特殊 Chef 檔案。此檔案可告知 Chef 要為此執行個體執行何種設定。
  3. 執行 Chef 並任其處理詳細的設定作業。

以下為完整的開機指令碼:

#! /bin/bash

# Install Chef
curl -L https://www.opscode.com/chef/install.sh | bash

# Download node.json (runlist)
curl -L https://github.com/googlecloudplatform/... > /tmp/node.json

# Run Chef
chef-solo -j /tmp/node.json -r https://github.com/googlecloudplatform/...

注意:此解決方案並未涉及 Chef 的使用方法。此用戶端的所有套件和教戰手冊皆為開放原始碼,您可以在 GitHub 存放區的在 Google Cloud Platform 上建構可擴充且具彈性的網路應用程式中取得。

提供應用程式設定

在新執行個體使用開機指令碼和 Chef 啟動並自行完成設定後,都需要先知道一些資訊才能開始為要求提供服務。在此範例中,每個執行個體都需要知道資料庫連線資訊 (如主機名稱、使用者名稱和密碼)、要使用的 Cloud Storage 值區名稱和連線用的憑證。

每個 Compute Engine 執行個體都有關聯的中繼資料屬性,而您可以定義這些屬性。您已經從之前的內容中瞭解如何新增 startup-script 這個特殊的中繼資料屬性,但您還可以新增任意鍵=值的組合。您可以在此指定執行個體範本中的屬性,以包含執行個體連線至資料庫和 Cloud Storage 值區所需要的設定資料。

以下是 GCP 主控台的執行個體範本中繼資料:

Google Cloud Platform 主控台的螢幕擷圖,顯示執行個體範本的自訂中繼資料資訊。

Chef 使用一個叫做 Ohai 的工具來剖析來自執行個體中繼資料的設定資訊,並將其填入範本,以建立應用程式所需的設定檔案。以下的範本可建立一個含有資料庫連線資訊的 database.yaml 檔案,並用該檔案來自動存取適當的中繼資料項目:

production:
    adapter: mysql2
    database: <%= node['gce']['instance']['attributes']['dbname'] %>
    host:     <%= node['gce']['instance']['attributes']['dbhost'] %>
    username: <%= node['gce']['instance']['attributes']['dbuser'] %>
    password: <%= node['gce']['instance']['attributes']['dbpassword'] %>
...

您也可以使用本機中繼資料服務,從執行個體內部手動存取中繼資料值。在此處,您可以使用 curl 來擷取資料庫密碼:

curl "http:/metadata.google.internal/computeMetadata/v1/instance/attributes/dbpassword" -H "Metadata-Flavor: Google"

效能與相依性考量

此解決方案採用的開機載入方法需用預設的作業系統映像檔啟動,需在啟動時使用 Chef 安裝所有軟體,並且需要使用執行個體中繼資料來提供應用程式設定資料。

顯示軟體如何在執行個體上堆疊的圖表。此堆疊顯示一些軟體如何與映像檔搭配組合,有些在啟動時安裝,有些則是在啟動後提供。

此方法的優點是系統的設定是在 Chef 教戰手冊中指定。教戰手冊較有利於版本的控管及共用,並可用於佈建測試用的本機虛擬機器 (使用 Vagrant 或 Docker),或是用於設定您資料中心或不同雲端服務供應商的伺服器。映像檔管理工作也會變得更加簡單:以此範例應用程式的情況來說,您只需要追蹤應用程式所使用的基本作業系統映像檔。

需列入考量的一些缺點包括:啟動時間可能較慢,這是因為需要下載及安裝所有軟體,有時甚至需要進行程式碼編譯。此外,您還應考慮此方法帶來的相依性問題:在此範例中,Chef 會從 apt、Rubygems 和 GitHub 安裝一些套件。如果其中有任何存放區在啟動新執行個體時無法使用,將會導致設定失敗。

自訂映像檔和開機載入

由於您可以使用 Compute Engine 建立自訂映像檔,因此在啟動時安裝所有軟體並不是唯一的開機載入方法。比如說,您可以:

  1. 啟動基本 Ubuntu 14.10 映像檔。
  2. 安裝 Redmine 應用程式「以外」的所有軟體 (Ruby、nginx 等等)。
  3. 從結果建立映像檔。
  4. 在執行個體範本中使用該映像檔。

現在,當新的執行個體啟動時,只需安裝 Redmine 即可。如此一來,不僅啟動時間將會縮短,外部相依套件數量也會減少。

顯示執行個體堆疊的圖表,其中安裝 Redmine 除外的所有軟體。

您還可進一步利用自訂映像檔的方法,將所有內容都製備到映像檔中,包括所有依附項目、應用程式原始碼和設定。此做法的優點是啟動時間最快,外部相依性為零,但如果應用程式有任何一點變更時,您就必須建立新的映像檔並更新執行個體範本。

顯示執行個體堆疊的圖表,其中所有軟體皆與映像檔搭配組合。

請考慮用連續模式的方法來進行執行個體的開機載入作業。啟動時的設定作業越多,啟動速度就越慢,但要管理的映像檔也越少。在自訂映像檔中製備越多設定,啟動速度就越快,但要管理的映像檔卻可能越多。對於大多數的客戶而言,採取折衷的做法才是明智之舉。換句話說,您應該選擇對您和您的應用程式而言最合理的做法。

顯示如何在執行個體上以連續模式安裝軟體的圖表。範圍從在啟動後安裝所有內容,到將所有內容與映像檔搭配組合。
本頁內容對您是否有任何幫助?請提供意見:

傳送您對下列選項的寶貴意見...

這個網頁
解決方案