你当前正在访问 Microsoft Azure Global Edition 技术文档网站。 如果需要访问由世纪互联运营的 Microsoft Azure 中国技术文档网站,请访问 https://docs.azure.cn

教程:使用托管标识从 Java Quarkus 容器应用连接到 PostgreSQL 数据库,而无需使用机密

Azure 容器应用为应用提供托管标识,这是一项统包解决方案,可以确保安全地访问 Azure Database for PostgreSQL 和其他 Azure 服务。 容器应用中的托管标识可以让应用更安全,因为不需在应用中存储机密,例如环境变量中的凭据。

本教程将指导你完成在 Azure 上生成、配置、部署和缩放 Java 容器应用的过程。 在本教程结束时,你将有一个 Quarkus 应用程序,该应用程序在 PostgreSQL 数据库中存储数据,并在容器应用上运行一个托管标识。

要学习的知识:

  • 将 Quarkus 应用配置为使用 Microsoft Entra ID 和 PostgreSQL 数据库进行身份验证。
  • 创建 Azure 容器注册表并向其推送 Java 应用映像。
  • 在 Azure 中创建容器应用。
  • 在 Azure 中创建 PostgreSQL 数据库。
  • 使用服务连接器通过托管标识连接到 PostgreSQL 数据库。

如果没有 Azure 订阅,请在开始之前创建一个 Azure 免费帐户

1.先决条件

2. 创建容器注册表

使用“az group create”命令创建资源组。 Azure 资源组是在其中部署和管理 Azure 资源的逻辑容器。

以下示例在“美国东部”Azure 区域创建一个名为 myResourceGroup 的资源组。

RESOURCE_GROUP="myResourceGroup"
LOCATION="eastus"

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

使用 az acr create 命令创建 Azure 容器注册表实例,并使用 az acr show 命令检索其登录服务器。 注册表名称在 Azure 中必须唯一,并且包含 5-50 个字母数字字符。 必须以小写形式指定所有字母。 在以下示例中,使用了 mycontainerregistry007。 将其更新为唯一值。

REGISTRY_NAME=mycontainerregistry007
az acr create \
    --resource-group $RESOURCE_GROUP \
    --name $REGISTRY_NAME \
    --sku Basic

REGISTRY_SERVER=$(az acr show \
    --name $REGISTRY_NAME \
    --query 'loginServer' \
    --output tsv | tr -d '\r')

3. 克隆示例应用并准备容器映像

本教程使用示例 Fruits 列表应用,该应用的 Web UI 可以调用 Azure Database for PostgreSQL 支持的 Quarkus REST API。 GitHub 上提供了该应用的代码。 如需详细了解如何使用 Quarkus 和 PostgreSQL 编写 Java 应用,请参阅 Quarkus Hibernate ORM with Panache 指南Quarkus 数据源指南

在终端中运行以下命令,以克隆示例存储库并设置示例应用环境。

git clone https://github.com/quarkusio/quarkus-quickstarts
cd quarkus-quickstarts/hibernate-orm-panache-quickstart

