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

在 Azure Kubernetes 服务群集上使用 Quarkus 部署 Java 应用程序

本文介绍如何使用简单的 CRUD 应用程序在 Azure Kubernetes 服务 (AKS) 上快速部署 Red Hat Quarkus。 该应用程序是具有 JavaScript 前端和 REST 终结点的“待办事项列表”。 Azure Database for PostgreSQL 灵活服务器为应用提供暂留层。 本文介绍如何在本地测试应用并将其部署到 AKS。

先决条件

  • 如果没有 Azure 订阅,请在开始之前创建一个 Azure 免费帐户
  • 准备一台安装了类似于 Unix 的操作系统(例如 Ubuntu、macOS 或适用于 Linux 的 Windows 子系统)的本地计算机。
  • 安装 Java SE 实现版本 17 或更高版本 - 例如,Microsoft 版 OpenJDK
  • 安装 Maven 3.9.8 或更高版本。
  • 安装适用于 OS 的 Docker
  • 安装 jq
  • 安装 cURL
  • 安装 Quarkus CLI 3.12.1 或更高版本。
  • 适用于 Unix 类环境的 Azure CLI。 本文仅需要 Azure CLI 的 Bash 环境。
    • 在代码中使用 DefaultAzureCredential 之前,开发人员应安装 Azure CLI 并使用 az login 命令以交互方式登录 Azure。
      az login
      
    • 本文需要的 Azure CLI 最低版本为 2.61.0。

创建应用项目

使用以下命令克隆本文的示例 Java 项目。 该示例位于 GitHub 上。

git clone https://github.com/Azure-Samples/quarkus-azure
cd quarkus-azure
git checkout 2024-12-16
cd aks-quarkus

如果看到有关处于拆离的 HEAD 状态的消息,可以放心忽略此消息。 由于本文不需要任何提交,因此拆离的 HEAD 状态是合适的。

在本地测试 Quarkus 应用

本部分的步骤介绍如何在本地运行应用。

Quarkus 支持在开发和测试模式下自动预配未配置的服务。 Quarkus 将此功能称为开发服务。 假设你有 Quarkus 功能,例如连接到数据库服务。 你想要测试应用,但尚未完全配置与真实数据库的连接。 Quarkus 会自动启动相关服务的容器化存根版本,并将应用程序与其相连接。 更多信息请参阅 Quarkus 文档中的《开发服务概述》 。

确保容器环境正在运行,并使用以下命令进入 Quarkus 开发模式:

quarkus dev

使用 mvn quarkus:dev 取代 quarkus dev 通过 Maven 完成相同的操作。

系统可能会询问你是否要发送 Quarkus 开发模式使用情况的遥测数据。 如果询问,请根据需要回答。

Quarkus 开发模式支持实时重载和后台编译。 对应用源代码进行任何修改后,刷新浏览器就可以看到更改。 错误页会显示任何编译或部署问题。 Quarkus 开发模式在 5005 端口上侦听调试程序。 如果要在运行之前等待附加调试程序,请在命令行输入 -Dsuspend。 如果根本不需要调试程序,可以使用 -Ddebug=false

输出应如以下示例所示:

__  ____  __  _____   ___  __ ____  ______
 --/ __ \/ / / / _ | / _ \/ //_/ / / / __/
 -/ /_/ / /_/ / __ |/ , _/ ,< / /_/ /\ \
--\___\_\____/_/ |_/_/|_/_/|_|\____/___/
INFO  [io.quarkus] (Quarkus Main Thread) quarkus-todo-demo-app-aks 1.0.0-SNAPSHOT on JVM (powered by Quarkus 3.2.0.Final) started in 3.377s. Listening on: http://localhost:8080

INFO  [io.quarkus] (Quarkus Main Thread) Profile dev activated. Live Coding activated.
INFO  [io.quarkus] (Quarkus Main Thread) Installed features: [agroal, cdi, hibernate-orm, hibernate-orm-panache, hibernate-validator, jdbc-postgresql, narayana-jta, resteasy-reactive, resteasy-reactive-jackson, smallrye-context-propagation, vertx]

--
Tests paused
Press [e] to edit command line args (currently ''), [r] to resume testing, [o] Toggle test output, [:] for the terminal, [h] for more options>

在运行 Quarkus 开发模式的终端上按 w 键。 w 键将打开默认 Web 浏览器并显示 Todo 应用程序。 还可以直接在 http://localhost:8080 访问应用程序 GUI。

