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

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

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

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

אם אתם רוצים להריץ Kubernetes במחשב המקומי שלכם, למשל במחשב נייד לפיתוח, כדאי לכם לבדוק את Minikube, שמציע הגדרה פשוטה של אשכול Kubernetes עם צומת יחיד למטרות פיתוח ובדיקה. אם רוצים, אפשר להשתמש ב-Minikube כדי לעבור על ה-codelab.

בשיעור הזה נשתמש בקוד לדוגמה מהמדריך בנושא יצירת אפליקציה באמצעות Spring Boot.

דרישות מוקדמות

  • היכרות עם שפת התכנות Java ועם הכלים שלה
  • ידע בכלי עריכת טקסט של Linux, כמו Vim,‏ Emacs ו-nano

מה עושים

  • לארוז אפליקציית Java פשוטה כקונטיינר Docker.
  • יוצרים את אשכול Kubernetes ב-GKE.
  • פריסת אפליקציית Java ב-Kubernetes ב-GKE.
  • להרחיב את השירות ולהשיק שדרוג.
  • גישה ל-Dashboard, ממשק משתמש של Kubernetes מבוסס-אינטרנט.

מה צריך להכין

הגדרת סביבה בקצב אישי

  1. נכנסים אל Cloud Console ויוצרים פרויקט חדש או משתמשים בפרויקט קיים. (אם אין לכם עדיין חשבון Gmail או G Suite, אתם צריכים ליצור חשבון).

חשוב לזכור את מזהה הפרויקט, שהוא שם ייחודי בכל הפרויקטים ב-Google Cloud (השם שמופיע למעלה כבר תפוס ולא יתאים לכם, מצטערים!). בהמשך ה-codelab הזה, נתייחס אליו כאל PROJECT_ID.

  1. לאחר מכן, תצטרכו להפעיל את החיוב ב-Cloud Console כדי להשתמש במשאבים של Google Cloud.

העלות של התרגול הזה לא אמורה להיות גבוהה מכמה דולרים, אבל היא יכולה להיות גבוהה יותר אם תחליטו להשתמש ביותר משאבים או אם תשאירו אותם פועלים.

משתמשים חדשים ב-Google Cloud זכאים לתקופת ניסיון בחינם בשווי 300$.

הפעלת Cloud Shell

  1. ב-Cloud Console, לוחצים על Activate Cloud Shell .

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

הקצאת המשאבים וחיבור ל-Cloud Shell נמשכים רק כמה רגעים.

המכונה הווירטואלית הזו כוללת את כל הכלים הדרושים למפתחים. יש בה ספריית בית בנפח מתמיד של 5GB והיא פועלת ב-Google Cloud, מה שמשפר מאוד את הביצועים והאימות ברשת. אפשר לבצע את רוב העבודה ב-codelab הזה, אם לא את כולה, באמצעות דפדפן או 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 > Images. עכשיו יש לכם קובץ אימג' של Docker שזמין בכל הפרויקט, ו-Kubernetes יכול לגשת אליו ולתזמן אותו, כפי שתראו בעוד כמה דקות.
  1. אחרי שהתהליך יסתיים (ייקח זמן להוריד ולחלץ את כל הנתונים), תוכלו לבדוק את האימג' באופן מקומי באמצעות הפקודה הבאה, שתפעיל קונטיינר של Docker כדמון ביציאה 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 ומקבוצה של צמתי עובדים. צמתי העובדים הם מכונות וירטואליות ב-Compute Engine.

  1. קודם כול, מוודאים שתכונות ה-API שקשורות מופעלות.
$ gcloud services enable compute.googleapis.com container.googleapis.com
Operation "operations/..." finished successfully
  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.

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

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

  1. ב-Cloud Shell, אפשר לחשוף את ה-Pod לאינטרנט הציבורי באמצעות הפקודה kubectl expose בשילוב עם הדגל --type=LoadBalancer. הדגל נדרש ליצירת כתובת IP שנגישה חיצונית.
$ kubectl create service loadbalancer hello-java --tcp=8080:8080

הדגל שבו משתמשים בפקודה מציין שתשתמשו במאזן העומסים שסופק על ידי התשתית הבסיסית. שימו לב שאתם חושפים ישירות את הפריסה, ולא את ה-Pod. כך תתבצע חלוקת עומסים של התנועה בין כל ה-Pods שמנוהלים על ידי הפריסה (במקרה הזה, רק 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. שימו לב שיש שתי כתובות IP שמופיעות בשירות, ושתיהן משרתות את יציאה 8080. אחת מהן היא כתובת ה-IP הפנימית שגלויות רק בתוך הענן הווירטואלי הפרטי. השנייה היא כתובת ה-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 כדי לעדכן בצורה חלקה את בקר השכפול לגרסה החדשה של האפליקציה.

  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.

מידע נוסף