מעבר מאפליקציית Google App Engine Java ל-Cloud Run באמצעות Jib

1. סקירה כללית

סדרת שיעורי ה-codelab (מדריכים מעשיים בקצב אישי) הזו נועדה לעזור למפתחי Java ב-Google App Engine (Standard) לחדש את האפליקציות שלהם באמצעות סדרה של העברות. בעזרת השלבים האלה תוכלו לעדכן את האפליקציה כדי שתהיה ניידת יותר, ולהחליט להכניס אותה לקונטיינר בשביל Cloud Run, שירות אירוח הקונטיינרים של Google Cloud שהוא שירות אחות של App Engine, ושירותים אחרים לאירוח קונטיינרים.

במדריך הזה נסביר איך להכניס לאריזת Container אפליקציית App Engine כדי לפרוס אותה לשירות המנוהל במלואו Cloud Run באמצעות Jib. בעזרת Jib, אפשר ליצור תמונות Docker, פלטפורמה מוכרת בתעשייה לפיתוח, למשלוח ולהרצה של אפליקציות בקונטיינרים.

בנוסף להסבר על השלבים הנדרשים למעבר מ-App Engine ל-Cloud Run, נסביר גם איך לשדרג אפליקציית Java 8 App Engine ל-Java 17.

אם האפליקציה שלכם עושה שימוש נרחב בשירותים מקובצים מדור קודם של App Engine או בתכונות אחרות של App Engine, מומלץ להעביר את האפליקציה מהשירותים המקובצים האלה או להחליף את התכונות האלה לפני המעבר ל-Cloud Run. אם אתם צריכים עוד זמן כדי לבדוק את אפשרויות המיגרציה או שאתם רוצים להמשיך להשתמש בשירותים הקודמים שצורפו לחבילה בינתיים, אתם יכולים להמשיך לגשת לשירותים שצורפו לחבילה של App Engine ל-Java 11/17 כשמשדרגים לסביבת זמן ריצה חדשה יותר. כשהאפליקציה שלכם תהיה ניידת יותר, תוכלו לחזור ל-Codelab הזה כדי ללמוד איך ליישם את ההוראות באפליקציה.

כאן אפשר להבין איך

  • שימוש ב-Cloud Shell
  • הפעלת Cloud Run,‏ Artifact Registry ו-Cloud Build APIs
  • העברת האפליקציה לקונטיינר באמצעות Jib ו-Cloud Build
  • פריסת קובצי אימג' של קונטיינרים ב-Cloud Run

מה תצטרכו

סקר

איך תשתמשו במדריך הזה?

רק לקרוא לקרוא ולבצע את התרגילים

איך היית מדרג את החוויה שלך עם Java?

מתחילים ביניים מומחים

איזה דירוג מתאים לדעתך לחוויית השימוש שלך בשירותי Google Cloud?

מתחילים ביניים מומחים

2. רקע

מערכות פלטפורמה כשירות (PaaS) כמו App Engine ו-Cloud Functions מספקות הרבה יתרונות לצוות ולאפליקציה, למשל הן מאפשרות לאדמינים של מערכות ולצוותי DevOps להתמקד בבניית פתרונות. פלטפורמות ללא שרתים מאפשרות לאפליקציה להגדיל את הקיבולת באופן אוטומטי לפי הצורך, לצמצם את הקיבולת לאפס באמצעות חיוב לפי שימוש כדי לעזור לכם לשלוט בעלויות, ולהשתמש במגוון שפות פיתוח נפוצות.

עם זאת, הגמישות של קונטיינרים היא גם יתרון משמעותי. האפשרות לבחור כל שפה, כל ספרייה וכל תוכנה בינארית מאפשרת לכם ליהנות מכל העולמות: הנוחות של שרתים וירטואליים יחד עם הגמישות של קונטיינרים. בדיוק בשביל זה יש את Cloud Run.

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

