在 Amazon,我們建構的服務必須滿足極高的可用性目標。這意味著我們需要謹慎考量系統所採用的相依項。我們將系統設計為即使這些相依項受損也能保持彈性。在本文中,我們將闡明一種稱為靜態穩定性的模式,以實現這種級別的彈性。我們將向您展示如何將此概念套用至可用區域,可用區域是 AWS 中的關鍵基礎架構區塊,因此也是建構所有服務相依的基礎。

在靜態穩定設計中,即使相依項受損,整個系統仍可正常工作。或許系統沒有看到本應傳遞的其相依項的任何更新資訊 (例如新物件、已刪除物件或已修改物件)。然而,雖然相依項受損,但在相依項受損之前其所做的一切仍可正常工作。我們將介紹如何建構 Amazon Elastic Compute Cloud (EC2) 來使其靜態穩定。然後,我們將提供兩種靜態穩定的範例架構,我們發現,它們對於在可用區域之上建構高度可用的區域系統很有用。

最後,我們將進一步深入了解 Amazon EC2 背後的一些設計理念,包括如何在軟體級別提供獨立於可用區域的架構。此外,我們將討論使用選擇的這種架構,在建構服務時需要進行的一些權衡。

可用區域的角色
可用區域是 AWS 區域在邏輯上進行隔離的部分:每個 AWS 區域都有多個旨在獨立運作的可用區域。可用區域以有意義的距離進行實體隔離,以防止受到雷擊、龍捲風和地震等潛在問題的關聯影響。它們不共用電源或其他基礎架構,但透過快速、加密的專用光纖網路相互連接,從而讓應用程式能夠快速進行容錯移轉,而不會發生中斷。換句話說,可用區域在我們的基礎架構隔離上提供了一個抽象層。需要可用區域的服務可讓發起人告知 AWS 在區域內實體佈建基礎架構的位置,以便其從這種獨立性中獲益。在 Amazon,我們建置了區域性 AWS 服務,能夠利用這種分區獨立性來實現其高可用性目標。諸如 Amazon DynamoDB、Amazon Simple Queue Service (SQS) 和 Amazon Simple Storage Service (S3) 等服務都是此類區域服務的範例。
 
與在 Amazon Virtual Private Cloud (VPC) 內提供雲端基礎架構的 AWS 服務互動時,其中許多服務都要求發起人不僅指定區域,還要指定可用區域。可用區域通常在所需的子網路引數中隱式指定,例如,在啟動 EC2 執行個體,佈建 Amazon Relational Database Service (RDS) 資料庫庫或建立 Amazon ElastiCache 叢集時。雖然可用區域中有多個子網路,單一子網路完全存留在單一可用區域內很常見,而透過提供子網路引數,發起人還可隱式提供了一個可用區域。

靜態穩定性

在可用區域之上建構系統時,我們學習到的經驗是,應在發生損壞之前做好準備。一種不太有效的方法可能是部署至多個可用區域,並期望若一個可用區域內存在損壞,則該服務將在其他可用區域中擴展 (或許使用 AWS Auto Scaling) 並還原至完全的健康運作狀態。這種方法之所以不太有效,是因為其依賴於在發生損壞時對其做出回應,而不是在損壞發生之前就做好準備。換句話說,它缺乏靜態穩定性。相比之下,更有效的靜態穩定服務會對其基礎結構進行超額佈建,使其可繼續正確運作,即使可用區域受損,也不必啟動任何新的 EC2 執行個體。
 
為了更好地闡述靜態穩定性的特性,我們來看一下 Amazon EC2,它本身就是根據這些原理設計的。
 
Amazon EC2 服務由控制平面和資料平面組成。「控制平面」和「資料平面」是網路技術方面的術語,但我們在 AWS 的方方面面都有用到。 控制平面機制涉及對系統做出變更 (新增資源、刪除資源、修改資源),並將這些變更傳播至需要生效的任何位置。相比之下, 資料平面則為這些資源的日常業務,即這些資源需要做什麼。
 
