Aspire 部署目标生产就绪指南从 Artifact 发布器到可观测的 Provisioning Deployer【免费下载链接】aspireAspire is the tool for code-first, extensible, observable dev and deploy.项目地址: https://gitcode.com/GitHub_Trending/as/aspire部署目标集成Deployment Target Integration是 Aspire 生态中承上启下的关键一环上游接收 AppHost 应用模型中的ProjectResource、ContainerResource、ExecutableResource等计算资源下游负责把它们变成真实的云端或集群工作负载。本文基于仓库内.agents/skills/hosting-integration-authoring/resources/deployment-production-readiness.md的完整规范结合src/Aspire.Hosting及src/Aspire.Hosting.Kubernetes、src/Aspire.Hosting.Docker、src/Aspire.Hosting.Azure.AppContainers等真实实现系统讲解一个部署目标在所有权、状态、前置条件、安全、服务引用、更新行为、销毁清理、测试与文档九大维度上必须满足的生产就绪契约帮助集成作者与评审者把“能产出 YAML”的玩具集成打磨成“敢上生产”的严肃发布器。生产就绪不是一个特性而是一组显式契约文档开宗明义地指出Production readiness is not one feature. It is a set of explicit contracts。生产就绪不是“多写几个 API”或“多产出一份 manifest”而是围绕 ownership所有权、state状态、prerequisites前置条件、security安全、service references服务引用、update behavior更新行为、teardown销毁、tests测试、docs文档九个方面的一整套契约。因此一个部署目标的设计应该从“把 Aspire 概念逐项映射到目标平台”开始而不是从“加 API”开始。在.agents/skills/hosting-integration-authoring/SKILL.md的“Then read the matching resources”矩阵中凡是涉及Docker Compose、Kubernetes、Azure Container Apps 或其他部署目标/发布器的集成都必须同时阅读resources/archetype-deployment-target-publisher.md与本篇deployment-production-readiness.md当集成预期会创建、更新或删除真实基础设施而不只是产出工件时本资源是强制要求。Aspire 概念映射动手写 API 之前的清单设计任何部署目标前第一步是把 Aspire 的每个核心概念映射为三种结果之一目标平台原生概念、显式 unsupported 错误、或文档化的外部前置条件。映射完成之前不要添加 API。下面对照源码把映射表逐行展开Aspire 概念在 Aspire 中的含义部署目标映射问题Resource name引用、Dashboard、日志与生成输出使用的稳定图身份创建了什么物理名如何归一化是否按环境唯一原始 Aspire 名称记录在哪里以便追溯Physical name供应商可见名称可能与 Aspire 名称不同目标是否有长度/字符约束名称是否确定冲突如何处理Compute resourceProjectResource、ContainerResource、ExecutableResource或其它IComputeResource成为工作负载创建哪种目标工作负载原语service、deployment、job、function、task、container app、pod支持/拒绝哪些计算资源类型Compute environmentIComputeEnvironmentResource在 publish/deploy 期间接收计算资源代表哪种目标上下文项目、订阅、集群、命名空间、区域、环境、账户运行可见还是仅 publish/deployContainer image构建镜像或通过容器注解选择的现有镜像镜像推送到哪标签如何选择是否支持 digest 固定谁拥有推送镜像与清理Container registry共享IContainerRegistry模型与WithContainerRegistry目标如何认证/拉取镜像registry 创建是外部还是托管的如何校验 registry 凭据Endpoints带 scheme、transport、host port、target port 与引用端点语义的命名端点暴露哪个目标端口TLS 由平台终止吗transport 是否映射到 HTTP/2/h2c 等协议字段哪些端点是 public、private、health-only 或 unsupportedService discoveryWithReference把逻辑服务端点注入消费者目标在 deploy 前是否提供稳定 DNS/服务绑定若 URL 是 post-deploy 输出跨服务引用是否失败、使用原生绑定、还是需要两阶段更新Connection strings/properties传给消费者的结构化资源值能否表达为 env vars、service bindings、secrets、config maps、managed identity 引用或供应商原生依赖绑定Environment variables通过环境回调发出的字面量与结构化值哪些值可以在 publish、deploy 或 runtime 解析哪些必须保持为目标原生引用Parameters用户提供或生成的值非 secret 参数是否作为字面量/占位符发出secret 参数是被拒绝、映射到原生 secret还是通过安全托管 secret 路径摄取Secrets带 secret 的ParameterResource与连接字符串原生 secret 存储/引用形状是什么谁创建 secret 版本哪个运行身份获得访问如何防止明文进入文件、日志、状态与 CLI 参数Identity部署者身份与运行时工作负载身份不同哪个身份应用基础设施工作负载以哪个身份运行如何分配或校验最小权限角色Access mode端点是 private、internal、authenticated 还是 public安全默认值是什么哪个 API 显式选择公开访问调用者身份/IAM 如何表达Networking内/外端点、私有出口、VPC、DNS、ingress是否需要 VPC connector、private endpoint、namespace、subnet、防火墙规则这些是现有前置条件还是托管资源Health checks/probesAspire 健康与就绪影响启动与 Dashboard生成哪些 readiness/liveness/startup probe哪些端点仅 health 用、被排除出引用Resource limits/scalingCPU/内存、副本数、min/max 扩缩、并发哪些目标旋钮映射到 Aspire 概念哪些目标约束需要校验保留什么默认值Arguments/commandIResourceWithArgs与容器 entrypoint/args如何避免 shell 引号问题保留 args目标是否区分 command 与 argsFiles/config生成的配置文件、WithContainerFiles、manifest文件是烤进镜像、挂载、上传还是转换为供应商配置对象secret 是否被排除Relationships/waitsWithReference、父子关系、wait 注解、依赖哪些关系影响部署顺序、IAM、服务绑定或清理顺序哪些仅影响 Dashboard、不应影响目标输出Parent/child resources数据库、队列、topic、deployment、container、模型子资源是目标对象、应用级配置还是 unsupported谁拥有其生命周期与删除Dashboard URLs/commands面向用户的资源链接与操作哪些已部署 URL 是摘要链接哪些仅详情命令是否安全且目标感知Deployment state先前部署的持久化输出存储哪些 ID、URL、所有权、镜像 tag/digest 与 schema 版本如何处理过期状态Destroy/cleanup移除已部署资源哪些目标对象被托管且可安全删除哪些保留需要什么顺序与重试行为Polyglot exportsTypeScript/Python 等 AppHost 使用生成的 SDKAPI 在需要处是否无回调或 adapter-backedDTO/导出模型是否 ATS 兼容生成名是否稳定、无冲突映射阶段的行为准则同样明确。DO把映射放进设计笔记、评审意见或实现计划对每个 unsupported 映射用可操作的错误信息失败并补测试优先使用目标原生机制处理目标自己拥有的概念服务绑定、身份、secret、探针、流量。DONT不要因为目标没有直接等价物就静默丢弃 Aspire 概念不要先把结构化值压平成字符串、再决定哪个生命周期阶段能解析它不要只靠暴露目标专属的“逃生舱”来满足常见 Aspire 概念。映射在源码中的落点映射并不是纸上谈兵Aspire 的应用模型已经为它提供了基础设施IComputeResourcesrc/Aspire.Hosting/ApplicationModel/IComputeResource.cs是所有可被部署目标托管执行资源的基接口——项目、容器、可执行文件均实现它。IComputeEnvironmentResourcesrc/Aspire.Hosting/ApplicationModel/IComputeEnvironmentResource.cs是部署目标的“计算环境”抽象提供实验性 APIGetHostAddressExpression与GetEndpointPropertyExpression。其默认实现揭示了 Aspire 对“部署后端点”的处理思路HTTP/HTTPS 端点缺省端口分别取 80/443非 HTTP(S) 端点必须显式指定端口否则抛InvalidOperationException且永远返回ReferenceExpression而不是已解析的字符串——这正是“哪些值必须保持为目标原生引用”的具体体现。DeploymentTargetAnnotationsrc/Aspire.Hosting/ApplicationModel/DeploymentTargetAnnotation.cs把目标资源、容器注册表与计算环境绑定在一起DeploymentTarget、ContainerRegistry、ComputeEnvironment三个属性构成了部署目标在应用模型中的身份。仓库中已有多个真实部署目标可作为映射范例KubernetesEnvironmentResourcesrc/Aspire.Hosting.Kubernetes/KubernetesEnvironmentResource.cs、DockerComposeEnvironmentResourcesrc/Aspire.Hosting.Docker/DockerComposeEnvironmentResource.cs、AzureContainerAppEnvironmentResourcesrc/Aspire.Hosting.Azure.AppContainers/AzureContainerAppEnvironmentResource.cs与RadiusEnvironmentResourcesrc/Aspire.Hosting.Radius/RadiusEnvironmentResource.cs。成熟度分级先分类再设计 API在设计 API 之前先把目标集成分入四级成熟度级别契约示例Artifact publisher仅生成工件由另一个工具应用它们Kubernetes YAML 导出、Docker Compose 文件Existing-target deployer将工件应用到既有目标与 registry校验前置条件而非供应它们Cloud Run 部署到既有项目/仓库Provisioning deployer创建或更新前置基础设施然后部署工作负载创建 registry、service account、API、namespace、secret storeReconciler/operator持续或反复收敛期望状态支持漂移、命令与删除控制器支撑的云或集群集成分级的行为准则DO——在 XML 文档、README、测试与评审意见中明确声明级别保持低级别诚实前置条件是外部的就校验并文档化不要假装托管只有集成真正拥有该级别所需的状态、权限、更新与清理语义时才向更高级别迁移。DONT——不要把“Artifact publisher”自动创建收费、受策略治理或共享的基础设施那需要显式的 provisioning 契约如果用户必须为了常见生产设置手工编辑生成的工件就不要自称 Existing-target deployer 已生产就绪。从源码看Aspire 的部署目标恰好覆盖这四级Docker Compose 集成偏 artifact 发布Kubernetes 集成支持向既有集群kubectl apply而 Azure 系列如 src/Aspire.Hosting.Azure 下的 Bicep provisioner属于典型的 provisioning deployer——先创建 registry、身份与网络再部署工作负载。所有权与部署状态每个真实目标对象都必须有所有权模型。文档定义了四类所有权Managed托管Aspire 创建允许更新/删除。Referenced existing引用既有用户提供Aspire 可读取/校验但除非特定 API 明确允许否则不得变更。Generated deployment artifact生成部署工件为一次部署运行而创建如镜像 tag 或 manifest清理策略必须显式。Shared prerequisite共享前置条件被多个应用/环境使用默认保留。DO在部署状态中记录稳定目标标识符项目/订阅/集群、区域、资源 ID/名称、URL、身份、访问模式、所有权包含状态 schema/版本使未来代码能安全迁移或忽略旧条目平台支持时用目标 label/tag/annotation 标记 Aspire 托管资源但绝不仅仅依赖 label 做删除所有权模糊时优先使用显式 APIAsExisting、PublishAsExisting、WithExisting*、WithManaged*应用模型名与物理目标名分开对待两者不同时都存储。DONT——不要仅按名称匹配就删除或覆盖资源除非 API 名称与文档明确该变更否则不要改动被引用既有资源的 IAM、网络、生命周期或数据面状态不要把 secret 存进部署状态。源码佐证ExistingAzureResourceExtensionssrc/Aspire.Hosting.Azure/ExistingAzureResourceExtensions.cs通过RunAsExisting、AsExisting等 API 与ExistingAzureResourceAnnotation实现“引用既有”语义并且明确“不要修改既有资源的 IAM、网络与生命周期”正是该文件设计的前提——资源一旦标记为 existingprovisioner 便只读不写。流水线形状八阶段生产部署器一个生产级部署器通常需要以下阶段每阶段都有明确职责Model validation模型校验应用模型形状、必需环境、物理名唯一性、不支持的引用。Preflight预检工具/SDK 可用性、已认证账户、目标上下文、启用的 API、registry 访问、权限、可行的配额/策略检查。Build/push构建/推送使用结构化 registry 注解构建镜像并推送。Prepare artifacts准备工件产出部署时工件晚绑定值仅在安全时才解析。Apply应用幂等地创建/更新目标资源。Verify验证查询供应商状态确认就绪 URL/状态/访问模式。Record记录把目标输出与所有权持久化到部署状态。Destroy/cleanup销毁/清理仅按所有权模型删除托管资源。DO保持 preflight 非变异apply 幂等且可重试重复部署同一应用应收敛目标apply 后向供应商验证不能只凭命令退出码推断成功只有验证成功后才保存输出使用结构化进程参数或 SDK 调用仅在显示/日志边界做引号处理。DONT——不要在应用模型构建期间发起云 API 调用不要让“第一次变更调用”成为用户发现缺权限、API 被禁用或上下文无效的时机不要让部分失败看起来像成功——要表面失败的操作、资源、目标上下文与脱敏后的供应商错误。aspire publish与aspire deploy两个独立契约设计上必须把aspire publish与aspire deploy当作两个独立契约。仓库中二者是独立的 CLI 命令实现PublishCommandsrc/Aspire.Cli/Commands/PublishCommand.cs与DeployCommandsrc/Aspire.Cli/Commands/DeployCommand.cs。aspire publish产出工件assets——期望部署形态及其支撑文件用户可检查、评审、归档或交给另一套部署系统。常见 publish 工件包括目标 manifestYAML、JSON、Bicep、Terraform 类文件、Compose 文件、Helm values 或供应商专属描述符生成的 Dockerfile、配置文件、container-file 输入与构建元数据镜像引用、tag 占位符、构建上下文或 registry 需求参数占位符与目标原生 secret 引用列出前置条件与 unsupported 映射的部署计划或 README 片段解释目标上下文、资源名与访问模式的非 secret 元数据。aspire deploy消费工件并变更目标。deploy 在有意延后解析值时可以生成第二批部署时工件但必须显式说明与 publish 输出的差异。常见 deploy 动作包括校验凭据、所选账户/项目/订阅/集群、已启用的供应商 API、registry 访问与权限构建推送镜像或解析镜像 digest/tag解析可安全写入的非 secret 晚绑定值应用目标 manifest 或调用供应商 API创建/更新用户显式选择的 IAM/访问绑定查询目标状态、URL、修订、路由与就绪性持久化部署状态与输出。DO保持 publish 输出确定性与可评审性对只有 deploy 才知道的值镜像 tag、生成的资源 ID、服务 URL、secret使用占位符或目标原生引用如果 deploy 需要已解析 manifest请写成独立的部署时工件以便用户对比 publish 资产与被应用资产纯 artifact 场景测试aspire publish无需真实凭据变更场景用真实/模拟供应商状态测试aspire deploy文档化哪些文件是 publish 资产、哪些是部署时资产、由哪些命令应用。DONT——不要让 publish 输出看起来已完全解析而 deploy 随后又替换关键字段不要把部署时才有的值、供应商状态或 secret 材料写进 publish 资产不要让 deploy 静默忽略过期的 publish 资产或缺失的生成文件不要要求用户先跑 deploy 才能知道会产出什么资产。前置条件供应与部署工作负载分离的设计契约供应前置条件是一个独立于部署工作负载的设计契约。常见前置条件包括启用的云 API/服务、容器 registry/仓库、service account 或 managed identity、IAM 角色绑定、secret store 与 secret 版本、网络、private endpoint、VPC connector、namespace 或集群。DO逐个决定前置条件是 out-of-band带外、existing-reference引用既有还是由 Aspire 托管对托管前置条件优先使用一等资源 API而不是在 deploy 内隐藏副作用让变更新建前置条件显式化——只有当行为清晰时才使用Add{Target}Registry、WithManagedServiceAccount、WithPrerequisiteProvisioning之类的名字用可操作的错误与尽可能精确的命令/文档校验外部前置条件把组织策略、配额、计费与权限失败当作一等错误。DONT——不要从泛化的Add{Target}Environment调用中静默启用云 API、创建仓库或授予 IAM当更窄的 deploy/runtime 角色足够时不要要求宽泛的 owner/contributor 权限不要通过把前置条件藏在环境 CLI 状态背后而使其不可测试。销毁与清理基于状态而非当前模型销毁有风险因为当前代码可能与先前部署创建的资源不匹配。DO销毁要基于部署状态加目标验证而不是仅凭当前应用模型按逆依赖顺序删除——先流量/路由、再服务、必要时再身份/权限、镜像最后默认保留共享前置条件与用户提供的既有资源对共享 registry 等场景破坏性镜像清理必须 opt-in 或基于策略目标表面广或删除代价高时支持 dry-run/plan 输出把“资源已缺失”视为成功收敛但报告无法证明可安全删除的资源。DONT——不要在没有 Aspire 托管状态条目或已验证所有权标记的情况下按前缀/名称删除除非用户显式选择托管所有权否则不要删除可能共享的 secret、registry、网络或身份不要忽略部分清理失败要持久化足够状态以便重试。服务间引用按目标能力决策部署目标在“服务地址何时存在”上差异巨大。使用如下决策表目标能力Publish 行为Deploy 行为部署前存在稳定逻辑名发出目标原生引用、DNS 名或服务绑定表达式验证其可解析或目标报告就绪URL 仅部署后存在对跨资源端点引用让 publish 失败或采用显式两阶段 deploy/update 设计把 URL 记录进部署状态并作为输出暴露而不是作为 publish 时环境变量需要私有服务认证仅当目标支持时才发出身份感知绑定配置最小权限调用者身份/IAM 并测试认证调用不支持的目标翻译带指引失败不要静默丢弃服务发现变量DO把稳定的目标原生引用建模为结构化值除非目标提供稳定的部署前地址否则把已部署 URL 作为部署输出区分面向用户的 URL 与工作负载间连接契约声称支持服务引用前先测试多服务应用。DONT——不要把本地运行模式 URL 序列化进 publish/deploy 输出不要让用户从 Dashboard 摘要里抠另一个资源需要的值不要发明目标并不提供的服务发现语义。Secrets 与身份生产的硬性要求Secret 与身份支持是生产部署的硬性要求。DO优先支持既有原生 secret 引用如 secret name/version/key若托管 secret通过安全 API/SDK 路径创建/更新绝不把明文写进生成的 manifest、日志、命令行参数或部署状态运行时身份与部署者身份分开建模——部署者应用基础设施运行时 service account/managed identity 访问依赖当集成拥有依赖关系两侧时为运行时身份接最小权限角色除非有显式公开访问 API带安全文档与测试否则保持默认私有同时测试 secret 引用输出与被拒绝的明文 secret 物化。DONT——不要把ParameterResourcesecret 解析进部署时文件除非该文件正是目标的安全摄取机制且立即清理不要为了省事授予 owner/contributor/editor 等宽泛角色不要为了让 smoke test 简单而把匿名公开入口设为默认。Aspire 的ReferenceExpression机制正是为此设计的IComputeEnvironmentResource的所有端点表达式都返回ReferenceExpression而非已解析字符串使 secret/URL 可以被安全地延后到 deploy 阶段解析见 src/Aspire.Hosting/ApplicationModel/IComputeEnvironmentResource.cs。目标功能建模一等 API 优先对常见生产功能优先提供一等 API 而非让用户手编 manifest。适合做一等 API 的候选public/private 入口与调用者访问、运行身份/service account、secret 引用、扩缩/并发/资源限制、健康/启动探针、registry/项目/区域/集群上下文、网络挂载/私有出口、数据库或队列连接等数据服务绑定、目标拥有路由时的自定义域名/路由。DO为罕见或快速演进的目标功能保留逃生舱校验目标会拒绝的组合如 private 入口与公开未认证访问不兼容时尽可能把 API 保持在 Aspire 概念层面内部再翻译为目标专属 schema。DONT——不要强迫用户为常见场景了解目标 YAML/JSON schema如果原始供应商 DTO 在多语言 AppHost 中投影不佳就不要把它们当作主 API。仓库中的实现印证了这一原则例如 Kubernetes 集成在KubernetesEnvironmentExtensionssrc/Aspire.Hosting.Kubernetes/KubernetesEnvironmentExtensions.cs中提供AddKubernetesEnvironment、ingress、gateway、helm chart、persistent volume 等一等 API而 Azure Container Apps 集成则在AzureContainerAppExtensionssrc/Aspire.Hosting.Azure.AppContainers/AzureContainerAppExtensions.cs中提供AddAzureContainerAppEnvironment等环境级 API——用户写的是 Aspire 概念环境、镜像、端点、身份翻译成目标 schema 的工作由集成内部完成。Stabilization Gate稳定发布前的检查清单在把部署目标包标记为 stable 之前以下所有适用项必须为真运行模式保持干净仅 publish/deploy 的资源在本地隐藏或 no-op。Publish 对 project 与 container 资源产生确定性工件。Deploy preflight 覆盖工具、认证/上下文、目标 API/服务启用、registry 访问与权限。真实 smoke deploy 完成构建、推送、应用、验证供应商状态、调用端点并清理。支持公开访问时同时测试私有/默认访问与显式公开访问。Secret 使用原生 secret 引用或托管 secret API明文 secret 物化被拒绝。服务间引用要么是目标原生且经过测试要么清晰失败。Destroy/cleanup 已实现或文档化为外部方式并提供安全的手工命令。Polyglot analyzer 诊断干净且已检查生成的 SDK 签名。README 文档化前置条件、部署命令、访问模式、secret、清理、限制与官方目标文档。这份清单与文档开篇的九类契约首尾呼应只有 ownership、state、prerequisites、security、service references、update behavior、teardown、tests、docs 全部满足一个部署目标才配得上“生产就绪”四个字。结语把清单变成集成的一部分本文档的价值在于它不是一篇泛泛而谈的架构文章而是一份可直接对照执行的验收清单概念映射表用于设计评审成熟度分级用于定位目标八阶段流水线用于约束实现顺序publish/deploy 双契约用于分隔职责所有权模型与部署状态用于界定“能删什么、能改什么”Stabilization Gate 则作为稳定发布的门禁。无论是为 Aspire 新增一个云平台发布器还是评审一个现有部署目标 PR都可以把本指南的 DO/DONT 列表逐条套用并在src/Aspire.Hosting.*的既有实现Kubernetes、Docker Compose、Azure Container Apps、Radius中找到对应范式作为参照。【免费下载链接】aspireAspire is the tool for code-first, extensible, observable dev and deploy.项目地址: https://gitcode.com/GitHub_Trending/as/aspire创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
