教程:使用 Azure CLI 将 Dapr 应用程序部署到 Azure 容器应用

Dapr (Distributed Application Runtime) 可帮助开发人员构建可复原的可靠微服务。 在本教程中,示例 Dapr 应用程序部署到 Azure 容器应用。

学习如何:

  • 为容器应用创建容器应用环境
  • 为容器应用创建 Azure Blob 存储状态存储
  • 部署两个生成和使用消息的应用,并将其保留在状态存储中
  • 验证两项微服务之间的交互情况。

使用 Azure 容器应用,你可以在生成微服务时获得完全托管的 Dapr API 版本。 在 Azure 容器应用中使用 Dapr 时,可以让挎斗在提供一组丰富功能的微服务旁边运行。 可用的 Dapr API 包括服务到服务调用发布/订阅事件绑定状态存储参与者

在本教程中,你将通过 Dapr Hello World 快速入门部署相同的应用程序。

此应用程序包括:

  • 用于生成消息的客户端 (Python) 容器应用。
  • 一个服务(节点)容器应用,用于在状态存储中消费和持久化这些消息

下面的体系结构关系图说明了构成本教程的组件:

Azure 容器应用上的 Dapr Hello World 微服务的体系结构关系图

设置

若要从 CLI 登录到 Azure,请运行以下命令,然后按照提示完成身份验证过程。

az cloud set -n AzureChinaCloud
az login
# az cloud set -n AzureCloud   //means return to Public Azure.

为了确保运行最新版本的 CLI,请运行升级命令。

az upgrade

接下来,安装或更新适用于 CLI 的 Azure 容器应用扩展。

如果在 Azure CLI 中运行 az containerapp 命令,或在 Azure PowerShell 中运行 Az.App 模块中的 cmdlet 时收到有关缺少参数的错误,请确保已安装最新版本的 Azure 容器应用扩展。

az extension add --name containerapp --upgrade

注意

从 2024 年 5 月开始,Azure CLI 扩展不再默认启用预览功能。 要访问容器应用预览功能,请使用 --allow-preview true 安装容器应用扩展。

az extension add --name containerapp --upgrade --allow-preview true

现在已安装当前扩展或模块,接下来请注册 Microsoft.AppMicrosoft.OperationalInsights 命名空间。

注意

Azure 容器应用资源已从 Microsoft.Web 命名空间迁移到 Microsoft.App 命名空间。 如需更多详细信息,请参阅 2022 年 3 月的从 Azure.Web 到 Microsoft.App 的命名空间迁移

az provider register --namespace Microsoft.App
az provider register --namespace Microsoft.OperationalInsights

设置环境变量。

设置以下环境变量。 将 <PLACEHOLDERS> 替换为你自己的值:

RESOURCE_GROUP="<RESOURCE_GROUP>"
LOCATION="<LOCATION>"
CONTAINERAPPS_ENVIRONMENT="<CONTAINERAPPS_ENVIRONMENT>"

创建 Azure 资源组

创建一个资源组来组织与你的容器应用部署相关的服务。

az group create \
  --name $RESOURCE_GROUP \
  --location "$LOCATION"

创建环境

Azure 容器应用中的环境围绕一组容器应用创建安全边界。 部署到相同环境的容器应用部署在同一虚拟网络中,并将日志写入同一个 Log Analytics 工作区。

若要创建环境,请运行以下命令:

az containerapp env create \
  --name $CONTAINERAPPS_ENVIRONMENT \
  --resource-group $RESOURCE_GROUP \
  --location "$LOCATION"

设置状态存储

创建 Azure Blob 存储帐户

部署环境后,下一步是部署由微服务之一用来存储数据的 Azure Blob 存储帐户。 在部署服务之前,需要为存储帐户选择一个名称。 存储帐户名称在 Azure 中必须是唯一的,长度为 3 到 24 个字符,并且只能包含数字和小写字母。

STORAGE_ACCOUNT_NAME="<storage account name>"

