可易

用 Azure Developer CLI 为托管代理配置持续集成与持续交付

可易团队阅读约 10 分钟

用 azd pipeline config 在 GitHub Actions 或 Azure DevOps 部署 Foundry 托管代理,并串行预配、门禁验证与生产提升。

目录

#用 Azure Developer CLI 为托管代理配置持续集成与持续交付

重要

本文中标为预览(preview)的项目目前处于预览阶段。该预览不提供服务级别协议,Microsoft 不建议将其用于生产工作负载。某些功能可能不受支持,或能力受到限制。更多信息参见Microsoft Azure 预览版补充使用条款。

用 azd pipeline config 自动化托管代理(hosted agent)的部署。在本文中,你将在 GitHub Actions 或 Azure DevOps 中建立持续集成与持续交付(CI/CD),然后为无人值守作业套用适合流水线的 azd ai 标志。

基础设施预配(infrastructure provisioning)可以选择 Terraform 或 Bicep。如果希望由 Terraform 管理托管代理的数据平面资源、而不经过 azd,请改用用 Terraform 部署托管代理。

先决条件

  • 一个已初始化的托管代理项目,并且能在本地用 azd ai agent run 和 azd ai agent invoke --local 正常工作。设置方法参见初始化代理项目。
  • 该项目已至少用 azd up 成功部署过一次。部署步骤参见部署托管代理。
  • 在本地和流水线运行器上都已安装 azd Foundry 扩展。
  • 一个已认证的 azd 会话。
  • 代码位于托管在 GitHub 或 Azure DevOps 上的 Git 仓库中。

选择基础设施提供程序

要使用 Terraform 而不是 Bicep,用下面的命令初始化项目:

azd ai agent init --infra=terraform

对于基于容器的代理,单独指定部署模式:

azd ai agent init --infra=terraform --deploy-mode container

基础设施选项不会改变 Python 和 .NET 项目默认的代码部署模式。对于 Bicep,使用 --infra=bicep 或 --infra。如果不加 --infra,azd 会从 azure.yaml 合成基础设施,而不是写出基础设施即代码(IaC)文件。

对于新项目,检查生成的 infra/ 目录,以及 azure.yaml 中的 Terraform 提供程序配置。现有项目可以使用单独的 Foundry 基础设施层。文件结构和弹出限制参见托管代理基础设施。

把基础设施配置和提供程序锁文件与应用代码一起提交。不要提交 Terraform 状态、.terraform/、已保存的计划或 .azure/ 环境状态。初始化是项目编写步骤,不是每次 CI 部署都要重新运行的命令。

配置 Terraform 状态

如果不使用 Terraform,跳过本节。

在配置流水线之前:

  1. 在本地和运行器上安装 Terraform。开发和 CI 中使用同一个经过审查的版本。
  2. 在工作负载部署之外,创建一个 Azure 存储帐户和用于远程状态的 Blob 容器。每个环境使用不同的状态键。
  3. 在 Terraform 提供程序文件里现有的 terraform 块中加入 azurerm 后端声明。保留已生成的提供程序和 Terraform 版本约束:
    terraform {
      backend "azurerm" {}
    }
  1. 在 Terraform 基础设施目录中创建 provider.conf.json。对于使用默认布局的新项目,路径是 infra/provider.conf.json:
    {
      "storage_account_name": "${RS_STORAGE_ACCOUNT}",
      "container_name": "${RS_CONTAINER_NAME}",
      "key": "hosted-agent-ci/${AZURE_ENV_NAME}.tfstate",
      "resource_group_name": "${RS_RESOURCE_GROUP}",
      "use_azuread_auth": true
    }

如果多个应用共用该容器,选择一个对本应用唯一的键前缀。azd 会解析这些环境替换,并把配置传给 terraform init;它们不是 Terraform 输入变量。

本示例有意用 use_azuread_auth 为 Blob 访问启用 Microsoft Entra 身份验证。仅有 OIDC 身份验证并不会选定该后端模式。如果没有它,后端可能需要检索存储帐户密钥的权限。更多信息参见启用远程状态。

  1. 在 azd 环境中设置后端取值:
    azd env set RS_RESOURCE_GROUP "<state-resource-group>"
    azd env set RS_STORAGE_ACCOUNT "<state-storage-account>"
    azd env set RS_CONTAINER_NAME "<state-container>"
  1. 向流水线身份授予后端的 Blob 数据平面访问权限,这与它的基础设施权限和 Foundry 权限是分开的。后端的角色和网络要求参见把 Terraform 状态存放在 Azure 存储中。
  2. 在配置流水线之前,确认 azd provision 使用的是远程后端。

