將使用 Jib 的 Micronaut 應用程式容器化部署至 Google Kubernetes Engine

1. 總覽

關於密克羅特州

Micronaut 是以 JVM 為基礎的現代化完整堆疊架構,用於建構可輕鬆測試的模組化微服務和無伺服器應用程式。Microaut 的目標是以最少的記憶體用量,提供出色的啟動時間、快速處理量。開發人員可以透過 Java、Groovy 或 Kotlin 使用 Micronaut 進行開發。

Microaut 提供:

  • 啟動時間短,低記憶體消耗量 - 以反映為基礎的 IoC 架構會為程式碼中的每個欄位、方法和建構函式載入及快取反射資料,而 Micronaut 的應用程式啟動時間和記憶體用量不受程式碼集大小限制。
  • 宣告式、反應式、編譯時間 HTTP 用戶端:以宣告方式建構回應式 HTTP 用戶端,這些用戶端會在編譯期間實作,減少記憶體消耗量。
  • 以 Netty 為基礎建構且不具阻斷的 HTTP 伺服器:Micronaut 的 HTTP 伺服器採用順暢的學習曲線,讓使用者盡可能輕鬆公開可透過 HTTP 用戶端使用的 API。
  • 快速簡單的測試:輕鬆啟動單元測試中的伺服器和用戶端,並立即執行。
  • 有效率的編譯時間依附元件插入和 AOP:Micronaut 提供了一個不需使用反射的簡易編譯時間導向程式設計 API。
  • 建構完全回應式和非封鎖的應用程式:Micronaut 支援任何實作回應式串流的架構,包括 RxJava 和 Reactor。

如要瞭解詳情,請造訪 Micronaut 網站

關於 Kubernetes

Kubernetes 是一項開放原始碼專案,可在許多不同環境中執行,從筆記型電腦、高可用性的多節點叢集、公有雲、地端部署環境、虛擬機器到裸機環境,一應俱全。

在本研究室中,您會將以 Groovy 為基礎的簡易微服務部署至在 Kubernetes Engine 上執行的 Kubernetes

本程式碼研究室的目標是協助您以複製服務的形式執行微服務,並在 Kubernetes 中運作。請將您在機器上開發的程式碼轉換為 Docker 容器映像檔,然後在 Kubernetes Engine 上執行該映像檔。

以下圖表說明本程式碼研究室中組成的各個部分,協助您瞭解各部分如何搭配在一起。在參與本程式碼研究室的過程中,可以做為參考資源。到了課程結束之後 應該就會發現這樣了 (但暫時您可以忽略這則訊息),

Kubernetes 程式碼研究室圖 1 (2.png)

就本程式碼研究室而言,使用 Kubernetes Engine (在 Compute Engine 上執行的 Google 託管 Kubernetes 版本) 等代管環境可讓您更專心體驗 Kubernetes,不必費心設定基礎架構。

如果您想在本機機器 (例如開發筆記型電腦) 上執行 Kubernetes,建議您前往 Minikube。如此一來,您就能輕鬆設定單一節點 Kubernetes 叢集,以便用於開發和測試。如有需要,您可以使用 Minikube 完成本程式碼研究室。

關於 Jib

Jib 是一項開放原始碼工具,可讓您針對 Java 應用程式建構 Docker 和 OCI 映像檔。這可做為 Maven 和 Gradle 的外掛程式以及 Java 程式庫使用。

Jib 的目標是:

  • 快速:快速部署變更。Jib 會將應用程式分成多個層,將依附元件與類別拆分。現在,您無需等待 Docker 重新建構整個 Java 應用程式,只需部署已變更的層即可。
  • 可重現 - 以相同內容重新建構容器映像檔時,一律會產生相同的映像檔。永不再次觸發不必要的更新。
  • Daemonless - 減少 CLI 依附元件。在 Maven 或 Gradle 中建構 Docker 映像檔,並推送至您選擇的任何登錄檔。不必再編寫 Dockerfile 和呼叫 docker build/push。

如要進一步瞭解 Jib,請前往 GitHub 的專案頁面