待办事项示例应用程序的屏幕截图。

请尝试在待办事项列表中选择待办事项。 UI 用删除线文本样式提示选择。 还可以通过键入“验证待办事项应用”并按 Enter 将新的待办事项添加到待办事项列表,如以下屏幕截图所示:

待办事项示例应用程序添加新事项的屏幕截图。

访问 RESTful API (/api) 以获取存储在本地 PostgreSQL 数据库中的所有待办事项:

curl --verbose http://localhost:8080/api | jq .

输出应如以下示例所示:

* Connected to localhost (127.0.0.1) port 8080 (#0)
> GET /api HTTP/1.1
> Host: localhost:8080
> User-Agent: curl/7.88.1
> Accept: */*
>
< HTTP/1.1 200 OK
< content-length: 664
< Content-Type: application/json;charset=UTF-8
<
{ [664 bytes data]
100   664  100   664    0     0  13278      0 --:--:-- --:--:-- --:--:-- 15441
* Connection #0 to host localhost left intact
[
  {
    "id": 1,
    "title": "Introduction to Quarkus Todo App",
    "completed": false,
    "order": 0,
    "url": null
  },
  {
    "id": 2,
    "title": "Quarkus on Azure App Service",
    "completed": false,
    "order": 1,
    "url": "https://learn.microsoft.com/en-us/azure/developer/java/eclipse-microprofile/deploy-microprofile-quarkus-java-app-with-maven-plugin"
  },
  {
    "id": 3,
    "title": "Quarkus on Azure Container Apps",
    "completed": false,
    "order": 2,
    "url": "https://learn.microsoft.com/en-us/training/modules/deploy-java-quarkus-azure-container-app-postgres/"
  },
  {
    "id": 4,
    "title": "Quarkus on Azure Functions",
    "completed": false,
    "order": 3,
    "url": "https://learn.microsoft.com/en-us/azure/azure-functions/functions-create-first-quarkus"
  },
  {
    "id": 5,
    "title": "Verify Todo apps",
    "completed": false,
    "order": 5,
    "url": null
  }
]

q 键退出 Quarkus 开发模式。

创建 Azure 资源以运行 Quarkus 应用

本部分的步骤介绍如何创建以下 Azure 资源来运行 Quarkus 示例应用:

  • Azure Database for PostgreSQL 灵活服务器
  • Azure 容器注册表
  • Azure Kubernetes 服务 (AKS)

注意

本文禁用 PostgreSQL 身份验证,以说明安全最佳做法。 Microsoft Entra ID 用于对与服务器的连接进行身份验证。 如果需要启用 PostgreSQL 身份验证,请参阅快速入门:将 Java 和 JDBC 与 Azure Database for PostgreSQL - 灵活服务器配合使用,然后选择“密码”选项卡。

其中一些资源必须在 Azure 订阅范围内具有唯一的名称。 若要确保这种唯一性,可以使用首字母缩写、序列、日期、后缀模式。 若要应用此模式,请通过首字母缩写、序列号、当日日期和特定资源后缀来命名资源,例如,rg 表示“资源组”。 以下环境变量使用此模式。 将占位符值 UNIQUE_VALUELOCATION 替换为自己的值,然后在终端中运行以下命令:

export UNIQUE_VALUE=<your unique value, such as ejb010717>
export RESOURCE_GROUP_NAME=${UNIQUE_VALUE}rg
export LOCATION=<your desired Azure region for deploying your resources - for example, northeurope>
export REGISTRY_NAME=${UNIQUE_VALUE}reg
export DB_SERVER_NAME=${UNIQUE_VALUE}db
export DB_NAME=demodb
export CLUSTER_NAME=${UNIQUE_VALUE}aks
export AKS_NS=${UNIQUE_VALUE}ns

创建 Azure Database for PostgreSQL 灵活服务器

Azure Database for PostgreSQL 灵活服务器是一种完全托管的数据库服务,旨在为数据库管理功能和配置设置提供更精细的控制和灵活性。 本部分介绍如何使用 Azure CLI 创建 Azure Database for PostgreSQL 灵活服务器实例。

首先,使用以下命令创建一个资源组以包含数据库服务器和其他资源:

az group create \
    --name $RESOURCE_GROUP_NAME \
    --location $LOCATION

接下来,使用以下命令创建 Azure Database for PostgreSQL 灵活服务器实例:

az postgres flexible-server create \
    --name $DB_SERVER_NAME \
    --database-name $DB_NAME \
    --resource-group $RESOURCE_GROUP_NAME \
    --location $LOCATION \
    --public-access 0.0.0.0 \
    --sku-name Standard_B1ms \
    --tier Burstable \
    --active-directory-auth Enabled \
    --yes

创建服务器、数据库、管理员用户和防火墙规则需要几分钟时间。 如果命令成功,输出将类似于以下示例:

{
  "connectionString": "postgresql://REDACTED@ejb011212qdb.postgres.database.azure.com/demodb?sslmode=require",
  "databaseName": "demodb",
  "firewallName": "AllowAllAzureServicesAndResourcesWithinAzureIps_2024-12-12_14-30-22",
  "host": "ejb011212qdb.postgres.database.azure.com",
  "id": "/subscriptions/c7844e91-b11d-4a7f-ac6f-996308fbcdb9/resourceGroups/ejb011211sfi/providers/Microsoft.DBforPostgreSQL/flexibleServers/ejb011212qdb",
  "location": "East US 2",
  "password": "REDACTED",
  "resourceGroup": "ejb011211sfi",
  "skuname": "Standard_B1ms",
  "username": "sorrycamel2",
  "version": "16"
}

使用 Azure Database for PostgreSQL 灵活服务器在本地测试应用

在上一部分中,你在开发模式下在本地测试 Quarkus 应用,并将 PostgreSQL 数据库预配为 Docker 容器。 现在,在本地测试与 Azure Database for PostgreSQL 灵活服务器实例的连接。

首先,使用以下命令将当前登录用户添加为 Microsoft Entra Admin 的 Azure Database for PostgreSQL 灵活服务器实例:

ENTRA_ADMIN_NAME=$(az account show --query user.name --output tsv)
az postgres flexible-server ad-admin create \
    --resource-group $RESOURCE_GROUP_NAME \
    --server-name $DB_SERVER_NAME \
    --display-name $ENTRA_ADMIN_NAME \
    --object-id $(az ad signed-in-user show --query id --output tsv)

成功的输出是一个包含属性 "type": "Microsoft.DBforPostgreSQL/flexibleServers/administrators" 的 JSON 对象。

接下来,按照以下步骤将本地 IP 地址添加到 Azure Database for PostgreSQL 灵活服务器实例防火墙规则:

  1. 获取在本地运行 Quarkus 应用的计算机的本地 IP 地址。 例如,访问 https://whatismyipaddress.com 以获取公共 IP v4 地址。

  2. 使用上一步中获取的本地 IP 地址定义环境变量。

    export AZ_LOCAL_IP_ADDRESS=<your local IP address>
    
  3. 运行以下命令,将本地 IP 地址添加到 Azure Database for PostgreSQL 灵活服务器实例防火墙规则:

    az postgres flexible-server firewall-rule create \
        --resource-group $RESOURCE_GROUP_NAME \
        --name $DB_SERVER_NAME \
        --rule-name $DB_SERVER_NAME-database-allow-local-ip \
        --start-ip-address $AZ_LOCAL_IP_ADDRESS \
        --end-ip-address $AZ_LOCAL_IP_ADDRESS
    

然后,在上一终端中设置以下环境变量。 这些环境变量用于从本地运行的 Quarkus 应用连接到 Azure Database for PostgreSQL 灵活服务器实例:

export AZURE_POSTGRESQL_HOST=${DB_SERVER_NAME}.postgres.database.azure.com
export AZURE_POSTGRESQL_PORT=5432
export AZURE_POSTGRESQL_DATABASE=${DB_NAME}
export AZURE_POSTGRESQL_USERNAME=${ENTRA_ADMIN_NAME}

注意

环境变量 AZURE_POSTGRESQL_HOSTAZURE_POSTGRESQL_PORTAZURE_POSTGRESQL_DATABASEAZURE_POSTGRESQL_USERNAME 的值由上一节中引入的 src/main/resources/application.properties 文件中定义的数据库配置属性读取。 将 Quarkus 应用部署到本文后面的 AKS 群集时,这些值会在运行时使用服务连接器无密码扩展自动注入到应用中。

现在,在本地运行 Quarkus 应用以测试与 Azure Database for PostgreSQL 灵活服务器实例的连接。 使用以下命令在生产模式下启动应用:

quarkus build
java -jar target/quarkus-app/quarkus-run.jar

注意

如果应用无法启动类似于 ERROR [org.hib.eng.jdb.spi.SqlExceptionHelper] (JPA Startup Thread) Acquisition timeout while waiting for new connection 的错误消息,很可能是因为本地计算机的网络设置。 请尝试再次从 Azure 门户选择“添加当前客户端 IP 地址”。 有关详细信息,请参阅“使用 Azure 门户为 Azure Database for PostgreSQL - 灵活服务器创建和管理防火墙规则”中的“创建服务器后创建防火墙规则”部分。 然后再次运行应用。

打开新的 Web 浏览器到 http://localhost:8080 以访问 Todo 应用程序。 应会看到 Todo 应用,类似于在开发模式下在本地运行应用时看到的内容。

创建 Azure 容器注册表实例

由于 Quarkus 是一种云原生技术,因此它内置了对创建在 Kubernetes 中运行的容器的支持。 Kubernetes 完全依赖于容器注册表,它从中查找要运行的容器映像。 AKS 内置了对 Azure 容器注册表的支持。

使用 az acr create 命令以创建容器注册表实例。 以下示例创建 n 个以环境变量 ${REGISTRY_NAME} 的值命名的容器注册表实例:

az acr create \
    --resource-group $RESOURCE_GROUP_NAME \
    --location ${LOCATION} \
    --name $REGISTRY_NAME \
    --sku Basic

很快,你应该会在 JSON 输出中看到以下行:

  "provisioningState": "Succeeded",
  "publicNetworkAccess": "Enabled",
  "resourceGroup": "<YOUR_RESOURCE_GROUP>",

使用以下命令获取容器注册表实例的登录服务器:

export LOGIN_SERVER=$(az acr show \
    --name $REGISTRY_NAME \
    --query 'loginServer' \
    --output tsv)
echo $LOGIN_SERVER

将 Docker 连接到容器注册表实例

登录到容器注册表实例。 登录后可以推送映像。 使用以下命令登录到注册表:

az acr login --name $REGISTRY_NAME

如果已成功登录到容器注册表实例,则应在命令输出的末尾看到 Login Succeeded

创建 AKS 群集

使用 az aks create 命令创建 AKS 群集。 以下示例用一个节点创建了以环境变量 ${CLUSTER_NAME} 的值为名的群集。 群集连接到在上一步中创建的容器注册表实例。 此命令需要几分钟才能完成。 群集会在启用了托管标识的情况下启动。 对于无密码数据库连接,此步骤是必需的。

az aks create \
    --resource-group $RESOURCE_GROUP_NAME \
    --name $CLUSTER_NAME \
    --attach-acr $REGISTRY_NAME \
    --node-count 1 \
    --generate-ssh-keys \
    --enable-managed-identity

数分钟后,命令完成并返回有关群集的 JSON 格式信息,包括以下内容:

  "nodeResourceGroup": "MC_<your resource_group_name>_<your cluster name>_<your region>",
  "privateFqdn": null,
  "provisioningState": "Succeeded",
  "resourceGroup": "<your resource group name>",

连接到 AKS 群集

若要管理 Kubernetes 群集,可以使用 Kubernetes 命令行客户端 kubectl。 若要在本地安装 kubectl,请使用 az aks install-cli 命令,如以下示例所示:

az aks install-cli

更多 kubectl 相关信息请参阅 Kubernetes 文档中的《命令行工具 (kubectl) 》。

若要将 kubectl 配置为连接到 Kubernetes 群集,请使用 az aks get-credentials 命令,如以下示例所示。 此命令将下载凭据,并将 Kubernetes CLI 配置为使用这些凭据。

az aks get-credentials \
    --resource-group $RESOURCE_GROUP_NAME \
    --name $CLUSTER_NAME \
    --overwrite-existing \
    --admin

成功的输出文本与下列内容相似:

Merged "ejb010718aks-admin" as current context in /Users/edburns/.kube/config

k 的别名设置为 kubectl 是个实用技巧。 如果出现此情况,请使用以下命令:

alias k=kubectl

若要验证群集的连接,请使用 kubectl get 命令返回群集节点列表,如以下示例所示:

kubectl get nodes

以下示例输出显示在上一步创建的单个节点。 请确保节点的状态为 Ready

NAME                                STATUS   ROLES   AGE     VERSION
aks-nodepool1-xxxxxxxx-yyyyyyyyyy   Ready    agent   76s     v1.28.9

在 AKS 创建新的命名空间

使用以下命令在 Kubernetes 服务中为 Quarkus 应用创建新的命名空间:

kubectl create namespace ${AKS_NS}

输出应如以下示例所示:

namespace/<your namespace> created

使用服务连接器在 AKS 中创建服务连接

在本部分中,你将结合使用服务连接器和 Microsoft Entra Workload ID,在 AKS 群集与 Azure PostgreSQL Database 灵活服务器数据库之间创建服务连接。 通过此连接,AKS 群集无需使用 SQL 身份验证即可访问 Azure Database for PostgreSQL 灵活服务器。

运行以下命令,使用 Microsoft Entra Workload ID 和服务连接器在 AKS 群集与 PostgreSQL 数据库之间创建连接:

# Register the Service Connector and Kubernetes Configuration resource providers
az provider register --namespace Microsoft.ServiceLinker --wait
az provider register --namespace Microsoft.KubernetesConfiguration --wait

# Install the Service Connector passwordless extension
az extension add --name serviceconnector-passwordless --upgrade --allow-preview true

# Retrieve the AKS cluster and Azure SQL Server resource IDs
export AKS_CLUSTER_RESOURCE_ID=$(az aks show \
    --resource-group $RESOURCE_GROUP_NAME \
    --name $CLUSTER_NAME \
    --query id \
    --output tsv)
export AZURE_POSTGRESQL_RESOURCE_ID=$(az postgres flexible-server show \
    --resource-group $RESOURCE_GROUP_NAME \
    --name $DB_SERVER_NAME \
    --query id \
    --output tsv)

# Create a user-assigned managed identity used for workload identity
export USER_ASSIGNED_IDENTITY_NAME=workload-identity-uami
az identity create \
    --resource-group ${RESOURCE_GROUP_NAME} \
    --name ${USER_ASSIGNED_IDENTITY_NAME}

# Retrieve the user-assigned managed identity resource ID
export UAMI_RESOURCE_ID=$(az identity show \
    --resource-group ${RESOURCE_GROUP_NAME} \
    --name ${USER_ASSIGNED_IDENTITY_NAME} \
    --query id \
    --output tsv)

# Create a service connection between your AKS cluster and your PostgreSQL database using Microsoft Entra Workload ID
az aks connection create postgres-flexible \
    --connection akspostgresconn \
    --kube-namespace $AKS_NS \
    --source-id $AKS_CLUSTER_RESOURCE_ID \
    --target-id $AZURE_POSTGRESQL_RESOURCE_ID/databases/$DB_NAME \
    --workload-identity $UAMI_RESOURCE_ID

上述步骤中最终命令的输出中存在以下 JSON 表示服务连接器的成功安装:

"name": "akspostgresconn",
"provisioningState": "Succeeded",

注意

建议使用 Microsoft Entra 工作负荷 ID 来保护对 Azure Database for PostgreSQL 灵活服务器的访问,而无需使用用户名/密码身份验证。 如果需要使用用户名/密码身份验证,请忽略本部分之前的步骤,并使用用户名和密码连接到 Azure SQL 数据库。

获取服务连接器创建的服务帐户和机密

若要向 Azure Database for PostgreSQL 灵活服务器进行身份验证,需要获取服务连接器创建的服务帐户和 Kubernetes 机密。 按照教程:将 AKS 应用连接到 Azure SQL 数据库中“更新容器”部分的说明操作。 采用“使用提供的 YAML 示例代码片段直接创建部署”选项,并使用以下步骤:

  • 从示例 Kubernetes 部署 YAML 中的突出显示部分,复制 serviceAccountNamesecretRef.name 的值,如在以下示例中表示 <service-account-name><secret-name>

    serviceAccountName: <service-account-name>
    containers:
    - name: raw-linux
        envFrom:
           - secretRef:
              name: <secret-name>
    

    下一部分中使用这些值将 Quarkus 应用程序部署到 AKS 群集。

自定义云原生配置

作为一项云原生技术,Quarkus 可以为标准 Kubernetes、Red Hat OpenShift 和 Knative 自动配置资源。 有关详细信息,请参阅 Quarkus Kubernetes 指南Quarkus OpenShift 指南Quarkus Knative 指南。 开发人员可以通过应用生成的清单将应用程序部署到目标 Kubernetes 群集。

若要生成适宜的 Kubernetes 资源,请使用以下命令在本地终端中添加 quarkus-kubernetescontainer-image-jib 扩展:

quarkus ext add kubernetes container-image-jib

Quarkus 修改 POM 以确保将这些扩展列为 <dependencies>。 如果系统要求安装名为 JBang 的内容,请点击“是”允许安装。

输出应如以下示例所示:

[SUCCESS] ✅  Extension io.quarkus:quarkus-kubernetes has been installed
[SUCCESS] ✅  Extension io.quarkus:quarkus-container-image-jib has been installed

若要验证是否已添加扩展,可以运行 git diff 检查输出。

作为一项云原生技术,Quarkus 支持配置文件概念。 Quarkus 拥有以下三个内置的配置文件:

  • dev - 处于开发模式时激活
  • test - 在运行测试时激活
  • prod - 未在开发或测试模式下运行时的默认配置文件

Quarkus 根据需要支持任意数量的命名配置文件。

本部分中的剩余步骤指示自定义 src/main/resources/application.properties 文件中的值。

prod. 前缀表明在 prod 配置文件中运行时这些属性处于活动状态。 有关配置文件的详细信息,请参阅Quarkus 文档

数据库配置

检查以下数据库配置变量。 数据库连接相关属性 %prod.quarkus.datasource.jdbc.url%prod.quarkus.datasource.username 分别从环境变量AZURE_POSTGRESQL_HOSTAZURE_POSTGRESQL_PORTAZURE_POSTGRESQL_DATABASEAZURE_POSTGRESQL_USERNAME 读取值。 这些环境变量映射到存储数据库连接信息的机密值。 出于安全原因,它们使用服务连接器无密码扩展自动生成,如本文其他位置所示。

# Database configurations
%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
%prod.quarkus.datasource.username=${AZURE_POSTGRESQL_USERNAME}
%prod.quarkus.datasource.jdbc.acquisition-timeout=10
%prod.quarkus.hibernate-orm.database.generation=drop-and-create
%prod.quarkus.hibernate-orm.sql-load-script=import.sql

Kubernetes 配置

检查以下 Kubernetes 配置变量。 将 service-type 设置为 load-balancer 以外部访问应用。 将 <service-account-name> 的值和 <secret-name> 的值替换为在上一节中复制的实际值的值。

# Kubernetes configurations
%prod.quarkus.kubernetes.deployment-target=kubernetes
%prod.quarkus.kubernetes.service-type=load-balancer
%prod.quarkus.kubernetes.labels."azure.workload.identity/use"=true
%prod.quarkus.kubernetes.service-account=<service-account-name>
%prod.quarkus.kubernetes.env.mapping.AZURE_CLIENT_ID.from-secret=<secret-name>
%prod.quarkus.kubernetes.env.mapping.AZURE_CLIENT_ID.with-key=AZURE_POSTGRESQL_CLIENTID
%prod.quarkus.kubernetes.env.mapping.AZURE_POSTGRESQL_HOST.from-secret=<secret-name>
%prod.quarkus.kubernetes.env.mapping.AZURE_POSTGRESQL_HOST.with-key=AZURE_POSTGRESQL_HOST
%prod.quarkus.kubernetes.env.mapping.AZURE_POSTGRESQL_PORT.from-secret=<secret-name>
%prod.quarkus.kubernetes.env.mapping.AZURE_POSTGRESQL_PORT.with-key=AZURE_POSTGRESQL_PORT
%prod.quarkus.kubernetes.env.mapping.AZURE_POSTGRESQL_DATABASE.from-secret=<secret-name>
%prod.quarkus.kubernetes.env.mapping.AZURE_POSTGRESQL_DATABASE.with-key=AZURE_POSTGRESQL_DATABASE
%prod.quarkus.kubernetes.env.mapping.AZURE_POSTGRESQL_USERNAME.from-secret=<secret-name>
%prod.quarkus.kubernetes.env.mapping.AZURE_POSTGRESQL_USERNAME.with-key=AZURE_POSTGRESQL_USERNAME

其他 Kubernetes 配置会指定机密值到 Quarkus 应用程序中环境变量的映射。 <secret-name> 机密包含数据库连接信息。 机密中的 AZURE_POSTGRESQL_CLIENTIDAZURE_POSTGRESQL_HOSTAZURE_POSTGRESQL_PORTAZURE_POSTGRESQL_DATABASEAZURE_POSTGRESQL_USERNAME 键分别映射到 AZURE_CLIENT_IDAZURE_POSTGRESQL_HOSTAZURE_POSTGRESQL_PORTAZURE_POSTGRESQL_DATABASEAZURE_POSTGRESQL_USERNAME 环境变量。

若要使用 kubectl 直接检查机密,请使用类似于以下示例的命令:

kubectl -n ${AKS_NS} get secret <secret-name> -o jsonpath="{.data.AZURE_POSTGRESQL_USERNAME}" | base64 --decode

容器映像配置

作为云原生技术,Quarkus 支持生成与 Docker 兼容的 OCI 容器映像。 将 <LOGIN_SERVER_VALUE> 的值替换为 ${LOGIN_SERVER} 环境变量的实际值。

# Container Image Build
%prod.quarkus.container-image.build=true
%prod.quarkus.container-image.image=<LOGIN_SERVER_VALUE>/todo-quarkus-aks:1.0

作为最终检查,在 application.properties 中完成所有必需的替换时,< 字符不得出现。 如果有,请仔细检查是否完成了所有必要的替换。

生成容器映像并将其推送到容器注册表

现在,运行以下命令以生成应用程序。 此命令使用 Kubernetes 和 Jib 扩展来生成容器映像。

quarkus build --no-tests

输出应 BUILD SUCCESS 结尾。 Kubernetes 清单文件在 target/kubernetes 中生成,如以下示例所示:

tree target/kubernetes
target/kubernetes
├── kubernetes.json
└── kubernetes.yml

0 directories, 2 files

可以使用 docker 命令行 (CLI) 验证是否生成了容器映像。 输出与以下示例类似:

docker images | grep todo-quarkus-aks
<LOGIN_SERVER_VALUE>/todo-quarkus-aks   1.0       b13c389896b7   18 minutes ago   422MB

使用以下命令将容器映像推送到容器注册表:

export TODO_QUARKUS_TAG=$(docker images | grep todo-quarkus-aks | head -n1 | cut -d " " -f1)
echo ${TODO_QUARKUS_TAG}
docker push ${TODO_QUARKUS_TAG}:1.0

输出应类似于以下示例:

The push refers to repository [<LOGIN_SERVER_VALUE>/todo-quarkus-aks]
dfd615499b3a: Pushed
56f5cf1aa271: Pushed
4218d39b228e: Pushed
b0538737ed64: Pushed
d13845d85ee5: Pushed
60609ec85f86: Pushed
1.0: digest: sha256:0ffd70d6d5bb3a4621c030df0d22cf1aa13990ca1880664d08967bd5bab1f2b6 size: 1995

将应用推送到容器注册表后,可以告知 AKS 运行该应用。

将 Quarkus 应用部署到 AKS

本部分中的步骤演示如何在创建的 Azure 资源上运行 Quarkus 示例应用。

使用 kubectl apply 将 Quarkus 应用部署到 AKS

在命令行上输入 kubectl 以部署 Kubernetes 资源,如以下示例所示:

kubectl apply -f target/kubernetes/kubernetes.yml -n ${AKS_NS}

输出应如以下示例所示:

service/quarkus-todo-demo-app-aks created
deployment.apps/quarkus-todo-demo-app-aks created

使用以下命令验证应用是否运行:

kubectl -n $AKS_NS get pods

如果 STATUS 字段的值显示除 Running 以外的任何内容,请在继续操作之前排查并解决问题。 使用以下命令检查 Pod 日志可能会有所帮助:

kubectl -n $AKS_NS logs $(kubectl -n $AKS_NS get pods | grep quarkus-todo-demo-app-aks | cut -d " " -f1)

使用以下命令获取 EXTERNAL-IP 以访问待办事项应用程序:

kubectl get svc -n ${AKS_NS}

输出应如以下示例所示:

NAME                        TYPE           CLUSTER-IP     EXTERNAL-IP     PORT(S)        AGE
quarkus-todo-demo-app-aks   LoadBalancer   10.0.236.101   20.12.126.200   80:30963/TCP   37s

可以使用以下命令将 EXTERNAL-IP 的值作为完全限定的 URL 保存到环境变量:

export QUARKUS_URL=http://$(kubectl get svc -n ${AKS_NS} | grep quarkus-todo-demo-app-aks | cut -d " " -f10)
echo $QUARKUS_URL

${QUARKUS_URL} 打开新的 Web 浏览器。 然后,添加一个文本内容为 Deployed the Todo app to AKS 的新待办事项。 此外,将 Introduction to Quarkus Todo App 事项选为完成。

AKS 上运行的待办事项示例应用程序的屏幕截图。

访问 RESTful API (/api) 以获取存储在 Azure PostgreSQL 数据库中的所有待办事项,如以下示例所示:

curl --verbose ${QUARKUS_URL}/api | jq .

输出应如以下示例所示:

* Connected to 20.237.68.225 (20.237.68.225) port 80 (#0)
> GET /api HTTP/1.1
> Host: 20.237.68.225
> User-Agent: curl/7.88.1
> Accept: */*
>
< HTTP/1.1 200 OK
< content-length: 828
< Content-Type: application/json;charset=UTF-8
<
[
  {
    "id": 2,
    "title": "Quarkus on Azure App Service",
    "completed": false,
    "order": 1,
    "url": "https://learn.microsoft.com/en-us/azure/developer/java/eclipse-microprofile/deploy-microprofile-quarkus-java-app-with-maven-plugin"
  },
  {
    "id": 3,
    "title": "Quarkus on Azure Container Apps",
    "completed": false,
    "order": 2,
    "url": "https://learn.microsoft.com/en-us/training/modules/deploy-java-quarkus-azure-container-app-postgres/"
  },
  {
    "id": 4,
    "title": "Quarkus on Azure Functions",
    "completed": false,
    "order": 3,
    "url": "https://learn.microsoft.com/en-us/azure/azure-functions/functions-create-first-quarkus"
  },
  {
    "id": 5,
    "title": "Deployed the Todo app to AKS",
    "completed": false,
    "order": 5,
    "url": null
  },
  {
    "id": 1,
    "title": "Introduction to Quarkus Todo App",
    "completed": true,
    "order": 0,
    "url": null
  }
]

验证数据库是否已更新

运行以下命令,验证数据库现已正确更新:

ACCESS_TOKEN=$(az account get-access-token --resource-type oss-rdbms --output tsv --query accessToken)
az postgres flexible-server execute \
    --admin-user $ENTRA_ADMIN_NAME \
    --admin-password $ACCESS_TOKEN \
    --name $DB_SERVER_NAME \
    --database-name $DB_NAME \
    --querytext "select * from todo;"

如果系统要求你安装扩展,请回答 Y

输出应类似于以下示例,并且应将相同的项包含在 Todo 应用 GUI 中,以及前面 curl 命令的输出:

Successfully connected to <DB_SERVER_NAME>.
Ran Database Query: 'select * from todo;'
Retrieving first 30 rows of query output, if applicable.
Closed the connection to <DB_SERVER_NAME>
[
  {
    "completed": false,
    "id": 2,
    "ordering": 1,
    "title": "Quarkus on Azure App Service",
    "url": "https://learn.microsoft.com/en-us/azure/developer/java/eclipse-microprofile/deploy-microprofile-quarkus-java-app-with-maven-plugin"
  },
  {
    "completed": false,
    "id": 3,
    "ordering": 2,
    "title": "Quarkus on Azure Container Apps",
    "url": "https://learn.microsoft.com/en-us/training/modules/deploy-java-quarkus-azure-container-app-postgres/"
  },
  {
    "completed": false,
    "id": 4,
    "ordering": 3,
    "title": "Quarkus on Azure Functions",
    "url": "https://learn.microsoft.com/en-us/azure/azure-functions/functions-create-first-quarkus"
  },
  {
    "completed": false,
    "id": 5,
    "ordering": 5,
    "title": "Deployed the Todo app to AKS",
    "url": null
  },
  {
    "completed": true,
    "id": 1,
    "ordering": 0,
    "title": "Introduction to Quarkus Todo App",
    "url": null
  }
]

完成后,请使用以下命令删除允许本地 IP 地址访问 Azure Database for PostgreSQL 灵活服务器实例的防火墙规则:

az postgres flexible-server firewall-rule delete \
    --resource-group $RESOURCE_GROUP_NAME \
    --name $DB_SERVER_NAME \
    --rule-name $DB_SERVER_NAME-database-allow-local-ip \
    --yes

清理资源

若要避免 Azure 费用,应清除不需要的资源。 如果不再需要群集,请使用 az group delete 命令来删除资源组、容器服务、容器注册表和所有的相关资源。

git reset --hard
docker rmi ${TODO_QUARKUS_TAG}:1.0
docker rmi postgres
az identity delete --ids ${UAMI_RESOURCE_ID}
az group delete --name $RESOURCE_GROUP_NAME --yes --no-wait

你可能还希望使用 docker rmi 删除由 Quarkus 开发模式生成的容器映像 postgrestestcontainers

后续步骤