Azure容器应用分层架构开发到生产部署指南

本文详细介绍如何使用Azure Developer CLI v1.20.0的新功能实现"一次构建,随处部署"模式,通过分层基础设施和分离的容器操作,在多个环境中部署相同的容器化应用。

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引入了两个解决这些挑战的功能:

  1. 分离的容器操作

    • azd publish:构建容器并将其推送到注册表
    • azd deploy --from-package:将特定容器版本部署到环境(无需重新构建)
  2. 分层基础设施(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提供可靠的模式。

comments powered by Disqus
使用 Hugo 构建
主题 StackJimmy 设计