教程:使用 VNet 中的 Azure Database for MySQL 灵活服务器在 AKS 群集上部署 Spring Boot 应用程序
适用于: Azure Database for MySQL - 灵活服务器
在本教程中,你将了解如何在后端使用 Azure Database for MySQL 灵活服务器在 Azure Kubernetes 服务 (AKS) 群集上部署 Spring Boot 应用程序,使其在 Azure 虚拟网络中安全地彼此通信。
注意
本教程假定你基本了解 Kubernetes 概念、Java Spring Boot 和 MySQL。 对于 Spring Boot 应用程序,我们建议使用 Azure Spring Apps。 但是,你仍然可以使用 Azure Kubernetes 服务作为目标。 如需建议,请参阅 Java 工作负载目标指南。
先决条件
- Azure 订阅 - 如果没有 Azure 订阅,请在开始前创建一个Azure 试用帐户。
- Azure 命令行接口 (CLI)。
- 一个受支持的 Java 开发工具包,版本 8。
- Apache Maven 生成工具。
- Git 客户端。
- Docker 客户端。
创建 Azure Database for MySQL 灵活服务器
创建资源组
Azure 资源组是一个逻辑组,用于部署和管理 Azure 资源。 我们在 chinaeast2 位置使用 az group create 命令创建一个资源组 rg-mysqlaksdemo。
- 打开命令提示符。
- 登录 Azure 帐户。
az login
- 选择自己的 Azure 订阅。
az account set -s <your-subscription-ID>
- 创建资源组。
az group create --name rg-mysqlaksdemo --location chinaeast2
创建 Azure Database for MySQL 灵活服务器实例
现在,我们将在虚拟网络中创建 Azure Database for MySQL 灵活服务器实例(专用访问连接方法)。
为本教程中的所有资源创建一个 Azure 虚拟网络 vnet-mysqlaksdemo,并为 Azure Database for MySQL 灵活服务器实例创建子网 subnet-mysql。
az network vnet create \ --resource-group rg-mysqlaksdemo \ --name vnet-mysqlaksdemo \ --address-prefixes 155.55.0.0/16 \ --subnet-name subnet-mysql \ --subnet-prefix 155.55.1.0/24
使用 az mysql flexible-server create 命令在上面创建的子网中创建 Azure Database for MySQL 灵活服务器实例 mysql-mysqlaksdemo。 将管理员用户名和密码替换为你的值。
az mysql flexible-server create \ --name mysql-mysqlaksdemo \ --resource-group rg-mysqlaksdemo \ --location chinaeast2 \ --admin-user <your-admin-username> \ --admin-password <your-admin-password> \ --vnet vnet-mysqlaksdemo \ --subnet subnet-mysql
现在,你已经在 chinaeast2 区域中创建了一个 Azure Database for MySQL 灵活服务器实例,该服务器具有可突发 B1MS 计算、32 GB 存储空间、7 天备份保持期,并且位于所提供的子网 subnet-mysql 中。 此子网不得具有其中部署的任何其他资源,并且将委托给 Microsoft.DBforMySQL/flexibleServers。
配置新的 Azure Database for MySQL 灵活服务器数据库
demo
,以便与 Spring Boot 应用程序一起使用。az mysql flexible-server db create \ --resource-group rg-mysqlaksdemo \ --server-name mysql-mysqlaksdemo \ --database-name demo
创建 Azure 容器注册表
在资源组中创建私有 Azure 容器注册表。 本教程的后续步骤会将示例应用作为 Docker 映像推送到此注册表。 用注册表的唯一名称替换 mysqlaksdemoregistry
。
az acr create --resource-group rg-mysqlaksdemo \
--location chinaeast2 \
--name mysqlaksdemoregistry \
--sku Basic
编写应用程序代码
在本部分,我们将对演示应用程序进行编码。 如果想要加快进度,可下载 https://github.com/Azure-Samples/tutorial-springboot-mysql-aks 处提供的已编码的应用程序,并跳转到下一部分 - 生成映像并推送到 ACR。
使用 Spring Initializr 生成应用程序。
curl https://start.spring.io/starter.tgz \ -d dependencies=web,data-jdbc,mysql \ -d baseDir=springboot-mysql-aks \ -d bootVersion=2.5.6.RELEASE \ -d artifactId=springboot-mysql-aks \ -d description="Spring Boot on AKS connecting to Azure DB for MySQL" \ -d javaVersion=1.8 | tar -xzvf -
将在
springboot-mysql-aks
文件夹中生成一个基础 Spring Boot 应用程序。请使用你喜欢的文本编辑器(如 VSCode)或任何 IDE 执行后续步骤。
将 Spring Boot 配置为使用 Azure Database for MySQL 灵活服务器。
打开 src/main/resources/application.properties 文件,添加以下片段。 此代码会从 Kubernetes 清单文件中读取数据库主机、数据库名称、用户名和密码。
logging.level.org.springframework.jdbc.core=DEBUG spring.datasource.url=jdbc:mysql://${DATABASE_HOST}:3306/${DATABASE_NAME}?serverTimezone=UTC spring.datasource.username=${DATABASE_USERNAME} spring.datasource.password=${DATABASE_PASSWORD} spring.datasource.initialization-mode=always
警告
配置属性
spring.datasource.initialization-mode=always
意味着 Spring Boot 将在每次服务器启动时使用我们稍后将创建的schema.sql
文件来自动生成数据库架构。 这非常适合测试,但请记住,这会在每次重启时删除数据,因此不应在生产中使用!注意
我们将
?serverTimezone=UTC
追加到配置属性spring.datasource.url
中,以指示 JDBC 驱动程序在连接到数据库时使用 UTC 日期格式(或协调世界时)。 否则,Java 服务器将不使用与数据库相同的日期格式,这将导致错误。创建数据库架构。
Spring Boot 会自动执行
src/main/resources/schema.sql
来创建数据库架构。 创建包含以下内容的文件:DROP TABLE IF EXISTS todo; CREATE TABLE todo (id SERIAL PRIMARY KEY, description VARCHAR(255), details VARCHAR(4096), done BOOLEAN);
对 Java Spring Boot 应用程序进行编码。
添加 Java 代码,以便使用 JDBC 在 MySQL 服务器中存储并检索数据。 在
DemoApplication
类旁创建新的Todo
Java 类并添加以下代码:package com.example.springbootmysqlaks; import org.springframework.data.annotation.Id; public class Todo { public Todo() { } public Todo(String description, String details, boolean done) { this.description = description; this.details = details; this.done = done; } @Id private Long id; private String description; private String details; private boolean done; public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String getDescription() { return description; } public void setDescription(String description) { this.description = description; } public String getDetails() { return details; } public void setDetails(String details) { this.details = details; } public boolean isDone() { return done; } public void setDone(boolean done) { this.done = done; } }
此类是映射在之前创建的
todo
表上的域模型。若要管理该类,你需要一个存储库。 在同一包中定义一个新的
TodoRepository
接口:package com.example.springbootmysqlaks; import org.springframework.data.repository.CrudRepository; public interface TodoRepository extends CrudRepository<Todo, Long> { }
此存储库是 Spring Data JDBC 管理的存储库。
创建可存储和检索数据的控制器,完成该应用程序。 在同一包中实现
TodoController
类,并添加以下代码:package com.example.springbootmysqlaks; import org.springframework.http.HttpStatus; import org.springframework.web.bind.annotation.*; @RestController @RequestMapping("/") public class TodoController { private final TodoRepository todoRepository; public TodoController(TodoRepository todoRepository) { this.todoRepository = todoRepository; } @PostMapping("/") @ResponseStatus(HttpStatus.CREATED) public Todo createTodo(@RequestBody Todo todo) { return todoRepository.save(todo); } @GetMapping("/") public Iterable<Todo> getTodos() { return todoRepository.findAll(); } }
在基目录 springboot-mysql-aks 中创建新的 Dockerfile,并复制此代码片段。
FROM openjdk:8-jdk-alpine RUN addgroup -S spring && adduser -S spring -G spring USER spring:spring ARG DEPENDENCY=target/dependency COPY ${DEPENDENCY}/BOOT-INF/lib /app/lib COPY ${DEPENDENCY}/META-INF /app/META-INF COPY ${DEPENDENCY}/BOOT-INF/classes /app ENTRYPOINT ["java","-cp","app:app/lib/*","com.example.springbootmysqlaks.DemoApplication"]
转到 pom.xml 文件,将 pom.xml 文件中的
<properties>
集合更新为 Azure 容器注册表的注册表名称和jib-maven-plugin
的最新版本。 注意:如果 ACR 名称包含大写字符,请务必将其转换为小写字符。<properties> <docker.image.prefix>mysqlaksdemoregistry.azurecr.io</docker.image.prefix> <jib-maven-plugin.version>3.1.4</jib-maven-plugin.version> <java.version>1.8</java.version> </properties>
更新 pom.xml 文件中的
<plugins>
集合,使<plugin>
元素包含jib-maven-plugin
的条目,如下所示。 请注意,我们将使用 Microsoft 容器注册表 (MCR) 中的基础映像:mcr.microsoft.com/java/jdk:8-zulu-alpine
,其中包含 Azure 正式支持的 JDK。 如需具有官方支持的 JDK 的其他 MCR 基础映像,请参阅 Docker Hub。<plugin> <artifactId>jib-maven-plugin</artifactId> <groupId>com.google.cloud.tools</groupId> <version>${jib-maven-plugin.version}</version> <configuration> <from> <image>mcr.microsoft.com/java/jdk:8-zulu-alpine</image> </from> <to> <image>${docker.image.prefix}/${project.artifactId}</image> </to> </configuration> </plugin>
生成映像并推送到 ACR
在命令提示符下,导航到 springboot-mysql-aks 文件夹,并运行以下命令来先设置 Azure 容器注册表的默认名称(否则将需要在 az acr login
中指定名称),生成映像,然后将映像推送到注册表。
确保在执行此步骤时 Docker 守护程序正在运行。
az config set defaults.acr=mysqlaksdemoregistry
az acr login && mvn compile jib:build
在 AKS 上创建 Kubernetes 群集
现在,我们将在虚拟网络 vnet-mysqlaksdemo 中创建一个 AKS 群集。
在本教程中,我们将在 AKS 中使用 Azure CNI 网络。 如果要改为配置 kubenet 网络,请参阅在 AKS 中使用 kubenet 网络。
为要使用的 AKS 群集创建子网 subnet-aks。
az network vnet subnet create \ --resource-group rg-mysqlaksdemo \ --vnet-name vnet-mysqlaksdemo \ --name subnet-aks \ --address-prefixes 155.55.2.0/24
获取子网资源 ID。
SUBNET_ID=$(az network vnet subnet show --resource-group rg-mysqlaksdemo --vnet-name vnet-mysqlaksdemo --name subnet-aks --query id -o tsv)
在虚拟网络中创建一个 AKS 群集,对其附加 Azure 容器注册表 (ACR) mysqlaksdemoregistry。
az aks create \ --resource-group rg-mysqlaksdemo \ --name aks-mysqlaksdemo \ --network-plugin azure \ --service-cidr 10.0.0.0/16 \ --dns-service-ip 10.0.0.10 \ --docker-bridge-address 172.17.0.1/16 \ --vnet-subnet-id $SUBNET_ID \ --attach-acr mysqlaksdemoregistry \ --dns-name-prefix aks-mysqlaksdemo \ --generate-ssh-keys
在创建群集的过程中还定义了以下 IP 地址范围:
--service-cidr 用于为 AKS 群集中的内部服务分配 IP 地址。 可以使用任何专用地址范围,只要其符合以下要求即可:
- 不得在群集的虚拟网络 IP 地址范围内
- 不得与群集虚拟网络对等互连的任何其他虚拟网络重叠
- 不得与任何本地 IP 重叠
- 不得在范围 169.254.0.0/16、172.30.0.0/16、172.31.0.0/16 或 192.0.2.0/24 中
--dns-service-ip 地址是群集 DNS 服务的 IP 地址。 此地址必须在 Kubernetes 服务地址范围内。 请勿使用地址范围内的第一个 IP 地址。 子网范围内的第一个地址用于 kubernetes.default.svc.cluster.local 地址。
--docker-bridge-address 是 Docker 网桥地址,它表示所有 Docker 安装中显示的默认 docker0 网桥地址 。 必须选择一个不与网络上其他 CIDR(包括群集的服务 CIDR 和 Pod CIDR)冲突的地址空间。
将应用程序部署到 AKS 群集
在 Azure 门户上转到 AKS 群集资源。
从任何资源视图(命名空间、工作负载、服务和流入量、存储或配置)中选择“添加”和“通过 YAML 添加” 。
粘贴到以下 YAML 中。 替换 Azure Database for MySQL 灵活服务器管理员用户名和密码的值。
apiVersion: apps/v1 kind: Deployment metadata: name: springboot-mysql-aks spec: replicas: 1 selector: matchLabels: app: springboot-mysql-aks template: metadata: labels: app: springboot-mysql-aks spec: containers: - name: springboot-mysql-aks image: mysqlaksdemoregistry.azurecr.io/springboot-mysql-aks:latest env: - name: DATABASE_HOST value: "mysql-mysqlaksdemo.mysql.database.chinacloudapi.cn" - name: DATABASE_USERNAME value: "<your-admin-username>" - name: DATABASE_PASSWORD value: "<your-admin-password>" - name: DATABASE_NAME value: "demo" --- apiVersion: v1 kind: Service metadata: name: springboot-mysql-aks spec: type: LoadBalancer ports: - port: 80 targetPort: 8080 selector: app: springboot-mysql-aks
选择 YAML 编辑器底部的“添加”,以部署应用程序。
添加 YAML 文件后,资源查看器会显示 Spring Boot 应用程序。 记下外部服务中包含的链接的外部 IP 地址。
测试应用程序
若要测试应用程序,可使用 cURL。
首先,使用以下命令在数据库中创建一个新的待办事项。
curl --header "Content-Type: application/json" \
--request POST \
--data '{"description":"configuration","details":"congratulations, you have deployed your application correctly!","done": "true"}' \
http://<AKS-service-external-ip>
接下来,使用新的 cURL 请求,或在浏览器中输入群集外部 IP 来检索数据。
curl http://<AKS-service-external-ip>
此命令会返回待办事项列表,其中包括已创建的项。
[{"id":1,"description":"configuration","details":"congratulations, you have deployed your application correctly!","done":true}]
下面是这些 cURL 请求的屏幕截图:
可通过浏览器查看类似的输出:
祝贺你! 你已在后端通过 Azure Database for MySQL 灵活服务器在 Azure Kubernetes 服务 (AKS) 群集上部署 Spring Boot 应用程序!
清理资源
若要避免 Azure 费用,应清除不需要的资源。 如果不再需要群集,可以使用 az group delete 命令删除资源组、容器服务及所有相关资源。
az group delete --name rg-mysqlaksdemo
注意
删除群集时,AKS 群集使用的 Microsoft Entra 服务主体不会被删除。 有关如何删除服务主体的步骤,请参阅 AKS 服务主体的注意事项和删除。 如果你使用了托管标识,则该标识由平台托管,不需要删除。