资讯动态

在 Linux Azure App Service 上部署 Orleans 集群:Bicep 基础设施、托管标识与槽位滚动发布实战

发布时间:2026/9/24 7:56:00 来源:尧图企业网站定制
后端微服务【免费下载链接】orleansCloud Native application framework for .NET项目地址https://gitcode.com/gh_mirrors/or/orleans点击查看免费下载本指南基于 Orleans 官方仓库的 AzureAppService 示例 与 部署文档完整讲解如何将 Orleans 购物车示例部署到 Linux 版 Azure App Service 的内置 .NET 栈上。你将掌握利用WEBSITE_PRIVATE_IP/WEBSITE_PRIVATE_PORTS动态发现并广播 Silo 私有端点、通过 Bicep 一次性交付虚拟网络、表存储、托管标识与槽位资源以及结合 App Service Authentication、健康检查和槽位交换实现安全的生产发布流程。阅读前建议先通读共享的 Azure App Service 目标总览本教程与 Windows 版指南 共享应用、存储、身份、网络、健康与 OIDC 设计但在 Linux 计划、运行时、启动方式与 Easy Auth 行为上做了独立验证。理解 Linux 拓扑一个 Worker 进程 一个托管应用 一个 SiloLinux 部署的拓扑与 Windows 保持一致在专用的多实例 Premium v3 计划上每个 Worker 内共同托管cohost一个 ASP.NET Core 应用进程与一个 Orleans Silo集群通过 Azure Table Storage 共享成员资格与持久化 Grain 状态。Bicep 入口 infra/linux/main.bicep 委托共享模块infra/flex/main.bicep并传入operatingSystem: linux最终创建一个kind: linux、reserved: true的 Premium v3 Linux 计划P1v3SKUcapacity默认 3见 app-service.bicep一个 Linux Web 应用与一个暂存staging槽位linuxFxVersion: DOTNETCORE|10.0三个 Worker每个同时承载 ASP.NET Core 与 Orleans Silo生产与暂存两套独立的虚拟网络集成子网由托管标识managed identity授权的 Azure Table Storage 集群与持久化状态App Service Authentication、Application Insights、Log Analytics、健康检查与预热warm-up设置。私有端点发现App Service 的前端无法路由 Silo 间连接App Service 的 HTTP 前端只能处理 Web 流量无法路由 Orleans Silo 之间的 TCP 连接。因此每个 Worker 在启动时必须自己发现平台为其分配的私有地址与端口读取WEBSITE_PRIVATE_IP和逗号分隔的WEBSITE_PRIVATE_PORTS中的第一个值将其作为本实例的动态 Silo 端点对外广播同时使用只读的WEBSITE_INSTANCE_ID作为 Orleans 的 Silo 名称便于在诊断与日志中关联具体实例。示例的生产环境配置逻辑见 Silo/Program.csvar privateIp IPAddress.Parse(GetRequiredSetting(builder, WEBSITE_PRIVATE_IP)); var privatePorts GetRequiredSetting(builder, WEBSITE_PRIVATE_PORTS) .Split(,, StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries); if (privatePorts.Length 1 || !int.TryParse(privatePorts[0], NumberStyles.None, CultureInfo.InvariantCulture, out var siloPort)) { throw new InvalidOperationException( WEBSITE_PRIVATE_PORTS must contain at least one TCP port.); } builder.UseOrleans(siloBuilder { siloBuilder .ConfigureSiloOptions(options { options.SiloName builder.Configuration[WEBSITE_INSTANCE_ID] ?? Environment.MachineName; }) .ConfigureEndpoints( privateIp, siloPort, gatewayPort: 0, listenOnAnyHostAddress: true) ... });官方文档片段 DeploymentSnippets.cs 给出了同样的端点配置方式siloBuilder.ConfigureEndpoints( privateIp, siloPort, gatewayPort: 0, listenOnAnyHostAddress: true);这里有两个关键点值得深入理解gatewayPort: 0表示禁用 Orleans 客户端网关。因为 Web 应用直接使用同进程 Silo 的本地客户端不需要对外暴露网关端口。这同时是一个安全决策它阻止了私有 Orleans 客户端绕过 Easy Auth 与ProductAdministrator角色检查直接修改目录数据。Orleans 网关不是面向终端用户的身份认证边界如果确实需要外部 Orleans 客户端应当只为完全受信任的应用客户端启用第二个私有端口并让不可信调用方始终停留在经过认证的 API 之后。listenOnAnyHostAddress: true表示监听所有本地接口。由于平台分配的广播地址并不保证能在本地绑定SilO 需要同时监听所有本地接口仅把平台分配的地址作为对外通告advertised地址。部署前必须完成的验证私有地址与端口是 App Service 的通用设置并非 Windows 专属但微软并未承诺针对 Orleans 的 Linux 映射保证因此部署验证是强制的。建议按以下步骤在目标区域、计划层级与规模上建立生产证据扩展到至少三个 Worker确认每个 Worker 都拿到了独立的WEBSITE_PRIVATE_IP和至少一个WEBSITE_PRIVATE_PORTS值检查 Orleans 成员表确认每个 Silo 广播的正是这些值在所有已广播的 Silo 端点之间测试双向 TCP 连通性在横向扩容、缩容、重启与槽位交换过程中重复上述验证。[!IMPORTANT] 区域级虚拟网络集成regional virtual network integration本质上主要是出站连接能力。不要假设仅启用它就能证明入站私有端口可达。Linux 特定要求运行时刻表、容器化启动与 Easy Auth Sidecar选择支持虚拟网络集成与部署槽位的服务计划必须使用支持虚拟网络集成与部署槽位的专用Standard、Premium 或 Isolated层级。示例使用 Premium v3 与三个 Worker模板参数workerCount的最小值被限制为 3minValue(3)见 linux/main.bicep以保证集群在任何时刻都有足够的存活成员。先查询目标区域的 Linux 内置运行时部署前请查询目标区域的内置 Linux 运行时确认其中包含模板字面量DOTNETCORE|10.0所代表的 .NET 版本az webapp list-runtimes --os linux运行时可用性因云环境与区域而异。如果输出中缺少该 token请将模板中的运行时字面量与项目的目标框架字面量一起更新到受支持的版本示例中使用net10.0可对照 Orleans.ShoppingCart.Silo.csproj 与仓库根目录的 global.json。容器化启动模型ZIP 部署与 OryxLinux 的启动模型基于容器。内置 .NET 栈会直接启动框架依赖framework-dependent的 ZIP 部署产物无需自定义启动命令。模板为 Linux 设置了SCM_DO_BUILD_DURING_DEPLOYMENTfalse见 app-service.bicep这样 Oryx 将直接运行已发布的二进制文件而不是重新还原并编译源码。ZIP 部署会把发布输出解压到区分大小写的/home/site/wwwrootWindows 上为D:\home\site\wwwroot。示例应用不依赖其中任何一个路径也不把持久化状态存放在 App Service 文件系统上——所有耐用状态都进入 Azure Table Storage。Easy Auth Sidecar 与启动相关环境变量Linux 上 App Service AuthenticationEasy Auth以ambassador sidecar形式运行而 Windows 上是进程内模块两种平台注入的认证主体头principal header契约相同。WEBSITE_WARMUP_PATH、WEBSITE_WARMUP_STATUSES、WEBSITE_SWAP_WARMUP_PING_PATH等设置仍然生效——模板中分别配置为/health/ready与200。如果应用启动确实超过了平台限制应在受支持的范围内调整WEBSITES_CONTAINER_START_TIME_LIMIT而不是在 Orleans 尚未启动时就返回就绪状态。前置条件与部署参数开始前准备一个 Azure 订阅以及创建资源和角色分配role assignment的权限global.json 选定的 .NET SDK带 Bicep 支持的 Azure CLI一份dotnet/orleans仓库的克隆一个用于 App Service Authentication 的 Microsoft Entra 应用注册与客户端密钥。设置部署变量注意appName为全局唯一、小写、不超过 16 个字符$location westus3 $resourceGroup orleans-shopping-cart-linux $appName globally-unique-lowercase-name-up-to-16-characters $authenticationTenantId microsoft-entra-tenant-id $authenticationClientId app-registration-client-id $authenticationClientSecret app-registration-client-secret配置认证与授权App Role 与主体头处理器在 App Service Authentication 的应用注册中创建一个ProductAdministrator应用角色将其分配给产品管理员并为生产/暂存添加以/.auth/login/aad/callback结尾的 Web 重定向 URI。商店前台允许匿名流量产品管理在路由层与导航层要求该应用角色并在每次变更 Grain 状态之前再次复核授权。认证处理器只接受 App Service 注入的有界 Entra 主体头自身不校验令牌——因此绝不能让应用暴露在绕过 Easy Auth 的路径上。精确的生产与暂存主机名是 Bicep 的输出值你可以在完成基础设施部署后、用户登录前再添加它们的回调 URI。应用侧的主体头解析实现在 Silo/Authentication/AppServiceAuthenticationHandler.cs读取X-MS-CLIENT-PRINCIPAL头限制最大 16 KiB要求恰好一个值、Base64 解码、JSON 反序列化并且IdentityProvider必须为aadHandleChallengeAsync会把未认证用户重定向到/.auth/login/aad?post_login_redirect_uri...。授权策略在 AuthorizationPolicies.cs 中定义组合了RequireAuthenticatedUser()与RequireRole(ProductAdministrator)。部署 Linux 基础设施Bicep 模板逐层拆解登录并创建资源组后使用 Azure CLI 部署 Linux 入口模板az login az group create --name $resourceGroup --location $location az deployment group create --resource-group $resourceGroup --template-file .\samples\Deployment\AzureAppService\infra\linux\main.bicep --parameters appName$appName location$location authenticationTenantId$authenticationTenantId authenticationClientId$authenticationClientId authenticationClientSecret$authenticationClientSecret入口参数与共享模块linux/main.bicep 只做两件事声明参数appName长度 2–16、serviceId默认ShoppingCartService、workerCount最小 3、assignStorageRoles默认 true、allowSharedKeyAccess默认 falseauthenticationClientSecret标记为secure()然后委托flex/main.bicep。flex/main.bicep创建虚拟网络地址空间172.17.0.0/16192.168.0.0/16default生产子网172.17.0.0/24、staging子网192.168.0.0/24两个子网均委托给Microsoft.Web/serverFarms并启用Microsoft.Storage服务终结点flex/main.bicep存储模块storage.bicep与日志模块logs-and-insights.bicep创建${appName}-logsLog Analytics 与${appName}-insightsApplication Insights应用服务模块app-service.bicep传入生产/暂存子网 ID、Application Insights 连接串与表存储 URI存储角色模块storage-role.bicep条件执行assignStorageRoles。表存储安全网络 ACL、OAuth 与最小角色storage.bicep 创建的StorageV2Standard_LRS账户禁止 Blob 公共访问allowSharedKeyAccess默认关闭defaultToOAuthAuthentication: true强制TLS1_2网络 ACLdefaultAction: Deny且仅放行两个集成子网的虚拟网络规则。也就是说存储网络访问被限制在生产与暂存子网内同时禁用共享密钥授权。角色分配由 storage-role.bicep 完成把应用的用户分配托管标识授予Storage Table Data Contributor角色定义 ID0a9a7e1f-b9d0-4cc4-a60d-0319b160aaa3。运行时的存储访问通过 Program.cs 中的DefaultAzureCredential显式指定ManagedIdentityClientId构建TableServiceClient聚类表名为${clusterId}ClusteringGrain 持久化表名为${clusterId}Persistence——生产与暂存集群因此拥有各自独立的成员表与状态表。槽位粘性设置与首次部署的引导权限模板为每个 Worker 请求 1 个私有 Silo 端口vnetPrivatePortsCount: 1并将AZURE_CLIENT_ID、MICROSOFT_PROVIDER_AUTHENTICATION_SECRET、ORLEANS_CLUSTER_ID声明为**槽位粘性slot-sticky**设置app-service.bicep生产槽位ORLEANS_CLUSTER_IDDefault、暂存槽位Staging两者共享稳定的ShoppingCartService服务 ID。首次部署是**引导bootstrap**操作需要创建资源与受限角色分配的权限。之后的例行部署可以传assignStorageRolesfalse。托管标识的角色分配可能需要几分钟才能传播生效。认证密钥以secure()标记并作为槽位粘性应用设置存储务必在过期前轮换生产加固场景建议改用 Key Vault 引用并为生产与暂存分别注册应用。发布与部署同一框架依赖包先入暂存再交换同一套框架依赖发布包在 Windows 与 Linux 上通用$publish Join-Path $env:TEMP orleans-shopping-cart-linux-publish $package Join-Path $env:TEMP orleans-shopping-cart-linux.zip dotnet publish .\samples\Deployment\AzureAppService\Silo\Orleans.ShoppingCart.Silo.csproj --configuration Release --framework net10.0 --output $publish Compress-Archive -Path $publish\* -DestinationPath $package -Force az webapp deploy --name $appName --resource-group $resourceGroup --slot ${appName}stg --type zip --src-path $package --clean true --restart true等待暂存槽位的输出主机名在/health/ready返回成功可直接用Invoke-WebRequest https://$stagingHost/health/ready检查把两个回调 URL 加入应用注册然后执行槽位交换az webapp deployment slot swap --name $appName --resource-group $resourceGroup --slot ${appName}stg --target-slot production槽位交换期间的集群语义两个槽位都保留稳定的ShoppingCartService服务 IDORLEANS_CLUSTER_ID是槽位粘性的每个集群拥有独立的成员表与持久化表。交换时暂存 Worker 会套用生产设置并在 HTTP 流量切换之前预热加入生产 Orleans 集群。新旧 Silo 会短暂共存因此发布版本必须保持线上协议、序列化器、状态与行为兼容。对于不兼容的发布应部署独立的应用与集群 ID不要切换现有 App Service 计划的 Windows/Linux 属性也不允许不兼容的集群拥有同一份可变状态。使用 GitHub OIDC 实现持续部署复制 infra/deploy.yml并配置一个受保护的production环境要求审阅人、限制部署分支然后按表添加环境变量NameKindValueAUTHENTICATION_CLIENT_IDVariableEasy Auth 应用注册客户端 IDAUTHENTICATION_CLIENT_SECRETSecretEasy Auth 应用注册客户端密钥AUTHENTICATION_TENANT_IDVariable用户认证所在的租户AZURE_APP_NAMEVariable全局唯一应用名AZURE_APP_SERVICE_OSVariablelinuxAZURE_CLIENT_IDVariable联合部署身份客户端 IDAZURE_RESOURCE_GROUP_LOCATIONVariableAzure 区域AZURE_RESOURCE_GROUP_NAMEVariable已有资源组AZURE_SUBSCRIPTION_IDVariable订阅 IDAZURE_TENANT_IDVariableAzure 部署所在的租户工作流要点对照 deploy.yml权限仅申请contents: read与id-token: writeAzure 部署身份使用OIDC而不是存储的 Azure 凭据。Easy Auth 密钥用途独立仅作为安全的 Bicep 参数传入。例行部署身份不需要角色分配权限工作流显式传assignStorageRolesfalse引导部署已用默认assignStorageRolestrue完成过一次角色分配。给该身份授予资源组的 Contributor或更窄的自定义部署角色。流水线顺序部署 Linux 入口模板 → 发布并部署到暂存槽 →curl轮询等待/health/ready--retry 30 --retry-delay 10→ 交换到生产 → 再次验证生产就绪。健康、关闭与可观测性/health/ready只在 .NET 宿主与 Orleans Silo 启动完成后返回成功并在关闭前变为不可用。实现见 Silo/Health/AppServiceLifecycle.csStartedAsync置_isReady trueStoppingAsync置false端点映射在 Program.cs未就绪时返回503。/health/live只检查本地进程避免在共享存储故障时重启所有 Worker。宿主为 Orleans 退出成员资格预留最多30 秒HostOptions.ShutdownTimeout见 Program.cs。Linux App Service 仍可能更早终止容器因此 Grain 调用必须容忍未知结果与 Silo 丢失。Application Insights 收集 ASP.NET Core 请求、依赖、异常、应用与 Orleans 日志运维查询应带上WEBSITE_INSTANCE_ID、集群 ID、槽位与部署元数据。监控项建议就绪 Worker/Silo 数量、成员变更、容器启动与重启、CPU/内存、请求延迟、Orleans 拒绝、存储故障与槽位操作。安全与平台约束模板强制 HTTPS、TLS 1.2、禁用 FTPSftpsState: Disabled存储使用托管标识而不用账户密钥app-service.bicep。Blazor Server 场景保留客户端亲和性clientAffinityEnabled: trueOrleans 不依赖 HTTP 亲和性。HTTPS 在 App Service 前端终结示例的 Orleans 私有 Silo 连接未加密。如果虚拟网络不足以构成信任边界请为 Orleans 启用 TLS。App Service 可能在未给满关闭间隔的情况下替换 Worker请为集成子网预留计划扩容 替换容量至少保留三个 Worker并在负载下验证故障恢复与滚动升级。持久化 Grain 状态应独立于成员数据备份。生产检查清单关注点Linux App Service 的达成标准拓扑与网络每个 Worker 广播其私有实例地址与分配的 Silo 端口且每个 Worker 都能连接到每一个活跃成员端点。依赖与数据Azure Table 聚类与 Grain 状态使用独立的生产数据并具备经过测试的备份与恢复使用提醒reminder与流stream提供程序时须显式配置。身份与密钥运行时存储访问使用托管标识App Service Authentication、例行部署与特权引导凭据相互分离并在过期前轮换。健康与生命周期容器启动、健康检查、槽位预热、就绪移除与有界宿主关闭真实反映应用生命周期。扩展与韧性计划至少保留三个 Worker 与经过测试的备用容量在负载下演练扩容、缩容、Worker 替换、依赖降级与突然丢失。升级与回滚兼容版本使用暂存槽交换并做混合版本验证不兼容版本使用独立应用、集群 ID、状态方案与流量切换。可观测性与事故Application Insights、Log Analytics、Orleans 遥测、Worker 身份、成员资格、提供程序信号、容器事件与槽位操作能够关联。基础设施交付Bicep 与受保护的 GitHub OIDC 工作流可复现基础设施并通过暂存槽部署不可变的应用产物。延伸阅读共享目标总览Azure App Service 上的 OrleansWindows 平台对照版Deploy Orleans to Azure App Service on Windows示例应用完整说明AzureAppService 示例 README通用运维指南生产就绪检查清单、拓扑、网络与集群、健康与可观测性、优雅关闭与升级、选择部署目标赞分享后端微服务【免费下载链接】orleansCloud Native application framework for .NET项目地址https://gitcode.com/gh_mirrors/or/orleans点击查看免费下载相关推荐Orleans 集群部署到 Azure App Service基于私有实例端点的 Windows/Linux 完整实战指南Orleans 集群部署到 Azure App Service基于私有实例端点的 Windows/Linux 完整实战指南 Azure App Service后端微服务.NET Aspire 集成 Azure App Service 实战环境建模、Web App 发布与基础设施编排.NET Aspire 集成 Azure App Service 实战环境建模、Web App 发布与基础设施编排 本文围绕开源仓库中 Aspire.Host云原生后端微服务可观测性开发工具在 Azure Service Fabric 上托管 Orleans基于无状态 Reliable Service 的完整部署指南在 Azure Service Fabric 上托管 Orleans基于无状态 Reliable Service 的完整部署指南 Orleans 可以作为一个后端微服务创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价