ב-Codelab הזה תלמדו איך ליצור ולפרוס קונטיינרים. במאמר הזה נסביר איך:

  • יצירת קונטיינר לאפליקציה באמצעות Jib
  • מעבר מהגדרת App Engine
  • ואם רוצים, מגדירים שלבי build ל-Cloud Build.

הפעולה הזו תכלול מעבר מתכונות מסוימות שספציפיות ל-App Engine. אם אתם לא רוצים לפעול לפי השלבים האלה, אתם יכולים לשדרג לסביבת ריצה של Java 11/17 תוך כדי השארת האפליקציות ב-App Engine.

3. הגדרה/עבודה מקדימה

1. הגדרת פרויקט

במדריך הזה נשתמש באפליקציה לדוגמה ממאגר appengine-java-migration-samples בפרויקט חדש לגמרי. מוודאים שיש בפרויקט חשבון פעיל לחיוב.

אם אתם מתכוונים להעביר אפליקציית App Engine קיימת אל Cloud Run, אתם יכולים להשתמש באפליקציה הזו כדי לפעול לפי ההוראות.

מריצים את הפקודה הבאה כדי להפעיל את ממשקי ה-API הנדרשים לפרויקט:

gcloud services enable artifactregistry.googleapis.com cloudbuild.googleapis.com run.googleapis.com

2. קבלת אפליקציה לדוגמה של בסיס

משכפלים את האפליקציה לדוגמה במחשב שלכם או ב-Cloud Shell, ואז עוברים לתיקייה baseline.

הדוגמה היא אפליקציית Datastore מבוססת-Servlet ב-Java 8, שמיועדת לפריסה ב-App Engine. פועלים לפי ההוראות בקובץ ה-README כדי להכין את האפליקציה לפריסה ב-App Engine.

3. (אופציונלי) פריסת אפליקציית בסיס

השלב הבא נדרש רק אם רוצים לוודא שהאפליקציה פועלת ב-App Engine לפני המעבר ל-Cloud Run.

פועלים לפי השלבים בקובץ README.md:

  1. התקנה או היכרות מחדש עם gcloud CLI
  2. מאתחלים את ה-CLI של gcloud עבור הפרויקט באמצעות gcloud init
  3. יוצרים את פרויקט App Engine באמצעות gcloud app create
  4. פריסת אפליקציית הדוגמה ב-App Engine
./mvnw package appengine:deploy -Dapp.projectId=$PROJECT_ID
  1. אישור שהאפליקציה פועלת ב-App Engine ללא בעיות

4. יצירת מאגר ב-Artifact Registry

אחרי שמכניסים את האפליקציה לקונטיינר, צריך מקום לשליחה ולאחסון של קובצי האימג' של הקונטיינרים. הדרך המומלצת לעשות זאת ב-Google Cloud היא באמצעות Artifact Registry.

יוצרים את המאגר בשם migration באמצעות gcloud באופן הבא:

gcloud artifacts repositories create migration --repository-format=docker \
--description="Docker repository for the migrated app" \
--location="northamerica-northeast1"

שימו לב שהמאגר הזה משתמש בפורמט docker, אבל יש כמה סוגים של מאגרים.

בשלב הזה, יש לכם אפליקציית App Engine בסיסית, והפרויקט שלכם ב-Google Cloud מוכן להעברה אל Cloud Run.

4. שינוי קבצים של אפליקציות

במקרים שבהם האפליקציה שלכם עושה שימוש נרחב בשירותים, בהגדרות או בתכונות אחרות של App Engine מדור קודם, אנחנו ממליצים להמשיך לגשת לשירותים האלה בזמן השדרוג לסביבת זמן הריצה החדשה. Codelab זה מדגים נתיב העברה לאפליקציות שכבר משתמשות בשירותים עצמאיים, או שאפשר לבצע בהן ארגון הקוד מחדש (Refactoring) כדי שיוכלו להשתמש בשירותים כאלה.

