פריסת אפליקציית Spring Boot Java ב-Kubernetes ב-Google Kubernetes Engine

1. לפני שמתחילים

Kubernetes הוא פרויקט בקוד פתוח שיכול לפעול בסביבות רבות ושונות, ממחשבים ניידים ועד אשכולות עם זמינות גבוהה של אשכולות רב-צמתים, מעננים ציבוריים לפריסות בארגון, ממכונות וירטואליות (VM) ועד למכונות וירטואליות.

בשיעור ה-Codelab הזה תפרסו אפליקציית אינטרנט פשוטה של Spring Boot Java ל-Kubernetes ב-GKE, כשהמטרה היא להריץ את אפליקציית האינטרנט כאפליקציה משוכפלת ב-Kubernetes. תקבלו קוד שפיתחתם במכונה, להפוך אותו לקובץ אימג' של קונטיינר של Docker ולהריץ את קובץ האימג' ב-GKE.

שימוש ב-GKE, שירות Kubernetes מנוהל ב-Google Cloud, כדי לאפשר לכם להתמקד יותר בחוויית השימוש ב-Kubernetes, במקום בהגדרת התשתית הבסיסית.

אם אתם רוצים להריץ את Kubernetes במכונה המקומית שלכם, למשל מחשב נייד לפיתוח, כדאי לכם לבדוק את Minikube, שמציע הגדרה פשוטה של אשכול Kubernetes עם צומת יחיד למטרות פיתוח ובדיקה. אם רוצים, אפשר להשתמש ב-Minekube כדי לעבור את ה-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 ויוצרים פרויקט חדש או עושים שימוש חוזר בפרויקט קיים. אם אין לכם עדיין חשבון Gmail או חשבון Google Workspace, עליכם ליצור חשבון.

b35bf95b8bf3d5d8.png

a99b7ace416376c4.png

bd84a6d3004737c5.png

  • Project name הוא השם המוצג של המשתתפים בפרויקט. זו מחרוזת תווים שלא משמשת את Google APIs. תמיד אפשר לעדכן.
  • Project ID הוא ייחודי בכל הפרויקטים ב-Google Cloud ואי אפשר לשנות אותו (אי אפשר לשנות אותו אחרי שמגדירים אותו). מסוף Cloud יוצר מחרוזת ייחודית באופן אוטומטי; בדרך כלל לא מעניין אותך מה זה. ברוב ה-codelabs תצטרכו להפנות למזהה הפרויקט שלכם (בדרך כלל מזוהה כ-PROJECT_ID). אם המזהה שנוצר לא מוצא חן בעיניכם, אתם יכולים ליצור מזהה אקראי אחר. לחלופין, אפשר לנסות שם משלך ולראות אם הוא זמין. לא ניתן לשנות אותו אחרי השלב הזה, והוא נשאר למשך הפרויקט.
  • לידיעתך, יש ערך שלישי, Project Number, שבו משתמשים בחלק מממשקי ה-API. מידע נוסף על כל שלושת הערכים האלה זמין במסמכי התיעוד.
  1. בשלב הבא צריך להפעיל את החיוב במסוף Cloud כדי להשתמש במשאבים או בממשקי API של Cloud. מעבר ב-Codelab הזה לא יעלה הרבה כסף, אם בכלל. כדי להשבית משאבים ולא לצבור חיובים מעבר למדריך הזה, אתם יכולים למחוק את המשאבים שיצרתם או למחוק את הפרויקט. משתמשים חדשים ב-Google Cloud זכאים להשתתף בתוכנית תקופת ניסיון בחינם בשווי 1,200 ש"ח.

הפעלת Cloud Shell

  1. במסוף Cloud, לוחצים על Activate Cloud Shell 853e55310c205094.png.

55efc1aaa7a4d3ad.png

אם זו הפעם הראשונה שאתם מפעילים את Cloud Shell, יוצג לכם מסך ביניים שמתוארת בו. אם הוצג לכם מסך ביניים, לוחצים על המשך.

9c92662c6a846a5c.png

ההקצאה וההתחברות ל-Cloud Shell נמשכת כמה דקות.

9f0e51b578fecce5.png

במכונה הווירטואלית הזו נמצאים כל כלי הפיתוח הדרושים. יש בה ספריית בית בנפח מתמיד של 5GB והיא פועלת ב-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. אחרי שהאפליקציה מתחילה, לוחצים על Web Preview 1a94d5bd10bfc072.pngבסרגל הכלים של Cloud Shell ובוחרים באפשרות Preview on Port 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. קובץ האימג' של הקונטיינר אמור להופיע במסוף על ידי מעבר אל הדף Artifacts Registry Images ב-Cloud Console. עכשיו יש לכם תמונת Docker ברמת הפרויקט, שאליה ניתן לגשת ולתזמר על ידי Kubernetes בעוד כמה דקות.
  2. (אופציונלי) בסיום התהליך (ההורדה והחילוץ של הכול יימשך זמן מה), בודקים את התמונה באמצעות הפקודה הבאה, שתריץ קונטיינר Docker כדי דימון ביציאה 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. אשכול מורכב משרת API של Kubernetes שמנוהל על ידי Google ומקבוצה של צמתים של עובדים. הצמתים של העובדים הם מכונות וירטואליות של Compute Engine.

  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  ...

עכשיו אמור להיות לכם אשכול Kubernetes תקין שמופעל על ידי GKE.

758c7fca14f70623.png

זה הזמן לפרוס את האפליקציה בקונטיינרים באשכול Kubernetes! מעכשיו משתמשים בשורת הפקודה kubectl (שכבר מוגדרת בסביבת Cloud Shell). בשאר השיעורים ב-Codelab צריך שהגרסה של השרת והלקוח של Kubernetes יהיו 1.2 ואילך. kubectl version יציג את הגרסה הנוכחית של הפקודה.

7. פריסת האפליקציה ב-Kubernetes

  1. פריסת Kubernetes יכולה ליצור, לנהל ולהתאים מספר מופעים של האפליקציה שלכם באמצעות קובץ האימג' שיצרתם. פריסת מופע אחד של האפליקציה ב-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, צריך לחשוף את ה-Pod בתור שירות Kubernetes.

  1. ב-Cloud Shell, אפשר לחשוף את ה-Pod לאינטרנט הציבורי על ידי יצירת שירות Kubernetes Load Balancer.
$ kubectl create service loadbalancer hello-java --tcp=8080:8080

שימו לב שאתם חושפים ישירות את הפריסה, ולא את ה-Pod. הדבר יגרום לשירות שנוצר לטעון את תעבורת הנתונים של כל קבוצות ה-Pod שמנוהלות על ידי הפריסה (במקרה הזה, רק Pod אחד, אבל יתווספו עוד רפליקות מאוחר יותר).

ה-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. כדי לפתוח את עורך הקוד, לוחצים על Open Editor 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

הכול מוכן! עכשיו אפשר לעדכן את בקר הרפליקציה לגרסה החדשה של האפליקציה בצורה חלקה.

  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 לפרוס את הגרסה החדשה של האפליקציה שלכם בכל האשכול אחד בכל פעם, באמצעות עדכונים בהדרגה (rolling).
$ 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

מידע נוסף