Azure Developer CLI:使用分层基础设施实现Azure容器应用开发到生产部署
本文介绍如何使用Azure Developer CLI v1.20.0中的新azd publish和分层基础设施功能,在Azure容器应用中实现"一次构建,随处部署"模式。您将学习如何在多个环境中部署相同的容器化应用程序,并实现适当的关注点分离。
这是我们Azure Developer CLI系列的第三部分,基于我们之前的探索:
- Azure应用服务和GitHub Actions
- Azure DevOps流水线
一次构建,随处部署
我们解决的挑战
如果您在生产环境中使用过容器,可能遇到过这个问题:azd deploy将所有操作捆绑在一起——构建容器、推送到注册表以及部署——一次性完成。虽然这对开发非常方便,但在生产场景中会带来一些麻烦:
- 您希望在所有环境中使用单个Azure容器注册表(ACR)
- 您需要一次构建并在各处部署,而无需重新构建容器
- 您需要对部署到生产的特定容器版本进行安全控制
- 您需要灵活性,以便在每个环境中使用不同配置部署相同的容器
从本系列之前的文章中学习
在我们前两篇博客文章中讨论了使用Azure应用服务的开发到生产模式后,我们意识到azd中的Azure容器应用支持存在一些限制,阻碍了团队有效实施相同的"一次构建,随处部署"模式。azd团队在最近的版本中解决了这些差距。
Azure Developer CLI v1.20.0引入了两个解决这些挑战的功能:
-
分离的容器操作
azd publish:构建容器并将其推送到注册表
azd deploy --from-package:将特定容器版本部署到环境(无需重新构建)
-
分层基础设施(Alpha功能)
- 通过适当的依赖管理按顺序部署基础设施层
- 在环境间共享ACR等资源,同时保持环境特定内容分离
- 早期层的输出自动成为后续层的输入
我将使用从Azure应用服务迁移到Azure容器应用的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
|
┌─────────────────────────────────────────────────────────────────┐
│ 共享资源 │
│ ┌─────────────────────────────────────────────────────────────┐│
│ │ 资源组: rg-acr-shared ││
│ │ ┌─────────────────────────────────────────────────────────┐ ││
│ │ │ Azure容器注册表 (Basic SKU) │ ││
│ │ │ - 存储所有环境的容器镜像 │ ││
│ │ │ - 应用程序容器的单一事实来源 │ ││
│ │ └─────────────────────────────────────────────────────────┘ ││
│ └─────────────────────────────────────────────────────────────┘│
└─────────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────────┐
│ 开发环境 │
│ ┌─────────────────────────────────────────────────────────────┐│
│ │ 资源组: rg-dev-environment ││
│ │ ┌─────────────────────────────────────────────────────────┐ ││
│ │ │ 容器应用环境 │ ││
│ │ │ ┌─────────────────────────────────────────────────────┐ │ ││
│ │ │ │ 容器应用 (Flask应用) │ │ ││
│ │ │ │ - 用于ACR访问的托管身份 │ │ ││
│ │ │ │ - 启用自动缩放 │ │ ││
│ │ │ └─────────────────────────────────────────────────────┘ │ ││
│ │ └─────────────────────────────────────────────────────────┘ ││
│ │ Azure存储账户 | Key Vault | Application Insights ││
│ └─────────────────────────────────────────────────────────────┘│
└─────────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────────┐
│ 生产环境 │
│ ┌─────────────────────────────────────────────────────────────┐│
│ │ 资源组: rg-prod-environment ││
│ │ ┌─────────────────────────────────────────────────────────┐ ││
│ │ │ 容器应用环境 (VNET集成) │ ││
│ │ │ ┌─────────────────────────────────────────────────────┐ │ ││
│ │ │ │ 容器应用 (与开发环境相同的镜像) │ │ ││
│ │ │ │ - 增强的安全配置 │ │ ││
│ │ │ │ - 生产级缩放规则 │ │ ││
│ │ │ └─────────────────────────────────────────────────────┘ │ ││
│ │ └─────────────────────────────────────────────────────────┘ ││
│ │ VNET | 存储 | Key Vault | App Insights | 监控 ││
│ └─────────────────────────────────────────────────────────────┘│
└─────────────────────────────────────────────────────────────────┘
|
分层基础设施配置
以下是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容器应用演示:使用共享ACR实现"一次构建,随处部署"
name: dev-prod
# 分层基础设施部署策略
infra:
layers:
# 第1层:基础 - 每个环境的核心基础设施
- name: foundation
path: infra/foundation
# 第2层:共享ACR - 所有环境的单一注册表
- name: shared-acr
path: infra/shared-acr
# 第3层:ACR角色分配 - 安全配置
- name: acr-role
path: infra/acr-role
# 第4层:容器应用 - 应用程序部署
- 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如何从共享ACR层流入ACR角色分配层:
1
|
"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
47
48
|
┌─────────────────────────────────────────────────────────────────┐
│ GitHub Actions工作流 │
└─────────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────────┐
│ 作业1: 构建 │
│ ┌─────────────────────────────────────────────────────────────┐ │
│ │ 1. 启用alpha功能(分层基础设施) │ │
│ │ 2. 设置环境名称(开发/生产) │ │
│ │ 3. 使用Azure登录(联合凭据) │ │
│ │ 4. 配置基础设施(开发环境) │ │
│ │ 5. 构建和发布容器到ACR │ │
│ │ └─ azd publish app │ │
│ │ └─ 获取镜像: azd env get-value SERVICE_APP_IMAGE_NAME │ │
│ └─────────────────────────────────────────────────────────────┘ │
│ │
│ 输出: │
│ • container-image: crXXXX.azurecr.io/app:azd-deploy-123456 │
│ • dev-env-name: myapp-dev │
│ • prod-env-name: myapp-prod │
└──────────────────────────────┬──────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────┐
│ 作业2: 部署-开发 │
│ ┌─────────────────────────────────────────────────────────────┐ │
│ │ 1. 启用alpha功能(分层基础设施) │ │
│ │ 2. 使用Azure登录(联合凭据) │ │
│ │ 3. 部署到开发环境 │ │
│ │ └─ azd deploy app --from-package <container-image> │ │
│ │ 4. 验证应用程序 │ │
│ │ └─ 运行验证测试、冒烟测试 │ │
│ └─────────────────────────────────────────────────────────────┘ │
└──────────────────────────────┬──────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────┐
│ 作业3: 部署-生产 │
│ ┌─────────────────────────────────────────────────────────────┐ │
│ │ 1. 启用alpha功能(分层基础设施) │ │
│ │ 2. 使用Azure登录(联合凭据) │ │
│ │ 3. 部署到生产环境 │ │
│ │ └─ azd deploy app --from-package <same container-image> │ │
│ │ └─ 使用环境变量中的共享ACR │ │
│ └─────────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────┘
关键:相同的容器镜像(一次构建)部署到两个环境
|
您可以在存储库的azure-dev.yml文件中查看完整的工作流实现。
需要注意的关键事项:
- 容器在构建阶段仅构建一次
azd env get-value SERVICE_APP_IMAGE_NAME获取已发布的镜像名称
- 开发和生产都部署完全相同的容器镜像
- 验证步骤在阶段之间充当质量门
注意:此工作流使用GitHub Actions作业输出在作业之间传递容器镜像名称。这仅在GitHub托管的运行器上有效。如果您使用自托管运行器,您需要不同的方法——可能将镜像名称存储在工件中或使用其他方法在作业之间共享数据。
总结
本文介绍了如何使用Azure Developer CLI v1.20.0中的新功能,在Azure容器应用中实现"一次构建,随处部署"模式。基于我们之前关于Azure应用服务的文章,这种容器应用方法展示了相同的核心原则如何在不同的Azure计算服务中工作。
分层基础设施和分离的容器操作(azd publish + azd deploy --from-package)的组合为您提供了坚实的基础,当您准备超越azd up的简单性但仍希望保持熟悉的azd开发人员体验时。
我们涵盖的内容:
- 容器应用集成:
azd如何与Azure容器应用开箱即用
- 分层基础设施:具有适当依赖管理的顺序部署
- 环境分离:保持开发便利性,同时添加生产就绪的控制
没有一种部署到生产的单一方法,根据组织需求,甚至有更复杂的方法。高级网络、复杂的合规性要求、不同的部署策略等;具体实现将根据您团队的情况而有所不同。我们希望这为您提供了一个起点和要遵循的示例。
我们正在继续探索和验证使用Azure Developer CLI的生产部署场景,确保随着您的应用程序从开发发展到生产,azd提供可靠的模式。