1. שדרוג ל-Java 17

אם האפליקציה שלכם מבוססת על Java 8, כדאי לשדרג לגרסה מאוחרת יותר של LTS כמו 11 או 17 כדי להתעדכן בעדכוני אבטחה ולקבל גישה לתכונות חדשות של השפה.

כדי להתחיל, צריך לעדכן את המאפיינים ב-pom.xml כך שיכללו את המאפיינים הבאים:

<properties>
    <java.version>17</java.version>
    <maven.compiler.source>17</maven.compiler.source>
    <maven.compiler.target>17</maven.compiler.target>
</properties>

הפעולה הזו תגדיר את גרסת הפרויקט ל-17, תודיע לתוסף של הקומפיילר שאתם רוצים גישה לתכונות השפה של Java 17, ותגרום לכך שהמחלקות המקומפלות יהיו תואמות ל-JVM של Java 17.

2. כולל שרת אינטרנט

יש כמה הבדלים בין App Engine לבין Cloud Run שכדאי לקחת בחשבון כשעוברים ביניהם. הבדל אחד הוא שבזמן הריצה של Java 8 ב-App Engine, שרת Jetty סופק ונוהל על ידי האפליקציות שהוא אירח, אבל ב-Cloud Run זה לא קורה. נשתמש ב-Spring Boot כדי לספק לנו שרת אינטרנט ומאגר סרוולטים.

מוסיפים את יחסי התלות הבאים:

<dependencies>
<!-- ... -->
   <dependency>
       <groupId>org.springframework.boot</groupId>
       <artifactId>spring-boot-starter-web</artifactId>
       <version>2.6.6</version>
       <exclusions>
           <!-- Exclude the Tomcat dependency -->
           <exclusion>
               <groupId>org.springframework.boot</groupId>
               <artifactId>spring-boot-starter-tomcat</artifactId>
           </exclusion>
       </exclusions>
   </dependency>
   <!-- Use Jetty instead -->
   <dependency>
       <groupId>org.springframework.boot</groupId>
       <artifactId>spring-boot-starter-jetty</artifactId>
       <version>2.6.6</version>
   </dependency>
<!-- ... -->
</dependencies>

‫Spring Boot מטמיע שרת Tomcat כברירת מחדל, אבל בדוגמה הזו לא נכלל הארטיפקט הזה, והמערכת תשתמש ב-Jetty כדי לצמצם את ההבדלים בהתנהגות ברירת המחדל אחרי ההעברה. אפשר גם להגדיר את גרסת Jetty כך שתהיה זהה לגרסה ש-App Engine מספקת כברירת מחדל.

<properties>
    <java.version>17</java.version>
    <maven.compiler.source>17</maven.compiler.source>
    <maven.compiler.target>17</maven.compiler.target>
    <jetty.version>9.4.46.v20220331</jetty.version>
</properties>

3. הגדרה של Spring Boot

מערכת Spring Boot תוכל לעשות שימוש חוזר ב-servlets שלכם בלי לבצע שינויים, אבל היא תדרוש הגדרה מסוימת כדי לאפשר גילוי.

יוצרים את המחלקה MigratedServletApplication.java הבאה בחבילה com.example.appengine:

package com.example.appengine;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.ServletComponentScan;

@ServletComponentScan
@SpringBootApplication
@EnableAutoConfiguration
public class MigratedServletApplication {
    public static void main(String[] args) {
        SpringApplication.run(MigratedServletApplication.class, args);
    }
}

שימו לב: זה כולל את ההערה @ServletComponentScan, שתחפש (בחבילה הנוכחית כברירת מחדל) כל @WebServlets ותהפוך אותם לזמינים כצפוי.

4. אריזת האפליקציה כקובץ JAR

