將 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 未使用的字元字串。您可以隨時更新付款方式。
  • 所有 Google Cloud 專案的專案 ID 均不得重複,而且設定後即無法變更。Cloud 控制台會自動產生一個不重複的字串。但通常是在乎它何在在大部分的程式碼研究室中,您必須參照專案 ID (通常為 PROJECT_ID)。如果您對產生的 ID 不滿意,可以隨機產生一個 ID。或者,您也可以自行嘗試,看看是否支援。在這個步驟後,這個名稱即無法變更,而且在專案期間內仍會保持有效。
  • 資訊中的第三個值是專案編號,部分 API 會使用這個編號。如要進一步瞭解這三個值,請參閱說明文件
  1. 接下來,您需要在 Cloud 控制台中啟用計費功能,才能使用 Cloud 資源/API。執行本程式碼研究室不會產生任何費用 (如果有的話)。如要關閉資源,以免產生本教學課程結束後產生的費用,您可以刪除自己建立的資源或刪除專案。新使用者符合 $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 控制台的 Artifacts Registry 映像檔頁面,應該就會看到控制台中列出的容器映像檔。您現在已取得適用於整個專案的 Docker 映像檔。稍後您將看到,Kubernetes 可以使用及自動化調度管理,您將在幾分鐘內看到該映像檔。
  2. (選用) 完成後 (下載並擷取所有內容需要一些時間),請使用下列指令來測試映像檔。下列指令會在通訊埠 8080 中,以通訊埠 8080 的形式執行 Docker 容器做為 Daemon。如果遇到權限問題,請先執行 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

請注意,您必須直接公開 Deployment,而非 Pod。這樣結果服務就會針對部署作業代管的所有 Pod 之間的流量進行負載平衡 (本例中只有一個 Pod,但之後會新增更多備用資源)。

Kubernetes 主要執行個體會建立負載平衡器以及相關的 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

瞭解詳情