在 Amazon EC2 中,控制平面即 EC2 啟動新的執行個體時執行的一切操作。控制平面邏輯透過執行大量任務,將新的 EC2 執行個體所需的一切匯總在一起。以下是一些範例:
 
• 在考慮放置群組和 VPC 租用要求的同時,找到實體伺服器進行運算。
• 將網路界面分配至 VPC 子網路之外。
• 準備 Amazon Elastic Block Store (EBS) 磁碟區。
• 產生 AWS Identity and Access Management (IAM) 角色憑證。
• 安裝安全群組規則。
• 將結果儲存在各種下游服務的資料存放區中。
• 在適當的情況下,將所需的組態傳播至 VPC 中的伺服器和網絡邊緣。
 
相比之下,Amazon EC2 資料平面則確保現有的 EC2 執行個體保持按預期運作,執行以下任務:
 
• 根據 VPC 的路由表來路由封包。
• 在 Amazon EBS 磁碟區讀取和寫入。
• 等等。
 
與資料平面和控制平面的通常情況一樣,Amazon EC2 資料平面比其控制平面簡單得多。由於其相對簡單,Amazon EC2 資料平面的設計目標是要比 Amazon EC2 控制平面具有更高的可用性。
 
重要的是,Amazon EC2 資料平面經過精心設計,可以在面對控制平面可用性事件 (例如啟動 EC2 執行個體的功能受損) 時保持靜態穩定。例如,為避免網路連線中斷,Amazon EC2 資料平面經過精心設計,以便執行 EC2 執行個體所在的實體機器,可以在本機存取將封包路由至其 VPC 內部和外部位置所需的一切資訊。Amazon EC2 控制平面的損壞意味著,事件期間實體伺服器可能看不到更新,例如,將新的 EC2 執行個體新增至 VPC 或新的安全群組規則。但在事件發生之前,其傳送和接收流量的功能將繼續運作。
 
控制平面、資料平面和靜態穩定性的概念適用廣泛,甚至超越了 Amazon EC2。能夠將系統分解為控制平面和資料平面,可能是設計高可用性服務的實用概念工具,有以下多種原因︰
 
• 在服務客戶取得成功方面,資料平面的可用性比控制平面更為關鍵。例如,EC2 執行個體在執行後的持續可用性和正確運作對大多數 AWS 客戶而言,比能夠啟動新的 EC2 執行個體更為重要。
• 通常,相較於控制平面,資料平面要以更高的容量運作 (通常為幾個數量級)。因此,最好將它們分離,以便根據其各自的相關縮放尺寸進行調整。
• 多年來,我們發現,系統的控制平面往往比資料平面具有更多的活動部件,因此從統計學上說,僅出於該原因,系統就會受到損壞。
 
綜合考量所有因素,我們的最佳實務根據控制平面和資料平面邊界來分離系統。
 
為了在實踐中實現這種分離,我們運用了靜態穩定性原理。資料平面通常依賴於從控制平面到達的資料。但為了實現更高的可用性目標,即使面臨控制平面損壞,資料平面仍能保持其現有狀態並繼續工作。資料平面在受損期間可能不會獲得更新,但受損之前其所做的一切仍可繼續工作。
 
之前我們發現,需要取代 EC2 執行個體來對可用區域受損做出回應的方案是一種不太有效的方法。不是因為我們無法啟動新的 EC2 執行個體,而是因為系統必須立即依賴 Amazon EC2 控制平面上的復原路徑,來對系統受損做出回應,加上新的執行個體需要所有應用程式特定系統,才能開始執行有用的工作。根據應用程式的不同,這些相依項可能包括下載執行階段組態,使用探索服務註冊執行個體,獲取憑證等步驟。控制平面系統必然比資料平面中的系統複雜,並且當整個系統受損時,它們更有可能無法正常運作。

靜態穩定性模式

在這個部分,我們將介紹兩種在 AWS 中使用的高級模式,透過充分利用靜態穩定性來設計系統,以實現高可用性。每種方法都適用於自己的一組情況,但兩者都利用了可用區域抽象。

