教學課程:在 VNet 中具有適用於 MySQL 的 Azure 資料庫 - 彈性伺服器的 AKS 叢集上部署 Spring Boot 應用程式

適用於:適用於 MySQL 的 Azure 資料庫 - 彈性伺服器

在本教學課程中,您將了解如何在後端使用適用於 MySQL 的 Azure 資料庫彈性伺服器Azure Kubernetes Service (AKS) 叢集上部署 Spring Boot 應用程式,並在 Azure 虛擬網路內安全地彼此通訊。

注意

本教學課程假設您對 Kubernetes 概念、Java Spring Boot 和 MySQL 有基本了解。 對於 Spring Boot 應用程式,建議使用 Azure Spring 應用程式。 不過,您仍可使用 Azure Kubernetes Service 作為目的地。 如需建議,請參閱 Java 工作負載目的地指導

必要條件

建立適用於 MySQL 的 Azure 資料庫彈性伺服器

建立資源群組

Azure 資源群組是部署及管理 Azure 資源所在的邏輯群組。 我們將使用 az-group-create 命令在 eastus 位置建立資源群組 rg-mysqlaksdemo

  1. 開啟命令提示字元。
  2. 登入您的 Azure 帳戶。
    az login
    
  3. 選擇 Azure 訂用帳戶。
    az account set -s <your-subscription-ID>
    
  4. 建立資源群組。
    az group create --name rg-mysqlaksdemo --location eastus
    

建立適用於 MySQL 的 Azure 資料庫彈性伺服器執行個體

我們現在會在虛擬網路中建立適用於 MySQL 的 Azure 資料庫彈性伺服器執行個體 (私人存取連線方法)。

  1. 針對本教學課程中的所有資源建立 Azure 虛擬網路 vnet-mysqlaksdemo,並為適用於 MySQL 的 Azure 資料庫彈性伺服器執行個體建立子網路 vnet-mysqlaksdemo

    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 
    
  2. 使用 az mysql flexible-server create 命令,在上述建立的子網路中建立適用於 MySQL 的 Azure 資料庫彈性伺服器執行個體 mysql-mysqlaksdemo。 取代系統管理員使用者名稱和密碼的值。

    az mysql flexible-server create \
    --name mysql-mysqlaksdemo \
    --resource-group rg-mysqlaksdemo \
    --location eastus \
    --admin-user <your-admin-username> \
    --admin-password <your-admin-password> \
    --vnet vnet-mysqlaksdemo \
    --subnet subnet-mysql
    

    您現在已在 eastus 區域中建立適用於 MySQL 的 Azure 資料庫彈性伺服器執行個體,其中包含可高載的 B1MS 計算、32 GB 儲存體、7 天的備份保留期間,並在提供的子網路 subnet-mysql 中。 此子網路不應部署任何其他資源,且會委派給 Microsoft.DBforMySQL/flexibleServers。

  3. 設定要與 Spring Boot 應用程式搭配使用的全新適用於 MySQL 的 Azure 資料庫彈性伺服器資料庫 demo

    az mysql flexible-server db create \
    --resource-group rg-mysqlaksdemo \
    --server-name mysql-mysqlaksdemo \
    --database-name demo
    

建立 Azure Container Registry

在資源群組中建立私用的 Azure Container Registry。 本教學課程會在稍後的步驟中,將範例應用程式以 Docker 映像推送至此登錄。 以登錄的唯一名稱取代 mysqlaksdemoregistry

az acr create --resource-group rg-mysqlaksdemo \
--location eastus \
--name mysqlaksdemoregistry \
--sku Basic

編碼應用程式

