將 Spring Boot Java 應用程式部署至 Google Kubernetes Engine 中的 Kubernetes

1. 事前準備

Kubernetes 是開放原始碼專案,可在許多不同環境中運作,包括筆記型電腦、高可用性的多節點叢集、公有雲、地端部署、虛擬機器 (VM) 執行個體和裸機環境。

在本程式碼研究室中,您將簡單的 Spring Boot Java 網頁應用程式部署至 GKE 上的 Kubernetes,目標是在 Kubernetes 上以複製應用程式的形式執行網頁應用程式。您將使用在本機開發的程式碼,將其轉換為 Docker 容器映像檔,並在 GKE 上執行該映像檔。

您將使用 Google Cloud 的全代管 Kubernetes 服務 GKE,專心體驗 Kubernetes,不必費心設定基礎架構。

如果您想在本機 (例如開發筆電) 上執行 Kubernetes,請考慮使用 Minikube,這項工具可輕鬆設定單一節點的 Kubernetes 叢集,用於開發和測試。如要使用 Minikube 完成本程式碼研究室,請按照相關步驟操作。

本程式碼研究室會使用「使用 Spring Boot 建構應用程式」指南中的範例程式碼。

必要條件

  • 熟悉 Java 程式設計語言和工具
  • 瞭解標準 Linux 文字編輯器,例如 Vim、Emacs 和 nano

執行步驟

  • 將簡單的 Java 應用程式封裝為 Docker 容器。
  • 在 GKE 上建立 Kubernetes 叢集。
  • 將 Java 應用程式部署至 GKE 上的 Kubernetes。
  • 擴充服務並推出升級版本。
  • 存取資訊主頁,這是網頁式 Kubernetes 使用者介面。

軟硬體需求

2. 設定和需求條件

自修實驗室環境設定

  1. 登入 Google Cloud 控制台,然後建立新專案或重複使用現有專案。如果沒有 Gmail 或 Google Workspace 帳戶,請先建立帳戶

b35bf95b8bf3d5d8.png

a99b7ace416376c4.png

bd84a6d3004737c5.png

  • 專案名稱是這個專案參與者的顯示名稱。這是 Google API 未使用的字元字串。你隨時可以更新。
  • 專案 ID 在所有 Google Cloud 專案中都是不重複的,而且設定後即無法變更。Cloud 控制台會自動產生專屬字串,通常您不需要在意該字串為何。在大多數程式碼研究室中,您需要參照專案 ID (通常標示為 PROJECT_ID)。如果您不喜歡產生的 ID,可以產生另一個隨機 ID。你也可以嘗試使用自己的名稱,看看是否可用。完成這個步驟後就無法變更,且專案期間會維持不變。
  • 請注意,有些 API 會使用第三個值,也就是「專案編號」。如要進一步瞭解這三種值,請參閱說明文件
  1. 接著,您需要在 Cloud 控制台中啟用帳單,才能使用 Cloud 資源/API。完成這個程式碼研究室的費用不高,甚至可能完全免費。如要關閉資源,避免在本教學課程結束後繼續產生費用,請刪除您建立的資源或專案。Google Cloud 新使用者可參加價值$300 美元的免費試用計畫。

啟用 Cloud Shell

  1. 在 Cloud 控制台,點選「啟用 Cloud Shell」 圖示 853e55310c205094.png

55efc1aaa7a4d3ad.png

如果您是首次啟動 Cloud Shell,系統會顯示中繼畫面,說明這個指令列環境。如果出現中繼畫面,請按一下「繼續」

9c92662c6a846a5c.png

佈建並連至 Cloud Shell 預計只需要幾分鐘。

9f0e51b578fecce5.png

這部虛擬機器已載入所有必要的開發工具,並提供永久的 5 GB 主目錄,而且可在 Google Cloud 運作,大幅提升網路效能並強化驗證功能。本程式碼研究室幾乎所有工作都可在瀏覽器上完成。

連至 Cloud Shell 後,您應該會看到驗證已完成,專案也已設為獲派的專案 ID。

  1. 在 Cloud Shell 中執行下列指令,確認您已通過驗證:
gcloud auth list

指令輸出

 Credentialed Accounts
ACTIVE  ACCOUNT
*       <my_account>@<my_domain.com>

To set the active account, run:
    $ gcloud config set account `ACCOUNT`
  1. 在 Cloud Shell 中執行下列指令,確認 gcloud 指令知道您的專案:
gcloud config list project

指令輸出

[core]
project = <PROJECT_ID>

如未設定,請輸入下列指令手動設定專案:

gcloud config set project <PROJECT_ID>

指令輸出

Updated property [core/project].

3. 取得原始碼

啟動 Cloud Shell 後,您可以使用指令列,在主目錄中複製範例原始碼。

$ git clone https://github.com/spring-guides/gs-spring-boot.git
$ cd gs-spring-boot/complete

4. 在本機執行應用程式

  1. 確認 JAVA_HOME 已設為正確版本:
$ export JAVA_HOME=/usr/lib/jvm/java-1.17.0-openjdk-amd64
  1. 您可以使用 Spring Boot 外掛程式正常啟動 Spring Boot 應用程式。
$ ./mvnw -DskipTests spring-boot:run
  1. 應用程式啟動後,請按一下 Cloud Shell 工具列中的「網頁預覽」1a94d5bd10bfc072.png,然後選取「透過以下通訊埠預覽:8080」

6252b94905f3f7bd.png

瀏覽器會開啟一個分頁,並連結至您剛剛啟動的伺服器。

9b6c29059957bd0.jpeg

5. 將 Java 應用程式封裝為 Docker 容器

接下來,您需要準備應用程式,以便在 Kubernetes 上執行。第一步是定義容器及其內容。

  1. 為應用程式建立可部署的 JAR。
$ ./mvnw -DskipTests package
  1. 啟用 Artifact Registry API,儲存您要建立的容器映像檔。
$ gcloud services enable artifactregistry.googleapis.com
  1. 如果沒有 Docker 存放區,請建立一個。您必須先建立存放區,才能向存放區推送映像檔:
$ gcloud artifacts repositories create codelabrepo     --repository-format=docker --location=us-central1 
  1. 圖片格式如下:

{LOCATION}-docker.pkg.dev/{PROJECT-ID}/{REPOSITORY}/{IMAGE-NAME}

舉例來說,如果您在名為 codelabrepous-central1 位置建立存放區,並想將映像檔命名為 hello-java:v1,則映像檔會是:

us-central1-docker.pkg.dev/{PROJECT-ID}/codelabrepo/hello-java:v1

  1. 使用 Jib 建立容器映像檔,並推送至 Artifact Registry。
$ export GOOGLE_CLOUD_PROJECT=`gcloud config list --format="value(core.project)"`

$ ./mvnw -DskipTests com.google.cloud.tools:jib-maven-plugin:build -Dimage=us-central1-docker.pkg.dev/${GOOGLE_CLOUD_PROJECT}/codelabrepo/hello-java:v1
  1. 前往 Cloud Console 的「Artifacts Registry Images」(Artifacts Registry 映像檔) 頁面 ,即可在主控台中查看列出的容器映像檔。您現在擁有專案適用的 Docker 映像檔,Kubernetes 可以存取並協調這個映像檔,您會在幾分鐘後看到相關資訊。
  2. (選用) 完成後 (下載及解壓縮所有內容需要一些時間),請使用下列指令測試映像檔,這會從您新建立的容器映像檔,在 8080 連接埠上以精靈身分執行 Docker 容器。如果發生權限問題,請先執行 gcloud auth configure-docker us-central1-docker.pkg.dev
$ docker run -ti --rm -p 8080:8080 \
  us-central1-docker.pkg.dev/$GOOGLE_CLOUD_PROJECT/codelabrepo/hello-java:v1
  1. 再次善用 Cloud Shell 的網頁預覽功能。

6252b94905f3f7bd.png

  1. 新分頁中應會顯示預設頁面。確認應用程式在本機的 Docker 容器中執行後,請按下 Control+C 停止執行中的容器。

6. 建立叢集

您現在可以建立 GKE 叢集。叢集由 Google 管理的 Kubernetes API 伺服器和一組工作站節點組成。工作站節點是 Compute Engine VM。

  1. 首先,請確認已啟用相關 API 功能。
$ gcloud services enable compute.googleapis.com container.googleapis.com
  1. 建立含兩個 n1-standard-1 節點的叢集 (需數分鐘才能完成)。
$ gcloud container clusters create hello-java-cluster \
  --num-nodes 2 \
  --machine-type n1-standard-1 \
  --zone us-central1-c

最後,您應該會看到建立的叢集。

