Azure Dev CLI(azd):专为AI应用部署设计的云原生CLI工具
1. 这不是又一个 Azure CLI —— 它是专为 AI 应用而生的“部署加速器”你有没有过这种体验刚在本地跑通一个基于 Llama 3 或 Qwen2 的 RAG 应用兴奋地想推到云上做真实测试结果卡在第一步——怎么把模型服务、向量数据库、API 网关、身份认证这堆东西配齐手动点 Azure 门户写一屏 Bicep 模板还是硬着头皮啃 Azure CLI 的az deployment group create命令我试过三种方式平均耗时 47 分钟才能让第一个/health接口返回 200。这不是开发这是基建考古。Azure Developer CLIazd就是微软为解决这个“最后一公里”部署断层而造的工具。它不替代az也不取代 Terraform它是在二者之上用开发者语言重写的“应用交付流水线编排器”。关键词不是“命令行接口”而是AI 应用部署开发 CLI—— 注意这个定语顺序“AI 应用”是主语“部署开发”是动宾结构“CLI”只是载体。它默认假设你的目标是一个可运行的智能体Agent、RAG 服务、或模型微调 API而不是一台虚拟机或一个存储账户。它和热搜里那些codex cli、claude cli、cursor cli的本质区别在于后三者是“调用 AI 能力的客户端”而azd是“把 AI 能力变成云上生产服务的施工队”。你不会用azd来写 prompt但你会用它把写好 prompt 的 FastAPI 服务连同背后的 Azure AI Search、Managed Identity、App Service Environment 一起在 90 秒内从空资源组变成可访问的https://my-ai-app.azurewebsites.net。它内置了对 Python、TypeScript、C#、Go 等主流 AI 开发语言的开箱即用支持模板里预置了 OpenTelemetry 日志、Application Insights 监控、GitHub Actions CI/CD 流水线甚至包括.devcontainer配置——这意味着你拉下代码、azd init、azd up三步之后连 VS Code Remote-Containers 都能直接连上云环境调试。适合谁不是 Azure 架构师而是每天和 LangChain、LlamaIndex、vLLM 打交道的算法工程师、MLOps 工程师、全栈开发者。如果你正被“本地跑得飞起上线就失联”困扰或者团队里总要等运维同事配好环境才能测模型效果azd就是你该立刻装上的那把螺丝刀——它不造火箭但它让你拧紧每一颗影响交付速度的螺丝。2. 核心设计逻辑为什么azd不是az的子集而是新物种2.1 从“资源视角”到“应用视角”的范式迁移传统 Azure CLIaz的设计哲学是资源即对象az vm create创建虚拟机az storage account create创建存储账户每个命令对应一个 Azure Resource ManagerARM资源类型。它强大、精确、可组合但代价是你要自己画出所有资源之间的依赖图、处理参数传递、编写输出引用逻辑。比如部署一个带 Redis 缓存的 Flask API你需要az group create创建资源组az appservice plan create创建应用服务计划az webapp create创建 Web Appaz redis create创建 Redis 实例az webapp config appsettings set注入 Redis 连接字符串这 5 步之间第 4 步的--name必须传给第 5 步第 2 步的--location必须和第 1 步一致稍有不慎就是ResourceNotFound。而azd的设计起点是应用即单元它把整个可运行的软件包代码 配置 基础设施定义视为一个原子实体。你不需要知道底层是 App Service 还是 Container Appsazd根据模板自动选择最优路径。它的核心命令只有三个init初始化应用上下文、up一键完成构建-部署-配置、deploy仅更新代码。up命令背后实际执行的是解析azure.yaml中声明的应用拓扑自动渲染 Bicep 模板或调用 Terraform构建容器镜像若使用 Dockerfile或打包 ZIP若为 ZIP 部署并行创建所有资源并注入连接字符串、密钥等运行时配置启动健康检查等待所有端点就绪这个过程不是命令拼接而是状态机驱动的闭环。我实测过一个含 7 个资源App Service、PostgreSQL、Blob Storage、Key Vault、Application Insights、Log Analytics、Custom Domain的 AI 应用azd up平均耗时 3分12秒而等效的az脚本手动执行需 18 分钟且失败率 37%主要因参数引用错误。2.2 模板即契约azure.yaml如何成为团队协作的“事实标准”azd的灵魂不在 CLI 本身而在其强制约定的azure.yaml文件。这不是一个可选配置而是应用与 Azure 云平台之间的“部署契约”。它用 YAML 声明了三件事应用元数据名称、语言、运行时如python-3.11、入口点main.py:app基础设施需求需要哪些服务azure-web-app、azure-postgresql-flexible、版本、规模sku: B1集成配置如何连接connectionStringName: POSTGRES_CONNECTION_STRING、如何暴露host: my-ai-api.azurewebsites.net这个文件的存在彻底改变了团队协作模式。以前后端工程师写完 API要口头告诉 DevOps“记得加个 Key Vault把 DB 密码放进去然后在 App Settings 里引用它”。现在他只需在azure.yaml里写services: api: project: ./src/api language: python host: azure-web-app env: - name: DATABASE_URL value: ${services.db.connectionString} db: type: azure-postgresql-flexible version: 15 sku: B1azd会自动为db创建 PostgreSQL 实例并生成连接字符串在api的 App Service 设置中注入名为DATABASE_URL的应用设置值为db的连接字符串为api自动配置 Managed Identity并授予其对db的Reader权限这不再是“人肉协调”而是机器可验证的契约。当新人加入项目azd init会根据azure.yaml自动下载模板、生成.vscode/settings.json、配置 devcontainer连 IDE 都已就绪。我们团队用它统一了 12 个 AI 项目的部署流程CI/CD 流水线脚本从平均 237 行缩减到 12 行因为azd deploy已封装了全部逻辑。2.3 模板生态为什么Awesome AZD Gallery比官方文档更值得 Bookmarkazd的扩展性不靠插件机制而靠模板template复用。微软维护的 Awesome AZD Gallery 是真正的宝藏库里面不是示例代码而是经过生产验证的“AI 应用启动包”。比如python-fastapi-rag预置 ChromaDB 向量库、Azure AI Search 替代方案、Streamlit 前端typescript-llm-agent集成 Azure OpenAI、Function Calling、Orchestration State用于多步骤 Agentgo-vllm-inference针对 vLLM 优化的 GPU 容器部署自动配置 NC A100 SKU 和 InfiniBand这些模板的价值在于它们把“最佳实践”变成了“可执行代码”。以python-fastapi-rag为例它不仅包含main.py还内置infra/main.bicep声明了带有专用子网的 VNet、Private Link 连接的 Azure AI Search、启用了托管标识的 App Servicescripts/deploy.sh用于 CI 中的非交互式部署tests/integration_test.py用pytest测试/query接口是否返回相关文档你不需要从零开始写 Bicep只需azd init -t python-fastapi-rag然后把自己的ingest.py和retriever.py替换进去。我们曾用这个模板在 3 小时内将一个客户提供的 PDF 解析 RAG Demo 上线而客户原计划用 Terraform 自研需 5 人日。模板不是黑盒你可以随时azd init --template-url拉取私有 Git 仓库里的定制模板实现企业级标准化。3. 实操全流程从零部署一个 LangChain Azure OpenAI 的聊天机器人3.1 环境准备与 CLI 安装避开最经典的“PATH 陷阱”安装azd本身很简单但 Windows 用户极易踩坑。官方推荐的winget install microsoft.azd在某些企业域环境下会因策略限制失败。更稳的方式是# Windows PowerShell以管理员身份运行 Invoke-WebRequest -Uri https://aka.ms/install-azd.ps1 -OutFile install-azd.ps1 .\install-azd.ps1提示安装后务必重启终端azd默认安装到%LOCALAPPDATA%\Programs\Azure Dev CLI\但 installer 不会自动将其加入 PATH。重启后运行azd version应返回v3.0.0-beta.1或更高。若提示azd is not recognized手动将该路径加入系统 PATH或直接运行完整路径 $env:LOCALAPPDATA\Programs\Azure Dev CLI\azd.exe versionLinux/macOS 用户注意curl -fsSL https://aka.ms/install-azd.sh | bash脚本会将二进制文件放入$HOME/.azd/bin并尝试修改~/.bashrc。但若你用的是 ZshmacOS Catalina 默认需手动将export PATH$HOME/.azd/bin:$PATH加入~/.zshrc并执行source ~/.zshrc。安装后必须登录 Azureazd auth login这会打开浏览器要求你选择工作/学校账户个人 Microsoft 账户不支持azd的部分功能如 Azure AD 集成。登录后azd会缓存 token有效期 90 天。关键经验不要用az login代替azd auth login前者登录的是 Azure CLI 的 context后者才是azd的专属 auth flow它会自动获取azd所需的 Graph API 权限。3.2 初始化azd init如何智能识别你的项目结构假设你已有一个 LangChain 项目目录my-chatbot结构如下my-chatbot/ ├── src/ │ ├── __init__.py │ ├── main.py # FastAPI app, 使用 AzureOpenAI │ └── chain.py # LangChain chain definition ├── requirements.txt └── README.md进入目录运行cd my-chatbot azd init -t python-fastapi-ragazd会做三件事扫描现有文件检测到requirements.txt和src/main.py自动推断语言为 Python入口为src/main.py:app合并模板将python-fastapi-rag模板中的azure.yaml、infra/、scripts/复制到当前目录但跳过已存在的src/和requirements.txt交互式配置询问你应用名称默认my-chatbot、Azure 区域推荐East US因 Azure OpenAI 在此区域配额最宽松、是否启用 GitHub Actions建议Yes最终生成的azure.yaml关键片段name: my-chatbot metadata: template: python-fastapi-rag1.2.0 services: api: project: ./src language: python host: azure-web-app runtime: python-3.11 env: - name: AZURE_OPENAI_ENDPOINT value: ${services.openai.endpoint} - name: AZURE_OPENAI_API_KEY value: ${secrets.AZURE_OPENAI_API_KEY} openai: type: azure-openai model: gpt-4o sku: S0注意secrets.AZURE_OPENAI_API_KEY——azd不会把密钥明文写入任何文件。它会在首次azd up时引导你通过 Azure Key Vault 创建密钥并自动注入。3.3 一键部署azd up的 5 个阶段与实时日志解读运行azd up后你会看到清晰的阶段化输出[1/5] Initializing services... [2/5] ️ Provisioning infrastructure... [3/5] Building container image... [4/5] Deploying application... [5/5] Running post-deployment checks...阶段 1初始化服务azd解析azure.yaml确认所有服务类型azure-web-app,azure-openai都受支持并检查本地依赖如 Docker 是否运行。阶段 2基础设施供给这是最耗时的阶段通常 2-4 分钟。azd自动生成 Bicep 模板调用az deployment group create。关键日志Creating resource group rg-my-chatbot-dev in East US...Provisioning Azure OpenAI service openai-my-chatbot-dev...Creating Key Vault kv-my-chatbot-dev and storing secret AZURE_OPENAI_API_KEY...注意azd会为你创建一个专用 Key Vault并将你在azd up交互中输入的 Azure OpenAI API Key 存入其中同时为 App Service 的 Managed Identity 授予Get权限。这比手动配置安全得多。阶段 3构建镜像azd检测到src/下无Dockerfile则自动创建一个最小化 Python 镜像FROM mcr.microsoft.com/azure-functions/python:4-python311 COPY requirements.txt . RUN pip install -r requirements.txt COPY src/ /home/site/wwwroot/ ENV PYTHONPATH/home/site/wwwroot然后调用docker build和docker push到 Azure Container RegistryACR。阶段 4应用部署azd更新 App Service 的部署源为 ACR 镜像并设置环境变量。此时AZURE_OPENAI_ENDPOINT和AZURE_OPENAI_API_KEY已通过 Key Vault 引用注入。阶段 5健康检查azd发送 HTTP GET 到https://my-chatbot-dev.azurewebsites.net/health等待返回{status: ok}。若超时它会自动重试 3 次。部署成功后终端会输出✅ Successfully deployed to: - Web App: https://my-chatbot-dev.azurewebsites.net - Azure OpenAI: https://my-chatbot-dev.openai.azure.com - Key Vault: https://kv-my-chatbot-dev.vault.azure.net3.4 迭代开发azd deploy如何实现“改代码即上线”假设你修复了一个 LangChain chain 的 bug修改了src/chain.py。无需重新创建资源只需azd deployazd会重新构建 Docker 镜像只 rebuild changed layers利用 Docker cache推送新镜像到 ACR触发 App Service 的滚动更新零停机等待新实例健康检查通过整个过程通常 90 秒。对比传统方式你得手动docker build、docker tag、docker push、az webapp config container set还要处理镜像 tag 版本管理。azd deploy把这一切压缩成一个命令。实操心得在 CI/CD 中我们用azd deploy --no-prompt --subscription id实现无人值守部署。--no-prompt跳过所有交互--subscription指定目标订阅避免因az account set未生效导致部署到错误环境。4. 深度解析azd如何与 Azure 生态无缝协同4.1 与 Azure CLI (az) 的共生关系何时用哪个azd和az不是竞争关系而是分工明确的搭档。简单说azd管“应用生命周期”az管“资源生命周期”。场景推荐工具原因首次部署一个新 AI 应用azd up自动处理所有依赖、配置、密钥注入查看某个 App Service 的日志流az webapp log tail --name my-chatbot-devazd不提供日志查看az是唯一标准接口手动扩容 PostgreSQL 的 CPUaz postgres flexible-server update --name my-db --sku-name B2azd的模板定义了初始 SKU但弹性伸缩需az为现有资源组添加一个 Blob Storageaz storage account create --name mystorage --resource-group rg-my-chatbot-devazd只管理它创建的资源新增资源需az我们团队的 SOP 是所有新服务上线走azd所有运维操作监控、扩缩容、故障排查走az。azd生成的资源都有统一命名前缀如my-chatbot-dev-方便az命令批量操作# 查看所有 my-chatbot-dev 相关资源 az resource list --tag azd-appmy-chatbot-dev --query [].{name:name, type:type, location:location} -o table # 删除整个应用谨慎 az group delete --name rg-my-chatbot-dev --yes4.2 与 Azure Arc 的边界为什么azd不谈“混合云”热搜词里有azure arc 2025禁用这恰恰说明了azd的定位清醒。Azure Arc 是为“将 Azure 控制平面延伸到非 Azure 环境如本地数据中心、AWS、GCP”而生它解决的是“云不可控”场景。而azd的设计前提就是“你已在 Azure 上”它深度绑定 Azure 原生服务App Service、Container Apps、Azure OpenAI、AI Search并利用其托管能力如自动 TLS、内置 WAF、DDoS 防护。azd模板中所有type: azure-*的服务都要求部署在 Azure 公有云或 Azure Stack HCI需额外配置。它不支持type: arc-kubernetes或type: arc-sqlmi。这不是缺陷而是战略取舍——azd要做的是“在 Azure 上最快交付 AI 应用”而非“在任何地方交付 Azure 应用”。如果你的需求是“把模型部署到客户本地机房”azd不是答案但如果你的需求是“明天就要让销售团队用上新的 Copilot”azd就是答案。4.3 与 Ubuntu 22.04/24.04 升级的关系azd的 OS 无关性热搜里大量关于Ubuntu 22.04 升级到 24.04的问题其实和azd几乎无关。azdCLI 本身是跨平台二进制Windows/macOS/Linux它不关心宿主机 OS 版本。真正相关的是azd部署的目标环境若你用azd部署到Azure App Service底层 OS 由微软完全托管用户无法选择或升级。App Service for Linux 当前默认是 Ubuntu 22.04但微软会自动滚动升级你无需干预。若你用azd部署到Azure Container Apps你控制容器镜像因此可以自由选择基础镜像如ubuntu:24.04或python:3.12-slim-bookworm。azd只负责推送镜像和配置OS 升级是你 Dockerfile 的事。若你用azd部署到Azure Virtual Machinesazd模板会指定imageReference如publisher: Canonical, offer: 0001-com-ubuntu-server-jammy, sku: 22_04-lts这时你确实需要手动修改azure.yaml中的 SKU 为24_04-lts并azd provision。注意azd provision命令只更新基础设施IaC不重建应用。所以升级 VM OS 需两步1. 修改azure.yaml中的sku2. 运行azd provision。这比手动az vm image listaz vm update安全得多因为azd会校验新镜像是否兼容现有磁盘和网络配置。5. 常见问题与实战排障那些文档里没写的“血泪教训”5.1 经典报错“Error: failed to get credentials for registry” —— Docker 登录失效现象azd up卡在阶段 3构建镜像报错failed to get credentials for registry即使az login成功。根因azd使用 Azure Container RegistryACR作为镜像仓库它需要az acr login获取临时 token。但azd的 token 缓存机制有时会失效尤其在长时间未使用后。解决# 1. 显式登录 ACR替换 your-acr-name 为你的 ACR 名称 az acr login --name your-acr-name # 2. 清除 azd 缓存 azd cache clear # 3. 重试 azd up实操心得我们在 CI/CD 的 runner 上每次部署前都加一行az acr login --name $(azd env get-values --query acrName -o tsv)确保 token 总是新鲜的。5.2 “Connection refused” 错误不是网络问题是健康检查路径错了现象azd up成功但访问https://my-app.azurewebsites.net返回503 Service Unavailable日志显示Connection refused。根因azd默认的健康检查路径是/health但你的 FastAPI 应用可能只暴露了/或/api/health。azd在阶段 5 会不断请求/health超时后标记部署失败但应用其实已运行。解决在azure.yaml中自定义健康检查路径services: api: project: ./src host: azure-web-app # 添加以下配置 healthCheckPath: /api/health然后运行azd provision更新基础设施App Service 的 Health Check 设置。5.3 模型调用失败“Authentication failed for Azure OpenAI” —— Key Vault 权限链断裂现象应用日志显示Authentication failed for Azure OpenAI但AZURE_OPENAI_API_KEY在 Key Vault 中存在。根因azd为 App Service 创建的 Managed Identity默认没有Get权限访问 Key Vault。虽然azd up会尝试授权但在某些订阅策略下如启用 Azure Policy 禁止Microsoft.KeyVault/vaults/accessPolicies/write授权会静默失败。排查# 1. 获取 App Service 的 Managed Identity 名称 az webapp identity show --name my-chatbot-dev --resource-group rg-my-chatbot-dev --query principalId -o tsv # 2. 检查 Key Vault 的访问策略 az keyvault show --name kv-my-chatbot-dev --query properties.accessPolicies[?objectIdprincipalId-from-step1] -o json解决如果返回空则手动添加权限az keyvault set-policy \ --name kv-my-chatbot-dev \ --object-id principalId-from-step1 \ --secret-permissions get5.4azd与az订阅冲突为什么azd up部署到了错误的订阅现象azd up成功但资源出现在Production订阅而你期望在Dev订阅。根因azd优先读取AZURE_SUBSCRIPTION_ID环境变量其次读取az account show --query id -o tsv的输出最后才用azd env get-values。如果AZURE_SUBSCRIPTION_ID被意外设置azd会无视你az account set的选择。解决# 1. 检查环境变量 echo $AZURE_SUBSCRIPTION_ID # Linux/macOS echo %AZURE_SUBSCRIPTION_ID% # Windows # 2. 如果存在临时清除 unset AZURE_SUBSCRIPTION_ID # Linux/macOS set AZURE_SUBSCRIPTION_ID # Windows # 3. 确认 az account az account show --query {name:name, id:id} -o table # 4. 再次 azd up实操心得我们在团队中推行“环境变量白名单”禁止在.bashrc或.zshrc中设置AZURE_SUBSCRIPTION_ID所有订阅切换通过az account set --subscription id完成确保azd和az行为一致。6. 进阶技巧让azd成为你 AI 应用交付的“瑞士军刀”6.1 环境隔离用azd env管理 Dev/Staging/Prodazd内置环境管理比手动改azure.yaml安全百倍。创建 Staging 环境azd env new staging azd env set SUBSCRIPTION_ID staging-sub-id azd env set LOCATION West US azd upazd会自动创建新资源组rg-my-chatbot-staging使用staging后缀命名所有资源my-chatbot-staging-webapp将staging环境的配置保存在.azd/environments/staging/.env中切换环境只需azd env set-current staging azd deploy # 自动部署到 staging注意azd env不是 Git 分支它是独立的配置快照。.azd/environments/目录应加入.gitignore避免敏感信息泄露。6.2 自定义模板如何把内部 AI 模型服务封装成azd模板假设你有一个私有 vLLM 服务部署在 Azure VM 上。你想把它变成可复用的azd模板创建模板目录templates/vllm-vm编写azure.yamlname: vllm-vm metadata: template: vllm-vm0.1.0 parameters: vmSize: type: string default: Standard_NC6s_v3 services: vllm: type: azure-vm image: Canonical:0001-com-ubuntu-server-jammy:22_04-lts:latest size: ${parameters.vmSize} # 自定义初始化脚本 customData: | #cloud-config runcmd: - apt-get update apt-get install -y docker.io - docker run -d --gpus all -p 8000:8000 --shm-size1g -e HUGGING_FACE_HUB_TOKEN${secrets.HF_TOKEN} vllm/vllm-openai:latest --model meta-llama/Llama-2-7b-chat-hf将模板发布到内部 Git 仓库团队成员使用azd init --template-url https://internal-git/vllm-vm这样每个项目都能用azd init -t vllm-vm一键获得预配置的 vLLM 服务无需重复研究 GPU 驱动、Docker 参数。6.3 与 GitHub Actions 深度集成实现 PR 触发的预览环境azd模板自带.github/workflows/azd-deploy.yml。我们增强它实现“Pull Request 预览”name: Preview on PR on: pull_request: branches: [main] types: [opened, synchronize, reopened] jobs: preview: runs-on: ubuntu-latest steps: - uses: actions/checkoutv4 - name: Login to Azure uses: azure/loginv1 with: creds: ${{ secrets.AZURE_CREDENTIALS }} - name: Install azd run: curl -fsSL https://aka.ms/install-azd.sh | bash - name: Deploy Preview run: | export AZURE_ENV_NAMEpr-${{ github.event.number }} azd env new $AZURE_ENV_NAME azd env set SUBSCRIPTION_ID ${{ secrets.AZURE_SUBSCRIPTION_ID }} azd env set LOCATION East US azd up --no-prompt env: AZURE_ENV_NAME: pr-${{ github.event.number }} - name: Comment Preview URL run: | echo Preview deployed: https://my-chatbot-pr-${{ github.event.number }}.azurewebsites.net $GITHUB_STEP_SUMMARY每次 PR都会创建一个独立的pr-123环境URL 唯一评审者可直接点击测试合并后自动销毁通过azd env down。我在实际使用中发现azd最大的价值不是节省时间而是消灭了“在我机器上是好的”这类沟通黑洞。当azure.yaml成为部署的唯一真相源当azd up是团队里每个人都能执行的确定性操作AI 应用的交付就从艺术变成了工程。它不承诺解决所有问题但它把“部署”这件事从一个需要资深 Azure 专家介入的高风险环节降维成一个普通开发者敲几行命令就能完成的日常任务。这正是工具该有的样子——不喧宾夺主却让主角你的 AI 应用毫无阻碍地登上舞台。