全球應用程式佈署需要考慮映像檔登入檔的佈署策略、多區域組態管理以及流量的負載平衡。映像檔登入檔可以選擇多區域佈署或使用網路組態連線特定儲存函式庫。引數化佈署和 Helm 等工具可以有效管理不同區域的組態差異。為了實作低延遲存取和容錯移轉,可以使用 DNS 或多播 IP 進行全球流量負載平衡。此外,分階段釋出策略可以降低全球中斷的風險,並結合金絲雀發布和負載測試等技術,在生產環境中驗證新版本的功能和效能。建立整合測試環境和生產資料的副本對於驗證應用程式行為至關重要,但同時需要注意資料安全。最後,制定清晰的任務檢查清單和緊急應變計畫,可以有效應對生產環境中發生的問題。
全球應用程式分佈與佈署
在前面的章節中,我們已經討論了多種建立、開發和佈署應用程式的最佳實踐。然而,當佈署和管理具有全球影響力的應用程式時,會出現一系列不同的挑戰。
為何需要全球分佈
有多種原因促使應用程式需要擴充套件至全球佈署。首先,也是最明顯的原因,是規模問題。如果應用程式非常成功或對業務至關重要,那麼就需要將其佈署在全球各地,以提供足夠的使用者容量。這類別應用程式的例子包括全球性的API閘道器、大規模的物聯網產品、成功的社群網路等。
雖然很少有系統需要達到全球規模,但更多應用程式需要全球佈局來降低延遲。即使用了容器和Kubernetes,仍然無法擺脫光速的限制。為了最小化客戶端與應用程式之間的延遲,有時需要將應用程式分散在全球各地,以縮短應用程式與使用者之間的實體距離。
另一個更常見的全球分佈原因是區域性需求。不論是因為頻寬限制(如遠端感測平台)還是資料隱私(如地理限制),有時需要在特定位置佈署應用程式,以滿足當地法規或確保應用程式的成功。隨著越來越多的國家和地區實施資料隱私和主權法規,越來越多的企業需要在特定位置佈署應用程式,以服務當地的使用者。
映像檔的分佈
在考慮如何在全球執行應用程式之前,首先需要確保映像檔可以在全球各地的叢集中使用。首先要考慮的是,映像檔登入是否具備自動的地理複製功能。許多由雲端供應商提供的映像檔登入服務,可以自動將映像檔分佈到全球各地,並將映像檔請求解析到最靠近叢集的儲存位置。許多雲端供應商允許您決定在哪裡複製映像檔;例如,您可能知道某些地區不會佈署您的應用程式。Microsoft Azure容器登入就是這樣一個例子,其他供應商也提供類別似的服務。如果您使用支援地理複製的雲端映像檔登入服務,那麼將映像檔分佈到全球各地就變得非常簡單。您只需將映像檔推播到登入中,選擇需要複製的地區,剩下的工作就會由登入服務自動完成。
程式碼範例:使用Azure容器登入進行地理複製
az acr create --resource-group myResourceGroup --name myContainerRegistry --sku Premium
az acr replication create --registry myContainerRegistry --location westus
az acr replication create --registry myContainerRegistry --location eastus
內容解密:
- 首先,使用
az acr create命令建立一個Azure容器登入,並指定--sku Premium以啟用地理複製功能。 - 然後,使用
az acr replication create命令在指定的地區(如westus和eastus)建立複製。
如果您沒有使用雲端映像檔登入,或者您的供應商不支援自動地理複製,那麼就需要自行解決這個問題。一個方法是使用位於特定位置的映像檔登入。這種方法有一些缺點,例如映像檔提取延遲可能會影響容器啟動的速度,從而影響到對機器故障的回應速度。此外,單一的映像檔登入可能會成為單點故障,如果該地區或資料中心發生重大事故,登入服務可能會離線,從而影響CI/CD流程和應用程式佈署。
如果您無法使用雲端供應商提供的地理複製功能,並且需要自行實作映像檔複製,那麼就需要自行設計解決方案。實作這樣一個服務有兩種選擇:一是使用地理名稱為每個映像檔建立不同的標籤,二是建立一個完整的映像檔複製服務。
管理全球應用程式佈署的挑戰
在全球佈署應用程式時,需要管理多個地理位置的叢集,以及確保全球服務的可靠性。這是一個重大的挑戰。本章將介紹如何成功地實作全球應用程式分佈和佈署的最佳實踐和方法。
圖表翻譯: 此圖示展示了使用Azure容器登入進行地理複製的流程。首先,建立Azure容器登入,然後啟用地理複製功能。接著,在多個地區建立複製,最後推播映像檔到登入,實作自動分佈到各個地區。
全球應用程式佈署與流量管理
在現代軟體開發中,將應用程式佈署到全球各地已成為常見需求。這不僅能夠提高應用程式的可用性和效能,還能確保使用者在不同地區都能獲得良好的體驗。本篇文章將探討如何在全球範圍內佈署應用程式、管理流量以及實作可靠的軟體釋出。
映像檔登入檔的全球佈署
要在全球範圍內佈署應用程式,首先需要考慮映像檔登入檔(Image Registry)的佈署。有兩種主要方法:
多區域映像檔登入檔:在不同地理區域佈署多個映像檔登入檔,每個登入檔都包含相同的映像檔。這種方法的優點是設定和管理相對簡單,每個登入檔都是獨立的,可以在 CI/CD 管道的末端將映像檔推播到所有登入檔。缺點是每個叢集需要稍微不同的組態,以便從最近的地理位置提取映像檔。
網路組態連線映像檔提取到特定儲存函式庫:仍然將映像檔推播到多個登入檔,但為它們分配一個單一的 DNS 端點(例如
my-registry.io)。可以使用地理感知 DNS(GeoDNS)或多播 IP 位址來實作。這種方法比較複雜,需要具備相關的網路經驗。
引數化佈署
當映像檔在全球範圍內複製後,需要引數化佈署以適應不同地區的組態差異。常見的做法是使用範本方法,將大部分組態保留在單一範本中,並根據不同地區的引數生成特定地區的範本。像 Helm 這樣的工具可以用於範本化組態。
全球範圍內的流量負載平衡
將應用程式佈署到全球各地後,需要確定如何將流量導向應用程式。通常,希望利用地理鄰近性來確保對服務的低延遲存取,同時也希望在發生中斷或其他服務故障時能夠跨地理區域進行容錯移轉。可以使用 DNS 協定或多播 IP 位址來實作跨區域端點的負載平衡。
全球範圍內可靠地釋出軟體
在範本化應用程式組態後,下一個重要的問題是如何在全球範圍內佈署這些組態。雖然同時在全球範圍內佈署應用程式可以快速迭代,但這也可能導致全球範圍內的中斷。相反,對於大多數生產應用程式,更謹慎的分階段釋出方法是更合適的。結合全球負載平衡等技術,可以在面對重大應用程式故障時保持高用性。
內容重點整理:
- 映像檔登入檔的全球佈署策略
- 引數化佈署以適應不同地區的組態
- 使用 DNS 或多播 IP 進行全球流量負載平衡
- 分階段釋出軟體以確保高用性
Plantuml 圖表演示全球應用程式佈署流程
圖表翻譯: 此圖示展示了全球應用程式佈署的流程,從建立映像檔到分階段釋出軟體,並透過監控與反饋進行持續最佳化。
全球軟體釋出的可靠策略
在進行全球軟體釋出時,假設您的應用程式已經透過基本的效能測試和負載測試。為了確保軟體的品質,在將特定映像檔(或映像檔集)認證為可進行全球釋出之前,應該進行足夠的測試,以確認應用程式的運作正確。然而,這並不代表您的應用程式在所有情況下都能正確運作。儘管測試能夠捕捉許多問題,但在實際生產環境中,應用程式問題往往是在佈署到生產流量時才首次被注意到。這是因為生產流量的真實特性往往難以完美模擬。例如,您可能只使用英文輸入進行測試,而在實際生產環境中,您會遇到來自多種語言的輸入。或者,您的測試輸入集對於應用程式所處理的真實資料可能並不全面。當然,每當您在生產環境中發現一個未被測試捕捉到的故障時,這都是您需要擴充套件和加強測試的有力指標。儘管如此,在生產環境中佈署時仍會遇到許多問題。
區域性釋出的重要性
鑑於此,每個您釋出到的地區都是一個發現新問題的機會。由於該地區是生產地區,因此也存在潛在的中斷,您需要對此做出反應。這些因素結合在一起,決定了您應該如何進行區域性釋出。在整個討論過程中,我們談論的是將軟體釋出到地理區域,但這種漸進式釋出只是漸進式曝光控制的一種形式。另一種釋出新功能的方式是使用功能旗標進行漸進式曝光。使用功能旗標,新功能首先透過遵循地理區域釋出的版本進行釋出;但是,該功能預設為關閉。一旦版本在所有地區佈署完成,就會逐漸開啟該功能的旗標,例如,先為 10% 的使用者啟用,然後是 20%,直到該功能完全釋出。有許多組態系統可用於根據旗標的實驗和漸進式釋出。將旗標與地理區域釋出相結合,是一種非常穩定的方式,可以在快速回應故障的同時釋出新功能。
釋出前的驗證
在考慮將特定版本的軟體釋出到全球之前,在某種合成測試環境中驗證該軟體至關重要。如果您的持續交付(CD)Pipeline設定正確,那麼在特定版本構建之前的所有程式碼都將經過某種形式的單元測試,可能還包括有限的整合測試。然而,即使有這些測試到位,仍需要考慮另外兩種測試。首先是完整的整合測試。這意味著將您的整個技術堆疊組裝成一個全規模的應用程式佈署,但不包含任何真實的生產流量。這個完整的技術堆疊通常會包括您的生產資料副本或與您的真實生產資料大小和規模相同的模擬資料。如果在真實世界中,您的應用程式中的資料是 500 GB,那麼在預生產測試中,您的資料集大小也應該大致相同(甚至可能是相同的資料集)。
建立真實的整合測試環境
一般來說,建立完整的整合測試環境是一項重大挑戰。通常,生產資料只存在於生產環境中,而生成相同大小和規模的合成資料集相當困難。因此,建立真實的整合測試資料集是值得早早開始做的事情的一個很好的例子。如果您在應用程式開發的早期就建立了資料集的合成副本,當資料集本身還很小時,您的整合測試資料就會與您的生產資料同步增長。這通常比在已經達到規模時再嘗試複製生產資料要容易得多。
使用生產資料進行測試的安全考量
不幸的是,許多人直到已經達到大規模時才意識到需要一份他們的資料副本,此時任務變得困難。在這種情況下,可以在生產資料儲存之前佈署一個讀寫分流層。顯然,您不希望整合測試寫入生產資料,但通常可以在生產資料儲存之前設定一個代理,它從生產讀取,但將寫入儲存在一個側表,也在後續讀取中被查詢。當然,如果您使用生產資料進行測試和開發,您必須非常小心地保護這些資料的安全。許多資料洩露事件都與開發人員意外地將生產使用者資料放在不安全的位置有關。
整合測試和負載測試
無論您如何設法建立整合測試環境,目標都是相同的:驗證您的應用程式在一系列測試輸入和互動下的行為是否符合預期。有多種方法可以定義和執行這些測試——從最手動的方式(不推薦,因為容易出錯),到模擬瀏覽器和使用者互動(如點選等)的測試。在這兩者之間,還有探測 RESTful API 但不一定測試構建在其上的 Web UI 的測試。無論您如何定義整合測試,目標都應該是相同的:一個自動化的測試套件,驗證您的應用程式對一整套真實世界輸入的正確行為。對於簡單的應用程式,可能可以在合併前測試中執行此驗證,但對於大多數大規模真實世界應用程式,需要一個完整的整合環境。
程式碼範例:負載測試
import locust
class UserBehavior(locust.TaskSet):
@locust.task
def test_api(self):
self.client.get("/api/test")
class WebsiteUser(locust.HttpLocust):
task_set = UserBehavior
min_wait = 5000
max_wait = 9000
內容解密:
- 這段程式碼定義了一個使用 Locust 進行負載測試的範例。
UserBehavior類別定義了使用者行為,其中包含一個任務test_api,該任務向/api/test傳送 GET 請求。WebsiteUser類別定義了 Locust 使用者,其task_set屬性設定為UserBehavior,表示該使用者將執行UserBehavior中定義的任務。min_wait和max_wait屬性定義了任務之間的最小和最大等待時間,分別為 5000 毫秒和 9000 毫秒。
負載測試與金絲雀發布:確保軟體可靠性的關鍵步驟
在軟體開發的過程中,確保應用程式的效能和可靠性是至關重要的。負載測試和金絲雀發布是兩個關鍵的實踐,可以幫助開發團隊在軟體發布之前發現潛在的問題,從而避免在生產環境中出現效能衰退或故障。
負載測試:模擬真實流量
負載測試是一種模擬真實流量對應用程式進行壓力測試的方法。它的目的是確保應用程式在面對大量請求時仍能保持穩定的效能。進行負載測試的一種簡單方法是重放真實生產環境中的流量日誌。這種方法可以模擬真實的生產環境,但也存在一些挑戰,例如日誌可能過時,或者應用程式或資料集已經發生變化。
執行負載測試的挑戰
- 日誌過時:如果日誌過時,應用程式或資料集可能已經發生變化,導致負載測試的結果不準確。
- 未模擬真實依賴:如果未模擬真實依賴,可能會導致舊的流量對依賴項無效,例如資料可能不再存在。
- 安全風險:記錄的真實請求可能包含私人資訊或安全憑證,需要妥善保護。
負載測試的最佳實踐
- 及早建立負載測試,並隨著應用程式的發展不斷改進和迭代。
- 監控關鍵指標,如每秒請求數和請求延遲。
- 測量延遲的分佈,包括平均延遲和異常百分位數(例如第90和第99百分位數)。
- 監控資源使用情況(CPU、記憶體、網路、磁碟),以識別資源使用量的顯著變化。
金絲雀發布:早期預警系統
金絲雀發布是一種將新版本的應用程式佈署到一小部分真實流量中的方法。這種方法可以讓開發團隊在新版本正式發布之前獲得早期預警,發現潛在的問題。
金絲雀發布的好處
- 早期預警:金絲雀發布可以讓開發團隊在新版本正式發布之前發現潛在的問題。
- 內部測試:金絲雀發布可以讓內部團隊測試新版本,發現問題並修復。
- 客戶驗證:金絲雀發布可以讓客戶驗證新版本,發現問題並提供反饋。
金絲雀發布的最佳實踐
- 將金絲雀區域視為生產環境,進行同樣的監控、擴充套件和功能測試。
- 將新版本佈署到金絲雀區域一段時間(例如幾天),以收集廣泛的客戶反饋。
- 使用HTTP重新導向器將公司內部的請求重新導向到金絲雀區域,讓內部團隊成為端對端測試者。
全球軟體滾動式佈署的策略與實踐
當你開始思考如何將軟體推廣到全球時,瞭解不同地區的特性是至關重要的。在將軟體滾動到生產區域後,你需要進行整合測試和初步的金絲雀測試。這意味著任何隨後發現的問題都將是未在這些環境中顯現的問題。思考一下你的不同區域,有些區域是否比其他區域獲得更多的流量?有些區域是否以不同的方式被存取?
識別地區型別
一個例子是,在開發中國家,流量更可能來自移動網頁瀏覽器。因此,一個地理位置接近更多開發中國家的地區可能會比你的測試或金絲雀區域有更多的移動流量。
另一個例子可能是輸入語言。世界非英語地區的區域可能會傳送更多的 Unicode 字元,這可能會導致字串或字元處理中的錯誤。如果你正在構建一個API驅動的服務,有些API在某些地區可能比其他地區更受歡迎。所有這些都是可能存在於你的應用程式中的差異,並且可能與你的金絲雀流量不同。每一個差異都可能是生產事故的來源。
特性分析表格
建立一個你認為重要的不同特性的表格。識別這些特性將有助於你規劃全球滾動式佈署。
| 特性 | 描述 | 重要性 |
|---|---|---|
| 流量來源 | 不同地區的流量來源是否有所不同 | 高 |
| 輸入語言 | 不同地區的輸入語言是否會影回應用程式 | 高 |
| API 使用率 | 不同地區的 API 使用率是否有所不同 | 中 |
構建全球滾動式佈署
在識別了你的區域特性之後,你需要制定一個計劃,以便將軟體滾動到所有區域。顯然,你希望最小化生產中斷的影響,因此一個很好的第一個區域是看起來與你的金絲雀區域相似且具有輕量使用者流量的區域。這樣的區域很不可能出現問題,但如果問題確實發生,影響也會較小,因為該區域接收的流量較少。
時間到煙霧(Time-to-Smoke)
成功地將軟體滾動到第一個生產區域後,你需要決定在轉移到下一個區域之前要等待多久。等待的原因不是人為地延遲你的發布;而是等待足夠長的時間,以便讓問題「冒煙」。這個時間到煙霧的週期是一個機率分佈,指示你應該等待多久才能有很高的機率確認你的發布正在正確執行。一般來說,一個好的經驗法則是將過去問題出現的平均時間加倍。
import statistics
# 過去六個月內每次中斷的平均時間(小時)
outage_times = [1, 1.5, 0.5, 2]
# 計算平均時間
average_outage_time = statistics.mean(outage_times)
# 將平均時間加倍作為等待時間
wait_time = average_outage_time * 2
print(f"建議的等待時間:{wait_time} 小時")
內容解密:
這段程式碼計算了過去幾次中斷的平均時間,並將其加倍作為區域滾動之間的等待時間。首先,我們匯入了 statistics 模組以使用其 mean 函式來計算列表中數值的平均值。然後,我們定義了一個列表 outage_times,其中包含了過去幾次中斷的時間(以小時為單位)。接著,我們使用 mean 函式計算這些時間的平均值,並將結果儲存在 average_outage_time 變數中。最後,我們將平均時間加倍,得到建議的等待時間,並將結果列印出來。
當事情出錯時
到目前為止,我們已經看到了設定全球軟體滾動式佈署的各個部分,並且已經看到了可以如何結構化這種滾動式佈署以最小化出錯的機會。但是,當事情確實出錯時,你該怎麼辦?所有的緊急回應人員都知道,在危機的熱度和恐慌中,你的大腦會受到很大的壓力,即使是最簡單的過程也更難記住。再加上當宕機發生時,從CEO到公司裡的每個人都會狂熱地等待「解除警示」訊號,你就可以看出犯錯是多麼容易。此外,在這種情況下,一個簡單的錯誤,比如忘記還原過程中的某個步驟,或者推出一個實際上問題更多的“修復”版本,都可以使糟糕的情況變得更加糟糕。
建立檢查清單
為了確保一切必要的工作都完成,並且按照正確的順序完成,制定一個清晰的任務檢查清單是有好處的,該清單按照任務執行的順序組織,並且包含每個步驟的預期輸出。把每一步驟都寫下來,無論它看起來多麼明顯。在緊急情況下,即使是最明顯和最簡單的步驟也可能被遺忘和意外跳過。
@startuml
skinparam backgroundColor #FEFEFE
skinparam componentStyle rectangle
title 全球應用程式佈署與可靠釋出策略
package "Docker 架構" {
actor "開發者" as dev
package "Docker Engine" {
component [Docker Daemon] as daemon
component [Docker CLI] as cli
component [REST API] as api
}
package "容器運行時" {
component [containerd] as containerd
component [runc] as runc
}
package "儲存" {
database [Images] as images
database [Volumes] as volumes
database [Networks] as networks
}
cloud "Registry" as registry
}
dev --> cli : 命令操作
cli --> api : API 呼叫
api --> daemon : 處理請求
daemon --> containerd : 容器管理
containerd --> runc : 執行容器
daemon --> images : 映像檔管理
daemon --> registry : 拉取/推送
daemon --> volumes : 資料持久化
daemon --> networks : 網路配置
@enduml
圖表翻譯: 此圖示展示了當事情出錯時的處理流程。首先,檢測到問題後啟動緊急應變計畫。接著,按照預先制定的檢查清單執行必要的步驟。然後,評估問題的影響範圍,以確定需要實施的修復措施。實施修復措施後,持續監控修復結果,以確保問題得到妥善解決。