Creating cluster hello-java-cluster...done.
Created [https://container.googleapis.com/v1/projects/...].
kubeconfig entry generated for hello-dotnet-cluster.
NAME                  ZONE            MASTER_VERSION  
hello-java-cluster  us-central1-c  ...

現在您應該已擁有由 GKE 支援的 Kubernetes 叢集,且可正常運作。

758c7fca14f70623.png

現在請將容器化應用程式部署至 Kubernetes 叢集!從現在起,您將使用 kubectl 指令列 (已在 Cloud Shell 環境中設定)。本程式碼研究室的其餘部分需要 Kubernetes 用戶端和伺服器版本為 1.2 以上。kubectl version 會顯示指令的目前版本。

7. 將應用程式部署至 Kubernetes

  1. Kubernetes Deployment 可使用您建立的容器映像檔,建立、管理及擴充應用程式的多個執行個體。使用 kubectl run 指令,將應用程式的一個執行個體部署至 Kubernetes。
$ kubectl create deployment hello-java --image=us-central1-docker.pkg.dev/$GOOGLE_CLOUD_PROJECT/codelabrepo/hello-java:v1
  1. 如要查看您建立的部署作業,只要執行下列指令即可:
$ kubectl get deployments

NAME         DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
hello-java   1         1         1            1           37s
  1. 如要查看部署作業建立的應用程式例項,請執行下列指令:
$ kubectl get pods

NAME                         READY     STATUS    RESTARTS   AGE
hello-java-714049816-ztzrb   1/1       Running   0          57s

此時,您應該已在 Kubernetes 的控管下執行容器,但仍須讓外部存取該容器。

8. 允許外部流量

根據預設,Pod 只能透過叢集內的內部 IP 存取。如要從 Kubernetes 虛擬網路外部存取 hello-java 容器,必須將 Pod 公開為 Kubernetes 服務。

  1. 在 Cloud Shell 中,您可以建立 Kubernetes LoadBalancer 服務,將 Pod 公開發布至網際網路。
$ kubectl create service loadbalancer hello-java --tcp=8080:8080

請注意,您直接公開的是部署作業,而非 Pod。這會導致產生的服務在 Deployment 管理的所有 Pod 之間進行負載平衡 (在本例中只有一個 Pod,但您稍後會新增更多副本)。

Kubernetes Master 會建立負載平衡器和相關的 Compute Engine 轉送規則、目標集區和防火牆規則,確保服務可從 Google Cloud 外部完全存取。

  1. 如要找出服務可公開存取的 IP 位址,只要要求 kubectl 列出所有叢集服務即可。
$ kubectl get services

NAME         CLUSTER-IP     EXTERNAL-IP      PORT(S)    AGE
hello-java   10.3.253.62    aaa.bbb.ccc.ddd  8080/TCP    1m
kubernetes   10.3.240.1     <none>           443/TCP    5m
  1. 現在只要將瀏覽器指向 http://<EXTERNAL_IP>:8080,應該就能連上服務。

9. 擴充服務規模

Kubernetes 的強大功能之一,就是能輕鬆擴充應用程式。假設您突然需要更多應用程式容量,只要告訴複製控制器管理應用程式例項的新副本數量即可。

$ kubectl scale deployment hello-java --replicas=3

deployment "hello-java" scaled

$ kubectl get deployment
NAME         DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
hello-java   3         3         3            3           22m

請注意宣告式方法。您不必啟動或停止新執行個體,只要宣告應隨時執行的執行個體數量即可。Kubernetes 調解迴圈只會確保實際情況符合您的要求,並視需要採取行動。

10. 推出服務升級

您部署至實際工作環境的應用程式,在某個時間點會需要修正錯誤或新增功能。Kubernetes 可協助您將新版本部署至正式環境,不會影響使用者。

  1. 按一下 Cloud Shell 選單中的「開啟編輯器」 2109d75686c889a.png,開啟程式碼編輯器。
  2. 前往 src/main/java/com/example/springboot/HelloController.java 並更新回應的值。
package com.example.springboot;

import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.RequestMapping;

@RestController
public class HelloController {

    @RequestMapping("/")
    public String index() {
        return "Greetings from Google Kubernetes Engine!";
    }
}
  1. 使用 Jib 建構及推送新版容器映像檔。充分運用快取功能後,建構及推送更新後的映像檔速度應該會快上許多。
$ ./mvnw -DskipTests package com.google.cloud.tools:jib-maven-plugin:build -Dimage=us-central1-docker.pkg.dev/$GOOGLE_CLOUD_PROJECT/codelabrepo/hello-java:v2

現在 Kubernetes 就能順利將複寫控制器更新為新版應用程式!

  1. 如要變更執行中容器的映像檔標籤,請編輯現有的 hello-java 部署作業,並將映像檔從 us-central1-docker.pkg.dev/PROJECT_ID/codelabrepo/hello-java:v1

us-central1-docker.pkg.dev/PROJECT_ID/codelabrepo/hello-java:v2

  1. 您可以使用 kubectl set image 指令,要求 Kubernetes 透過滾動更新,一次一個執行個體地在整個叢集中部署新版應用程式。
$ kubectl set image deployment/hello-java hello-java=us-central1-docker.pkg.dev/$GOOGLE_CLOUD_PROJECT/codelabrepo/hello-java:v2

deployment "hello-java" image updated
  1. 再次檢查 http://EXTERNAL_IP:8080,確認傳回的是新回應。

11. 復原

糟糕!您是否不小心發布了新版應用程式?或許新版本含有錯誤,您需要快速還原。使用 Kubernetes 時,您可以輕鬆復原至先前的狀態。執行下列指令來復原應用程式:

$ kubectl rollout undo deployment/hello-java

再次檢查 http://EXTERNAL_IP:8080 時,應該會看到舊的回覆。

12. 恭喜

您已學會如何建構新的 Java 網頁應用程式,並部署至 GKE 上的 Kubernetes。

清理

$ gcloud container clusters delete hello-java-cluster --zone us-central1-c

$ gcloud container images delete us-central1-docker.pkg.dev/$GOOGLE_CLOUD_PROJECT/codelabrepo/hello-java:v1 us-central1-docker.pkg.dev/$GOOGLE_CLOUD_PROJECT/codelabrepo/hello-java:v2

瞭解詳情