状态和已保存的计划可能包含敏感值。限制对二者的访问,不要把它们作为不受限制的工作流产物上传。

后端锁定保护的是 Terraform 状态操作。它不会协调其他正在更新同一托管代理的工具。在 azd、Terraform 以及任何其他部署写入方之间,把生产发布串行化。

配置流水线

运行流水线配置命令:

azd pipeline config

这个交互式命令会:

  1. 检测 Git 提供程序,例如 GitHub 或 Azure DevOps。
  2. 为 CI/CD 身份验证创建一个服务主体(service principal)。
  3. 用你的 azd 环境值配置仓库密钥和变量。
  4. 生成工作流文件,例如用于 GitHub Actions 的 .github/workflows/azure-dev.yml,或一份 Azure Pipelines YAML 文件。

对于 GitHub 上的 Terraform 项目,该命令会检查三个 RS_* 值是否存在,并把它们复制到仓库变量。这项检查不验证存储是否存在、权限或连通性。

查看流水线流程

生成的流水线默认在推送到 main 时运行,并执行:

  1. azd provision:使用 azure.yaml 中配置的提供程序创建或更新 Azure 基础设施,包括已弹出的 Terraform 或 Bicep 文件。
  2. azd deploy:构建容器,推送到 Azure 容器注册表(ACR),并创建新的托管代理版本。

对于代码部署,azd deploy 上传的是源码包,而不是构建你的容器。无论哪种模式,代理版本部署都由 azd 负责;选择 Terraform 基础设施并不会把这些版本纳入 Terraform 管理。

这与在本地运行 azd up 的流程相同,只是在 CI 中自动化了。部署本身不能代替应用级冒烟测试。

如果只针对现有基础设施做应用发布,并且基础设施配置没有变化,可以只运行 azd deploy,不必重复预配。如果共享资源的生命周期由平台团队负责,把共享资源的预配留在该团队的工作流中。

如果应用团队还需要 Terraform 管理逻辑代理本身,使用独立的 Terraform 部署阶段。那条路径把基础基础设施、镜像构建与推送、以及代理定义更新分开,并且不要求使用 azd。

配置 GitHub Actions

运行 azd pipeline config 之后,检查 .github/workflows/azure-dev.yml。如果选择了 Terraform,保留生成的 Terraform 安装和身份验证步骤。

下面的示例展示预配和部署流程。对于 Terraform,用后端配置三个 RS_* 仓库变量,并把 TERRAFORM_VERSION 设为经过审查的 Terraform 版本。使用 Bicep 时不需要这些值。

name: Azure Developer CLI

on:
  push:
    branches:
      - main
  workflow_dispatch:

permissions:
  id-token: write
  contents: read

concurrency:
  group: hosted-agent-deployment
  cancel-in-progress: false

jobs:
  build:
    runs-on: ubuntu-latest
    env:
      AZURE_CLIENT_ID: ${{ vars.AZURE_CLIENT_ID }}
      AZURE_TENANT_ID: ${{ vars.AZURE_TENANT_ID }}
      AZURE_SUBSCRIPTION_ID: ${{ vars.AZURE_SUBSCRIPTION_ID }}
      AZURE_ENV_NAME: ${{ vars.AZURE_ENV_NAME }}
      AZURE_LOCATION: ${{ vars.AZURE_LOCATION }}
      ARM_CLIENT_ID: ${{ vars.AZURE_CLIENT_ID }}
      ARM_TENANT_ID: ${{ vars.AZURE_TENANT_ID }}
      ARM_SUBSCRIPTION_ID: ${{ vars.AZURE_SUBSCRIPTION_ID }}
      ARM_USE_OIDC: "true"
      RS_RESOURCE_GROUP: ${{ vars.RS_RESOURCE_GROUP }}
      RS_STORAGE_ACCOUNT: ${{ vars.RS_STORAGE_ACCOUNT }}
      RS_CONTAINER_NAME: ${{ vars.RS_CONTAINER_NAME }}
    steps:
      - name: Checkout
        uses: actions/checkout@v4

      - name: Install azd
        uses: Azure/setup-azd@v2

      - name: Install Terraform
        if: ${{ hashFiles('infra/**/*.tf') != '' }}
        uses: hashicorp/setup-terraform@v3
        with:
          terraform_version: ${{ vars.TERRAFORM_VERSION }}
          terraform_wrapper: false

      - name: Install Foundry extensions
        run: azd ext install microsoft.foundry

      - name: Sign in to Azure (federated credentials)
        run: azd auth login --client-id $AZURE_CLIENT_ID --federated-credential-provider github --tenant-id $AZURE_TENANT_ID

      - name: Provision infrastructure
        run: azd provision --no-prompt

      - name: Deploy agent
        run: azd deploy --no-prompt

