Azure AD 托管标识: Azure Kubernetes Service 上的 Java 应用





5.00/5 (1投票)
托管标识如何支持在 Azure Kubernetes Service 上运行的容器化 Spring Boot Web 应用程序。
第二篇文章继续我们关于 Azure AD 托管标识如何帮助应用程序连接到服务的三个系列文章。使用托管标识消除了管理每个应用程序连接服务的凭据的需要,并有助于保护这些服务免受与凭据相关的漏洞利用。在上一篇文章中,我们探讨了如何在 Azure App Service 中使用托管标识。然而,它们适用于多种服务。
在这里,我们将引导您完成在 Azure Kubernetes Service 上部署的 Spring Boot 应用程序的托管标识设置。Spring Boot 服务将连接到 Azure Cosmos DB 数据库,读取数据,并在网页上显示它。我们将创建一个应用程序特定的标识来访问所需的数据库。
必备组件
要遵循本教程,您应该了解 Java,并且需要先进行一些设置
- 访问 Azure 云平台。注册可享受 12 个月热门服务免费使用以及 200 美元的积分。
- 已在本地计算机上安装 Azure CLI。
- Rkord 应用程序。这个演示 Spring Boot 应用程序用于创建用户笔记,是使用 Spring MVC、Thymeleaf 框架和数据库开发的。之前,我们在本系列的第一篇文章 中将此应用程序与 Azure App Service 一起使用。在这里,我们将重构相同的应用程序并将其与 Cosmos DB 集成。
您可以在 GitHub 上找到本文档版本 Rkord 应用程序的完整代码。
创建 Spring Boot 应用程序
首先,重构 Rkord 应用程序以集成 Cosmos DB 而不是 SQL Server。通过删除 Spring Data JPA 和 SQL Server 依赖项以及相关的属性来执行清理。代码将因 JPA 注释和 JPA 存储库而引发编译错误。
接下来,添加 Spring Boot Cosmos DB starter 依赖项。此操作还将导入所需的 Cosmos DB 库。
<dependency>
<groupId>com.azure.spring</groupId>
<artifactId>azure-spring-boot-starter-cosmos</artifactId>
<version>3.11.0</version>
</dependency>
更新 Notes 实体
接下来,使用 `Container` 注释更新 `Notes` 实体。还将 `ID` 属性从 `int` 数据类型更新为 `String` 数据类型。此外,像这样添加 `Id` 和 `GeneratedValue` 注释
@Container(containerName = "notescollection")
public class Notes {
@Id
@GeneratedValue
private String id;
private String message;
// Removed for Brevity
}
设置 Notes Repository
该项目采用 Spring Data 编程模型来消除访问 `Cosmos` DB 集合的样板代码。因此,您只需要创建一个实体特定的接口,通过扩展 `ReactiveCosmosRepository` 接口来实现,如下所示
public interface NotesRepository extends ReactiveCosmosRepository<Notes,String> {
}
使用 Azure Cosmos DB 服务
上述更改将编译应用程序代码,但测试仍会失败。应用程序无法启动,因为缺少 Cosmos DB 详细信息。您需要连接到 Cosmos DB 实例才能成功构建和部署应用程序。
因此,在 Azure 门户中,使用 Azure Cosmos DB 服务创建一个实例。提供服务器名称、位置和关联的资源组。
还需提供实例的预配容量。无服务器模型适用于开发和测试需求。或者,根据应用程序的需求选择预配的吞吐量。
最后,在“**评审**”屏幕上点击“**创建**”按钮,根据指定配置生成实例。
生成实例后,记下访问密钥。接下来,在 `application.properties` 中更新上面生成的实例的详细信息(位置、密钥和数据库名称)。
# Specify the DNS URI of your Azure Cosmos DB.
azure.cosmos.uri=https://rkord.documents.azure.com:443/
azure.cosmos.key=uXNFTFcAUwzAq4o7ds1l9hnhKnNnIVNrJ6fqWtvLWYhrIKKgHkRtCwdJ2PjwJIkbA216DzM8E2wyYcugGAUYOw==
azure.cosmos.database=rkord
测试应该通过,提供成功的构建。您现在可以在本地计算机上部署应用程序。
设置 Azure Kubernetes Service
现在我们要将应用程序部署到 Azure Kubernetes Service (AKS)。因此,请使用 Azure Kubernetes Service 管理控制台创建一个集群。
控制台会打开一个对话框,其中包含各种配置选项。Azure 为不同的可用性需求提供了多种配置预设。您可以选择“**开发/测试**”配置来创建一个配置最少的集群。
提供有效的集群名称,查看配置,然后点击“**创建**”。
生成集群后,您必须使用其访问详细信息更新 `kubeconfig` 文件。您可以使用 CLI 如下
az aks get-credentials --resource-group rkord-notes-rg --name rkord-dev-aks
更新配置后,您可以使用 `kubectl` 命令与集群进行交互
kubectl get deployments --all-namespaces=true
部署应用程序
我们只能将 Kubernetes 应用程序部署为 Pod 和 Service。每个 Pod 都是从容器注册表中下载的应用程序容器。我们可以将 AKS 与任何容器注册表集成,包括 Docker、Harbor 和 Quay。
AKS 还提供了一个部署控制台,用于将项目与 Azure 容器注册表集成。集成需要一个特定于项目的 Dockerfile,因此请将以下文件添加到项目中
FROM azul/zulu-openjdk:11
COPY target/rkord.jar rkord.jar
EXPOSE 8080
CMD ["java", "-jar","/rkord.jar"]
请注意,Dockerfile 引用项目工件为 `rkord.jar`。您需要在 POM 文件构建部分的 `finalName` XML 标记中指定该名称
<finalName>rkord</finalName>
接下来,使用“**部署**”控制台集成 Azure 容器注册表。该过程将在项目目录的 manifest 文件夹中生成模板部署和服务文件。然后,它将构建项目并将服务部署到集群。部署成功后,它将从“**服务和入口**”控制台提供应用程序访问 URL。使用指定的 IP 和端口访问应用程序。
启用托管标识
在上一个部分中,我们成功部署了 Rkord 应用程序。但是,应用程序代码包含 Cosmos DB 的访问密钥,这使我们的数据库面临未经授权访问的风险。我们应该为环境启用托管标识,并从代码中删除凭据。
让我们从为 Kubernetes 集群配置托管标识开始
az aks update --resource-group rkord-notes-rg --name rkord-dev-aks --enable-managed-identity
托管标识服务提供以下凭据
- Kubernetes 服务凭据,用于访问 API 服务器
- Kubelet 服务凭据,由节点用于访问其他服务
应用程序 Pod 将使用 Kubelet 服务凭据访问 Cosmos DB。因此,使用此命令确定 kubelet 服务主体
az aks show --resource-group rkord-notes-rg --name rkord-dev-aks
--query "identityProfile.kubeletidentity"
启用 Cosmos RBAC
接下来,我们必须允许上述服务主体的 Cosmos DB 访问。Cosmos DB 采用基于角色的访问控制 (RBAC)。它有一些内置角色,但您也可以为应用程序的需求自定义角色。
首先,确定内置角色
az cosmosdb SQL role definition list --account-name rkord --resource-group rkord-notes-rg
Contributor 角色提供对数据库的完全访问权限。记下角色定义 ID。然后,使用此命令为 Kubelet 服务主体启用授权
az cosmosdb sql role assignment create --account-name rkord --resource-group rkord-notes-rg
--scope "/" --principal-id 00b01194-00a6-4dca-9ac0-0ba8a6a84a31
--role-definition-id /subscriptions/9b55b4b6-5a78-420f-a669-fdb43873b0ce/resourceGroups/
rkord-notes-rg/providers/Microsoft.DocumentDB/databaseAccounts/rkord/sqlRoleDefinitions/
00000000-0000-0000-0000-000000000002
集成托管标识
Azure Identity SDK 提供了加载标识所需的抽象。因此,将库添加到项目依赖项集中
<dependency>
<groupId>com.azure</groupId>
<artifactId>azure-identity</artifactId>
<version>1.3.7</version>
</dependency>
Cosmos DB Spring Boot starter 没有提供配置托管标识的方法。因此,我们必须重构代码以显式加载托管标识。另一方面,测试使用访问密钥连接到数据库。因此,应用程序必须根据不同环境支持连接到 Cosmos DB 的不同方法。
Spring profiles 提供实现这种多样化连接能力所需的支持。开始禁用自动 Cosmos DB Bean 创建,并创建各种特定于环境的配置
@SpringBootApplication(exclude = CosmosAutoConfiguration.class)
public class RkordApplication {
public static void main(String[] args) {
SpringApplication.run(RkordApplication.class, args);
}
}
现在,创建以下配置类以加载托管标识(使用 `ManagedIdentityCredential`)。然后,配置将这些托管标识凭据传递给 Cosmos DB 客户端。配置类需要 `Cosmos` DB 位置和数据库名称的属性,因此请将这些属性添加到 `src/main/resources` 目录下的 `application.properties` 文件中。
@Profile("prod")
@Configuration
public class CosmosDBConfig extends AbstractCosmosConfiguration {
@Value("${cosmos.dbname}")
private String dbname;
@Value("${cosmos.loc}")
private String url;
protected String getDatabaseName() {
return dbname;
}
@Bean
public ManagedIdentityCredential dbCredential() {
ManagedIdentityCredential managedIdentityCredential =
new ManagedIdentityCredentialBuilder()
.build();
return managedIdentityCredential;
}
@Bean
public CosmosClientBuilder cosmosClientBuilder(ManagedIdentityCredential dbCredential) {
CosmosClientBuilder cosmosClientBuilder = new CosmosClientBuilder();
cosmosClientBuilder.credential(dbCredential).endpoint(url);
return cosmosClientBuilder;
}
}
上面的类标有 profile 注释,因此仅在激活相应的 Spring profile 时才有效。因此,通过修改 Dockerfile 中的 `CMD` 来激活容器 profile,如下所示
CMD ["java", "-jar", "-Dspring.profiles.active=prod","/rkord.jar"]
此外,创建一个 `CosmosDBTestConfig` 类,该类加载访问密钥并使用 `AzureKeyCredential` 连接到 `Cosmos` DB。还要更新基于测试的 `application.properties` 以获取相关属性。
@Configuration
public class CosmosTestConfig extends AbstractCosmosConfiguration {
@Value("${cosmos.dbname}")
private String dbname;
@Value("${cosmos.loc}")
private String url;
@Value("${cosmos.key}")
private String key;
protected String getDatabaseName() {
return dbname;
}
@Bean
public AzureKeyCredential dbCredential() {
return new AzureKeyCredential(key);
}
@Bean
public CosmosClientBuilder cosmosClientBuilder(AzureKeyCredential dbCredential) {
CosmosClientBuilder cosmosClientBuilder = new CosmosClientBuilder();
cosmosClientBuilder.credential(dbCredential).endpoint(url);
return cosmosClientBuilder;
}
}
将更改推送到 GitHub 存储库以触发构建和部署。部署成功后,从 AKS **ingress 控制台**确定应用程序 URL。
摘要
现在我们已经探讨了托管标识如何实现部署在 Azure Kubernetes Service 上的容器化 Spring Boot Web 应用程序。由于该过程消除了对凭据的需求,因此消除了围绕安全凭据交换的挑战。这样,开发人员就可以专注于他们需要支持的业务,而不是处理各种部署挑战,例如更新和保护凭据。
托管标识的功能不仅限于连接在 Azure App Service 或 Azure Kubernetes Service 上运行的应用程序。继续阅读本系列的第三部分,了解 如何使用 Azure AD 托管标识获取密钥存储凭据。
要详细了解 Java Azure 身份库,请参阅 Java 和 Azure Identity 的 Azure 身份验证。