可用區域主動-主動模式範例:負載平衡服務
若干 AWS 服務在內部由可水平擴展、無狀態 EC2 執行個體機群或 Amazon Elastic Container Service (ECS) 容器組成。我們在三個或更多個可用區域的 Auto Scaling 群組中執行這些服務。此外,這些服務超額佈建了容量,因此,即使整個可用區域受損,其餘可用區域中的伺服器也可以承載負載。例如,當我們使用三個可用區域時,我們超額佈建了 50%。換句話說,我們超額佈建的方式是,讓可用區域僅以我們對其進行負載測試時所達水準的 66% 執行。
 
最常見的範例是負載平衡 HTTPS 服務。下圖顯示了提供 HTTPS 服務的對外 Application Load Balancer。負載平衡器的目標是 Auto Scaling 群組,該群組可跨越 eu-west-1 區域中的三個可用區域。這是使用可用區域的主動-主動高可用性範例。

若可用區域受損,上圖中所示架構無需採取任何措施。受損可用區域中的 EC2 執行個體將開始無法通過運作狀態檢查,並且 Application Load Balancer 會將流量從這些執行個體移開。實際上,Elastic Load Balancing 服務就是根據該原理設計的。其佈建了足夠的負載平衡容量,能夠承受可用區域損壞,而無須擴大規模。

即使沒有負載平衡器或 HTTPS 服務,我們也會使用該模式。例如,處理 Amazon Simple Queue Service (SQS) 佇列訊息的 EC2 執行個體機群也可以遵循該模式。將執行個體部署在跨多個可用區域的 Auto Scaling 群組中,並進行適當的超額佈建。若可用區域受損,該服務無須執行任何操作。受損的執行個體停止工作,其他執行個體會彌補不足。

可用區域主用-備用模式範例:關聯式資料庫
我們建構的某些服務可設定狀態,需要單一主節點或領導者節點來協調工作。這方面的範例是使用關聯式資料庫的服務,例如配備 MySQL 或 Postgres 資料庫引擎的 Amazon RDS。對於這種關聯式資料庫,典型的高可用性設定具有一個主執行個體和一個備用候選項目,主執行個體是指所有寫入操作都必須使用的執行個體。此外,我們可能還會有額外的僅供讀取複本,下圖中未顯示。當我們使用這類具狀態基礎架構時,可用區域中有一個與主節點不同的的熱備用節點。
 
下圖顯示了 Amazon RDS 資料庫。當我們使用 Amazon RDS 佈建資料庫時,它需要一個子網路群組。 子網路群組是一組跨越多個可用區域的子網路,在這些可用區域中將佈建資料庫執行個體。Amazon RDS 將備用候選項目與主節點放在不同的可用區域中。這是使用可用區域的主動-備用高可用性範例。

與無狀態主動-主動範例一樣,當具有主節點的可用區域受損時,具狀態服務對基礎架構不起作用。對於使用 Amazon RDS 的服務,RDS 將管理容錯移轉,並將 DNS 名稱重新指向工作可用區域中新的主節點。此模式也適用於其他主動-備用設定,即使它們不使用關聯式資料庫。我們尤其將此套用至採用具有領導者節點的叢集架構的系統。我們在可用區域中部署這些叢集,並從備用候補項目中選出新的領導者節點,而不是「及時」啟動取代方案。

這兩種模式的共同點是,早在發生任何實際損壞之前,就已佈建了在可用區域受損時所需的容量。在這兩種情況下,服務都不會刻意採用任何控制平面相依項,例如佈建新的基礎架構或進行修改,來對可用區域損壞做出回應。

內幕:Amazon EC2 內部的靜態穩定性

本文最後這部分將更深入地介紹彈性的可用區域架構,涵蓋我們遵循 Amazon EC2 中可用區域獨立性原則的某些方式。當我們建構的服務不僅本身需要高度可用,而且還需要提供可讓其他元件高度可用的基礎結構時,理解其中一些概念將很有幫助。作為低級別 AWS 基礎架構的提供者,Amazon EC2 是應用程式可用於實現高可用性的基礎架構。有時,其他系統可能也希望採用該策略。