并发组把这个工作流的部署串行化。还要协调部署同一代理的其他仓库或工具;GitHub 并发组不是服务范围的锁。

Terraform 的 Azure 提供程序身份验证和 azd 身份验证是分开的。既要保留 ARM_* 的 OIDC 设置,也要保留 azd 登录步骤。不要仅仅因为基础设施使用 Terraform,就额外添加一个长期有效的客户端密钥。

注意

CI 中需要 azd ext install microsoft.foundry 这一步,因为运行器镜像不包含该扩展。这个元包会安装每一个单独的 Foundry 扩展(azure.ai.agents、azure.ai.connections、azure.ai.inspector、azure.ai.projects、azure.ai.routines、azure.ai.skills 和 azure.ai.toolboxes)。如果只安装代理相关表面,把它换成 azd ext install azure.ai.agents,该命令也会把 azure.ai.inspector 作为依赖拉进来。

配置 Azure DevOps

azd pipeline config 也支持 Azure DevOps。

  1. 在提示中选择 “Azure DevOps”。
  2. 检查生成的 azure-pipelines.yml 文件。
  3. 确认生成的文件包含对等的安装、登录、预配和部署步骤。

对于 Terraform,还要配置远程后端、Terraform 安装,以及后端和提供程序的身份验证。不要把 GitHub 专用的 OIDC 环境假设复制到 Azure Pipelines 中。参见配置 Azure Pipelines。

设置适合流水线的标志

大多数 azd ai 命令都接受一些标志,使它们可以在 CI 中无人值守地安全运行。在流水线里相关的 azd ai 步骤上设置这些标志。

  • --no-prompt:关闭交互式提示。命令会快速失败并给出有用的错误,而不是阻塞在输入上。每个 azd ai 命令都支持它。在 CI 中始终设置它;否则,缺少必填值时作业可能一直挂起,直到超时。
  • --output json:对支持该标志的命令发出结构化输出,可以用 jq、PowerShell 的 ConvertFrom-Json 或任何其他 JSON 工具解析,例如 azd ai agent show,以及 connection、toolbox、skill 和 routine 命令。azd ai agent invoke 改用 --output raw。
  • --project-endpoint(-p):为单个资源命令(connection、toolbox、skill 或 routine)固定 Microsoft Foundry 项目终结点(endpoint)。azd ai agent 命令会从当前 azd 环境、全局配置或 FOUNDRY_PROJECT_ENDPOINT 环境变量解析项目。
  • --debug:发出详细的诊断输出。排查 CI 失败时有用,但平时运行会很嘈杂。

示例:

azd ai agent invoke my-agent "ping" --no-prompt --output raw

在 CI 中设置项目上下文

流水线运行在交互式 azd 项目上下文之外,因此 azd ai 直接命令需要知道要指向哪个 Foundry 项目。选择下面两种模式中适合你流水线的一种。

设置环境变量

在作业或整个工作流上设置一次 FOUNDRY_PROJECT_ENDPOINT。在项目内的 azd 环境和全局配置之后,每个 azd ai 命令都会自动读取它。

jobs:
  agent-checks:
    runs-on: ubuntu-latest
    env:
      FOUNDRY_PROJECT_ENDPOINT: ${{ vars.FOUNDRY_PROJECT_ENDPOINT }}
    steps:
      - uses: actions/checkout@v4
      - uses: Azure/setup-azd@v2
      - run: azd ext install microsoft.foundry
      - run: azd ai agent show --no-prompt --output json

用 azd ai project set 固定终结点

