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

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

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

ใน Codelab นี้ คุณจะได้ทำให้เว็บแอป Spring Boot Java ใช้งานได้อย่างง่ายกับ 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 ของระบบคลาวด์ การใช้งาน Codelab นี้จะไม่มีค่าใช้จ่ายใดๆ หากมี หากต้องการปิดทรัพยากรเพื่อหลีกเลี่ยงการเรียกเก็บเงินที่นอกเหนือจากบทแนะนำนี้ คุณสามารถลบทรัพยากรที่คุณสร้างหรือลบโปรเจ็กต์ได้ ผู้ใช้ Google Cloud ใหม่มีสิทธิ์เข้าร่วมโปรแกรมช่วงทดลองใช้ฟรี$300 USD

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

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

55efc1aaa7a4d3ad.png

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

9c92662c6a846a5c.png

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

9f0e51b578fecce5.png

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

เมื่อเชื่อมต่อกับ 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 Images ใน 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 และชุดโหนดของผู้ปฏิบัติงาน โหนดของผู้ปฏิบัติงานคือ VM ของ Compute Engine

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

โดยค่าเริ่มต้น พ็อดจะเข้าถึงได้โดย IP ภายในภายในคลัสเตอร์เท่านั้น หากต้องการทำให้คอนเทนเนอร์ hello-java เข้าถึงได้จากภายนอกเครือข่ายเสมือนของ Kubernetes คุณจะต้องแสดงพ็อดเป็นบริการ Kubernetes

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

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

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. เปิดตัวแก้ไขโค้ดโดยคลิกเปิดตัวแก้ไข 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 อัปเดตตัวควบคุมการจำลองเป็นแอปเวอร์ชันใหม่ได้อย่างราบรื่น

  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 ทำให้แอปเวอร์ชันใหม่ใช้งานได้ทั่วทั้งคลัสเตอร์ครั้งละ 1 อินสแตนซ์ด้วยการอัปเดตอย่างต่อเนื่องได้
$ 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

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