ทำให้แอป Spring Boot Java ใช้งานได้กับ Kubernetes บน Google Kubernetes Engine

1. ก่อนเริ่มต้น

Kubernetes เป็นโปรเจ็กต์โอเพนซอร์สที่สามารถทำงานในสภาพแวดล้อมที่แตกต่างกันได้มากมาย ตั้งแต่แล็ปท็อปไปจนถึงคลัสเตอร์แบบหลายโหนดที่มีความพร้อมใช้งานสูง ตั้งแต่ระบบคลาวด์สาธารณะไปจนถึงการติดตั้งใช้งานในองค์กร และตั้งแต่อินสแตนซ์เครื่องเสมือน (VM) ไปจนถึง Bare Metal

ในโค้ดแล็บนี้ คุณจะได้ทำให้เว็บแอป Java ของ Spring Boot แบบง่ายใช้งานได้ใน Kubernetes บน GKE โดยมีเป้าหมายเพื่อให้คุณเรียกใช้เว็บแอปเป็นแอปที่จำลองแบบใน Kubernetes ได้ คุณจะนำโค้ดที่พัฒนาในเครื่องมาเปลี่ยนเป็นอิมเมจคอนเทนเนอร์ Docker แล้วเรียกใช้อิมเมจใน GKE

คุณจะใช้ GKE ซึ่งเป็นบริการ Kubernetes ที่มีการจัดการเต็มรูปแบบใน Google Cloud เพื่อให้คุณมุ่งเน้นที่การสัมผัสประสบการณ์ Kubernetes มากขึ้น แทนที่จะตั้งค่าโครงสร้างพื้นฐานที่อยู่เบื้องหลัง

หากคุณสนใจที่จะเรียกใช้ Kubernetes ในเครื่อง เช่น แล็ปท็อปสำหรับพัฒนาซอฟต์แวร์ โปรดดู Minikube ซึ่งมีการตั้งค่าคลัสเตอร์ Kubernetes แบบโหนดเดียวอย่างง่ายเพื่อวัตถุประสงค์ในการพัฒนาและการทดสอบ คุณใช้ Minikube เพื่อทำตาม Codelab ได้หากต้องการ

Codelab จะใช้โค้ดตัวอย่างจากคู่มือเกี่ยวกับการสร้างแอปด้วย Spring Boot

ข้อกำหนดเบื้องต้น

  • ความคุ้นเคยกับภาษาโปรแกรมและเครื่องมือ Java
  • ความรู้เกี่ยวกับโปรแกรมแก้ไขข้อความมาตรฐานของ Linux เช่น Vim, Emacs และ nano

สิ่งที่คุณต้องทำ

  • จัดแพ็กเกจแอป Java แบบง่ายเป็นคอนเทนเนอร์ Docker
  • สร้างคลัสเตอร์ Kubernetes บน GKE
  • ทําให้แอป Java ใช้งานได้ใน Kubernetes บน GKE
  • ปรับขนาดบริการและเปิดตัวการอัปเกรด
  • เข้าถึงแดชบอร์ด ซึ่งเป็นอินเทอร์เฟซผู้ใช้ Kubernetes บนเว็บ

สิ่งที่คุณต้องมี

  • โปรเจ็กต์ Google Cloud
  • เบราว์เซอร์ เช่น Google Chrome

2. การตั้งค่าและข้อกำหนด

การตั้งค่าสภาพแวดล้อมแบบเรียนรู้ด้วยตนเอง

  1. ลงชื่อเข้าใช้ Google Cloud Console แล้วสร้างโปรเจ็กต์ใหม่หรือใช้โปรเจ็กต์ที่มีอยู่ซ้ำ หากยังไม่มีบัญชี Gmail หรือ Google Workspace คุณต้องสร้างบัญชี

b35bf95b8bf3d5d8.png

a99b7ace416376c4.png