在本節中,我們將撰寫示範應用程式的程式碼。 如果您想要更快速地執行,您可以從 https://github.com/Azure-Samples/tutorial-springboot-mysql-aks 下載可用的程式碼應用程式,並跳至下一節 - 建置映像並推送至 ACR

  1. 使用 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 -
    

    基本 Spring Boot 應用程式將會在資料夾 springboot-mysql-aks 內產生。

    針對下列步驟,請使用您慣用的文字編輯器,例如 VSCode 或任何 IDE。

  2. 設定 Spring Boot 以使用適用於 MySQL 的 Azure 資料庫彈性伺服器。

    開啟 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 伺服器不會使用與資料庫相同的日期格式,這會導致錯誤。

  3. 建立資料庫結構。

    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);
    
  4. 撰寫 Java Spring Boot 應用程式的程式碼。

    新增將使用 JDBC 的 Java 程式碼,以從您的 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();
        }
    }
    
  5. 在基本目錄 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"]
    
  6. 移至 pom.xml 檔案並將其中的 <properties> 集合更新為 Azure Container Registry 的登錄名稱以及 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>
    
  7. 更新 pom.xml 檔案中的 <plugins> 集合,讓 <plugin> 元素中包含 jib-maven-plugin 項目,如下列範例所示。 請注意,我們會使用 Microsoft Container Registry (MCR) 中的基底映像:mcr.microsoft.com/java/jdk:8-zulu-alpine,其中包含適用於 Azure 的正式支援 JDK。 有關具有正式支援 JDK 的其他 MCR 基礎映像,請參閱 docker 中樞

    <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 Container Registry 的預設名稱 (否則您必須在 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 網路功能

  1. 針對 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
    
  2. 取得子網路資源識別碼。

    SUBNET_ID=$(az network vnet subnet show --resource-group rg-mysqlaksdemo --vnet-name vnet-mysqlaksdemo --name subnet-aks --query id -o tsv)
    
  3. 在虛擬網路中建立 AKS 叢集,並附加 Azure Container Registry (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 叢集

  1. 移至 Azure 入口網站上的 AKS 叢集資源。

  2. 從任何資源檢視中選取 [新增],然後選取 [使用 YAML 新增] (命名空間、工作負載、服務和輸入、儲存體或設定)。

    螢幕擷取畫面顯示 Azure 入口網站上的 Azure Kubernetes Service 資源檢視。

  3. 在下列 YAML 中貼上。 取代適用於 MySQL 的 Azure 資料庫彈性伺服器管理員使用者名稱和密碼的值。

    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.azure.com"
            - 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
    
  4. 選取 YAML 編輯器底部的 [新增] 以部署應用程式。

    螢幕擷取畫面顯示使用 YAML 編輯器 [新增]。

  5. 新增 YAML 檔案之後,資源檢視器會顯示 Spring Boot 應用程式。 記下包含在外部服務中連結的外部 IP 位址。

    螢幕擷取畫面顯示 Azure Kubernetes 叢集服務外部 IP 的 Azure 入口網站檢視。

測試應用程式

若要測試應用程式,您可以使用 cURL。

首先,使用下列命令在資料庫中建立新的 "todo" 項目。

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>

此命令會傳回 "todo" 項目,包括您已建立的項目。

[{"id":1,"description":"configuration","details":"congratulations, you have deployed your application correctly!","done":true}]

以下是這些 cURL 要求的螢幕擷取畫面:螢幕擷取畫面顯示 cURL 要求的命令列輸出。

您可以透過瀏覽器看到類似輸出:螢幕擷取畫面顯示瀏覽器要求輸出。

恭喜! 您已使用位於後端的適用於 MySQL 的 Azure 資料庫彈性伺服器,在 Azure Kubernetes Service (AKS) 上成功部署 Spring Boot 應用程式!

清除資源

若要避免 Azure 費用,您應該清除不需要的資源。 若不再需要叢集,可使用 az group delete 命令來移除資源群組、容器服務和所有相關資源。

az group delete --name rg-mysqlaksdemo

注意

當您刪除叢集時,系統不會移除 AKS 叢集所使用的 Microsoft Entra 服務主體。 如需有關如何移除服務主體的步驟,請參閱 AKS 服務主體的考量和刪除。 如果您使用受控識別,則身分識別會由平台負責管理,您不需要刪除。

下一步