使用以下命令创建 Azure 存储帐户。

az storage account create \
  --name $STORAGE_ACCOUNT_NAME \
  --resource-group $RESOURCE_GROUP \
  --location "$LOCATION" \
  --sku Standard_RAGRS \
  --kind StorageV2

为节点应用配置用户分配的标识

虽然容器应用同时支持用户分配的托管标识和系统分配的托管标识,但用户分配的标识为已启用 Dapr 的节点应用提供访问 Blob 存储帐户的权限。

  1. 创建用户分配的标识。
az identity create --resource-group $RESOURCE_GROUP --name "nodeAppIdentity" --output json

检索 principalIdid 属性并将其存储在变量中。

PRINCIPAL_ID=$(az identity show -n "nodeAppIdentity" --resource-group $RESOURCE_GROUP --query principalId | tr -d \")
IDENTITY_ID=$(az identity show -n "nodeAppIdentity" --resource-group $RESOURCE_GROUP --query id | tr -d \")
CLIENT_ID=$(az identity show -n "nodeAppIdentity" --resource-group $RESOURCE_GROUP --query clientId | tr -d \")
  1. Storage Blob Data Contributor 角色分配给用户分配的标识

检索当前订阅的订阅 ID。

SUBSCRIPTION_ID=$(az account show --query id --output tsv)
az role assignment create --assignee $PRINCIPAL_ID  \
--role "Storage Blob Data Contributor" \
--scope "/subscriptions/$SUBSCRIPTION_ID/resourceGroups/$RESOURCE_GROUP/providers/Microsoft.Storage/storageAccounts/$STORAGE_ACCOUNT_NAME"

配置状态存储组件

可使用多种方式通过 Dapr 向外部资源进行身份验证。 此示例在运行时不是使用 Dapr 机密 API,而是使用基于 Azure 的状态存储。 因此,可以放弃创建机密存储组件,改为提供使用托管标识从节点应用直接访问 Blob 存储的权限。 如果要在运行时使用非 Azure 状态存储或 Dapr 机密 API,可以创建机密存储组件。 此组件会加载运行时机密,因此你可以在运行时引用它们。

打开文本编辑器并创建名为 statestore.yaml 的配置文件,该文件拥有你在前面的步骤中提供的属性。 此文件可帮助 Dapr 应用访问状态存储。 以下示例显示了当为 Azure Blob 存储帐户配置了 statestore.yaml 文件时,该文件的外观:

# statestore.yaml for Azure Blob storage component
componentType: state.azure.blobstorage
version: v1
metadata:
  - name: accountName
    value: "<STORAGE_ACCOUNT_NAME>"
  - name: containerName
    value: mycontainer
  - name: azureClientId
    value: "<MANAGED_IDENTITY_CLIENT_ID>"
scopes:
  - nodeapp

若要使用此文件,请更新占位符:

  • <STORAGE_ACCOUNT_NAME> 替换为你定义的 STORAGE_ACCOUNT_NAME 变量的值。 若要获取其值,请运行以下命令:
echo $STORAGE_ACCOUNT_NAME
  • <MANAGED_IDENTITY_CLIENT_ID> 替换为你定义的 CLIENT_ID 变量的值。 若要获取其值,请运行以下命令:
echo $CLIENT_ID

导航到存储了组件 yaml 文件的目录,运行以下命令,以在容器应用环境中配置 Dapr 组件。 有关配置 Dapr 组件的详细信息,请参阅配置 Dapr 组件

az containerapp env dapr-component set \
    --name $CONTAINERAPPS_ENVIRONMENT --resource-group $RESOURCE_GROUP \
    --dapr-component-name statestore \
    --yaml statestore.yaml

部署服务应用程序(HTTP Web 服务器)

az containerapp create \
  --name nodeapp \
  --resource-group $RESOURCE_GROUP \
  --user-assigned $IDENTITY_ID \
  --environment $CONTAINERAPPS_ENVIRONMENT \
  --image dapriosamples/hello-k8s-node:latest \
  --min-replicas 1 \
  --max-replicas 1 \
  --enable-dapr \
  --dapr-app-id nodeapp \
  --dapr-app-port 3000 \
  --env-vars 'APP_PORT=3000'

如果使用 Azure 容器注册表,则在命令中包含 --registry-server <REGISTRY_NAME>.azurecr.cn 标志。

默认情况下,将从 Docker Hub 拉取映像。

部署客户端应用程序(无外设客户端)

运行以下命令以部署客户端容器应用。

az containerapp create \
  --name pythonapp \
  --resource-group $RESOURCE_GROUP \
  --environment $CONTAINERAPPS_ENVIRONMENT \
  --image dapriosamples/hello-k8s-python:latest \
  --min-replicas 1 \
  --max-replicas 1 \
  --enable-dapr \
  --dapr-app-id pythonapp

如果使用 Azure 容器注册表,则在命令中包含 --registry-server <REGISTRY_NAME>.azurecr.cn 标志。

验证结果

确认状态持久性是否成功

可以通过查看 Azure 存储帐户中的数据来确认服务是否正常工作。

  1. 在浏览器中打开 Azure 门户并导航到存储帐户。

  2. 选择“容器”左侧菜单。

  3. 选择“mycontainer”。

  4. 验证是否可以在容器中看到名为 order 的文件。

  5. 选择文件。

  6. 选择“编辑”选项卡。

  7. 选择“刷新”按钮以观察数据自动更新的方式。

查看日志

容器应用中的日志存储在 Log Analytics 工作区的 ContainerAppConsoleLogs_CL 自定义表中。 可通过 Azure 门户或 CLI 查看日志。 表出现在工作区中时,一开始可能会有小的延迟。

通过命令行使用以下 CLI 命令查看日志。

LOG_ANALYTICS_WORKSPACE_CLIENT_ID=`az containerapp env show --name $CONTAINERAPPS_ENVIRONMENT --resource-group $RESOURCE_GROUP --query properties.appLogsConfiguration.logAnalyticsConfiguration.customerId --out tsv`

az monitor log-analytics query \
  --workspace $LOG_ANALYTICS_WORKSPACE_CLIENT_ID \
  --analytics-query "ContainerAppConsoleLogs_CL | where ContainerAppName_s == 'nodeapp' and (Log_s contains 'persisted' or Log_s contains 'order') | project ContainerAppName_s, Log_s, TimeGenerated | sort by TimeGenerated | take 5" \
  --out table

以下输出演示了期望从 CLI 命令获得的响应类型。

ContainerAppName_s    Log_s                            TableName      TimeGenerated
-------------------- -------------------------------  ------------- ------------------------
nodeapp               Got a new order! Order ID: 61    PrimaryResult  2021-10-22T21:31:46.184Z
nodeapp               Successfully persisted state.    PrimaryResult  2021-10-22T21:31:46.184Z
nodeapp               Got a new order! Order ID: 62    PrimaryResult  2021-10-22T22:01:57.174Z
nodeapp               Successfully persisted state.    PrimaryResult  2021-10-22T22:01:57.174Z
nodeapp               Got a new order! Order ID: 63    PrimaryResult  2021-10-22T22:45:44.618Z

清理资源

祝贺你! 你已完成此教程。 如果要删除在本演练过程中创建的资源,请运行以下命令。

注意

此命令删除指定的资源组及其包含的所有资源。 如果指定的资源组中存在本教程范围外的资源,这些资源也会被删除。

az group delete --resource-group $RESOURCE_GROUP

注意

由于 pythonapp 通过持久保存在配置的状态存储中的消息持续调用 nodeapp,因此请务必完成这些清理步骤,以免计费操作持续进行。

提示

遇到问题? 在 Azure 容器应用存储库中提交问题,告知我们有关 GitHub 的信息。

后续步骤