אפשר להכניס את האפליקציה לקונטיינר באמצעות Jib החל מקובץ WAR, אבל יהיה קל יותר אם תארזו את האפליקציה כקובץ JAR שניתן להפעלה. הפעולה הזו לא דורשת הרבה הגדרות, במיוחד בפרויקטים שמשתמשים ב-Maven ככלי בנייה, כי אריזת jar היא התנהגות ברירת המחדל.

מסירים את התג packaging בקובץpom.xml:

<packaging>war</packaging>

לאחר מכן, מוסיפים את spring-boot-maven-plugin:

<plugins>
<!-- ... -->
  <plugin>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-maven-plugin</artifactId>
    <version>2.6.6</version>
  </plugin>
<!-- ... -->
</plugins>

5. מעבר מהגדרות, משירותים ומהתלויות של App Engine

כמו שציינו בתחילת ה-codelab, ‏ Cloud Run ו-App Engine נועדו לספק חוויות משתמש שונות. תכונות מסוימות ש-App Engine מציע מחוץ לקופסה – כמו השירותים Cron ו-Task Queue – צריך ליצור מחדש באופן ידני, והן יוסברו בפירוט רב יותר במודולים הבאים.

אפליקציית הדוגמה לא משתמשת בשירותים מדור קודם שצורפו לחבילה, אבל משתמשים שהאפליקציות שלהם כן משתמשות בשירותים כאלה יכולים לעיין במדריכים הבאים:

מעכשיו תבצעו פריסה ל-Cloud Run, ולכן אפשר להסיר את appengine-maven-plugin:

<plugin>
 <groupId>com.google.cloud.tools</groupId>
 <artifactId>appengine-maven-plugin</artifactId>
 <version>2.4.1</version>
 <configuration>
   <!-- can be set w/ -DprojectId=myProjectId on command line -->
   <projectId>${app.projectId}</projectId>
   <!-- set the GAE version or use "GCLOUD_CONFIG" for an autogenerated GAE version -->
   <version>GCLOUD_CONFIG</version>
 </configuration>
</plugin>

5. העברה של אפליקציה לקונטיינר

בשלב הזה אפשר לפרוס את האפליקציה באופן ידני ב-Cloud Run ישירות מקוד המקור. זו אפשרות מצוינת שמשתמשת ב-Cloud Build מאחורי הקלעים כדי לספק חוויית פריסה ללא מגע יד. במודולים הבאים נסביר על פריסות של מקורות בצורה מפורטת יותר.

לחלופין, אם אתם צריכים יותר שליטה באופן הפריסה של האפליקציה, אתם יכולים להשיג זאת על ידי הגדרת קובץ cloudbuild.yaml שמפרט באופן מפורש את שלבי ה-build הרצויים:

1. הגדרת קובץ cloudbuild.yaml

יוצרים את הקובץ cloudbuild.yaml הבא באותה רמה כמו pom.xml:

steps:
  # Test your build
  - name: maven:eclipse-temurin
    entrypoint: mvn
    args: ["test"]
  # Build with Jib
  - name: maven:eclipse-temurin
    entrypoint: mvn
    args: [ "compile", "com.google.cloud.tools:jib-maven-plugin:3.2.1:build", "-Dimage=northamerica-northeast1-docker.pkg.dev/PROJECT_ID/migration/visitors:jib"]
  # Deploy to Cloud Run
  - name: 'gcr.io/google.com/cloudsdktool/cloud-sdk'
    entrypoint: gcloud
    args: [ 'run', 'deploy', 'visitors', '--image', 'northamerica-northeast1-docker.pkg.dev/PROJECT_ID/migration/visitors:jib', '--region', 'northamerica-northeast1', '--allow-unauthenticated']

אחרי שאומרים ל-Cloud Build לפעול לפי השלבים האלה, הוא:

  1. הרצת הבדיקות באמצעות ./mvnw test
  2. יצירה, העברה ותיוג של תמונה ב-Artifact Registry באמצעות Jib
  3. פריסת האימג' ב-Cloud Run באמצעות gcloud run deploy