關於本教學課程

本教學課程使用 Jib 工具中的範例程式碼,為 Java 應用程式建構容器。

這個範例是簡單的 hello world 服務,使用 Micronaut 架構和 Apache Groovy 程式設計語言。

課程內容

  • 如何使用 Jib 將簡易的 Java 應用程式封裝為 Docker 容器
  • 瞭解如何在 Kubernetes Engine 中建立 Kubernetes 叢集。
  • 如何將 Microaut 服務部署至 Kubernetes Engine 上的 Kubernetes
  • 如何擴充服務並推出升級版本。
  • 如何存取 Kubernetes 圖形資訊主頁。

軟硬體需求

  • Google Cloud Platform 專案
  • 瀏覽器,例如 ChromeFirefox
  • 熟悉 Vim、EMACs 或 Nano 等標準 Linux 文字編輯器

您會如何使用這個教學課程?

僅供閱讀 閱讀並完成練習

針對建立 HTML/CSS 網頁應用程式的經驗,您會給予什麼評價?

新手 中級 還算容易

根據您使用 Google Cloud Platform 服務的經驗,您會給予什麼評價?

新手 中級 還算容易

2. 設定和需求

自修環境設定

  1. 登入 Cloud 控制台建立新專案,或是重複使用現有專案。(如果您還沒有 Gmail 或 G Suite 帳戶,請先建立帳戶)。

dMbN6g9RawQj_VXCSYpdYncY-DbaRzr2GbnwoV7jFf1u3avxJtmGPmKpMYgiaMH-qu80a_NJ9p2IIXFppYk8x3wyymZXavjglNLJJhuXieCem56H30hwXtd8PvXGpXJO9gEUDu3cZw

ci9Oe6PgnbNuSYlMyvbXF1JdQyiHoEgnhl4PlV_MFagm2ppzhueRkqX4eLjJllZco_2zCp0V0bpTupUSKji9KkQyWqj11pqit1K1faS1V6aFxLGQdkuzGp4rsQTan7F01iePL5DtqQ

8-tA_Lheyo8SscAVKrGii2coplQp2_D1Iosb2ViABY0UUO1A8cimXUu6Wf1R9zJIRExL5OB2j946aIiFtyKTzxDcNnuznmR45vZ2HMoK3o67jxuoUJCAnqvEX6NgPGFjCVNgASc-lg

提醒您,專案 ID 是所有 Google Cloud 專案的專屬名稱 (已經有人使用上述名稱,很抱歉對您不符!)。稍後在本程式碼研究室中會稱為 PROJECT_ID

  1. 接下來,您需要在 Cloud 控制台中啟用計費功能,才能使用 Google Cloud 資源。

執行這個程式碼研究室並不會產生任何費用,如果有的話。請務必依照「清除所用資源」一節指示本節將說明如何關閉資源,這樣您就不會產生本教學課程結束後產生的費用。Google Cloud 的新使用者符合 $300 美元免費試用計畫的資格。

3. 取得 Micronaut 程式碼範例

Cloud Shell 啟動後,您可以使用指令列將範例原始碼複製到主目錄中,並使用 cd 到包含範例服務的目錄:

$ git clone https://github.com/GoogleContainerTools/jib.git
$ cd jib/examples/micronaut/

4. 快速查看程式碼

我們的 Mi Cronaut 簡易服務是由控制器組成,可輸出惡名的 Hello World 訊息:

@Controller("/hello")
class HelloController {
    @Get("/")
    String index() {
        "Hello World"
    }
}

HelloController 控制器會回應 /hello 路徑下的要求,而 index() 方法則會接受 HTTP GET 要求。

您也可以使用 Spock 測試類別檢查輸出內容中的訊息是否正確。

class HelloControllerSpec extends Specification {
    @Shared
    @AutoCleanup
    EmbeddedServer embeddedServer = ApplicationContext.run(EmbeddedServer)

    @Shared
    @AutoCleanup
    RxHttpClient client = embeddedServer.applicationContext.createBean(RxHttpClient, embeddedServer.getURL()) 