在作业早期运行 azd ai project set $FOUNDRY_PROJECT_ENDPOINT --no-prompt。它把终结点写入全局 azd 配置(~/.azd/config.json),同一作业中随后的 azd ai 命令会使用该上下文。

- run: azd ai project set ${{ vars.FOUNDRY_PROJECT_ENDPOINT }} --no-prompt
- run: azd ai agent show --no-prompt --output json

CLI 按以下顺序解析终结点:--project-endpoint 标志、azd 项目内的当前 azd 环境、由 azd ai project set 设置的全局配置,最后是 FOUNDRY_PROJECT_ENDPOINT 环境变量。如果都无法解析,命令会以结构化错误退出。

关于在磁盘上没有 azd 项目时运行 azd ai 命令,参见设置 azd 项目上下文。

在 CI 中用评估做验证

流水线完成部署,或已经能够访问目标项目之后,用 azd ai agent eval run 做回归检查。针对当前代理运行已保存的评估(eval),如果分数低于阈值就让作业失败。

azd ai agent eval run --no-prompt

eval run 默认解析项目根目录中的 eval.yaml,也可以传入 --config <path>。它不会顺便重新生成数据集和评估器。要在 CI 中准备评估套件,先运行 azd ai agent eval generate。该命令要求有一个可以调用的已部署代理。

配置按环境区分的部署

对于多个环境,例如开发、预发和生产:

  1. 创建各自的 azd 环境:
    azd env new staging
    azd env set AZURE_LOCATION=eastus2
  1. 为每个环境配置一条流水线,或使用基于分支的触发器:
  • main -> 生产
  • develop -> 预发
  1. 让每次流水线运行使用自己的 azd 环境变量,从而使资源相互隔离。

在提升到生产之前验证候选版本

默认情况下,Foundry 终结点跟随最新版本。因此,一条先部署再测试的流水线,可能在测试运行之前就改变了生产流量。

对于有门禁的发布,在部署之前把生产固定到现有版本。记下部署创建的版本,验证的就是这个确切候选,只有在批准之后才提升它。

azd deploy 会等待版本激活,但仅仅就绪并不能证明代理行为正确。使用一个新的、固定到该版本的会话,并检查期望的响应内容。不要把任何非空的 CLI 输出当成成功的冒烟测试。

部署期间,azd 还会应用为该代理配置的终结点设置。检查这些设置和部署挂钩,避免它们覆盖生产固定。把提升与普通的 azd deploy 以及基础设施预配分开。

管理密钥

azd pipeline config 把下列值存为仓库密钥或变量:

  • AZURE_CLIENT_ID:服务主体客户端 ID。
  • AZURE_TENANT_ID:Microsoft Entra 租户 ID。
  • AZURE_SUBSCRIPTION_ID:目标订阅。
  • AZURE_ENV_NAME:azd 环境名称。
  • AZURE_LOCATION:Azure 区域。

把代理专用密钥,例如 azure.yaml 里 azure.ai.agent 服务的 env 映射所引用的 MCP API 密钥,作为更多仓库密钥添加。在流水线中把每一个映射到一个 azd 环境变量。

排查流水线问题

重新运行流水线之前,先查看常见问题。对于 CI 预配,除 Azure 角色之外,你可能还需要 Foundry Owner。

重要

Foundry 的 RBAC 角色最近已重命名。Foundry User、Foundry Owner、Foundry Account Owner 和 Foundry Project Manager 以前分别叫做 Azure AI User、Azure AI Owner、Azure AI Account Owner 和 Azure AI Project Manager。在重命名铺开期间,有些地方可能仍显示旧名称。角色 ID 和核心权限不因这次重命名而改变。

问题解决办法
CI 中 azd ext install 失败确认运行器可以访问互联网,并且已安装 azd 1.25.2+。
预配期间出现 AuthorizationFailed核对服务主体是否具有 Contributor 和 Foundry Owner 角色。
找不到 Foundry 扩展在任何 azd ai 或 azd up 命令之前加入 azd ext install microsoft.foundry,或对应的单个扩展。
密钥不可用检查 azd pipeline config 是否已完成,以及密钥在仓库设置中是否可见。

PRIMARY_SOURCE: https://learn.microsoft.com/en-us/azure/foundry/agents/how-to/set-up-ci-cd-cli

  • #持续交付
  • #托管代理
  • #GitHub Actions
  • #Terraform
  • #azd