我們在部署實務中遵循 Amazon EC2 中的可用區域獨立性原則。在 Amazon EC2 中,軟體被部署至託管 EC2 執行個體、邊緣裝置、DNS 解析程式、EC2 執行個體啟動路徑中的控制平面元件,以及 EC2 執行個體所依賴的許多其他元件的實體伺服器上。這些部署遵循分區部署行事曆。這意味著,同一區域中的兩個可用區域將在不同的日期收到給定部署。在整個 AWS 中,我們分階段進行部署。例如,我們遵循最佳實務 (不受我們部署的服務類型影響),首先部署整體方案,然後部署 1/N 的伺服器,等等。然而,在像 Amazon EC2 這類服務的特定情況下,我們的部署更進一步,並刻意與可用區域邊界保持一致。這樣,部署問題會影響一個可用區域,然後復原並修復。它不會影響其他繼續正常運作的可用區域。

在 Amazon EC2 中建構時,我們使用獨立可用區域原理的另一種方式是,將所有封包流設計為留在可用區域之內,而不是跨越邊界。這第二種方式,即網路流量保持在可用區域本機,值得更詳細地探究。這是一個有趣的例證,闡述了我們在建構高可用性區域系統 (獨立可用區域的取用者) 時,我們會以何種不同的方式思考 (也就是說,在建構高可用性服務時,它以保證可用區域獨立性為基礎),這與我們向其他元件提供獨立於可用區域的基礎架構,以讓他們建構高可用性的情況相反。

下圖說明了一項高可用性外部服務 (以橙色顯示),該服務依賴於另一項內部服務 (以綠色顯示)。透過簡單的設計將這兩種服務作為獨立 EC2 可用區域的取用者。橙色和綠色服務各由一個 Application Load Balancer 作為前端,並且各個服務都具有佈建良好的後端主機機群,分佈在三個可用區域中。一項高度可用的區域服務叫用另一項高度可用的區域服務。這是一個簡單的設計,對於我們建構的許多服務,它都是很好的設計。

但是,假設綠色服務是基礎服務。也就是說,假設該服務不僅旨在高度可用,而且其本身也可以用作提供可用區域獨立性的建構區塊。在此情況下,我們可以將其設計為區域本機服務的三個執行個體,在其上我們遵循可用區域感知部署實務。下圖說明了這種設計,其中一項高度可用的區域服務叫用另一項高度可用的分區服務。

我們將建構區塊的服務設計為獨立於可用區域的原因歸結為簡單的演算法。假設可用區域受損。對於絕對化故障,Application Load Balancer 會自動從受影響的節點移開。然而,並非所有故障都如此顯而易見。可能存在灰色故障,例如軟體中的錯誤,負載平衡器無法在其運作狀態檢查中看到這些故障,並且不能完全處理。

在之前的範例中,一項高度可用的區域服務叫用另一項高度可用的區域服務,若透過傳送了一個請求,則在進行某些簡化的假設情況下,該請求避開受損可用區域的機會為 2/3 * 2/3 = 4/9。也就是說,該請求甚至比避免事件清除的可能性還要差。相比之下,若像最近範例中那樣將綠色服務建構為分區服務,則橙色服務中的主機可以叫用同一可用區域中的綠色端點。在此架構中,避開受損可用區域的機會是 2/3。若此叫用路徑中有 N 項服務,則對於 N 項區域服務該數據一般為 (2/3)^N,而對於 N 項分區服務則保持為恆定的 2/3。

正是由於這個原因,我們將 Amazon EC2 NAT 閘道建構為分區服務。NAT 閘道是 Amazon EC2 的一項功能,允許來自專有子網路的對外網際網路流量,並且不是顯示為整個 VPC 的區域閘道,而是作為一種分區資源,客戶可在每個可用區域中如下圖所示單獨具現化。NAT 閘道位於 VPC 的網際網路連線路徑上,因此,它是該 VPC 內任何 EC2 執行個體資料平面的一部分。若一個可用區域中存在連線損壞,我們希望將該損壞保留在該可用區域內,而不是將其分散至其他區域。最後,我們希望知道,若其建構的架構與本文前面提到的架構類似 (即,通過在三個可用區域中佈建一個機群,並在任意兩個可用區域中提供足夠的容量來承載全部負載),則其他可用區域將完全不受受損可用區域中發生任何事情的影響。我們實現此目標的唯一方法是,確保所有基礎元件 (如 NAT 閘道) 確實位於可用區域內。