    void "test hello world response"() {
        when:
        HttpRequest request = HttpRequest.GET('/hello')
        String rsp  = client.toBlocking().retrieve(request)

        then:
        rsp == "Hello World"
    }
}

不僅僅是簡單的單元測試,這項測試實際上也會執行在實際工作環境中執行的 Micronaut 伺服器堆疊 (以 Netty 架構為基礎)。因此程式碼在產品中的行為將與測試中的相同。

如要執行測試,您可以執行下列指令,確認一切是否正常:

./gradlew test

5. 在本機執行應用程式

您可以使用下列 Gradle 指令正常啟動 Micronaut 服務:

$ ./gradlew run

應用程式啟動後,您可以使用小型 + 圖示開啟額外的 Cloud Shell 執行個體,然後向 curl 檢查您是否得到預期的輸出內容:

$ curl localhost:8080/hello

您應該會看到簡單的「Hello World」會出現訊息。

6. 使用 Jib 將應用程式封裝為 Docker 容器

接下來,請為應用程式做好準備,以便在 Kubernetes 中執行。為了這個目的,我們將利用 Jib 進行複雜的工作,因為我們不需要自己親手操作 Dockerfile

執行下列指令來建構容器:

$ ./gradlew jibDockerBuild

您應該會看到下列輸出內容:

Tagging image with generated image reference micronaut-jib:0.1. If you'd like to specify a different tag, you can set the jib.to.image parameter in your build.gradle, or use the --im
age=<MY IMAGE> commandline flag.

Containerizing application to Docker daemon as micronaut-jib:0.1...
warning: Base image 'gcr.io/distroless/java' does not use a specific image digest - build may not be reproducible
Getting base image gcr.io/distroless/java...
Building dependencies layer...
Building resources layer...
Building classes layer...
Finalizing...

