1. סקירה כללית
מידע על מיקרונאוט
Micronaut היא framework מודרני שמבוסס על JVM ו-Full-stack, לפיתוח של אפליקציות מיקרו-שירות (microservice) מודולריות שניתנות לבדיקה בקלות, ואפליקציות ללא שרת (serverless). המטרה של Micronaut היא לספק זמן סטארט-אפ מצוין, תפוקה מהירה, תוך טביעת אצבע של זיכרון מינימלי. מפתחים יכולים לפתח באמצעות Micronaut ב-Java, Groovy או Kotlin.
מיקרונאוט מספק:
- זמן הפעלה מהיר צריכת זיכרון נמוכה — frameworks של IoC שמבוססות על השתקפויות טוענים ושומרים נתוני השתקפות במטמון לכל שדה, method ו-constructor בקוד. לעומת זאת, זמן ההפעלה של האפליקציה וצריכת הזיכרון שלהם לא קשורים לגודל של בסיס הקוד.
- לקוח HTTP תגובתי, תגובתי ובזמן הידור — יצירת הצהרה של לקוחות HTTP תגובתיים, שמוטמעים בזמן ההידור ומפחיתים את צריכת הזיכרון.
- שרת HTTP שמבוסס על Netty ללא חסימה – בזכות עקומת למידה חלקה, שרת ה-HTTP של Micronaut מקל מאוד על חשיפה של ממשקי API שאפשר לצרוך על ידי לקוחות HTTP.
- בדיקה מהירה וקלה — אפשר להפעיל בקלות שרתים ולקוחות בבדיקות היחידה ולהריץ אותם באופן מיידי.
- החדרה ו-AOP יעילים של תלות בזמן הידור — Micronaut מספק ממשק API לתכנות פשוט שמיועד לזמן הידור (compiles) שאינו משתמש בהחזרות.
- בניית אפליקציות מגיבות לגמרי ולא חוסמות — Micronaut תומך בכל framework שמטמיע באמצעות Reactive Streams, כולל RxJava ו-Reactor.
מידע נוסף זמין באתר של Micronaut.
מידע על Kubernetes
Kubernetes הוא פרויקט בקוד פתוח שיכול לפעול בסביבות רבות ושונות, החל ממחשבים ניידים ועד אשכולות בזמינות גבוהה של צמתים מרובים, החל מעננים ציבוריים ועד פריסות מקומיות, ממכונות וירטואליות ועד בשרת פיזי.
בשיעור ה-Lab הזה פרסתם מיקרו-שירות (micronaut) פשוט מבוסס-Groovy ל-Kubernetes שפועל ב-Kubernetes Engine.
המטרה של ה-Codelab הזו היא להריץ את המיקרו-שירות (microservice) כשירות משוכפל שפועל ב-Kubernetes. לוקחים קוד שפיתחתם במכונה, הופכים אותו לקובץ אימג' של קונטיינר של Docker, ומריצים את קובץ האימג' הזה ב-Kubernetes Engine.
הנה תרשים של החלקים השונים במשחק ב-Codelab הזה, כדי לעזור לכם להבין איך חלקים משתלבים זה בזה. תוכלו להיעזר בו כחומר עזר להתקדמות ב-Codelab. עד שתגיעו לסוף התהליך, הכול אמור להיות הגיוני (אבל בינתיים אפשר להתעלם ממנו).
לצורך ה-Codelab הזה, שימוש בסביבה מנוהלת כמו Kubernetes Engine (גרסה של Kubernetes ב-Google שפועלת ב-Compute Engine) מאפשרת להתמקד יותר בחוויית השימוש ב-Kubernetes במקום בהגדרת התשתית הבסיסית.
אם אתם רוצים להריץ את Kubernetes במכונה המקומית, למשל מחשב נייד למפתחים, כדאי לבדוק את Minikube. השיטה הזו מציעה הגדרה פשוטה של אשכול kubernetes של צומת יחיד למטרות פיתוח ובדיקה. אם רוצים, אפשר להשתמש ב-Minekube כדי לעבור את הקוד הזה.
מידע על Jib
Jib הוא כלי בקוד פתוח שמאפשר ליצור קובצי אימג' של Docker ו-OCI לאפליקציות Java. היא זמינה כיישומי פלאגין ל-Maven ו-Gradle, וגם כספריית Java.
המטרה של Jib היא:
- מהיר – פורסים את השינויים במהירות. Jib מפריד את האפליקציה שלך למספר שכבות, ומפצל את יחסי התלות מהמחלקות. עכשיו אתם לא צריכים לחכות ש-Docker יבנה מחדש את כל אפליקציית Java – פשוט פרסו את השכבות שהשתנו.
- שחזור — יצירה מחדש של קובץ אימג' בקונטיינר עם אותו תוכן תמיד יוצרת את אותה תמונה. לא להפעיל שוב עדכון מיותר.
- Daemonless — מצמצמים את יחסי התלות של ה-CLI. בונים את קובץ האימג' של Docker מתוך Maven או Gradle, ודוחפים אותו לכל מרשם שרוצים. כבר לא צריך לכתוב Dockerfiles ולקרוא ל-Docker build/push.
מידע נוסף על Jib זמין בדף הפרויקט של GitHub.
מידע על המדריך הזה
במדריך הזה נשתמש בקוד לדוגמה מהכלי Jib כדי לבנות קונטיינרים לאפליקציות Java.
הדוגמה היא שירות שלום עולם פשוט, שמשתמש ב-framework של Micronaut ובשפת התכנות Apache גרובי.
מה תלמדו
- איך לארוז אפליקציית Java פשוטה כקונטיינר Docker באמצעות Jib
- איך יוצרים אשכול Kubernetes ב-Kubernetes Engine.
- איך לפרוס את שירות המיקרונאוט ב-Kubernetes ב-Kubernetes Engine
- איך מרחיבים את השירות ומשיקים שדרוג.
- איך לגשת ללוח הבקרה הגרפי של Kubernetes.
מה צריך להכין
- פרויקט ב-Google Cloud Platform
- דפדפן, למשל Chrome או Firefox
- היכרות עם עורכי טקסט סטנדרטיים של Linux, כגון Vim, EMAC או Nano
איך תשתמשו במדריך הזה?
איזה דירוג מגיע לחוויה שלך עם בניית אפליקציות אינטרנט מסוג HTML/CSS?
איזה דירוג מגיע לדעתך לחוויית השימוש בשירותי Google Cloud Platform?
2. הגדרה ודרישות
הגדרת סביבה בקצב עצמאי
- נכנסים למסוף Cloud ויוצרים פרויקט חדש או עושים שימוש חוזר בפרויקט קיים. (אם עדיין אין לכם חשבון Gmail או G Suite, עליכם ליצור חשבון).
חשוב לזכור את מזהה הפרויקט, שם ייחודי לכל הפרויקטים ב-Google Cloud (השם שלמעלה כבר תפוס ולא מתאים לכם, סליחה). בהמשך ב-Codelab הזה, היא תיקרא PROJECT_ID
.
- בשלב הבא צריך להפעיל את החיוב במסוף Cloud כדי להשתמש במשאבים של Google Cloud.
מעבר ב-Codelab הזה לא אמור לעלות הרבה, אם בכלל. חשוב לבצע את כל ההוראות בקטע 'ניקוי' שמסביר איך להשבית משאבים כדי שלא תצברו חיובים מעבר למדריך הזה. משתמשים חדשים ב-Google Cloud זכאים להשתתף בתוכנית תקופת ניסיון בחינם בשווי 1,200 ש"ח.
3. קבלת קוד המקור לדוגמה של המיקרונאוט
אחרי ההשקה של Cloud Shell, תוכלו להשתמש בשורת הפקודה כדי לשכפל את קוד המקור לדוגמה בספריית הבית, וכדי ליצור cd לספרייה שמכילה את השירות לדוגמה שלנו:
$ git clone https://github.com/GoogleContainerTools/jib.git
$ cd jib/examples/micronaut/
4. הצצה מהירה בקוד
שירות המיקרונאוט הפשוט שלנו מורכב מבקר שמפיק את הודעת Hello World הנודעת לשמצה:
@Controller("/hello") class HelloController { @Get("/") String index() { "Hello World" } }
הבקר של HelloController
מגיב לבקשות שנמצאות בנתיב /hello
, וה-method index()
מקבלת את בקשות HTTP GET.
אפשר גם לגשת לכיתת בדיקה של Spock כדי לוודא שההודעה הנכונה מוצגת בפלט.
class HelloControllerSpec extends Specification { @Shared @AutoCleanup EmbeddedServer embeddedServer = ApplicationContext.run(EmbeddedServer) @Shared @AutoCleanup RxHttpClient client = embeddedServer.applicationContext.createBean(RxHttpClient, embeddedServer.getURL()) void "test hello world response"() { when: HttpRequest request = HttpRequest.GET('/hello') String rsp = client.toBlocking().retrieve(request) then: rsp == "Hello World" } }
הבדיקה הזו, יותר מבדיקת יחידה פשוטה, מפעילה את אותה מחסנית שרת של מיקרונאוט (על סמך מסגרת Netty) שרצה בסביבת הייצור. כלומר, ההתנהגות של הקוד תהיה זהה במוצר שבבדיקות שלכם.
כדי להריץ את הבדיקות, מריצים את הפקודה הבאה כדי לבדוק שהכול תקין:
./gradlew test
5. הפעלה מקומית של האפליקציה
אתם יכולים להפעיל את שירות המיקרונאוט כרגיל באמצעות הפקודה הבאה של Gradle:
$ ./gradlew run
כשהתחלתם להשתמש באפליקציה אפשר לפתוח מכונה נוספת של Cloud Shell הודות לסמל + הקטן, ואז בודקים באמצעות curl שקיבלתם את הפלט הצפוי:
$ curl localhost:8080/hello
אתם אמורים לראות הודעת 'שלום עולם' פשוט מופיעה הודעה.
6. לארוז את האפליקציה כקונטיינר Docker באמצעות Jib
לאחר מכן, צריך להכין את האפליקציה להפעלה ב-Kubernetes. למטרה הזו, נשתמש ב-Jib כדי לעשות את העבודה הקשה בשבילנו, כי לא נצטרך לגעת בDockerfile
בעצמנו!
נריץ את הפקודה כדי ליצור את הקונטיינר:
$ ./gradlew jibDockerBuild
זה הפלט אמור להופיע:
Tagging image with generated image reference micronaut-jib:0.1. If you'd like to specify a different tag, you can set the jib.to.image parameter in your build.gradle, or use the --im age=<MY IMAGE> commandline flag. Containerizing application to Docker daemon as micronaut-jib:0.1... warning: Base image 'gcr.io/distroless/java' does not use a specific image digest - build may not be reproducible Getting base image gcr.io/distroless/java... Building dependencies layer... Building resources layer... Building classes layer... Finalizing... Container entrypoint set to [java, -cp, /app/resources:/app/classes:/app/libs/*, example.micronaut.Application] Loading to Docker daemon... Built image to Docker daemon as micronaut-jib:0.1
עכשיו, אחרי שבנינו את התמונה, מריצים את תמונת ה-Docker בכרטיסייה הראשונה של Cloud Shell כדי לראות אם אנחנו רואים את הודעת ה'שלום' הידידותית שלנו:
$ docker run -it -p 8080:8080 micronaut-jib:0.1 16:57:20.255 [main] INFO i.m.context.env.DefaultEnvironment - Established active environments: [cloud, gcp] 16:57:23.203 [main] INFO io.micronaut.runtime.Micronaut - Startup completed in 2926ms. Server Running: http://97b7d76ccf3f:8080
השירות שלנו פועל, ועכשיו אנחנו יכולים להפעיל את פקודת ה-curl בכרטיסייה השנייה של Cloud Shell, כדי לבדוק אם היא עובדת כצפוי:
$ curl localhost:8080/hello Hello World
כדי לעצור את הקונטיינר, לוחצים על Ctrl+C
ב-Cloud Shell.
7. דחיפת השירות בקונטיינרים שלנו למרשם
עכשיו, כשהתמונה פועלת כמו שצריך, אפשר להעביר אותה ל-Google Container Registry – מאגר פרטי לתמונות Docker שאפשר לגשת אליהן מכל פרויקט ב-Google Cloud (אבל גם מחוץ ל-Google Cloud Platform).
לפני שתהיה אפשרות לדחוף למרשם, עלינו לוודא ש-Container Registry מופעל עבור הפרויקט שלנו, על ידי מעבר אל כלים > Container Registry אם האפשרות לא מופעלת, אמורה להופיע תיבת הדו-שיח הבאה, ולאחר מכן ללחוץ על "Enable Container Registry API" כדי להפעיל אותה:
כאשר הרישום מוכן, כדי לדחוף את התמונה למרשם, מפעילים את הפקודות הבאות:
$ gcloud auth configure-docker $ docker tag micronaut-jib:0.1 \ gcr.io/$GOOGLE_CLOUD_PROJECT/micronaut-jib:0.1 $ docker push gcr.io/$GOOGLE_CLOUD_PROJECT/micronaut-jib:0.1
הפקודות שלמעלה מאפשרות ל-gcloud SDK להגדיר ולאשר ל-Docker דחיפת תמונות למופע שלכם ב-Container Registry, לתייג את התמונה כך שתציב את התמונה במיקום שלה במרשם, ואז להעביר אותה למרשם.
אם הכול תקין ולאחר זמן מה התמונה אמורה להופיע במסוף: כלים > Container Registry בשלב הזה יש לכם עכשיו קובץ אימג' של Docker ברמת הפרויקט, שניתן לגשת אליו ולתזמר על ידי Kubernetes, כפי שתראו בעוד כמה דקות.
8. יצירת האשכול
עכשיו אתם מוכנים ליצור את האשכול של Kubernetes Engine, אבל לפני כן, מנווטים לקטע Google Kubernetes Engine במסוף האינטרנט ומחכים עד שהמערכת תופעל (התהליך נמשך רק כמה שניות).
אשכול מורכב משרת API ראשי של Kubernetes שמנוהל על ידי Google ומקבוצה של צמתים של עובדים. צמתים של עובדים הם מכונות וירטואליות של Compute Engine. נשתמש ב-CLI של gcloud
מהסשן של CloudShell כדי ליצור אשכול עם שני צמתים של n1-standard-1
(הפעולה תימשך כמה דקות):
$ gcloud container clusters create hello-cluster \ --num-nodes 2 \ --machine-type n1-standard-1 \ --zone us-central1-c
בסוף אתם אמורים לראות שהאשכול נוצר.
Creating cluster hello-cluster in us-central1-c...done. Created [https://container.googleapis.com/v1/projects/mn-gke-test/zones/us-central1-c/clusters/hello-cluster]. To inspect the contents of your cluster, go to: https://console.cloud.google.com/kubernetes/workload_/gcloud/us-central1-c/hello-cluster?project=mn-gke-test kubeconfig entry generated for hello-cluster. NAME LOCATION MASTER_VERSION MASTER_IP MACHINE_TYPE NODE_VERSION NUM_NODES STATUS hello-cluster us-central1-c 1.9.7-gke.7 35.239.224.115 n1-standard-1 1.9.7-gke.7 2 RUNNING
עכשיו אמור להיות לכם אשכול Kubernetes תקין שמופעל על ידי Google Kubernetes Engine:
זה הזמן לפרוס אפליקציה משלכם בקונטיינרים באשכול Kubernetes! מעכשיו משתמשים בשורת הפקודה kubectl
(שכבר מוגדרת בסביבת Cloud Shell). בשאר השלבים של ה-Codelab הזה צריך שגם גרסת השרת והלקוח של Kubernetes יהיו 1.2 ואילך. ב-kubectl version
תוצג הגרסה הנוכחית של הפקודה.
9. פריסת האפליקציה ב-Kubernetes
פריסת Kubernetes יכולה ליצור, לנהל ולהתאים לעומס מספר מכונות של האפליקציה שלכם באמצעות קובץ האימג' שיצרתם כרגע. ניצור פריסה של האפליקציה ב-Kubernetes באמצעות הפקודה kubectl create deployment
:
$ kubectl create deployment hello-micronaut \ --image=gcr.io/$GOOGLE_CLOUD_PROJECT/micronaut-jib:0.1
כדי להציג את הפריסה שיצרתם כרגע, מריצים את הפקודה:
$ kubectl get deployments NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE hello-micronaut 1 1 1 1 5m
כדי להציג את המכונות של האפליקציה שנוצרו על ידי הפריסה, מריצים את הפקודה הבאה:
$ kubectl get pods NAME READY STATUS RESTARTS AGE hello-micronaut-5647fb98c5-lh5h7 1/1 Running 0 5m
בשלב הזה הקונטיינר צריך לפעול בשליטת Kubernetes, אבל עדיין צריך לאפשר לו גישה לעולם החיצוני.
10. התרת תנועה חיצונית
כברירת מחדל, אפשר לגשת לרצף המודעות רק דרך כתובת ה-IP הפנימית שלו בתוך האשכול. כדי שהמאגר hello-micronaut
יהיה נגיש מחוץ לרשת הווירטואלית של kubernetes, צריך לחשוף את רצף המודעות בתור שירות kubernetes.
מ-Cloud Shell אפשר לחשוף את רצף המודעות לאינטרנט הציבורי באמצעות הפקודה kubectl expose
בשילוב עם הדגל --type=LoadBalancer
. הדגל הזה נדרש כדי ליצור כתובת IP שניתן לגשת אליה באופן חיצוני :
$ kubectl expose deployment hello-micronaut --type=LoadBalancer --port=8080
הדגל שבו נעשה שימוש בפקודה הזו מציין שייעשה שימוש במאזן העומסים שסופק על ידי התשתית הבסיסית (במקרה הזה מאזן העומסים של Compute Engine). שימו לב שאתם חושפים את הפריסה ולא את רצף המודעות באופן ישיר. הדבר יגרום לשירות שמתקבל לטעון את תעבורת הנתונים המופעלת בכל הרצפים שמנוהלים על ידי הפריסה (במקרה הזה רק רצף אחד, אבל בהמשך יתווספו עוד רפליקות).
המאסטר ב-Kubernetes יוצר את מאזן העומסים וכללי העברה, מאגרי יעד וכללי חומת אש ב-Compute Engine קשורים כדי שהשירות יהיה נגיש באופן מלא מחוץ ל-Google Cloud Platform.
כדי למצוא את כתובת ה-IP של השירות הנגישה לציבור, צריך פשוט לבקש מ-kubectl
להציג רשימה של כל שירותי האשכולות:
$ kubectl get services NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE hello-micronaut LoadBalancer 10.39.243.251 aaa.bbb.ccc.ddd 8080:30354/TCP 1m kubernetes ClusterIP 10.39.240.1 <none> 443/TCP 31m
שימו לב שרשומות 2 כתובות IP עבור השירות שלך, שתיהן יציאות 8080
. אחת היא כתובת ה-IP הפנימית שגלויה רק ברשת הווירטואלית בענן. השני הוא IP חיצוני עם איזון עומסים. בדוגמה הזו, כתובת ה-IP החיצונית היא aaa.bbb.ccc.ddd
.
עכשיו אמורה להיות לך אפשרות להגיע לשירות באמצעות ההפניה של הדפדפן לכתובת הזו: http://<EXTERNAL_IP>
:8080
/hello
11. הרחבת השירות
אחת התכונות העוצמתיות של Kubernetes היא הקלות שבה ניתן להתאים את האפליקציה שלכם. נניח שאתם צריכים פתאום נפח גדול יותר של קיבולת לאפליקציה שלכם. אפשר פשוט להורות לבקר הרפליקציה לנהל מספר חדש של רפליקות למכונות של האפליקציה:
$ kubectl scale deployment hello-micronaut --replicas=3 deployment.extensions "hello-micronaut" scaled $ kubectl get deployment NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE hello-micronaut 3 3 3 3 16m
שימו לב לגישה ההצהרתית כאן. במקום להתחיל או להפסיק מכונות חדשות, אתם צריכים להצהיר כמה מכונות צריכות לפעול כל הזמן. לולאות התאמה של Kubernetes פשוט מוודאות שהמציאות תואמת למה שביקשתם ופועלת לפי הצורך.
12. השקת שדרוג לשירות
בשלב מסוים, האפליקציה שפרסתם לסביבת הייצור תדרוש תיקוני באגים או תכונות נוספות. Kubernetes כאן כדי לעזור לך לפרוס גרסה חדשה לסביבת הייצור בלי להשפיע על המשתמשים שלך.
קודם נשנה את האפליקציה. פותחים את עורך הקוד מ-Cloud Shell.
עוברים אל /jib/examples/micronaut/src/main/groovy/example/micronaut/HelloController.groovy
ומעדכנים את ערך התשובה:
@Controller("/hello") class HelloController { @Get("/") String index() { "Hello Kubernetes World" } }
החל מ-/jib/examples/micronaut/build.gradle
נשדרג את גרסת התמונה שלנו מ-0.1 ל-0.2 על ידי עדכון השורה הזו:
version '0.2'
לאחר מכן בונים מחדש ואריזות את האפליקציה עם השינויים האחרונים:
$ ./gradlew jibDockerBuild
יש לתייג את התמונה בדחיפה ולדחוף אותה למרשם של קובצי האימג' בקונטיינר:
$ docker tag micronaut-jib:0.2 \ gcr.io/$GOOGLE_CLOUD_PROJECT/micronaut-jib:0.2 $ docker push gcr.io/$GOOGLE_CLOUD_PROJECT/micronaut-jib:0.2
עכשיו אתם מוכנים לאפשר ל-Kubernetes לעדכן בצורה חלקה את בקר הרפליקציה לגרסה החדשה של האפליקציה. כדי לשנות את תווית התמונה של הקונטיינר הפעיל, צריך לערוך את hello-micronaut deployment
הקיים ולשנות את התמונה מ-gcr.io/PROJECT_ID/micronaut-jib:0.1
ל-gcr.io/PROJECT_ID/micronaut-jib:0.2
.
אתם יכולים להשתמש בפקודה kubectl set image
כדי לבקש מ-Kubernetes לפרוס את הגרסה החדשה של האפליקציה שלכם בכל האשכול אחד בכל פעם באמצעות עדכון מתגלגל:
$ kubectl set image deployment/hello-micronaut \ micronaut-jib=gcr.io/$GOOGLE_CLOUD_PROJECT/micronaut-jib:0.2 deployment.apps "hello-micronaut" image updated
צריך לבדוק שוב בכתובת http://EXTERNAL_IP:8080 כדי לראות שהיא מחזירה את התגובה החדשה.
13. חזרה למצב קודם
אופס — האם טעית בגרסה החדשה של האפליקציה? ייתכן שהייתה שגיאה בגרסה החדשה ועליך לחזור לגרסה הקודמת במהירות. בעזרת Kubernetes, אפשר לחזור בקלות למצב הקודם. כדי להחזיר את האפליקציה למצב קודם, מריצים את:
$ kubectl rollout undo deployment/hello-micronaut
אם מסתכלים על הפלט של השירות, נחזור להנחיה הראשונית שלנו "Hello World" הודעה.
14. סיכום
בשלב הזה הגדרתם שירות פשוט מבוסס Apache Graovy Micronaut hello World, והרצתם אותו ישירות מתוך Cloud Shell, ארזה אותו כקונטיינר באמצעות Jib ופרסתם אותו ב-Google Kubernetes Engine.
15. מעולה!
למדתם איך לפתח ולפרוס מיקרו-שירות מבוסס-אינטרנט חדש מסוג Apache Guovy או Micronaut ל-Kubernetes ב-Google Kubernetes Engine.
מידע נוסף
- מסמכים ודוגמאות של Jib: https://github.com/GoogleContainerTools/jib/
- אתר אינטרנט של מיקרונאוט: http://micronaut.io/
- Java ב-Google Cloud Platform: https://cloud.google.com/java/
- לדוגמאות של Java: https://cloud.google.com/java/samples
- למדריך ארוך יותר ומלא יותר של Kubernetes, ראו bit.ly/k8s-lab, ונציג לכם הוראות לפריסה של אפליקציית פול סטאק.
רישיון
היצירה הזו בשימוש ברישיון Creative Commons Attribution 2.0 גנרי.