AWS的雲端架構框架-可靠度篇
這一篇我們概述AWS提倡的雲端架構框架的第三個面向 — 系統的可靠度.所謂的可靠度是指我們預期系統會照我們想要的方式來運作,在整個系統的生命週期中持續且正確(我們想像中的)的運作下去.這裡我們將會介紹如何將我們的系統服務依照AWS的可靠度最佳實踐運行在AWS上.
在可靠度的部分, AWS給了我們設計原則的概觀,最佳實踐以及在這個過程中我們需要回答的問題.
五個設計原則
AWS在雲端的可靠度層面上提出了五個設計原則,它們分別是:
- 能自動從故障的系統中回復:要達到這個目的靠的是監控我們系統服務的KPI(Key performance indicate),到達到一個我們預定的閥值之後就會自動行進回復.而監控量測值的KPI不是屬於技術層面的,而是業務層面的.這讓我們能夠有自動通知和追蹤故障的功能,以及解決或修復故障的自動回復過程。 借助更複雜的自動化,可以在故障發生之前預測並修復故障。
- 測試回復的程序:在地端機房環境中,我們只能測試系統服務在特定場景中運作的情況。 而這些測試通常不用於驗證系統回復。 在AWS中,我們可以測試我們的系統服務是如何掛掉的,並且我們也可以驗證我們的回復過程是否正確。 雖然地端機房也可以做這樣的方式,但哪只有大公司才有這樣的人力與資源才能進行.我們在AWS中使用自動化來模擬不同的故障或全部重新建立系統掛掉之前的良好狀態。 這種方法會揭示了系統掛掉是怎麼發生的,而我們就可以在真正的系統掛掉發生之前對其進行測試和修復,從而降低組織的業務風險。
- 水平式的擴展以便增加系統的總體可用性:用多個小機器來替換一個大機器,以減少單點故障對整體系統服務的影響。 跨多個較小的機器分發服務請求,以確保它們不會有同一個端點故障。
- 不用再猜要多少資源來運作系統:地端機房的系統服務掛掉的一個常見原因是資源用滿了,此時對系統服務的需求超過了我們地端機房的整體機器容量。 在AWS中,我們可以監控需求和系統服務使用率,並自動增減機器以保持最佳水準來滿足業務需求,而不會過度給太多資源或給過少。 但我們仍然應該有一些限制存在,這可以用配額的方式來控制。
- 自動化的變更管理:對於基礎架構的變更我們應該使用自動化的方式來進行。 我們需要管理的變更包括對其自動化的修改,所以我們可以對其進行AWS中整體變更的追踪和稽核。
四個最佳實踐
它們分別是
- 基礎面(Foundations)
- 系統服務的架構(Workload Architecture)
- 變更管理(Chnage Management)
- 故障管理(Failure Management)
要實現可靠性,我們要從基礎開始 — — service quota和network topology要去適應我們系統服務的環境。 如果是分佈式系統的架構則必須設計成預防和減緩發生故障的衝擊。 系統服務必須處理需求或需求的變化,並且必須設計為偵測故障並能自動修復。
關於基礎面
基礎面的需求是那些範圍超出單一個系統服務或整體平台的需求。 我們在建立任何系統之前,會影響可靠性的基本要求應該到位。 例如,在地端機房對外要有足夠的頻寬。
借由AWS,這些基本要求中的大部分AWS都有資源與方案滿足我們了。 雲端的設計方式與資源幾乎是無限的(理論上是這樣且是你的公司夠有錢的話),AWS讓我們可以根據需要自由更改資源分配的大小。
以下問題是我們在基礎面設計考量時需要回答一些問題:
Q1:我們如何管理管理服務的配額與侷限性?
對於基於雲端的系統服務架構,存在服務配額(也稱為服務限制)。 這些配額的存在是為了防止意外超額使用,並限制 API calls的request rates,以防止服務被濫用。 還有資源限制,例如,一些實體機器的物理極限也需要被考量。
最佳實踐的方式有:
- 要認知到雲端服務資源一開始有配額與其侷限性
- 管理服務配額是跨account跟region的
- 用架構的方式來適應固定的服務配額和侷限性
- 監控與管理配額
- 自動化的配額管理
- 確保當前用到的配額量和最大使用量之間存在足夠的配額以適應來適應failover的情況發生
Q2:我們如何規劃我們的網路拓樸圖?
我們系統服務通常存在於多個環境中。 其中包括多個雲端環境(外部跟內部的),可能還會連接到我們的地端機房。 規劃的內容可能是系統內和系統間的連接、內外部IP 管理或域名解析。
最佳實踐的方式有:
- 針對面向Internet的服務建立高可用的網路連結(如HA的DNS/CDN/API Gateway/ ELB等)
- 對地端與雲端之間的網路建立冗餘的專線
- 網路網段的規劃需要考慮道未來的使用
- 使用Hub-and-spoke的網路拓樸而非星狀網路
系統架構
可靠的系統服務始在於軟體和基礎架構的前期設計決策。 我們的架構抉擇將影響我們在所有AWS架構框架中的系統服務行為。 為了可靠性,我們必須遵循特定的模式。
借由 AWS,系統服務開發人員可以選擇使用的語言和技術。 AWS 開發工具箱通過由 AWS 服務提供特定對開發語言的 API 來消除寫程式的複雜性。 這些 SDK 以及開發語言的選擇讓開發人員實做AWS的可靠性最佳實踐。 開發人員還可以在 AWS Builders’ Library 中認識並了解 AWS如何構建和運作軟體。
以下問題是我們在系統架構設計考量時需要回答一些問題:
Q3:我們如何設計我們的系統服務架構?
使用SOA(service-oriented architecture)或微服務架構構建高度可擴展且可靠的系統。 SOA是通過service interface使軟體組件可重複使用的實踐。 微服務架構進一步使組件更小更簡單。
最佳實踐的方式有:
- 選擇如何切分我們的系統服務(盡量避免Monolithic的設計)
- 建立的service是聚焦在特定的business domain與功能性上
- 為每一個API提供不同的服務內容(例如rate limits/ performance expectations)
Q4:我們如何設計在分佈式架構內的各組件互相通訊來防止故障?
分佈式系統內的組件是依靠網路來互相通訊的。 因為網路本身就是不穩定的所有有時可能會有資料丟失或延遲,雖然有這樣的狀況但我們的系統服務仍必須可靠運作。 分佈式系統的組件必須以不會對其他組件或其他系統產生負面影響的方式運作。 這些最佳實踐可防止故障並提高MBTF(mean time between failures).
最佳實踐的方式有:
- 辨識哪一類的分佈式系統是我們需要的
- 系統是loosely coupled dependencies
- 讓所有的回應都是冪等的(idempotent) — 冪等服務讓每個request只完成一次,因此發出多個相同的request與發出單一個request效果是一樣的。 冪等服務使client更容易進行retry,而不必擔心request會被錯誤地處理多次。 為此,客戶端可以發出具有idempotent token的 API request— 每當request是同一個時使用相同的token。
- 持續不斷地作業 — 當系統的負載變化波動性又大又快時,系統可能會掛掉。例如,如果系統服務正在進行監控幾千台服務器的健康狀況,則它應該每次發送相同大小的有效負載。 無論是沒有服務器出現故障,還是所有服務器都出現故障,健康檢查系統都在持續工作,沒有大的、快速的變化。
Q5:我們如何設計在分佈式架構內的各組件互相通訊來減緩甚至能夠抵抗故障?
分佈式系統內的組件是依靠網路來互相通訊的。 因為網路本身就是不穩定的所有有時可能會有資料丟失或延遲,雖然有這樣的狀況但我們的系統服務仍必須可靠運作。 這些最佳實踐使系統服務能夠承受壓力或故障,更快地從中恢復,並減輕此類故障的影響。 其結果會是縮短了MTTR(mean time to recovery)。
最佳實踐的方式有:
- 慢速且平順的將各組件的hard dependencies轉換為soft dependencies — 當組件的dependencies是不健康時,組件本身仍然可以運作,儘管是以降低服務等級的方式運作。 例如,當dependency 呼叫失敗時,failover到預定的靜態回應。
- request的油門控制(throttle) — 這是緩解模式對需求意外增加的回應方式。一些request被接受,但超過定義限制的request會被拒絕,並返回一個訊息,說明該request已被限制。 對client的預期是他們將退出並放棄request或以較慢的速度重試。
- 控制與限制重試的呼叫
- 快速失敗並限制queue大小 — 如果系統服務無法成功回應request,則讓它快速失敗。 這將釋放與request相關的資源,並允許服務在資源耗盡時回復。 如果系統服務能夠成功回應但request rate太高,則使用queue來緩衝request。 但是,不要使用可能導致client已經放棄的old request的long queue。
- 設定client端的timeout
- 盡量讓service是無狀態的(stateless)
- 有緊急手段 — 這些是可以減緩可用性對系統服務的影響的過程。 它們可以在不知道root cuase的情況下運行。 理想的應急手段是通過提供百分百的啟用和停用標準,將我們在處理警急情況的認知負擔降低到零。 範例手段包括停止所有機器人流量或提供靜態回應。 警急手段通常是手動的,但它們也可以是自動化的。
變更管理
我們必須能夠預見並適應系統服務跟其環境的變化,以實現系統服務的可靠運作。 變更是包括對我們的系統服務施加的變更,例如業務需求高峰,以及來自內部團隊的變更要求,例如功能部署和安全補丁。
使用 AWS,我們可以監控系統服務的行為並自動達到我們 KPI。 例如,隨著系統服務有更多的用戶在使用,我們的系統服務可以添加額外的伺服器。 我們可以控制誰有權進行系統服務的變更並審核這些變更的歷史記錄。
以下問題是我們在變更管理設計考量時需要回答一些問題:
Q6:我們如何監控系統服務的資源?
日誌和指標是深入了解我們系統服務的有效工具。 我們需要將系統服務能夠產生這些運作日誌和指標,並在超過閾值或發生重大事件時發送通知。 監控服務使我們的系統服務能夠識別何時效能有達到變差的閾值或發生故障,當發生類似事件時,系統能夠自動回應並回復到正常狀態。
最佳實踐的方式有:
- 對系統服務的所有組件進行監控
- 定義與計算指標(集中式的儲存指標)
- 發出及時處理與告警的通知
- 自動化且即時的回應
- 儲存與分析
- 定期進行審查 — 經常檢查我們是如何實施系統的監控並根據重大事件和變更對其進行更新
- 監控end-to-end request 的追蹤(例如使用X-ray)
Q7:我們如何設計我們的系統服務是能即時的進行業務成長的需求變更?
可擴展的系統服務提供了自動添加或刪除資源的彈性,以便它們在任何特定時間點與當前的業務需求緊密結合。
最佳實踐的方式有:
- 在擷取或擴展資源時使用自動化
- 在偵測到系統受損時拿到雲端資源
- 在偵測到系統需要更多資源時拿到更多雲端資源
- 對系統服務加上負載
Q8: 我們如何實行變更?
可控的變更對於部署新功能以及確保系統服務和運行環境正在運作軟體,而這些軟體都是在我們的清單中的並且可以用可預測的方式進行修補或替換,而這些是必要運作我們在雲端環境中的系統服務需求。 如果這些變更不受控,那麼就很難預測這些變更的影響,或者解決由這些變更產生的問題。
最佳實踐的方式有:
- 將運作手冊用於部署等標準作業
- 將功能測試變成為部署的一部分
- 將韌性(resiliency)測試變成為部署的一部分
- 使用不可變基礎架構進行部署
- 使用自動化部署方式
當我們的系統服務設計成能自動添加和刪除資源以回應前端業務需求變化時,這不僅可以提高可靠性,還可以確保業務的成長不會成為系統的負擔。 有了監控,當 KPI 偏離我們規定的界線時,我們的團隊將自動收到告警。 自動記錄對雲端與我們系統環境的變更,讓我們可以審核並快速識別可能影響可靠性的運作。 對變更管理的控制確保我們可以執行提供所需可靠性的標準。
故障管理
只要是人類做的系統,不可避免的有一天一定會發生故障.因為人類本身就是不完美的動物,不完美的事物不會創造出完美的事物。 可靠性要求我們的系統負載在故障發生時能意識到故障並採取行動避免對可用性產生太大的影響。 我們系統服務必須能夠承受故障並自動修復問題。
借助由AWS,我們可以利用自動化對監控資料做出回應。 例如,當特定指標超過閾值時,我們可以觸發自動回應的腳本來解決問題。 此外,與其嘗試診斷和修復屬於生產環境一部分的故障資源,不如將其替換為新資源(這就是牛群與寵物理論),並對故障資源做out-of-band的分析。 由於雲端讓我們能夠以低成本建立整個系統服務的另一個環境,因此我們可以使用自動化測試來驗證完整的恢復過程。低成本的原因是做完驗證後就可以馬上移除掉這個環場,而我們只需要支付測試時間所使用到的資源.在地端環境這則需要購置兩套一模ㄧ樣的設備與解決方案.
以下問題是我們在故障管理設計考量時需要回答一些問題:
Q9: 我們是進行資料備份的?
備份資料/應用程式/設定檔以滿足業務對RTO)和RPO的要求。
最佳實踐的方式有:
- 識別並備份所有需要備份的資料,或從來源端複製資料
- 加密備份資料
- 備份作業是自動化的
- 定期的回復資料並確認其資料的完整性與流程
Q10:我們是如何隔離故障來保護我們的系統服務?
“故障隔離邊界”將系統服務內的故障影響限制在有限數量的組件中。 邊界外的組件不受故障影響。 使用多個故障隔離邊界,我們可以限制對系統服務的影響。
最佳實踐的方式有:
- 將系統部署在多個位置並選擇合適的位置
- 自動回復受限於單一個位置的組件
- 使用Bulkhead架構限制影響範圍
Q11:我們如何設計我們的系統服務來抵抗部分組件的故障?
需要高可用性和很小的MTTR 的系統服務必須設計為是具有韌性的。
最佳實踐的方式有:
- 對系統服務的所有組件來偵測故障
- failover到健康的resource
- 所有的系統layer做到自動修復
- 回復期間依賴data plane而不是control plane
- 使用靜態穩定性防止Bimodal Behavior — Bimodal Behavior是指您的系統服務在正常模式和故障模式下表現出不同的行為,例如,如果可用區出現故障,則依賴於啟用新的insatnce。 相反,我們應該構建靜態穩定且只在一種模式下運行的系統服務。 在這種情況下,如果刪除一個可用區,我們需要在剩餘的每個可用區中預置足夠的insatnce來處理系統服務容量,然後使用 ELB或 Route 53 進行狀況檢查將負載從受損insatnce中轉移。
- 當事件衝擊到可用度時發出通知
Q12:我們如何測試系統服務的可靠度?
在我們將系統服務設計為對生產環境有大量業務需求的壓力是具韌性之後,測試是確保其按設計運作並提供我們預期韌性的唯一方法。
最佳實踐的方式有:
- 使用定義好的程序來調查系統為什麼掛掉
- 進行事後事故分析
- 測試功能性需求
- 測試資源擴展跟效能需求
- 用chaos engineering來測試系統韌性
- 定期進行系統災害演練
Q13: 我們如何規劃我們的DR(Disaster recovery)?
準備好資料備份和另一組系統服務的組件是 DR 策略起始點。 RTO 和 RPO 是我們回復系統服務的目標。 這是根據業務需求所設定的。 實施DR策略以滿足這些目標,同時考慮系統服務資源和資料的位置和功能。 中斷的可能性和回復成本也是有助於讓組織或業務單位知道為系統服務提供災難回復的業務價值的關鍵因素。
最佳實踐的方式有:
- 定義組織所需的RTO/RPO目標
- 使用已經定義的回復策略(如backup and restore/ active-passive / pilot light / warm standby等)滿足回復目標
- 測試DR以驗證RPO/RTO的正確性
- 管理 DR site或region的configuration drift
- 自動化的回復作業
定期備份資料與系統並其進行測試,以確保我們可以從邏輯和物理的錯誤與故障中回復。 管理故障的一個關鍵是對導致故障的系統服務進行頻繁的自動化測試,然後觀察它們如何回復。 定期執行這類的作業,並確保在系統服務發生重大變化後也觸發此類測試。 主動追踪 KPI 以及RTO和RPO,以評估系統服務的韌性(尤其是在故障測試場景下)。 以KPI為標準將幫助我們識別和減緩單點故障。 目標是徹底測試我們的系統服務的回復流程,以便我們有信心恢復所有資料並能持續組織的業務進行,即使面對持續存在的問題。 我們的回復作業應該與我們的正常運作過程一樣得到訓練。