Container entrypoint set to [java, -cp, /app/resources:/app/classes:/app/libs/*, example.micronaut.Application]
Loading to Docker daemon...

Built image to Docker daemon as micronaut-jib:0.1

映像檔已建構完成,接著在 Cloud Shell 的第一個分頁中執行 Docker 映像檔,看看是否能看到友善的 Hello 訊息:

$ docker run -it -p 8080:8080 micronaut-jib:0.1
16:57:20.255 [main] INFO  i.m.context.env.DefaultEnvironment - Established active environments: [cloud, gcp]
16:57:23.203 [main] INFO  io.micronaut.runtime.Micronaut - Startup completed in 2926ms. Server Running: http://97b7d76ccf3f:8080

我們的服務正在執行中,現在可以在第二個 Cloud Shell 分頁中啟動 curl 指令,確認服務是否正常運作:

$ curl localhost:8080/hello
Hello World

如要停止容器,請在 Cloud Shell 中點選 Ctrl+C

7. 將容器化服務推送至登錄檔

映像檔現已如預期運作,您可以將其推送至 Google Container Registry,這是用來存放 Docker 映像檔的私人存放區,而且可從每項 Google Cloud 專案存取 (但也能從 Google Cloud Platform 外部存取)。

在將 Container Registry 推送至登錄檔之前,請先依序前往「Tools」>「Tools」> 確認專案已啟用 Container RegistryContainer Registry。如果尚未啟用 Container Registry API,系統會顯示下列對話方塊,然後按一下「Enable Container Registry API」。如何啟用該功能:

ac812e6260ac7dfb.png

登錄檔準備就緒後,如要將映像檔推送至登錄檔,請啟動下列指令:

$ gcloud auth configure-docker
$ docker tag micronaut-jib:0.1 \
         gcr.io/$GOOGLE_CLOUD_PROJECT/micronaut-jib:0.1
$ docker push gcr.io/$GOOGLE_CLOUD_PROJECT/micronaut-jib:0.1

以上指令可讓 gcloud SDK 設定並授權 docker,將映像檔推送至 Container Registry 的執行個體,為映像檔標記指向在登錄檔中的位置,並推送至登錄檔。

如果一切順利,請稍候片刻,控制台中應該就會顯示容器映像檔:工具 >Container Registry。此時,您已取得適用於專案層級的 Docker 映像檔,稍後您將在幾分鐘內看到 Kubernetes 可以存取及自動化調度管理。

12224c4e42183b4e.png

8. 建立叢集

您現在已可建立 Kubernetes Engine 叢集。在此之前,請前往網路控制台的「Google Kubernetes Engine」區段,並等待系統初始化 (應該只需要幾秒鐘的時間)。

20c0587c0108b8ba.png

叢集是由 Google 代管的 Kubernetes 主要 API 伺服器,以及一組工作站節點所組成。工作站節點是 Compute Engine 虛擬機器。讓我們使用 CloudShell 工作階段中的 gcloud CLI 建立具有兩個 n1-standard-1 節點的叢集 (這需要幾分鐘的時間才能完成):

$ gcloud container clusters create hello-cluster \
  --num-nodes 2 \
  --machine-type n1-standard-1 \
  --zone us-central1-c

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

Creating cluster hello-cluster in us-central1-c...done.
Created [https://container.googleapis.com/v1/projects/mn-gke-test/zones/us-central1-c/clusters/hello-cluster].
To inspect the contents of your cluster, go to: https://console.cloud.google.com/kubernetes/workload_/gcloud/us-central1-c/hello-cluster?project=mn-gke-test
kubeconfig entry generated for hello-cluster.
NAME           LOCATION       MASTER_VERSION  MASTER_IP       MACHINE_TYPE   NODE_VERSION  NUM_NODES  STATUS
hello-cluster  us-central1-c  1.9.7-gke.7     35.239.224.115  n1-standard-1  1.9.7-gke.7   2          RUNNING

現在,您應該有一組採用 Google Kubernetes Engine 技術的 Kubernetes 叢集,而且其功能正常:

d9e1e314769753e7.png

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

9. 將應用程式部署至 Kubernetes

Kubernetes Deployment 可以使用剛建立的容器映像檔,建立、管理及擴充應用程式的多個執行個體。接著使用 kubectl create deployment 指令,將應用程式部署至 Kubernetes:

$ kubectl create deployment hello-micronaut \
  --image=gcr.io/$GOOGLE_CLOUD_PROJECT/micronaut-jib:0.1

如要檢視您剛剛建立的 Deployment,只要執行下列指令:

$ kubectl get deployments
NAME              DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
hello-micronaut   1         1         1            1           5m

如要查看部署作業建立的應用程式執行個體,請執行下列指令:

$ kubectl get pods
NAME                               READY     STATUS    RESTARTS   AGE
hello-micronaut-5647fb98c5-lh5h7   1/1       Running   0          5m

此時,您應該就能在 Kubernetes 的控制下執行容器,但還是必須開放容器供外界存取。

10. 允許外部流量

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

您可以在 Cloud Shell 中使用 kubectl expose 指令搭配 --type=LoadBalancer 旗標,在公開網際網路上公開 Pod。建立可外部存取的 IP 時,必須要有這個標記:

$ kubectl expose deployment hello-micronaut --type=LoadBalancer --port=8080

在此指令中使用的旗標,指出您將使用基礎架構提供的負載平衡器 (在本例中為 Compute Engine 負載平衡器)。請注意,您必須公開 Deployment,而非直接公開 Pod。這會讓產生的服務針對該部署項目代管的所有 Pod 之間的流量進行負載平衡 (本案例中只有 1 個 Pod,但您之後會新增更多備用資源)。

Kubernetes 主要執行個體會建立負載平衡器和相關 Compute Engine 轉送規則、目標集區和防火牆規則,藉此從 Google Cloud Platform 外部完全存取服務。

如要找出服務的可公開存取 IP 位址,只要要求 kubectl 列出所有叢集服務即可:

$ kubectl get services
NAME              TYPE           CLUSTER-IP      EXTERNAL-IP     PORT(S)          AGE
hello-micronaut   LoadBalancer   10.39.243.251   aaa.bbb.ccc.ddd 8080:30354/TCP   1m
kubernetes        ClusterIP      10.39.240.1     <none>          443/TCP          31m

請注意,系統為您的服務列出 2 個 IP 位址,兩者均為服務通訊埠 8080。一個是只會顯示在雲端虛擬網路的內部 IP;另一個是外部負載平衡的 IP在這個範例中,外部 IP 位址為 aaa.bbb.ccc.ddd

現在,只要將瀏覽器指向下列網址,即可連線至服務:http://<EXTERNAL_IP>:8080/hello

11. 擴充服務

Kubernetes 提供一項強大的功能,就是能輕鬆擴充應用程式。假設您突然需要更多應用程式容量您可以直接告訴複製控制器,為應用程式執行個體管理新的數量備用資源:

$ kubectl scale deployment hello-micronaut --replicas=3
deployment.extensions "hello-micronaut" scaled

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

請注意這裡的宣告式方法,不要啟動或停止您宣告隨時執行的新執行個體數量。Kubernetes 對帳迴圈只會確保實際情況與您的要求相符,並視情況採取行動。

12. 推出服務升級版本

您部署至實際工作環境的應用程式有時會需要修正錯誤或額外功能。Kubernetes 可協助您將新版本部署至實際工作環境,而且不會影響使用者。

首先,我們可以修改應用程式。從 Cloud Shell 開啟程式碼編輯器。

5aee8f3d1e003571.png

前往 /jib/examples/micronaut/src/main/groovy/example/micronaut/HelloController.groovy 並更新回應的值:

@Controller("/hello")
class HelloController {
    @Get("/")
    String index() {
        "Hello Kubernetes World"
    }
}

/jib/examples/micronaut/build.gradle 中,我們會更新以下這行程式碼,將映像檔版本從 0.1 升級至 0.2:

version '0.2'

接著以最新變更重新建構及封裝應用程式:

$ ./gradlew jibDockerBuild

然後標記並推送映像檔至容器映像檔註冊資料庫:

$ docker tag micronaut-jib:0.2 \
         gcr.io/$GOOGLE_CLOUD_PROJECT/micronaut-jib:0.2
$ docker push gcr.io/$GOOGLE_CLOUD_PROJECT/micronaut-jib:0.2

您現在可以讓 Kubernetes 順利將複製控制器更新至新版應用程式。如要變更執行中容器的映像檔標籤,您必須編輯現有的 hello-micronaut deployment,並將映像檔從 gcr.io/PROJECT_ID/micronaut-jib:0.1 變更為 gcr.io/PROJECT_ID/micronaut-jib:0.2

您可以使用 kubectl set image 指令要求 Kubernetes,透過滾動式更新,一次在整個叢集內部署新版應用程式:

$ kubectl set image deployment/hello-micronaut \
          micronaut-jib=gcr.io/$GOOGLE_CLOUD_PROJECT/micronaut-jib:0.2

deployment.apps "hello-micronaut" image updated

再次檢查 http://EXTERNAL_IP:8080,確認回應會傳回新的回應。

13. 復原

糟糕 — 您用新版的應用程式是否出錯?有可能新版本含有錯誤,因此您需要迅速復原。有了 Kubernetes,您可以輕鬆復原至之前的狀態。請執行以下指令,復原應用程式:

$ kubectl rollout undo deployment/hello-micronaut

如果您查看服務的輸出內容,就會回到初始的「Hello World」撰寫新的電子郵件訊息

14. 摘要

在這個步驟中,您將設定以 Apache Groovy 為基礎的簡易 Micronaut hello World 服務,並直接從 Cloud Shell 執行,並透過 Jib 將其封裝為容器,並部署至 Google Kubernetes Engine。

15. 恭喜!

您已瞭解如何建構新的 Apache Groovy / Micronaut 網頁型微服務,並部署至 Google Kubernetes Engine 中的 Kubernetes。

瞭解詳情

授權

這項內容採用的是創用 CC 姓名標示 2.0 通用授權。