.NET Aspire 集成 Azure App Service 实战:环境建模、Web App 发布与基础设施编排
2026/9/17 16:30:04 网站建设 项目流程

.NET Aspire 集成 Azure App Service 实战:环境建模、Web App 发布与基础设施编排

【免费下载链接】aspireAspire is the tool for code-first, extensible, observable dev and deploy.项目地址: https://gitcode.com/GitHub_Trending/as/aspire

本文围绕开源仓库中 Aspire.Hosting.Azure.AppService 集成文档 展开,系统讲解如何在 .NET Aspire 方案(AppHost)中为计算资源建模、配置并编排 Azure App Service:从安装集成、编写 AppHost 代码,到 App Service 的部署约束、虚拟网络集成、Application Insights 与 App Service Plan 的自定义。读完本文,你将掌握AddAzureAppServiceEnvironmentPublishAsAzureAppServiceWebsite的完整用法,并理解底层基础设施的生成逻辑与校验机制,能够直接在自己的 Aspire 方案中落地 Azure App Service 发布。

集成概览:在 Aspire 中编排 Azure App Service

Aspire.Hosting.Azure.AppService是一个 Aspire Hosting 集成,用于在 Aspire 方案中对 Azure App Service 进行建模、配置与编排,让应用的计算资源(如项目、容器)可以发布为 Azure App Service Web App。它的核心价值在于:

  • 以声明式代码(AppHost 中的 C#)描述"我要一个 App Service 环境 + 若干 Web App",而不是手写 Bicep 模板;
  • 由 Aspire 自动生成配套的 Azure 基础设施(App Service Plan、容器注册中心、托管标识、可选 Dashboard 与 Application Insights);
  • 与 Aspire 的部署流水线(pipeline)深度集成,负责镜像推送、基础设施预配、部署与结果汇总。

该集成源码位于 src/Aspire.Hosting.Azure.AppService,核心公开 API 可查看 api/Aspire.Hosting.Azure.AppService.cs。

入门:前置条件与安装集成

前置条件

  • 一个Azure 订阅,并且对目标订阅拥有Owner 权限(用于角色分配,例如 ACR Pull 角色、Website Contributor 角色等,这些角色由 Aspire 在预配过程中自动创建)。

安装集成

在 AppHost 目录下使用 Aspire CLI 添加集成:

aspire add Aspire.Hosting.Azure.AppService

该命令会把集成包引用写入 AppHost 项目,之后即可在Program.cs中使用相关扩展方法。

快速上手:一个完整的使用示例

在 AppHost 中,先添加一个Azure App Service 环境AzureAppServiceEnvironment),再把计算资源发布为 Web App:

var builder = DistributedApplication.CreateBuilder(args); var appServiceEnvironment = builder.AddAzureAppServiceEnvironment("env"); builder.AddProject<Projects.MyWebApp>("webapp") .WithExternalHttpEndpoints() .PublishAsAzureAppServiceWebsite((infrastructure, website) => { // Customize the App Service health check path and appsettings website.SiteConfig.HealthCheckPath = "/health"; website.SiteConfig.AppSettings.Add(new AppServiceNameValuePair() { Name = "Environment", Value = "Production" }); });

说明:

  • AddAzureAppServiceEnvironment("env")创建环境资源(详见下文"环境资源与默认基础设施");
  • WithExternalHttpEndpoints()声明外部 HTTP 端点——这是 App Service 的硬性要求;
  • PublishAsAzureAppServiceWebsiteconfigure回调接收AzureResourceInfrastructureWebSite(Azure Provisioning SDK 类型),可在其中直接修改 Web App 的站点配置,如健康检查路径、应用设置等。

从源码看,PublishAsAzureAppServiceWebsite(AzureAppServiceComputeResourceExtensions.cs)支持两个可选回调:configure(定制WebSite)与configureSlot(定制部署槽WebSiteSlot),并且仅在发布模式(IsPublishMode)下生效,本地运行(run 模式)时调用它不会产生副作用。

Azure App Service 约束:部署前必须了解

把资源发布到 Azure App Service 时,以下约束由平台决定,Aspire 会在代码生成阶段强制校验:

  • 仅支持外部端点(External endpoints only):App Service 只支持外部端点,所有端点必须通过WithExternalHttpEndpoints()配置。
  • 仅支持 HTTP/HTTPS:其他协议(如 gRPC、TCP)不被支持。源码 AzureAppServiceWebsiteContext.cs 中,若解析到的端点UriScheme不是httphttps,会抛出NotSupportedException
  • 单一端点(Single endpoint):App Service 只支持一个目标端口。带不同目标端口的多个外部端点不被支持。默认目标端口为8000,可通过WithHttpEndpoint扩展方法覆盖:
builder.AddProject<Projects.Api>("api") .WithHttpEndpoint(targetPort: 8080)

在 AzureAppServiceWebsiteContext.cs 中,Aspire 会收集所有外部端点的目标端口并去重,若出现多于一个不同端口,直接抛出"App Service does not support resources with multiple external endpoints"异常。此外,非外部端点也会被拒绝("App Service only supports external endpoints")。

将计算资源发布为 Azure App Service Web App

PublishAsAzureAppServiceWebsite扩展方法把计算资源配置为"部署到 Azure 时发布为 App Service Web App"。该方法允许你通过Azure Provisioning SDK自由定制 Web App 的配置。

更完整的定制示例

builder.AddProject<Projects.Api>("api") .WithHttpEndpoint(targetPort: 8080) .WithExternalHttpEndpoints() .WithHealthProbe(ProbeType.Liveness, "/health") .WithArgs("--environment", "Production") .PublishAsAzureAppServiceWebsite((infrastructure, website) => { // Customize the App Service Web App appsettings website.SiteConfig.IsWebSocketsEnabled = true; website.SiteConfig.MinTlsVersion = SupportedTlsVersions.Tls1_2; });

这个示例展示了几个在 App Service 场景下常用的链式调用:

  • WithHttpEndpoint(targetPort: 8080):覆盖默认目标端口(默认 8000);
  • WithHealthProbe(ProbeType.Liveness, "/health"):声明存活探针。从源码看,AzureAppServiceWebsiteContext.cs 会把探针注解转换为SiteConfig.HealthCheckPath,且由于 App Service 只允许一个健康检查路径,Aspire 会优先选择 Liveness 探针(否则取第一个);
  • WithArgs("--environment", "Production"):命令行参数。App Service 不支持数组形式的启动参数,AzureAppServiceWebsiteContext.cs 会把参数 join 成单个字符串,写入主容器的StartUpCommand
  • 回调内通过website.SiteConfig直接修改IsWebSocketsEnabledMinTlsVersion等站点级设置。

关于环境变量:连字符校验与跳过

Azure App Service 在运行时会移除环境变量名中的-(连字符),这会导致连接字符串等含连字符名称的配置键被改写,从而让 Aspire 客户端集成找不到预期的连接字符串。因此,Aspire 在发布流水线中默认执行校验:任何名称含-的环境变量都会使发布失败,并给出可读的错误提示(包括"受影响设置"清单与修复建议)。

对应的校验逻辑位于 AzureAppServiceEnvironmentResource.cs,其给出两种修复方式:

  1. 在 AppHost 中为引用使用不含连字符的连接名称,例如WithReference(resource, connectionName: "mydb")
  2. 对确实需要保留连字符名称的资源,调用SkipEnvironmentVariableNameChecks()跳过校验:
builder.AddProject<Projects.Api>("api") .WithExternalHttpEndpoints() .PublishAsAzureAppServiceWebsite(configure: (_, _) => { }) .SkipEnvironmentVariableNameChecks();

从源码看,SkipEnvironmentVariableNameChecks(AzureAppServiceComputeResourceExtensions.cs)要求必须先调用PublishAsAzureAppServiceWebsite,否则抛出InvalidOperationException。测试 tests/Aspire.Hosting.Azure.Tests/AzureAppServiceTests.cs 中同时覆盖了"含连字符连接名导致校验失败"与"调用SkipEnvironmentVariableNameChecks后校验通过"两条路径。

环境资源与默认基础设施

AddAzureAppServiceEnvironment创建的 App Service 环境资源会生成托管应用所需的底层基础设施,包括:

  • 一个Azure App Service Plan(默认 SKU:P0v3,Premium 层级);
  • 一个Azure Container Registry(ACR),用于存放容器镜像;
  • 一个用于访问容器注册中心的托管标识(managed identity)
  • 可选的Aspire Dashboard(默认启用),以 App Service Web App 形式部署;
  • 可选的Application Insights,用于监控与遥测。
var appServiceEnvironment = builder.AddAzureAppServiceEnvironment("env");

从源码看,AzureAppServiceEnvironmentExtensions.cs 的实现细节包括:

  • 自动创建名为{name}-acr的默认 ACR;
  • 创建UserAssignedIdentity{prefix}_mi)并为其在 ACR 上分配AcrPull角色,供 Web App 拉取镜像;
  • 创建AppServicePlanP0V3/Premium/Linux,并启用IsPerSiteScaling,使每个 Web App 可以独立伸缩(这也是后续NumberOfWorkers被设为 30 的原因,见 AzureAppServiceWebsiteContext.cs);
  • 通过 Provisioning Output 暴露环境级引用,如AZURE_CONTAINER_REGISTRY_ENDPOINTAZURE_CONTAINER_REGISTRY_MANAGED_IDENTITY_ID等,供每个 Web App 模块消费。

关闭默认的 Aspire Dashboard

默认情况下,Aspire Dashboard 会包含在 App Service 环境中。使用WithDashboard扩展方法可以关闭它:

var appServiceEnvironment = builder.AddAzureAppServiceEnvironment("env") .WithDashboard(enable: false);

Dashboard 被部署为kind = "app,linux,aspiredashboard"的 Web App,使用ASPIREDASHBOARD|1.0的 Linux 运行时(见 AzureAppServiceEnvironmentUtility.cs)。它同时承担两个职责:其一,复用环境的用户托管标识从 ACR 拉取自身镜像;其二,作为 OTLP 遥测的接收端——每个 Web App 都会通过WEBSITE_ENABLE_ASPIRE_OTEL_SIDECAROTEL_EXPORTER_OTLP_ENDPOINT(指向本地 6001 端口的 OTLP sidecar)与OTEL_EXPORTER_OTLP_CLIENT_ID等应用设置把遥测发送到 Dashboard(见 AzureAppServiceWebsiteContext.cs)。

配置区域虚拟网络集成(Regional VNet Integration)

要让环境中的 Web App 使用区域虚拟网络集成,需要先添加Aspire.Hosting.Azure.Network集成:

aspire add Aspire.Hosting.Azure.Network

然后创建虚拟网络与子网,并将其委托给环境:

#pragma warning disable ASPIREAZURE003 // Azure Virtual Network APIs are experimental. var vnet = builder.AddAzureVirtualNetwork("vnet"); var subnet = vnet.AddSubnet("app-service-subnet", "10.0.0.0/24"); var appServiceEnvironment = builder.AddAzureAppServiceEnvironment("env") .WithDelegatedSubnet(subnet); #pragma warning restore ASPIREAZURE003

TypeScript(Polyglot AppHost)版本

const vnet = await builder.addAzureVirtualNetwork("vnet"); const subnet = await vnet.addSubnet("app-service-subnet", "10.0.0.0/24"); const appServiceEnvironment = await builder.addAzureAppServiceEnvironment("env") .withDelegatedSubnet(subnet);

要点:

  • WithDelegatedSubnet会把子网委托给Microsoft.Web/serverFarms,并让环境中生成的每一个 Web App、部署槽(deployment slot)以及默认的 Aspire Dashboard 都使用该子网进行区域虚拟网络集成;
  • 子网必须满足 Azure App Service 区域虚拟网络集成的要求(地址空间、大小等,参见 Aspire.Hosting.Azure.Network 集成文档);
  • 区域虚拟网络集成只影响出站流量:它不会让 Web App 或 Dashboard 的入站访问变成私有,也不会启用 Route All。如果需要私有入站、访问限制或 Route All,需要另行配置私有端点(private endpoints)或访问限制(access restrictions)。

从实现上看,环境资源实现了IAzureDelegatedSubnetResource接口,其委托服务名正是Microsoft.Web/serverFarms(见 AzureAppServiceEnvironmentResource.cs),生成的每个站点会把子网 ID 写入VirtualNetworkSubnetId。相关测试见 tests/Aspire.Hosting.Azure.Tests/AzureAppServiceTests.cs(覆盖有无部署槽两种场景)以及AddAppServiceWithDelegatedSubnet系列用例。

启用 Application Insights

使用WithAzureApplicationInsights扩展方法可为 App Service 环境启用 Application Insights。可选地,通过 location 参数为 Application Insights 指定不同的位置:

var appServiceEnvironment = builder.AddAzureAppServiceEnvironment("env") .WithAzureApplicationInsights();

从源码看,AzureAppServiceEnvironmentExtensions.cs 提供了多个重载,实际使用时可灵活选用:

重载形式说明
WithAzureApplicationInsights()使用默认位置(资源组位置),Aspire 自动创建 Log Analytics 工作区(PerGB2018SKU)+ Application Insights 组件
WithAzureApplicationInsights(string location)指定 Application Insights 的位置字符串
WithAzureApplicationInsights(IResourceBuilder<ParameterResource> location)通过参数资源指定位置
WithAzureApplicationInsights(IResourceBuilder<AzureApplicationInsightsResource> insights)复用已存在的 Application Insights 资源

启用后,每个生成的 Web App(及部署槽)会自动追加APPINSIGHTS_INSTRUMENTATIONKEYAPPLICATIONINSIGHTS_CONNECTION_STRINGApplicationInsightsAgent_EXTENSION_VERSION~3)等应用设置(见 AzureAppServiceWebsiteContext.cs)。

自定义 App Service Plan(SKU 与层级)

App Service Plan 可以使用ConfigureInfrastructure扩展方法进行自定义。默认 SKU 为P0V3(Premium),可通过以下方式修改:

var appServiceEnvironment = builder.AddAzureAppServiceEnvironment("env") .ConfigureInfrastructure((infra) => { var plan = infra.GetProvisionableResources().OfType<AppServicePlan>().Single(); plan.Sku = new AppServiceSkuDescription { Name = "P2V3", Tier = "Premium" }; });

要点:

  • infra.GetProvisionableResources()返回环境中所有待预配的 Azure 资源,从中筛选出唯一的AppServicePlan实例;
  • 通过plan.Sku可以修改 SKU 名称与层级(例如从 P0V3 升到 P2V3);同时KindLinux)、IsReservedIsPerSiteScaling等属性也在此处管理(见 AzureAppServiceEnvironmentExtensions.cs)。

注意:计划启用IsPerSiteScaling后,各 Web App 的NumberOfWorkers被设置为 Premium 系列允许的最大值(30),以保证 Web App 可以按计划自身定义正常伸缩。

部署流水线:从代码到 Azure 的关键步骤

理解 Aspire 如何"编排"App Service 发布,有助于排查部署问题。从 AzureAppServiceEnvironmentResource.cs 与 AzureAppServiceWebSiteResource.cs 可以看到流水线的核心步骤:

  1. prepare-azure-app-service-{name}:为环境中的每个计算资源物化"部署目标"(DeploymentTargetAnnotation),即把ProjectResource或带 Dockerfile 的容器资源转换为AzureAppServiceWebSiteResource,并注入环境上下文;
  2. validate-appservice-config-{name}:在发布前校验配置,重点是环境变量名校验(连字符问题),错误会通过活动报告器(activity reporter)以CompletedWithError状态呈现;
  3. deploy-{resource}:聚合步骤,保证"推送容器镜像(PushContainerImage)→ 预配基础设施(ProvisionInfrastructure)→ 部署"的依赖顺序;
  4. print-{resource}-summary:输出部署结果,包括最终 URL(https://{website-name}.azurewebsites.net)与 Azure 门户链接;
  5. print-dashboard-url-{name}:若启用了 Dashboard,输出 Dashboard 地址。

此外,环境默认会把 HTTP 端点自动升级为 HTTPS(这也是为什么 App Service 平台本身会强制 HTTP→HTTPS 重定向,禁用升级主要影响的是为下游依赖生成的连接字符串中的 scheme 与端口)。如需保留 HTTP 端点,可在环境上使用WithHttpsUpgrade(false)

var appService = builder.AddAzureAppServiceEnvironment("appservice") .WithHttpsUpgrade(false);

升级行为与端口映射的底层逻辑见 AzureAppServiceEnvironmentResource.cs:升级后 URL 使用https与端口 443;保留 HTTP 时使用http与端口 80。

更多进阶能力

除本文覆盖的内容外,该集成还提供了以下能力(详见 AzureAppServiceEnvironmentExtensions.cs):

  • WithDeploymentSlot:为环境中所有 App Service 指定部署槽(deployment slot),支持字符串或参数资源两种形式。配置槽后,Aspire 会同时生成主站点(带@onlyIfNotExists()保护)与槽资源,并把端点引用、OTEL_SERVICE_NAME等设置为粘性槽设置(sticky slot settings),避免槽交换时配置被覆盖;
  • WithAcrPullIdentity:复用已有的用户分配托管标识作为 ACR Pull 标识(需自行保证该标识已具备 ACR 的AcrPull角色),适用于向预先预配好的 App Service Plan + ACR 部署的场景,避免 Aspire 额外生成新的标识与角色分配资源。

测试验证:集成行为有据可查

该集成的行为在 tests/Aspire.Hosting.Azure.Tests/AzureAppServiceTests.cs 中有大量测试覆盖,可作为理解与排错时的参考:

  • AddAppServiceWithDelegatedSubnet/AddAppServiceWithDelegatedSubnetWithoutDeploymentSlot:验证子网委托与生成的 Bicep;
  • PublishAsAzureAppServiceWebsite_CanOverrideEnvironmentDelegatedSubnet:验证 Web App 级别可覆盖环境的子网配置;
  • PublishToAppService_WithDashedConnectionStringName_FailsValidationInPipeline/_CanBeIgnored:验证连字符环境变量名校验及跳过机制;
  • KeyvaultReferenceHandling:验证环境变量中 Key Vault 密钥引用会被转换为@Microsoft.KeyVault(...)形式的 App Service 应用设置;
  • EndpointReferencesAreResolvedAcrossProjects:验证跨项目端点引用在 App Service 环境中的解析;
  • AddDockerfileWithAppServiceInfrastructureAddsDeploymentTargetWithAppServiceToContainerResources:验证带 Dockerfile 的容器资源同样支持发布为 Web App。

总结

Aspire.Hosting.Azure.AppService让开发者用纯代码方式完成 Azure App Service 的建模与发布:一条AddAzureAppServiceEnvironment声明环境,一条PublishAsAzureAppServiceWebsite把项目或容器发布为 Web App,其余的基础设施生成、镜像推送、配置注入、校验与部署汇总都由 Aspire 接管。需要进一步探索源码时,可重点阅读:

  • AzureAppServiceComputeResourceExtensions.cs:PublishAsAzureAppServiceWebsiteSkipEnvironmentVariableNameChecks的公开 API;
  • AzureAppServiceEnvironmentExtensions.cs:AddAzureAppServiceEnvironment及全部配置扩展方法;
  • AzureAppServiceEnvironmentResource.cs:环境资源模型、校验与流水线步骤;
  • AzureAppServiceWebsiteContext.cs:单个 Web App 的端点、环境变量、参数、探针与遥测配置生成逻辑。

【免费下载链接】aspireAspire is the tool for code-first, extensible, observable dev and deploy.项目地址: https://gitcode.com/GitHub_Trending/as/aspire

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询