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

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

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

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

โปรดจดจำรหัสโปรเจ็กต์ ซึ่งเป็นชื่อที่ไม่ซ้ำกันในโปรเจ็กต์ Google Cloud ทั้งหมด (ชื่อด้านบนถูกใช้ไปแล้วและจะใช้ไม่ได้ ขออภัย) ซึ่งจะเรียกว่า PROJECT_ID ในภายหลังใน Codelab นี้

  1. จากนั้นคุณจะต้องเปิดใช้การเรียกเก็บเงินใน Cloud Console เพื่อใช้ทรัพยากร Google Cloud

การทำตาม Codelab นี้ไม่น่าจะมีค่าใช้จ่ายเกิน 2-3 ดอลลาร์ แต่ก็อาจมีค่าใช้จ่ายมากกว่านี้หากคุณตัดสินใจใช้ทรัพยากรเพิ่มเติมหรือปล่อยให้ทรัพยากรทำงานต่อไป

ผู้ใช้ใหม่ของ Google Cloud มีสิทธิ์ทดลองใช้ฟรี$300

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

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

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

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

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

เมื่อเชื่อมต่อกับ 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`
gcloud config list project

เอาต์พุตของคำสั่ง

[core]
project = <PROJECT_ID>

หากไม่ได้ตั้งค่าไว้ คุณตั้งค่าได้ด้วยคำสั่งนี้

gcloud config set project <PROJECT_ID>

เอาต์พุตของคำสั่ง

Updated property [core/project].

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

$ git clone https://github.com/spring-guides/gs-spring-boot.git
$ cd gs-spring-boot/complete
  1. คุณสามารถเริ่มแอป Spring Boot ได้ตามปกติด้วยปลั๊กอิน Spring Boot
$ ./mvnw -DskipTests spring-boot:run
  1. หลังจากแอปเริ่มทำงานแล้ว ให้คลิกตัวอย่างเว็บในแถบเครื่องมือ Cloud Shell แล้วเลือกแสดงตัวอย่างบนพอร์ต 8080

แท็บในเบราว์เซอร์จะเปิดขึ้นและเชื่อมต่อกับเซิร์ฟเวอร์ที่คุณเพิ่งเริ่ม

จากนั้นคุณต้องเตรียมแอปให้ทำงานบน Kubernetes ขั้นตอนแรกคือการกำหนดคอนเทนเนอร์และเนื้อหาของคอนเทนเนอร์

  1. สร้าง JAR ที่สามารถนำไปใช้กับแอปได้
$ ./mvnw -DskipTests package
  1. เปิดใช้ Container Registry เพื่อจัดเก็บอิมเมจคอนเทนเนอร์ที่คุณจะสร้าง
$ gcloud services enable containerregistry.googleapis.com
  1. ใช้ Jib เพื่อสร้างอิมเมจคอนเทนเนอร์และพุชไปยัง Container Registry
$ ./mvnw -DskipTests com.google.cloud.tools:jib-maven-plugin:build \
  -Dimage=gcr.io/$GOOGLE_CLOUD_PROJECT/hello-java:v1
  1. หากทุกอย่างเป็นไปด้วยดี คุณควรจะเห็นอิมเมจคอนเทนเนอร์แสดงอยู่ในคอนโซลโดยไปที่ Container Registry > อิมเมจ ตอนนี้คุณมีอิมเมจ Docker ระดับโปรเจ็กต์แล้ว ซึ่ง Kubernetes สามารถเข้าถึงและจัดระเบียบได้ตามที่คุณจะเห็นในอีกไม่กี่นาที
  1. หลังจากนั้น (ระบบจะใช้เวลาสักครู่ในการดาวน์โหลดและแตกไฟล์ทุกอย่าง) คุณจะทดสอบอิมเมจในเครื่องได้ด้วยคำสั่งต่อไปนี้ ซึ่งจะเรียกใช้คอนเทนเนอร์ Docker เป็น Daemon บนพอร์ต 8080 จากอิมเมจคอนเทนเนอร์ที่สร้างขึ้นใหม่
$ docker run -ti --rm -p 8080:8080 \
  gcr.io/$GOOGLE_CLOUD_PROJECT/hello-java:v1
  1. และอย่าลืมใช้ประโยชน์จากฟีเจอร์ตัวอย่างเว็บของ Cloud Shell

  1. คุณควรเห็นหน้าเริ่มต้นในแท็บใหม่ หลังจากยืนยันว่าแอปทำงานในคอนเทนเนอร์ Docker ในเครื่องแล้ว คุณจะหยุดคอนเทนเนอร์ที่ทำงานได้โดยกด Control+C

คุณพร้อมที่จะสร้างคลัสเตอร์ GKE แล้ว คลัสเตอร์ประกอบด้วยเซิร์ฟเวอร์ Kubernetes API ที่ Google จัดการและชุดโหนดของผู้ปฏิบัติงาน โหนดผู้ปฏิบัติงานคือ VM ของ Compute Engine

  1. ก่อนอื่น โปรดตรวจสอบว่าได้เปิดใช้ฟีเจอร์ API ที่เกี่ยวข้องแล้ว
$ gcloud services enable compute.googleapis.com container.googleapis.com
Operation "operations/..." finished successfully
  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

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

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

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

  1. ใน Cloud Shell คุณสามารถเปิดเผย Pod ต่ออินเทอร์เน็ตสาธารณะได้ด้วยคำสั่ง kubectl expose ร่วมกับแฟล็ก --type=LoadBalancer ต้องใช้ Flag นี้ในการสร้าง IP ที่เข้าถึงได้จากภายนอก
$ 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. โปรดสังเกตว่ามีที่อยู่ IP 2 รายการสำหรับบริการของคุณ ซึ่งทั้ง 2 รายการใช้พอร์ต 8080 โดยที่อยู่ IP หนึ่งเป็นที่อยู่ IP ภายในซึ่งมองเห็นได้เฉพาะภายใน Virtual Private Cloud อีกอันคือที่อยู่ IP ที่โหลดบาลานซ์ภายนอก ในตัวอย่างนี้ ที่อยู่ IP ภายนอกคือ aaa.bbb.ccc.ddd ตอนนี้คุณควรจะเข้าถึงบริการได้โดยป้อน http://<EXTERNAL_IP>:8080 ในเบราว์เซอร์

ฟีเจอร์ที่มีประสิทธิภาพอย่างหนึ่งของ 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 เพียงแค่ตรวจสอบว่าความเป็นจริงตรงกับสิ่งที่คุณขอและดำเนินการหากจำเป็น

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

  1. เปิดโปรแกรมแก้ไขโค้ดโดยคลิกเปิดตัวแก้ไข ในเมนู Cloud Shell
  2. ไปที่ src/main/java/hello/HelloController.java แล้วอัปเดตค่าของคำตอบ
package hello;

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=gcr.io/$GOOGLE_CLOUD_PROJECT/hello-java:v2

คุณพร้อมแล้วสำหรับ Kubernetes ที่จะอัปเดต Replication Controller เป็นแอปเวอร์ชันใหม่ได้อย่างราบรื่น

  1. หากต้องการเปลี่ยนป้ายกำกับรูปภาพสำหรับคอนเทนเนอร์ที่ทำงานอยู่ คุณต้องแก้ไขhello-javaการติดตั้งใช้งานที่มีอยู่และเปลี่ยนรูปภาพจาก gcr.io/PROJECT_ID/hello-java:v1 เป็น gcr.io/PROJECT_ID/hello-java:v2
  1. คุณใช้คำสั่ง kubectl set image เพื่อขอให้ Kubernetes นำแอปเวอร์ชันใหม่ไปใช้ในคลัสเตอร์ทั้งหมดทีละอินสแตนซ์ด้วยการอัปเดตแบบต่อเนื่องได้
$ kubectl set image deployment/hello-java \
  hello-java=gcr.io/$GOOGLE_CLOUD_PROJECT/hello-java:v2

deployment "hello-java" image updated
  1. ตรวจสอบ http://EXTERNAL_IP:8080 อีกครั้งเพื่อดูว่ามีการส่งคืนการตอบกลับใหม่

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

$ kubectl rollout undo deployment/hello-java

คุณได้เรียนรู้วิธีสร้างและทําให้เว็บแอปใหม่ที่ใช้ Java ใช้งานได้ใน Kubernetes บน GKE

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