Azure Developer CLI:Azure Container Apps从开发到生产的部署与分层基础设施
本指南将介绍如何使用Azure Developer CLI v1.20.0中的新功能——azd publish和分层基础设施——来实现Azure Container Apps的“一次构建,随处部署”模式。您将学习如何跨多个环境部署相同的容器化应用程序,同时保持适当的关注点分离。
这是Azure Developer CLI系列的第三部分,基于我们之前的探索:
- Azure App Service与GitHub Actions
- Azure DevOps管道
一次构建,随处部署
我们正在解决的挑战
如果您在生产环境中使用过容器,您可能遇到过这个问题:azd deploy将所有步骤捆绑在一起——构建容器、推送到注册表以及部署——一次性完成。这对于开发来说非常方便,但在生产场景中会带来一些麻烦:
- 您希望在所有环境中使用同一个Azure容器注册表(ACR)
- 您需要一次构建,随处部署,无需重建容器
- 您需要对部署到生产环境的特定容器版本进行安全控制
- 您需要灵活性,以便在不同环境中使用不同配置部署同一容器
从本系列之前的文章中学习
在前两篇博客文章中讨论了Azure App Service的开发到生产模式后,我们意识到azd对Azure Container Apps的支持存在一些限制,阻碍了团队有效实施相同的“一次构建,随处部署”模式。azd团队在最近的版本中解决了这些差距。
Azure Developer CLI v1.20.0引入了两项解决这些挑战的功能:
-
分离的容器操作
azd publish:构建容器并将其推送到注册表
azd deploy --from-package:将特定容器版本部署到环境中(无需重建)
-
分层基础设施(Alpha功能)
- 以顺序层的方式部署基础设施,并管理适当的依赖关系
- 跨环境共享资源(如ACR),同时保持环境特定的资源分离
- 早期层的输出自动成为后续层的输入
我将通过一个从Azure App Service迁移到Azure Container Apps的Flask应用程序示例向您展示其工作原理。
示例应用程序
我们正在构建什么
该示例应用程序是一个简单的基于Flask的文件管理器,用于演示关键概念:
- 功能:上传文件、列出文件和查看文件(全部由Azure Blob Storage支持)
- 安全方法:使用Azure托管标识(不存储任何连接字符串)
基础设施的组织方式
我没有将所有内容都塞进一个大模板中,而是采用了一种分层方法,将共享资源与环境特定的资源分开组织:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
|
┌─────────────────────────────────────────────────────────────────┐
│ Shared Resources │
│ ┌─────────────────────────────────────────────────────────────┐│
│ │ Resource Group: rg-acr-shared ││
│ │ ┌─────────────────────────────────────────────────────────┐ ││
│ │ │ Azure Container Registry (Basic SKU) │ ││
│ │ │ - Stores container images for all environments │ ││
│ │ │ - Single source of truth for application containers │ ││
│ │ └─────────────────────────────────────────────────────────┘ ││
│ └─────────────────────────────────────────────────────────────┘│
└─────────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────────┐
│ Development Environment │
│ ┌─────────────────────────────────────────────────────────────┐│
│ │ Resource Group: rg-dev-environment ││
│ │ ┌─────────────────────────────────────────────────────────┐ ││
│ │ │ Container Apps Environment │ ││
│ │ │ ┌─────────────────────────────────────────────────────┐ │ ││
│ │ │ │ Container App (Flask Application) │ │ ││
│ │ │ │ - Managed Identity for ACR access │ │ ││
│ │ │ │ - Auto-scaling enabled │ │ ││
│ │ │ └─────────────────────────────────────────────────────┘ │ ││
│ │ └─────────────────────────────────────────────────────────┘ ││
│ │ Azure Storage Account | Key Vault | Application Insights ││
│ └─────────────────────────────────────────────────────────────┘│
└─────────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────────┐
│ Production Environment │
│ ┌─────────────────────────────────────────────────────────────┐│
│ │ Resource Group: rg-prod-environment ││
│ │ ┌─────────────────────────────────────────────────────────┐ ││
│ │ │ Container Apps Environment (VNET-integrated) │ ││
│ │ │ ┌─────────────────────────────────────────────────────┐ │ ││
│ │ │ │ Container App (Same Image as Dev) │ │ ││
│ │ │ │ - Enhanced security configuration │ │ ││
│ │ │ │ - Production-grade scaling rules │ │ ││
│ │ │ └─────────────────────────────────────────────────────┘ │ ││
│ │ └─────────────────────────────────────────────────────────┘ ││
│ │ VNET | Storage | Key Vault | App Insights | Monitoring ││
│ └─────────────────────────────────────────────────────────────┘│
└─────────────────────────────────────────────────────────────────┘
|
分层基础设施配置
以下是在azure.yaml文件中定义的序列:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
|
# Azure Container Apps Demo: "Build Once, Deploy Everywhere" with Shared ACR
name: dev-prod
# Layered Infrastructure Deployment Strategy
infra:
layers:
# Layer 1: Foundation - Core infrastructure for each environment
- name: foundation
path: infra/foundation
# Layer 2: Shared ACR - Single registry for all environments
- name: shared-acr
path: infra/shared-acr
# Layer 3: ACR Role Assignment - Security configuration
- name: acr-role
path: infra/acr-role
# Layer 4: Container App - Application deployment
- name: container-app
path: infra/container-app
services:
app:
project: .
host: containerapp
language: python
|
这种分层方法解决了容器部署中典型的“先有鸡还是先有蛋”问题。开发和生产环境需要共享同一个ACR。您的生产环境容器应用需要权限才能从ACR拉取镜像,但在容器应用标识和ACR实际存在之前,您无法分配这些权限。通过以正确的顺序预配资源,我们确保所有资源都能获得所需的权限。
以下是各层的工作方式:
- 基础层:根据您的
AZURE_ENV_TYPE设置核心资源——包括容器应用环境和托管标识
- 共享ACR层:创建您的集中式容器注册表(除非您已经有一个)
- ACR角色分配层:这是魔法发生的地方——为您的托管标识授予正确的权限(开发环境获得推送+拉取权限,生产环境仅获得拉取权限)
- 容器应用层:最终部署您的应用程序,现在它已经具有适当的ACR访问权限
每一层都会输出后续层所需的内容——资源ID、端点等——而azd会自动将这些输出作为输入传递给下一层。
例如,如果您查看infra/acr-role/main.parameters.json,您会看到AZURE_CONTAINER_REGISTRY_NAME如何从shared-acr层流入ACR角色分配层:
"AZURE_CONTAINER_REGISTRY_NAME": { "value": "${AZURE_CONTAINER_REGISTRY_NAME}"}
动手尝试
生产环境现实检查
虽然我将向您展示如何使用azd up在本地进行部署,但请在生产部署中使用CI/CD管道。我在这里演示的本地工作流程非常适合快速原型设计和开发,但对于任何重要的事情,您都需要适当的CI/CD控制。
先决条件
- Azure Developer CLI v1.20.0或更高版本(在此下载)
- Docker(用于本地容器测试)
1. 克隆示例仓库
1
|
azd init -t https://github.com/puicchan/azd-dev-prod-aca-storage
|
2. 设置您的开发环境
开发环境设置使用您可能已经熟悉的azd up工作流程:
1
2
3
4
5
6
7
8
9
|
# 启用分层基础设施的Alpha功能
azd config set alpha.layers on
# 创建并配置开发环境
azd env new myapp-dev
azd env set AZURE_ENV_TYPE dev
# 部署所有内容:基础设施 + 构建 + 推送 + 部署
azd up
|
3. 准备您的生产基础设施
现在您需要设置生产环境基础设施。这通常是在设置CI/CD管道之前的一次性操作:
1
2
3
4
5
6
7
8
9
10
|
# 创建生产环境
azd env new myapp-prod
azd env set AZURE_ENV_TYPE prod
# 引用现有的共享ACR(替换为从开发部署中获取的实际值)
azd env set ACR_RESOURCE_GROUP_NAME rg-shared-acr-resource-group-name
azd env set AZURE_CONTAINER_REGISTRY_ENDPOINT shared-acr-endpoint
# 仅预配基础设施(不构建/推送/部署)
azd provision
|
关于基础设施的关键说明
- 我在这里本地使用
azd provision是为了在正式上线前设置基础设施。在您的CI/CD管道中,绝对不要运行azd provision——只使用azd deploy。生产环境的基础设施变更应经过适当的审批流程,因为意外修改可能导致服务中断。
- 当
envType = 'prod'时,基础设施会自动包含VNET集成。出于演示目的(便于测试),我在aca-environment.bicep的第42行设置了internal: false,因此您的应用程序保持公开可访问,而计算资源是隔离的。对于真正的私有环境,您可以将其切换为internal: true并添加反向代理。
4. 设置CI/CD管道
现在是激动人心的部分——让我们看看管道的实际运行!进行一个简单的代码更改并提交。
例如,修改index.html中的<h1>标签,然后运行:
1
2
3
4
|
# 选择您的开发环境并配置管道
azd env select myapp-dev
# 当提示时,确保选择GitHub作为管道提供程序
azd pipeline config
|
需要注意的事项:
- GitHub Actions选项卡:转到您仓库的Actions选项卡
- 构建阶段:观察容器如何以唯一标签构建
- 开发部署:查看其自动部署到开发环境
- 同一容器,处处运行:检查两个环境——它们正在运行完全相同的容器镜像
GitHub Actions工作流程如何运作
该工作流程遵循清晰的三阶段模式:构建 → 部署-开发 → 部署-生产
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
|
┌─────────────────────────────────────────────────────────────────┐
│ GitHub Actions Workflow │
└─────────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────────┐
│ Job 1: BUILD │
│ ┌─────────────────────────────────────────────────────────────┐ │
│ │ 1. Enable alpha features (layered infrastructure) │ │
│ │ 2. Set environment names (dev/prod) │ │
│ │ 3. Log in with Azure (Federated Credentials) │ │
│ │ 4. Provision Infrastructure (dev environment) │ │
│ │ 5. Build & Publish Container to ACR │ │
│ │ └─ azd publish app │ │
│ │ └─ Get image: azd env get-value SERVICE_APP_IMAGE_NAME │ │
└─────────────────────────────────────────────────────────────┘ │
│ │
│ Outputs: │
│ • container-image: crXXXX.azurecr.io/app:azd-deploy-123456 │
│ • dev-env-name: myapp-dev │
│ • prod-env-name: myapp-prod │
└──────────────────────────────┬──────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────┐
│ Job 2: DEPLOY-DEV │
│ ┌─────────────────────────────────────────────────────────────┐ │
│ │ 1. Enable alpha features (layered infrastructure) │ │
│ │ 2. Log in with Azure (Federated Credentials) │ │
│ │ 3. Deploy to Development │ │
│ │ └─ azd deploy app --from-package <container-image> │ │
│ │ 4. Validate Application │ │
│ │ └─ Run validation tests, smoke tests │ │
└─────────────────────────────────────────────────────────────┘ │
└──────────────────────────────┬──────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────┐
│ Job 3: DEPLOY-PROD │
│ ┌─────────────────────────────────────────────────────────────┐ │
│ │ 1. Enable alpha features (layered infrastructure) │ │
│ │ 2. Log in with Azure (Federated Credentials) │ │
│ │ 3. Deploy to Production │ │
│ │ └─ azd deploy app --from-package <same container-image> │ │
│ │ └─ Uses shared ACR from environment variables │ │
└─────────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────┘
|
关键点:同一容器镜像(一次构建)部署到两个环境
您可以在仓库的azure-dev.yml文件中查看完整的工作流程实现。
需要注意的关键事项:
- 容器在构建阶段仅构建一次
azd env get-value SERVICE_APP_IMAGE_NAME获取已发布的镜像名称
- 开发和生产环境都部署完全相同的容器镜像
- 验证步骤充当阶段之间的质量关卡
注意:此工作流程使用GitHub Actions作业输出来在作业之间传递容器镜像名称。这仅适用于GitHub托管的运行器。如果您使用自托管运行器,则需要不同的方法——可能将镜像名称存储在工件中,或使用其他方法在作业之间共享数据。
总结
本指南介绍了如何使用Azure Developer CLI v1.20.0中的新功能,在Azure Container Apps中实现“一次构建,随处部署”模式。基于我们之前关于Azure App Service的文章,这种Container Apps方法展示了相同的核心原则如何跨不同的Azure计算服务工作。
分层基础设施和分离的容器操作(azd publish + azd deploy --from-package)的结合为您奠定了坚实的基础,当您准备超越azd up的简单性,但仍希望保持熟悉的azd开发者体验时。
我们涵盖的内容:
- 容器应用集成:
azd如何与Azure Container Apps开箱即用
- 分层基础设施:具有适当依赖关系管理的顺序部署
- 环境分离:在保持开发便利性的同时,增加生产就绪的控制
没有一种固定的生产部署方式,根据组织的需求,甚至存在更复杂的方法。高级网络、复杂的合规性要求、不同的部署策略等;具体实现将根据您团队的情况而有所不同。我们希望这为您提供了一个起点和一个可遵循的示例。
我们将继续探索和验证Azure Developer CLI的生产部署场景,确保随着您的应用程序从开发发展到生产,azd能提供可靠的方法。
对实现有疑问或想分享您自己的方法?在此加入讨论。
有关更多Azure Developer CLI内容,请关注Azure Developer CLI博客并查看官方文档。