雲端服務滾動升級的一種思路
April 30, 2021
傳統的服務部屬方案
一個軟體服務在線上都有機會面臨到需要升級的時候,
一般傳統的軟體升級方式可能是這樣的,
Artifact 是可用於部屬的包
- 準備新的 Artifact 到 Server 的暫存資料夾
- 停止線上執行環境
- 清除目前執行環境上的資料夾資料
- 將新的 Artifact 放到執行環境的資料夾
- 啟動執行環境
這樣的升級方式會面臨幾個情形,
- 升級服務期間會造成服務短暫中斷
- 服務如果需要退版的時候需要重新準備降版
服務不下線的滾動升級方案
要讓一個服務可以在不下線的情況下完成升級,
需要幾個準備:
- 準備一個新版本的服務
- 檢查新部屬的服務是否正常
- 將流量導向新的服務
- 如果新的服務沒問題的話關閉舊服務
- 反之新服務有問題需退版則流量導回舊服務
實際的實作大略如底下的圖
Health Check Service 是用來檢查服務是否健康的服務
Artifact Server 是用來提供 download artifact 的服務
Provisioning 是指一個服務從無到準備到可上線的過程
- Health Check 服務持續檢查 Instance 是否正常,在這裡提到的 Instance 可能是一台 Server,或是機器上的一個預備服務
- 由即將負責服務線上的 Instance 發起一個請求從 Artifact Server 取得 Artifact。
- 在取得 Artifact 以後做完後續服務部屬的準備
- 部屬完成後,Health Check API 會改成回應服務正常
- 當服務正常以後,將流量切換到新準備的 Instance
其中步驟 2 以及步驟 3 通常是從 Instance 中執行一個 Script 來完成的
Container 服務的滾動升級
如果服務是透過 Container 做部屬的話,
則可以直接使用準備好的 Image 啟動,
而不用從 Artifact Server 取得 Artifact,
Provisioning 的時間就會縮短。
在新的 Container 在完成準備以後,
就可以將流量導到新的 Container 服務切換到線上。
在雲端上實作服務不下線滾動升級
在非雲端服務上要準備額外一組服務來做類似上述藍綠部屬的方案不太容易,
因為機房的伺服器通常是買斷的,
準備額外的閒置伺服器資源是比較昂貴的。
但這樣的方案在雲端租用機器的環境上是較容易實現的。
運用先額外租用一組機器做服務上線準備,
服務完成準備以後,
將新的服務切換到線上,
再將舊的機器還給雲端服務商,
如果退版也可以將先前服務在線上的機器切回線上繼續服務,
達成快速退版的目的。
AWS EC2 實作服務不下線滾動升級
如果用 AWS 來實作的話,
大致的實作流程如下
Auto Scaling Group 是用來定義可擴展的群組,可定義群組採用相同 Launch Templete 產生出新的 EC2 Instance,並可以定義對應的 Scaling Policy 做機器數量的伸縮。
EC2 Instance 是 AWS 上的機器實例
Target Group 是用來定義一群目標變成一個群組,可以讓 Load Balancer 將流量導入
- 建立 Auto Scaling Group
- Auto Scaling Group 透過 Launch Templete 產生出新的機器群
上述是搭配 Auto Scaling Group 的方案,
如果直接產生出機器的話通常是如下
- 透過 Launch Templete 產生出機器
通常會透過 Launch Templete 產生出機器的原因是可以透過 Launch Templete 定義的 User Data,來執行 Script 做 Provisioning,Script 可能是 PowerShell 或是 ShellScript。
接下來的動作就是一致的
- 將 EC2 Instance 掛載在新的 Target Group 上
- 新的 Target Group 會開始進行 Health Check 檢查
- EC2 Instance 會從 Artifact server 取得 Artifact
- EC2 Instance 開始進行服務上線準備,
以我所做過的實作,
Script 會透過機器上的 Tag 來取得一些服務資訊,
進而從 S3 取得對應的 Script 做後續的服務上線準備。 - 新的 Target Group 會持續呼叫指定的 Health Check Endpoint
- 如果新的 Target Group 呼叫 Health Check Endpoint 回應成功,則可以將 Load Balancer 換上新的 Target Group,流量就會進到新的 Target Group。
AWS ECS 實作服務不下線滾動升級
ECS 的實作就簡單許多了,
省去了 EC2 Instance,
改成建立新的 Task Definition,
Task Definition 使用準備好的新 Image,
再從 Task Definition 建立出新的 Task,
新的 Task 要指定新的 Target Group,
並於 Task 準備完成後 Load Balancer 切換新的 Target Group 上線,
最後刪除舊的 Task。
大致流程如下