在 Azure 容器應用程式上部署和調整 ASP.NET Core 應用程式
部署至 Azure 且遇到間歇性高需求的應用程式可受益於可擴縮性,以符合需求。 可調整的應用程式可以進行擴增以確保工作負載尖峰期間的容量,然後在尖峰下降時自動進行縮小,進而降低成本。 水平調整 (擴增) 會新增資源執行個體,例如 VM 或資料庫複本。 本文示範如何完成下列工作,以將可水平調整的 ASP.NET Core 應用程式部署至 Azure 容器應用程式:
本文使用 Razor Pages,但其中大部分套用至其他 ASP.NET Core 應用程式。
在某些情況下,基本 ASP.NET Core 應用程式能夠調整,而沒有特殊考量。 不過,特用特定架構功能或架構模式的應用程式需要額外設定,包括下列各項:
保護表單提交: Razor Pages、MVC 和 Web API 應用程式通常依賴表單提交。 根據預設,這些應用程式使用跨網站偽造權杖和內部資料保護服務來保護要求。 部署至雲端時,必須將這些應用程式設定為在安全且集中的位置管理資料保護服務疑慮。
SignalR 線路:Blazor Server 應用程式需要使用集中式 Azure SignalR 服務,才能安全地進行調整。 這些服務也會利用先前所提及的資料保護服務。
集中式快取或狀態管理服務:可調整的應用程式可能會使用 Azure Cache for Redis 來提供分散式快取。 可能需要 Azure 儲存體來儲存 Microsoft Orleans 這類架構的狀態,以協助撰寫可跨許多不同應用程式執行個體來管理狀態的應用程式。
本文中的步驟示範如何將可調整的應用程式部署至 Azure 容器應用程式,以正確解決上述疑慮。 本教學課程中的大部分概念也適用於調整 Azure App Service 執行個體。
設定範例專案
使用 GitHub Explorer 範例應用程式來遵循本教學課程。 使用以下命令,從 GitHub 複製應用程式:
git clone "https://github.com/dotnet/AspNetCore.Docs.Samples.git"
導覽至 /tutorials/scalable-razor-apps/start
資料夾,然後開啟 ScalableRazor.csproj
。
範例應用程式使用搜尋表單,以依名稱瀏覽 GitHub 存放庫。 表單依賴內建 ASP.NET Core 資料保護服務來處理防偽疑慮。 根據預設,在容器應用程式上水準調整應用程式時,資料保護服務會擲回例外狀況。
測試應用程式
- 在 Visual Studio 中,啟動應用程式。 專案包括 Docker 檔案,這表示可以選取 [執行] 按鈕旁邊的箭號,以使用 Docker Desktop 設定或標準 ASP.NET Core 本機 Web 伺服器來啟動應用程式。
使用搜尋表單,以依名稱瀏覽 GitHub 存放庫。
將應用程式部署至 Azure 容器應用程式
使用 Visual Studio 以將應用程式部署至 Azure 容器應用程式。 容器應用程式提供受控服務,而此受控服務的設計目的是簡化裝載容器化應用程式和微服務。
注意
針對應用程式所建立的許多資源都需要位置。 在此應用程式中,位置並不重要。 實際應用程式應該選取最接近用戶端的位置。 您可能想要選取您附近的位置。
在 Visual Studio 方案總管中,以滑鼠右鍵按一下最上層專案節點,然後選取 [發佈]。
在發佈對話方塊中,選取 [Azure] 作為部署目標,然後選取 [下一步]。
針對特定目標,選取 [Azure 容器應用程式 (Linux)],然後選取 [下一步]。
建立要部署的新容器應用程式。 選取綠色 + 圖示以開啟新的對話方塊,然後輸入下列值:
- 容器應用程式名稱:保留預設值或輸入名稱。
- 訂用帳戶名稱:選取要部署的訂用帳戶。
- 資源群組:選取 [新增],然後建立稱為 msdocs-scalable-razor 的新資源群組。
- 容器應用程式環境:選取 [新增] 以開啟容器應用程式環境對話方塊,然後輸入下列值:
- 環境名稱:請保留預設值。
- 位置:選取與您接近的位置。
- Azure Log Analytics 工作區:選取 [新增] 以開啟記錄分析工作區對話方塊。
- 名稱:保留預設值。
- 位置:選取靠近您的位置,然後選取 [確定] 以關閉對話方塊。
- 選取 [確定] 以關閉容器應用程式環境對話方塊。
- 選取 [建立] 以關閉原始容器應用程式對話方塊。 Visual Studio 會在 Azure 中建立容器應用程式資源。
建立資源之後,請確定在容器應用程式清單中選取該資源,然後選取 [下一步]。
您需要建立 Azure Container Registry 來儲存您應用程式的已發佈映像成品。 選取容器登錄畫面上的綠色 + 圖示。
保留預設值,然後選取 [建立]。
建立容器登錄之後,請確定已將其選取,然後選取 [完成] 以關閉對話方塊工作流程,並顯示發佈設定檔的摘要。
如果 Visual Studio 提示您讓系統管理員使用者存取已發佈的 Docker 容器,請選取 [是]。
在發行設定檔摘要的右上方選取 [發佈],以將應用程式部署至 Azure。
部署完成時,Visual Studio 會啟動瀏覽器以顯示所裝載的應用程式。 在表單欄位中,搜尋 Microsoft
,並顯示存放庫清單。
調整應用程式並針對其進行疑難排解
應用程式目前正在運作,而且未發生任何問題,但我們想要在預期有大量流量的情況下,跨更多執行個體來調整應用程式。
- 在 Azure 入口網站中,於最上層搜尋列中搜尋
razorscaling-app-****
容器應用程式,然後從結果中進行選取。 - 在概觀頁面上,從左側導覽中選取 [調整],然後選取 [+ 編輯與部署]。
- 在修訂頁面上,切換至 [調整] 索引標籤。
- 將最小和最大執行個體都設定為 4,然後選取 [建立]。 此設定變更可保證在四個執行個體之間水平調整您的應用程式。
導覽回應用程式。 頁面載入時,一開始會顯示一切正常運作。 不過,輸入並提交搜尋字詞時,可能會發生錯誤。 如果未顯示錯誤,則請多次提交表單。
針對錯誤進行疑難排解
目前無法立即清楚搜尋要求失敗的原因。 瀏覽器工具指出已傳回「400 不正確的要求回應」。 不過,您可以使用容器應用程式的記錄功能來診斷環境中所發生的錯誤。
在容器應用程式的概觀頁面上,選取左側導覽中的 [記錄]。
在 [記錄] 頁面上,關閉可開啟並導覽至 [表格] 索引標籤的快顯視窗。
展開 [自訂記錄] 項目以顯示 ContainerAppConsoleLogs_CL 節點。 此表格會保存容器應用程式的各種記錄,而針對問題進行疑難排解時可查詢這些記錄。
在查詢編輯器中,撰寫基本查詢來搜尋 ContainerAppConsoleLogs_CL Logs 表格中是否有最近的例外狀況,例如下列指令碼:
ContainerAppConsoleLogs_CL | where Log_s contains "exception" | sort by TimeGenerated desc | limit 500 | project ContainerAppName_s, Log_s
上述查詢會搜尋 ContainerAppConsoleLogs_CL 表格中是否有包含字組例外狀況的任何資料列。 結果會依產生的時間進行排序,並限制為 500 個結果,而且只包括 ContainerAppName_s 和 Log_s 資料行,讓結果更容易讀取。
選取 [執行],隨即顯示結果清單。 閱讀記錄,並注意其中大部分都與防偽權杖和密碼編譯有關。
重要
應用程式中的錯誤是 .NET 資料保護服務所造成。 應用程式有多個執行個體正在執行時,不保證會將提交表單的 HTTP POST 要求路由傳送至最初從 HTTP GET 要求載入頁面的相同容器。 如果是由不同的執行個體處理要求,則不會正確地處理防偽權杖,而且會發生例外狀況。
在後續步驟中,此問題的解決方式是集中 Azure 儲存體服務中的資料保護金鑰並透過 Key Vault 進行保護。
建立 Azure 服務
為了解決上述錯誤,會建立下列服務,並將其連線至應用程式:
- Azure 儲存體帳戶:處理資料保護服務的資料儲存。 提供集中式位置,以在應用程式調整時儲存金鑰資料。 儲存體帳戶也可以用來保存文件、佇列資料、檔案共用,以及幾乎任何類型的 Blob 資料。
- Azure KeyVault:此服務會儲存應用程式的祕密,並用來協助管理資料保護服務的加密疑慮。
建立儲存體帳戶服務
- 在 Azure 入口網站搜尋列中,輸入
Storage accounts
,然後選取相符的結果。 - 在儲存體帳戶清單頁面上,選取 [+建立]。
- 在 [基本] 索引標籤上,輸入下列值:
- 訂用帳戶:選取您為容器應用程式所選擇的相同訂用帳戶。
- 資源群組:選取您先前所建立的 msdocs-scalable-razor 資源群組。
- 儲存體帳戶名稱:將帳戶命名為 scalablerazorstorageXXXX,其中 X 是您選擇的亂數。 在所有 Azure 中,此名稱必須是唯一的。
- 區域:選取您先前所選取的相同區域。
- 保留其餘值的預設值,然後選取 [檢閱]。 在 Azure 驗證輸入之後,請選取 [建立]。
Azure 會佈建新的儲存體帳戶。 工作完成時,請選擇 [移至資源] 以檢視新的服務。
建立儲存體容器
建立容器來儲存應用程式的資料保護金鑰。
- 在新儲存體帳戶的概觀頁面上,選取左側導覽上的 [儲存體瀏覽器]。
- 選取 [Blob 容器]。
- 選取 [+ 新增容器],以開啟 [新增容器] 飛出功能表。
- 輸入名稱 scalablerazorkeys,並保留其餘設定的預設值,然後選取 [建立]。
新的容器會出現在頁面清單上。
建立金鑰保存庫服務
建立金鑰保存庫,以保存可保護 Blob 儲存體容器中資料的金鑰。
- 在 Azure 入口網站搜尋列中,輸入
Key Vault
,然後選取相符的結果。 - 在金鑰保存庫清單頁面上,選取 [+ 建立]。
- 在 [基本] 索引標籤上,輸入下列值:
- 訂用帳戶:選取先前所選取的相同訂用帳戶。
- 資源群組:選取先前所建立的 msdocs-scalable-razor 資源群組。
- 金鑰保存庫名稱:輸入名稱 scalablerazorvaultXXXX。
- 區域:選取靠近您所在位置的區域。
- 保留其餘設定的預設值,然後選取 [檢閱 + 建立]。 等待 Azure 驗證您的設定,然後選取 [建立]。
Azure 會佈建新的金鑰保存庫。 工作完成時,請選取 [移至資源] 以檢視新的服務。
建立金鑰
建立祕密金鑰來保護 Blob 儲存體帳戶中的資料。
- 在金鑰保存庫的主要概觀頁面上,從左側導覽中選取 [金鑰]。
- 在 [建立金鑰] 頁面上,選取 [+ 產生/匯入] 以開啟 [建立金鑰] 飛出功能表。
- 在 [名稱] 欄位中,輸入 razorkey。 保留其餘設定的預設值,然後選取 [建立]。 新的金鑰會出現在金鑰清單頁面上。
連線 Azure 服務
容器應用程式需要與儲存體帳戶和金鑰保存庫服務的安全連線,才能解決資料保護錯誤以及正確進行調整。 新的服務會使用下列步驟連線在一起:
重要
透過服務連接器和其他工具的安全性角色指派通常需要一或兩分鐘的時間進行傳播,而在一些罕見情況下,最多可能需要八分鐘的時間。
連線儲存體帳戶
- 在 Azure 入口網站中,導覽至 [容器應用程式概觀] 頁面。
- 在左側導覽上,選取 [服務連接器]
- 在 [服務連接器] 頁面上,選擇 [+ 建立] 以開啟 [建立連線] 飛出面板,然後輸入下列值:
- 容器:選取先前所建立的容器應用程式。
- 服務類型:選擇 [儲存體 - blob]。
- 訂用帳戶:選取先前使用的訂用帳戶。
- 連線名稱:保留預設值。
- 儲存體帳戶:選取先前所建立的儲存體帳戶。
- 用戶端類型:選取 [.NET]。
- 選取 [下一步: 驗證],以繼續進行下一個步驟。
- 選取 [系統指派的受控身分識別],然後選擇 [下一步: 網路]。
- 保留選取的預設網路選項,然後選取 [檢閱 + 建立]。
- 在 Azure 驗證設定之後,選取 [建立]。
服務連接器會在容器應用程式上啟用系統指派的受控身分識別。 其也會將 [儲存體 Blob 資料參與者] 的角色指派給身分識別,讓它可以在儲存體容器上執行資料作業。
連線金鑰保存庫
- 在 Azure 入口網站中,導覽至您的 [容器應用程式概觀] 頁面。
- 在左側導覽上,選取 [服務連接器]。
- 在 [服務連接器] 頁面上,選擇 [+ 建立] 以開啟 [建立連線] 飛出面板,然後輸入下列值:
- 容器:選取先前所建立的容器應用程式。
- 服務類型:選擇 [金鑰保存庫]。
- 訂用帳戶:選取先前使用的訂用帳戶。
- 連線名稱:保留預設值。
- 金鑰保存庫:選取先前所建立的金鑰保存庫。
- 用戶端類型:選取 [.NET]。
- 選取 [下一步: 驗證],以繼續進行下一個步驟。
- 選取 [系統指派的受控身分識別],然後選擇 [下一步: 網路]。
- 保留選取的預設網路選項,然後選取 [檢閱 + 建立]。
- 在 Azure 驗證設定之後,選取 [建立]。
服務連接器會將角色指派給身分識別,以在金鑰保存庫金鑰上執行資料作業。
設定和重新部署應用程式
已建立必要的 Azure 資源。 在本節中,應用程式程式碼設定為使用新的資源。
安裝下列 NuGet 套件:
- Azure.Identity:提供類別以使用 Azure 身分識別與存取管理服務。
- Microsoft.Extensions.Azure:提供有用的擴充方法來執行核心 Azure 設定。
- Azure.Extensions.AspNetCore.DataProtection.Blobs:允許在 Azure Blob 儲存體中儲存 ASP.NET Core DataProtection 金鑰,以在 Web 應用程式的數個執行個體之間共用金鑰。
- Azure.Extensions.AspNetCore.DataProtection.Keys:使用 Azure Key Vault 金鑰加密/包裝功能來啟用保護待用金鑰。
dotnet add package Azure.Identity dotnet add package Microsoft.Extensions.Azure dotnet add package Azure.Extensions.AspNetCore.DataProtection.Blobs dotnet add package Azure.Extensions.AspNetCore.DataProtection.Keys
使用下列醒目提示的程式碼更新
Program.cs
:using Azure.Identity; using Microsoft.AspNetCore.DataProtection; using Microsoft.Extensions.Azure; var builder = WebApplication.CreateBuilder(args); var BlobStorageUri = builder.Configuration["AzureURIs:BlobStorage"]; var KeyVaultURI = builder.Configuration["AzureURIs:KeyVault"]; builder.Services.AddRazorPages(); builder.Services.AddHttpClient(); builder.Services.AddServerSideBlazor(); builder.Services.AddAzureClientsCore(); builder.Services.AddDataProtection() .PersistKeysToAzureBlobStorage(new Uri(BlobStorageUri), new DefaultAzureCredential()) .ProtectKeysWithAzureKeyVault(new Uri(KeyVaultURI), new DefaultAzureCredential()); var app = builder.Build(); if (!app.Environment.IsDevelopment()) { app.UseExceptionHandler("/Error"); app.UseHsts(); } app.UseHttpsRedirection(); app.UseStaticFiles(); app.UseRouting(); app.UseAuthorization(); app.MapRazorPages(); app.Run();
上述變更可讓應用程式使用集中式且可調整的架構來管理資料保護。 DefaultAzureCredential
會探索稍早在重新部署應用程式時所啟用的受控身分識別設定。
更新 appsettings.json
檔案 AzureURIs
區段中的預留位置,以包包括下列項目:
將
<storage-account-name>
預留位置取代為scalablerazorstorageXXXX
儲存體帳戶的名稱。將
<container-name>
預留位置取代為scalablerazorkeys
儲存體容器的名稱。將
<key-vault-name>
預留位置取代為scalablerazorvaultXXXX
金鑰保存庫的名稱。將金鑰保存庫 URI 中的
<key-name>
預留位置取代為先前所建立的razorkey
名稱。{ "GitHubURL": "https://api.github.com", "Logging": { "LogLevel": { "Default": "Information", "Microsoft.AspNetCore": "Warning" } }, "AllowedHosts": "*", "AzureURIs": { "BlobStorage": "https://<storage-account-name>.blob.core.windows.net/<container-name>/keys.xml", "KeyVault": "https://<key-vault-name>.vault.azure.net/keys/<key-name>/" } }
重新部署應用程式
應用程式現在已正確地設定為使用先前所建立的 Azure 服務。 重新部署要套用程式碼變更的應用程式。
- 以滑鼠右鍵按一下方案總管中的專案節點,然後選取 [發佈]。
- 在發佈設定檔摘要檢視上,選取右上角的 [發佈] 按鈕。
Visual Studio 會將應用程式重新部署至先前所建立的容器應用程式環境。 處理序完成時,瀏覽器會啟動至應用程式首頁。
在搜尋欄位中搜尋 Microsoft,以再次測試應用程式。 頁面現在應該會在每次您提交時重新載入正確的結果。
設定本機開發的角色
應用程式的現有程式碼和設定也可以在開發期間於本機執行時運作。 先前設定的 DefaultAzureCredential
類別能夠挑選本機環境認證來向 Azure 服務進行驗證。 您需要將相同的角色指派給已指派給應用程式受控身分識別的您自己的帳戶,才能讓驗證運作。 這應該是您用來登入 Visual Studio 或 Azure CLI 的相同帳戶。
登入您的本機開發環境
您需要登入 Azure CLI、Visual Studio 或 Azure PowerShell,DefaultAzureCredential
才能挑選到您的認證。
az login
將角色指派給開發人員帳戶
- 在 Azure 入口網站中,導覽至先前建立的
scalablerazor****
儲存體帳戶。 - 從左側導覽中,選取 [存取控制 (IAM)]。
- 選擇 [+ 新增],然後從下拉式功能表中選擇 [新增角色指派]。
- 在 [新增角色指派] 頁面上,搜尋
Storage blob data contributor
,並選取相符的結果,然後選取 [下一步]。 - 請確定已選取 [使用者、群組或服務主體],然後選取 [+ 選取成員]。
- 在 [選取成員] 飛出視窗中,搜尋您自己的 user@domain 帳戶,然後從結果中予以選取。
- 選擇 [下一步],然後選取 [檢閱 + 指派]。 在 Azure 驗證設定之後,請再次選取 [檢閱 + 指派]。
如先前所述,角色指派權限可能需要一或兩分鐘的時間進行傳播,或在罕見情況下,最多需要八分鐘的時間。
重複上述步驟,以將角色指派給您的帳戶,使其可以存取金鑰保存庫服務和祕密。
- 在 Azure 入口網站中,導覽至先前建立的
razorscalingkeys
金鑰保存庫。 - 從左側導覽中,選取 [存取控制 (IAM)]。
- 選擇 [+ 新增],然後從下拉式功能表中選擇 [新增角色指派]。
- 在 [新增角色指派] 頁面上,搜尋
Key Vault Crypto Service Encryption User
,並選取相符的結果,然後選取 [下一步]。 - 請確定已選取 [使用者、群組或服務主體],然後選取 [+ 選取成員]。
- 在 [選取成員] 飛出視窗中,搜尋您自己的 user@domain 帳戶,然後從結果中予以選取。
- 選擇 [下一步],然後選取 [檢閱 + 指派]。 在 Azure 驗證您的設定之後,請再次選取 [檢閱 + 指派]。
您可能需要再次等待傳播此角色指派。
然後,您可以返回 Visual Studio,並在本機執行應用程式。 程式碼應該會繼續如預期般運作。 DefaultAzureCredential
會使用來自 Visual Studio 或 Azure CLI 的現有認證。
可靠的 Web 應用程式模式
請參閱 The Reliable Web App Pattern for.NETYouTube 影片和文章,以取得從頭建立新式、可靠、效能強、可測試、具成本效益及可調整的 ASP.NET Core 應用程式或重構現有應用程式的指導。
意見反應
https://aka.ms/ContentUserFeedback。
即將登場:在 2024 年,我們將逐步淘汰 GitHub 問題作為內容的意見反應機制,並將它取代為新的意見反應系統。 如需詳細資訊,請參閱:提交並檢視相關的意見反應