bd84a6d3004737c5.png

  • ชื่อโปรเจ็กต์คือชื่อที่แสดงสำหรับผู้เข้าร่วมโปรเจ็กต์นี้ ซึ่งเป็นสตริงอักขระที่ Google APIs ไม่ได้ใช้ คุณอัปเดตได้ทุกเมื่อ
  • รหัสโปรเจ็กต์จะไม่ซ้ำกันในโปรเจ็กต์ Google Cloud ทั้งหมดและเปลี่ยนแปลงไม่ได้ (เปลี่ยนไม่ได้หลังจากตั้งค่าแล้ว) Cloud Console จะสร้างสตริงที่ไม่ซ้ำกันโดยอัตโนมัติ ซึ่งโดยปกติแล้วคุณไม่จำเป็นต้องสนใจว่าสตริงนั้นคืออะไร ใน Codelab ส่วนใหญ่ คุณจะต้องอ้างอิงรหัสโปรเจ็กต์ (โดยทั่วไปจะระบุเป็น PROJECT_ID) หากไม่ชอบรหัสที่สร้างขึ้น คุณอาจสร้างรหัสแบบสุ่มอีกรหัสหนึ่งได้ หรือคุณอาจลองใช้ชื่อของคุณเองและดูว่ามีชื่อนั้นหรือไม่ คุณจะเปลี่ยนแปลงรหัสนี้หลังจากขั้นตอนนี้ไม่ได้ และรหัสจะคงอยู่ตลอดระยะเวลาของโปรเจ็กต์
  • โปรดทราบว่ายังมีค่าที่ 3 ซึ่งคือหมายเลขโปรเจ็กต์ที่ API บางตัวใช้ ดูข้อมูลเพิ่มเติมเกี่ยวกับค่าทั้ง 3 นี้ได้ในเอกสารประกอบ
  1. จากนั้นคุณจะต้องเปิดใช้การเรียกเก็บเงินใน Cloud Console เพื่อใช้ทรัพยากร/API ของ Cloud การทำตาม Codelab นี้จะไม่มีค่าใช้จ่ายมากนัก หรืออาจไม่มีค่าใช้จ่ายเลย หากต้องการปิดทรัพยากรเพื่อหลีกเลี่ยงการเรียกเก็บเงินนอกเหนือจากบทแนะนำนี้ คุณสามารถลบทรัพยากรที่สร้างขึ้นหรือลบโปรเจ็กต์ได้ ผู้ใช้ Google Cloud รายใหม่มีสิทธิ์เข้าร่วมโปรแกรมช่วงทดลองใช้ฟรีมูลค่า$300 USD

เปิดใช้งาน Cloud Shell

  1. จาก Cloud Console ให้คลิกเปิดใช้งาน Cloud Shell 853e55310c205094.png

55efc1aaa7a4d3ad.png

หากคุณเริ่มใช้ Cloud Shell เป็นครั้งแรก คุณจะเห็นหน้าจอระดับกลางที่อธิบายว่า Cloud Shell คืออะไร หากเห็นหน้าจอระดับกลาง ให้คลิกต่อไป

9c92662c6a846a5c.png

การจัดสรรและเชื่อมต่อกับ Cloud Shell จะใช้เวลาไม่นาน

9f0e51b578fecce5.png

เครื่องเสมือนนี้โหลดเครื่องมือพัฒนาซอฟต์แวร์ทั้งหมดที่จำเป็นไว้แล้ว โดยมีไดเรกทอรีหลักแบบถาวรขนาด 5 GB และทำงานใน Google Cloud ซึ่งช่วยเพิ่มประสิทธิภาพเครือข่ายและการตรวจสอบสิทธิ์ได้อย่างมาก คุณสามารถทำงานส่วนใหญ่หรือทั้งหมดในโค้ดแล็บนี้ได้ด้วยเบราว์เซอร์

เมื่อเชื่อมต่อกับ Cloud Shell แล้ว คุณควรเห็นว่าคุณได้รับการตรวจสอบสิทธิ์และระบบได้ตั้งค่าโปรเจ็กต์เป็นรหัสโปรเจ็กต์ของคุณ

  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. หลังจากแอปเริ่มทำงานแล้ว ให้คลิกตัวอย่างเว็บ1a94d5bd10bfc072.pngในแถบเครื่องมือ Cloud Shell แล้วเลือกแสดงตัวอย่างบนพอร์ต 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}