這種選擇會帶來額外的複雜性。對我們來說,在 Amazon EC2 中,額外的複雜性在於管理分區 (而不是區域) 服務環境。對於 NAT 閘道的客戶而言,額外的複雜性在於擁有多個 NAT 閘道和路由表,以便在 VPC 的不同可用區域中使用。額外的複雜性是適當的,因為 NAT 閘道本身是基礎服務,也是 Amazon EC2 資料平面的一部分,應能提供分區可用性保證。

在建構獨立於可用區域的服務時,我們還要考量的另一點是資料持久性。雖然之前所述的每個分區架構都顯示,單一可用區域內包含整個堆疊,但出於災難復原的目的,我們跨多個可用區域複製了任何硬狀態。例如,我們通常將資料庫定期備份儲存在 Amazon S3 中,並跨可用區域邊界維護資料儲存的僅供讀取複本。這些複本對於主要的可用區域不是必要的。取而代之的是,他們要確保我們將客戶或業務關鍵資料儲存在多個位置。

在設計將在 AWS 中執行的服務型架構時,我們學會了使用以下兩種模式之一,或兩種模式的組合:

• 更簡單的模式:區域-叫用-區域。這通常是對外服務的最佳選擇,並且也適合大多數內部服務。例如,當在 AWS 中建構更高級別的應用程式服務 (如 Amazon API Gateway 和 AWS 無伺服器技術) 時,即使面臨可用區域受損,我們也可採用此模式來提供高可用性。
• 更複雜的模式:區域-叫用-分區,或分區-叫用-分區。在設計 Amazon EC2 中的內部資料平面元件時 (在某些情況下是外部資料),例如,直接位於關鍵資料路徑中的網路設備或其他基礎架構,我們遵循可用區域獨立性模式,並使用在可用區域中孤立的執行個體,以便網路流量保持在其相同的可用區域中。此模式不僅有助於將損害隔離到可用區域,而且在 AWS 中具有良好的網路流量成本特徵。

結論

在本文中,我們討論了在 AWS 上使用的一些簡單的策略,這些策略用於成功處理可用區域上的相依項。我們了解到,靜態穩定性的關鍵是在發生損壞之前就進行預測。無論系統是在主動-主動水平可擴展機群上執行,還是系統為可設定狀態的主動-備用模式,我們都可以使用可用區域來實現高級別的可用性。我們部署系統的方式為,若系統發生損壞,其所需的容量均已充分佈建並且隨時可用。最後,我們進一步深入地研究了 Amazon EC2 本身如何使用靜態穩定性概念來讓可用區域彼此獨立。


作者簡介

Becky Weiss 是 Amazon Web Services 的資深首席工程師。她目前的工作重點在於 AWS 的 Identity and Access Management,並為雲端的客戶提供靈活、全面和權威的安全控制機制。過去,她曾負責 Amazon Virtual Private Cloud (即網絡) 和 AWS Lambda 的工作,還曾使用 AWS 專業服務,協助企業客戶成功地保護其 AWS 環境。Becky 恰好也是 AWS 最忠實的粉絲,她利用業餘時間在 AWS 上建構了各種有用和無用的物件。在 AWS 任職之前,Becky 在 Microsoft 負責 Windows 和 Windows Phone 的工作。

Mike Furr 是 Amazon Web Services 的資深首席工程師。他在馬里蘭大學公園分校攻讀電腦科學博士學位,之後於 2009 年加入 Amazon。在 Amazon 任職期間,他曾負責 Virtual Private Cloud、Direct Connect 以及 AWS 計量和計費堆疊的工作。現在,他的工作重點是 EC2,他在此協助團隊擴展雲端。

使用負載卸除以免過載