使用 Azure DevOps 部署到 App Service 預備環境 (Slot) 並進行切換

前言

App Service 有一個很實用的功能就是預備環境 (Slot),他可以方便我們在部署程式的時候可以先佈到預備環境,測試完成之後可以直接和正式環境進行切換 (Swap),也可以在發現有沒測試到的嚴重問題的時候可以再切換一次,就可以快速的退到前一版的環境,那要結合 Azure Devops 的話就可以達到自動化的部署和切換,而且可以加上審核的關卡,測試完成之後審核完成就自動的進行切換,本文就來針對這樣得情境進行介紹如何完成這樣的自動化流程。

說明

準備和介紹 App Service Slot 環境

首先先確認 App Service 定價層是否為標準或以上,因為 Slot 功能需要至少標準定價層才可以使用,基本定價層是不支援的,而不同定價層可以在同一個 App Service Web App 上面建立的個數上限也不同,標準為 5 個,進階或以上定價層則為 20 個,詳情可以參考官方文件說明。

在 App Service 選單內點選部署位置,然後點選加入位置,輸入 Slot 的名稱以及選擇是否從現有的 App Service 複製設定。名稱部分輸入完之後,建立起來的 App Service 網址會如 https://{AppServiceName}-{SlotName}.azurewebsites.net/ ,建立好之後就可以使用該網址來瀏覽預備環境站台。

等待建立完成之後會如下圖顯示,其中目前的生產環境會標示生產環境,後面有個欄位是流量百分比,可以設定流量的分配,假設我們上了新版本功能之後想先開放 20% 的使用者使用,就可以分配流量成 80 和 20,這樣使用者在瀏覽的時候就還是可以使用原本的網址瀏覽,但是會有一定機率會連到新版本站台,就可以方便進行 AB Testing 的操作了。

再來為了更進一步說明切換的功能,我在 App Service 的組態上加上設定 Server 和 Config,並分別設定成。其中 Server 設定成部署位置設定,他代表的意思是在切換的時候他會跟著 Slot 環境,不會因為切換而被更新,所以切換之後就可以知道目前的 Server 是哪一個,方便作為判斷,而 Config 參數則分別設定成 Old 和 NewConfig,在切換的時候就會把這兩個參數也進行交換,這在我們新版程式針對同一個參數需要更新的時候會很有幫助。

然後建立一個 .NET 6 Razore Page 站台,並且讀取該參數在頁面上顯示,然後分別預先部署到兩個站台上面。

Index.cshtml.cs

public class IndexModel : PageModel
{
    private readonly ILogger<IndexModel> _logger;
    private readonly IConfiguration _configuration;

    public IndexModel(ILogger<IndexModel> logger, IConfiguration configuration)
    {
        _logger = logger;
        _configuration = configuration;
    }

    public void OnGet()
    {
        ViewData["Server"] = _configuration.GetValue<string>("Server");
        ViewData["Config"] = _configuration.GetValue<string>("Config");
    }
}

Index.cshtml

伺服器:@ViewData["Server"] <br/>
參數:@ViewData["Config"] <br/>

分別用各自的網址去瀏覽,就可以看到我們的站台設定不同,分別呈現 Production 和 Stage 參數的不同。

接下來點選交換,就會出現預覽畫面,會顯示組態在切換之後會有什麼不同。可以看到來源的 Config 參數和目標的參數會交換,而 Server 則沒有出現在交換清單上。

完成之後一樣的網址去瀏覽就可以看到參數已經更新了,當然如果程式有不同的話也會交換了。

到這邊我們就設定好我們的 App Service 環境了,接下來就是針對 Azure DevOps 進行自動化部署的流程設定。

Azure DevOps Release Pipeline 設定

首先到我們站台專案的 Azure DevOps 專案建立 Pipeline,主要是設定程式 Build 的 Pipeline。

這邊我選擇用傳統編輯模式來設定。

選擇程式碼的位置和分支,實務上我們可以建立 release 分支,可以在程式測試完成之後將準備上版的程式合併到 release 分支來觸發自動化部署的流程。

因為我的專案是 .NET 6 ,所以選擇 ASP.NET Core 這一個範本來建立。

基本上只需要確認用來執行 Pipeline 的 Agent 就可以設定完成了。

另外可以設定 Triggers 把 CI 打開,這樣在程式碼 commit 的時候就會自動觸發 Pileline 執行了。

再來設定 Release,點選 Pipelines 並選擇 Releases 來新增一個 pipeline。

首先針對程式來源作設定。

這邊就選擇剛剛建立的 build pipeline。

再來新增第一個步驟,把 commit 上來的程式部署到我們前面建立的 App Service Stage 這一個 Slot。

直接選擇內建的樣版套用,因為我們要部署到 Slot,所以選擇包含 Slot 的樣版。

接下來來設定部署的 Job,樣版會包含兩個 Job 將第一個設定成部署到我們前面建立的 Spp Service Slot,然後移除第二個 Job,因為我們情境上要測試完成之後審核完才會進行自動切換的操作。

接下來新增一個 Stage 一樣選擇 Slot 範本,這次設定上就只保留切換的 Job。

 

接下來就是設定各種事件,首先是設定 Build pipeline 完成的時候會觸發 Release Pipeline,點選 Artifacts 右上角的閃電服務來設定 trigger,把 Build 選項打開。

接下來設定部署到 Slot 這一個 Stage 在完成後會觸發審核的事件,通常是可以設定成測試的相關人員,都測試完成之後就可以進行審核確認。

接下來設定在進行切換之前也要過審核,通常是設定成主管或是相關人員,確認要將部署位置的版本上版到正式環境了。

到這邊就都設定完成了,就可以儲存 pipeline 了。

執行結果

再來就是進行測試了,可以到修改程式碼之後 commit 來觸發 build pipeline,確定 Build 的 Pipeline 已執行完成。

而 Release Pipeline 也確實被觸發,而狀態是處於 Pending,因為我們有設定需要審核才會進行下一步。

這時候審核的人會收到自動寄發的信件,提醒要去進行審核。

然後我們就可以看一下我們的站台,確認 Stage 環境,部署之後的程式是否正常運作,可以看到右邊的 Stage 環境已經有部署了新的程式了。

確認沒問題之後就可以點選信件的 View approval 連結,就會連到 Azure DevOps 的 Release 裡面,可以看到第一個階段正等候我們 Approve,點選之後就會觸發第二的階段的切換到正式環境的 Job。

而這時候也就觸發了第二層的審核,確定是否要切換到正式環境了,一樣點選 Approve 來做確認,就會執行切換的操作了。

確認執行都完成了,就可以到我們站台進行確認了。

環境確實做交換了,如此就完成了一次的上版操作了。

結論

Azure DevOps 內建很多的 Pileline 範本,可以很方便協助我們設定,本次以最基本的一個情境,針對我們程式部署到 App Service 上,並結合 App Service 部署位置功能來達到部署之後可以先測試程式,確保 Stage 環境可以正確運行再切換到正式環境,而這些過程也都加上了審核的機制,避免直接就自動完成部署跟切換,而根據程式和架構的不同,可以在進行調整,以符合大家的環境來達到自動化的流程。

參考資料