ตัวอย่างเช่น หากคุณสร้างที่เก็บในตำแหน่ง us-central1 ชื่อ codelabrepo และต้องการตั้งชื่อรูปภาพเป็น 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. คุณควรจะเห็นอิมเมจคอนเทนเนอร์แสดงอยู่ในคอนโซลโดยไปที่หน้าอิมเมจ Artifact Registry ใน Cloud Console ตอนนี้คุณมีอิมเมจ Docker ระดับโปรเจ็กต์แล้ว ซึ่ง Kubernetes สามารถเข้าถึงและจัดระเบียบได้ตามที่คุณจะเห็นในอีกไม่กี่นาที
  2. (ไม่บังคับ) หลังจากเสร็จสิ้น (ระบบจะใช้เวลาสักครู่ในการดาวน์โหลดและแตกไฟล์ทุกอย่าง) ให้ทดสอบอิมเมจด้วยคำสั่งต่อไปนี้ ซึ่งจะเรียกใช้คอนเทนเนอร์ Docker เป็น Daemon บนพอร์ต 8080 จากอิมเมจคอนเทนเนอร์ที่สร้างขึ้นใหม่ หากพบปัญหาเกี่ยวกับสิทธิ์ ให้เรียกใช้ 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 แล้ว คลัสเตอร์ประกอบด้วยเซิร์ฟเวอร์ Kubernetes API ที่ Google จัดการและชุดโหนด Worker โหนดผู้ปฏิบัติงานคือ VM ของ Compute Engine

  1. ก่อนอื่น โปรดตรวจสอบว่าได้เปิดใช้ฟีเจอร์ API ที่เกี่ยวข้องแล้ว
$ gcloud services enable compute.googleapis.com container.googleapis.com
  1. สร้างคลัสเตอร์ที่มีโหนด n1-standard-1 2 โหนด (การดำเนินการนี้จะใช้เวลาสักครู่)
$ 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  ...

ตอนนี้คุณควรมีคลัสเตอร์ Kubernetes ที่ทำงานได้อย่างเต็มรูปแบบซึ่งขับเคลื่อนโดย GKE

758c7fca14f70623.png

ตอนนี้ได้เวลาทําให้แอปที่มีคอนเทนเนอร์ใช้งานได้ในคลัสเตอร์ Kubernetes แล้ว นับจากนี้ไป คุณจะใช้บรรทัดคำสั่ง kubectl (ตั้งค่าไว้แล้วในสภาพแวดล้อม Cloud Shell) ส่วนที่เหลือของ Codelab กำหนดให้ไคลเอ็นต์และเซิร์ฟเวอร์ Kubernetes ต้องเป็นเวอร์ชัน 1.2 ขึ้นไป kubectl version จะแสดงเวอร์ชันปัจจุบันของคำสั่ง

7. ทําให้แอปใช้งานได้ใน Kubernetes

  1. การติดตั้งใช้งาน Kubernetes สามารถสร้าง จัดการ และปรับขนาดอินสแตนซ์หลายรายการของแอปโดยใช้รูปภาพคอนเทนเนอร์ที่คุณสร้างขึ้น ทำให้แอป 1 อินสแตนซ์ใช้งานได้กับ Kubernetes โดยใช้คำสั่ง kubectl run
$ 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 ภายในภายในคลัสเตอร์เท่านั้น หากต้องการทำให้เข้าถึงคอนเทนเนอร์ hello-java จากภายนอกเครือข่ายเสมือนของ Kubernetes ได้ คุณต้องเปิดเผยพ็อดเป็นบริการของ Kubernetes

  1. ใน Cloud Shell คุณสามารถเปิดเผยพ็อดต่ออินเทอร์เน็ตสาธารณะได้โดยการสร้างบริการ LoadBalancer ของ Kubernetes
$ kubectl create service loadbalancer hello-java --tcp=8080:8080

โปรดทราบว่าคุณจะเปิดเผยการติดตั้งใช้งานโดยตรง ไม่ใช่พ็อด ซึ่งจะทำให้บริการที่ได้โหลดบาลานซ์การรับส่งข้อมูลในพ็อดทั้งหมดที่การติดตั้งใช้งานจัดการ (ในกรณีนี้มีเพียงพ็อดเดียว แต่คุณจะเพิ่มรีพลิก้าในภายหลัง)

มาสเตอร์ 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. เปิดโปรแกรมแก้ไขโค้ดโดยคลิกเปิดโปรแกรมแก้ไข 2109d75686c889a.pngในเมนู Cloud Shell
  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 ที่จะอัปเดต Replication Controller เป็นแอปเวอร์ชันใหม่ได้อย่างราบรื่น

  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 ใช้งานได้ใน Kubernetes บน GKE

ล้างข้อมูล

$ 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

ดูข้อมูลเพิ่มเติม