修改项目

  1. 向项目 BOM 文件中添加所需的依赖项。

    <dependency>
       <groupId>com.azure</groupId>
       <artifactId>azure-identity-extensions</artifactId>
       <version>1.1.20</version>
    </dependency>
    
  2. 配置 Quarkus 应用属性。

    Quarkus 配置位于 src/main/resources/application.properties 文件中。 在编辑器中打开此文件,并观察几个默认属性。 只有当生成和部署应用程序时,才会使用前缀为%prod的属性,例如部署到Azure 应用服务时。 当应用程序在本地运行时, 将忽略%prod属性。 同样,%dev属性在 Quarkus 的实时编码/开发模式下使用,并在持续测试期间使用%test属性。

    删除 application.properties 中的现有内容,将其替换为以下内容,以将数据库配置为在开发、测试和生产模式下使用:

    quarkus.hibernate-orm.database.generation=drop-and-create
    quarkus.datasource.db-kind=postgresql
    quarkus.datasource.jdbc.max-size=8
    quarkus.datasource.jdbc.min-size=2
    quarkus.hibernate-orm.log.sql=true
    quarkus.hibernate-orm.sql-load-script=import.sql
    quarkus.datasource.jdbc.acquisition-timeout = 10
    
    %dev.quarkus.datasource.username=${CURRENT_USERNAME}
    %dev.quarkus.datasource.jdbc.url=jdbc:postgresql://${AZURE_POSTGRESQL_HOST}:${AZURE_POSTGRESQL_PORT}/${AZURE_POSTGRESQL_DATABASE}?\
    authenticationPluginClassName=com.azure.identity.extensions.jdbc.postgresql.AzurePostgresqlAuthenticationPlugin\
    &sslmode=require
    
    %prod.quarkus.datasource.username=${AZURE_POSTGRESQL_USERNAME}
    %prod.quarkus.datasource.jdbc.url=jdbc:postgresql://${AZURE_POSTGRESQL_HOST}:${AZURE_POSTGRESQL_PORT}/${AZURE_POSTGRESQL_DATABASE}?\
    authenticationPluginClassName=com.azure.identity.extensions.jdbc.postgresql.AzurePostgresqlAuthenticationPlugin\
    &sslmode=require
    
    %dev.quarkus.class-loading.parent-first-artifacts=com.azure:azure-core::jar,\
    com.azure:azure-core-http-netty::jar,\
    io.projectreactor.netty:reactor-netty-core::jar,\
    io.projectreactor.netty:reactor-netty-http::jar,\
    io.netty:netty-resolver-dns::jar,\
    io.netty:netty-codec::jar,\
    io.netty:netty-codec-http::jar,\
    io.netty:netty-codec-http2::jar,\
    io.netty:netty-handler::jar,\
    io.netty:netty-resolver::jar,\
    io.netty:netty-common::jar,\
    io.netty:netty-transport::jar,\
    io.netty:netty-buffer::jar,\
    com.azure:azure-identity::jar,\
    com.azure:azure-identity-extensions::jar,\
    com.fasterxml.jackson.core:jackson-core::jar,\
    com.fasterxml.jackson.core:jackson-annotations::jar,\
    com.fasterxml.jackson.core:jackson-databind::jar,\
    com.fasterxml.jackson.dataformat:jackson-dataformat-xml::jar,\
    com.fasterxml.jackson.datatype:jackson-datatype-jsr310::jar,\
    org.reactivestreams:reactive-streams::jar,\
    io.projectreactor:reactor-core::jar,\
    com.microsoft.azure:msal4j::jar,\
    com.microsoft.azure:msal4j-persistence-extension::jar,\
    org.codehaus.woodstox:stax2-api::jar,\
    com.fasterxml.woodstox:woodstox-core::jar,\
    com.nimbusds:oauth2-oidc-sdk::jar,\
    com.nimbusds:content-type::jar,\
    com.nimbusds:nimbus-jose-jwt::jar,\
    net.minidev:json-smart::jar,\
    net.minidev:accessors-smart::jar,\
    io.netty:netty-transport-native-unix-common::jar,\
    net.java.dev.jna:jna::jar
    

构建 Docker 映像并将其推送到容器注册表

  1. 生成容器映像。

    运行以下命令以生成 Quarkus 应用映像。 必须使用注册表登录服务器的完全限定的名称对它进行标记。

    CONTAINER_IMAGE=${REGISTRY_SERVER}/quarkus-postgres-passwordless-app:v1
    
    mvn quarkus:add-extension -Dextensions="container-image-jib"
    mvn clean package -Dquarkus.container-image.build=true -Dquarkus.container-image.image=${CONTAINER_IMAGE}
    
  2. 登录到注册表。

    在推送容器映像之前,必须登录到注册表。 为此,请使用 [az acr login][az-acr-login] 命令。

    az acr login --name $REGISTRY_NAME
    

    该命令在完成后会返回消息 Login Succeeded

  3. 将映像推送到注册表。

    使用 [docker push][docker-push] 将映像推送到注册表实例。 此示例创建 quarkus-postgres-passwordless-app 存储库,其中包含 quarkus-postgres-passwordless-app:v1 映像。

    docker push $CONTAINER_IMAGE
    