שימו לב ש-‘visitors' מסופק ל-Cloud Run כשם השירות הרצוי. הדגל –allow-unauthenticated מאפשר למשתמשים לבקר באפליקציית האינטרנט בלי לדרוש אימות. חשוב להחליף את PROJECT_ID במזהה הפרויקט שלכם בקובץ cloudbuild.yaml.

לאחר מכן, מוסיפים את הקישורים הבאים של מדיניות IAM כדי לאפשר לחשבון השירות של Cloud Build לגשת ל-Artifact Registry:

export PROJECT_ID=$(gcloud config list --format 'value(core.project)')
export PROJECT_NUMBER=$(gcloud projects describe $PROJECT_ID --format="value(projectNumber)" )

gcloud projects add-iam-policy-binding $PROJECT_ID \
--member=serviceAccount:$PROJECT_NUMBER@cloudbuild.gserviceaccount.com \
--role=roles/run.admin \
--project=$PROJECT_ID
gcloud iam service-accounts add-iam-policy-binding $PROJECT_NUMBER-compute@developer.gserviceaccount.com \
--member=serviceAccount:$PROJECT_NUMBER@cloudbuild.gserviceaccount.com \
--role roles/iam.serviceAccountUser --project=$PROJECT_ID

2. הפעלת תהליך build

אחרי שעדכנתם את Cloud Build לגבי שלבי ה-build הרצויים, אתם מוכנים לפריסה בלחיצה אחת.

מריצים את הפקודה הבאה:

gcloud builds submit

בסיום התהליך, קובץ אימג' של קונטיינר נבנה, אוחסן ב-Artifact Registry ונפרס ב-Cloud Run.

בסיום ה-codelab, האפליקציה שלכם אמורה להיראות כמו האפליקציה ב- java17-and-cloud-run/finish.

זהו, אתה מוכן! הצלחתם להעביר אפליקציית Java 8 App Engine ל-Java 17 ול-Cloud Run, ועכשיו יש לכם הבנה ברורה יותר של העבודה הנדרשת כשעוברים בין אפשרויות אירוח ובוחרים ביניהן.

6. סיכום/ניקוי

מזל טוב, שדרגת, יצרת קונטיינר, העברת את האפליקציה שלך, ובכך סיימת את המדריך הזה!

מכאן, השלב הבא הוא לקרוא מידע נוסף על תכונות האבטחה של CI/CD ושל שרשרת אספקת התוכנה, שזמינות לכם עכשיו כשאתם יכולים לבצע פריסה באמצעות Cloud Build:

אופציונלי: פינוי נפח אחסון או השבתה של שירות

אם פרסתם את האפליקציה לדוגמה ב-App Engine במהלך המדריך הזה, אל תשכחו להשבית את האפליקציה כדי להימנע מחיובים. כשרוצים לעבור ל-codelab הבא, אפשר להפעיל אותו מחדש. בזמן שאפליקציות App Engine מושבתות, הן לא מקבלות תנועה ולכן לא צוברות חיובים. עם זאת, יכול להיות שיהיו חיובים על השימוש ב-Datastore אם הוא חורג מהמכסה החינמית, לכן צריך למחוק מספיק נתונים כדי שלא לחרוג מהמגבלה הזו.

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

7. מקורות מידע נוספים

App Engine migration module codelabs issues/feedback

אם נתקלתם בבעיות ב-codelab הזה, כדאי לחפש את הבעיה לפני ששולחים דיווח. קישורים לחיפוש וליצירה של בעיות חדשות:

מקורות מידע על העברת נתונים

משאבים באינטרנט

בהמשך מופיעים מקורות מידע באינטרנט שעשויים להיות רלוונטיים למדריך הזה:

App Engine

מידע אחר על Cloud

סרטונים

רישיון

עבודה זו מורשית תחת רישיון Creative Commons שמותנה בייחוס 2.0 כללי.