4. 在 Azure 上创建容器应用

  1. 通过运行以下命令创建容器应用实例。 请确保将环境变量的值替换为要使用的实际名称和位置。

    CONTAINERAPPS_ENVIRONMENT="my-environment"
    
    az containerapp env create \
        --resource-group $RESOURCE_GROUP \
        --name $CONTAINERAPPS_ENVIRONMENT \
        --location $LOCATION
    
  2. 通过运行以下命令来创建一个包含你的应用映像的容器应用:

    APP_NAME=my-container-app
    az containerapp create \
        --resource-group $RESOURCE_GROUP \
        --name $APP_NAME \
        --image $CONTAINER_IMAGE \
        --environment $CONTAINERAPPS_ENVIRONMENT \
        --registry-server $REGISTRY_SERVER \
        --registry-identity system \
        --ingress 'external' \
        --target-port 8080 \
        --min-replicas 1
    

    注意

    仍支持 --registry-username--registry-password 选项,但不建议使用,因为使用标识系统更安全。

5.创建 PostgreSQL 数据库并使用标识连接性来连接它

接下来,创建 PostgreSQL 数据库,并将容器应用配置为使用系统分配的托管标识连接到 PostgreSQL 数据库。 Quarkus 应用会在运行时连接到此数据库并存储自己的数据,无论你在哪里运行此应用程序,都会保存应用程序状态。

  1. 创建数据库服务。

    DB_SERVER_NAME='msdocs-quarkus-postgres-webapp-db'
    
    az postgres flexible-server create \
        --resource-group $RESOURCE_GROUP \
        --name $DB_SERVER_NAME \
        --location $LOCATION \
        --public-access None \
        --sku-name Standard_B1ms \
        --tier Burstable \
        --active-directory-auth Enabled
    

    注意

    仍支持 --admin-user--admin-password 选项,但不建议使用,因为使用标识系统更安全。

    上述 Azure CLI 命令使用以下参数:

    • resource-group → 使用在其中创建 Web 应用的相同资源组名称,例如 msdocs-quarkus-postgres-webapp-rg
    • name → PostgreSQL 数据库服务器名称。 此名称必须在整个 Azure 中唯一(服务器终结点将变为 https://<name>.postgres.database.azure.com)。 允许的字符有 A-Z0-9-。 良好的模式是结合使用公司名称和服务器标识符。 (msdocs-quarkus-postgres-webapp-db)
    • location → 使用用于 Web 应用的同一个位置。 如果它不起作用,请更换到其他位置。
    • public-access → None,即,将服务器设置为不使用防火墙规则的公共访问模式。 将在后面的步骤中创建规则。
    • sku-name → 定价层和计算配置的名称,例如 Standard_B1ms。 有关详细信息,请参阅 Azure Database for PostgreSQL 定价
    • 层级 →服务器的计算层。 有关详细信息,请参阅 Azure Database for PostgreSQL 定价
    • active-directory-auth → 设置为 Enabled 以启用 Microsoft Entra 身份验证。
  2. 使用以下命令在 PostgreSQL 服务中创建名为 fruits 的数据库:

    DB_NAME=fruits
    az postgres flexible-server db create \
        --resource-group $RESOURCE_GROUP \
        --server-name $DB_SERVER_NAME \
        --database-name $DB_NAME
    
  3. 为 Azure CLI 安装服务连接器无密码扩展:

    az extension add --name serviceconnector-passwordless --upgrade --allow-preview true
    
  4. 通过连接命令使用系统分配的托管标识将数据库连接到容器应用。

    az containerapp connection create postgres-flexible \
        --resource-group $RESOURCE_GROUP \
        --name $APP_NAME \
        --target-resource-group $RESOURCE_GROUP \
        --server $DB_SERVER_NAME \
        --database $DB_NAME \
        --system-identity \
        --container $APP_NAME
    

6. 查看所作更改

可以使用以下命令找到应用程序 URL (FQDN):

echo https://$(az containerapp show \
    --name $APP_NAME \
    --resource-group $RESOURCE_GROUP \
    --query properties.configuration.ingress.fqdn \
    --output tsv)

当新网页显示水果列表时,表明应用使用了托管标识连接到数据库。 现在应该可以像以前一样编辑水果列表了。

清理资源

在前面的步骤中,你在资源组中创建了 Azure 资源。 如果认为将来不需要这些资源,请在 Cloud Shell 中运行以下命令删除资源组:

az group delete --name myResourceGroup

此命令可能需要花费一点时间运行。

后续步骤

在开发人员指南中详细了解如何在 Azure 上运行 Java 应用。