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

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

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

המדריך הזה מלמד איך ליצור קונטיינרים של אפליקציית App Engine לפריסה בשירות מנוהל של Cloud Run באמצעות קובץ Docker. קובצי Docker הם שיטת הפריסה המעשית ביותר להעברה הזו, אבל הם גם מציעים את רוב האפשרויות להתאמה אישית של תהליך ה-build.

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

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

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

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

מה צריך להכין

סקר

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

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

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

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

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

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

2. רקע

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

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

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

ב-Codelab הזה תלמדו איך לפתח ולפרוס קונטיינרים. תלמדו איך ליצור קונטיינרים לאפליקציה באמצעות קובץ Docker, לבצע מיגרציה מהגדרות 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 מבוססת-Java 8 שמבוססת על Servlet, שמיועדת לפריסה ב-App Engine. יש לפעול לפי ההוראות ב-README שמסבירות איך להכין את האפליקציה הזו לפריסה של App Engine.

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

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

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

  1. התקנה או היכרות מחדש עם ה-CLI של gcloud
  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

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

יוצרים את המאגר בשם 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 שמוגדרות ב-App Engine, מומלץ להמשיך לגשת לשירותים האלה ולשדרג לסביבת זמן הריצה החדשה. ה-Codelab הזה מדגים נתיב העברה לאפליקציות שכבר משתמשות בשירותים עצמאיים, או שסביר להניח שאפשר להגדיר אותן מחדש כדי לעשות זאת.

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, תודיע לפלאגין המהדר (compiler) על כך שאתם רוצים לגשת לתכונות השפה של Java 17 ושאתם רוצים שהמחלקות הידור יהיו תואמות ל-Java 17 JVM.

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

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

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

<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 יטמיע שרת Tomcat כברירת מחדל, אבל הדוגמה הזו לא תכלול ארטיפקט הזה ויישאר עם Jetty כדי למזער את ההבדלים בהתנהגות ברירת המחדל לאחר ההעברה.

3. הגדרת מגף קפיץ

ניתן יהיה להשתמש שוב בשרת ה- הזאתs (שרתים) ללא שינויים, אבל יהיה צורך לקבוע הגדרות אישיות כדי לוודא שהם גלויים.

יוצרים את המחלקה הבאה 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

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

מסירים את התג 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

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

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

מעכשיו, הפריסה של 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 Build איך לבנות בפועל את הקונטיינר של האפליקציה. באמצעות שיטת הקונטיינרים הזו, לא נדרש קובץ תצורת build נפרד (cloudbuild.yaml). אפשר פשוט להגדיר קובץ Docker מינימלי כנקודת התחלה:

FROM ליקוי חמה

ARG JAR_FILE=JAR_FILE_MUST_BE_SPECIFIED_AS_BUILD_ARG

העתקה של ${JAR_FILE} app.jar

ENTRYPOINT ["Java", "-jar","/app.jar"]

קובץ ה-Docker הזה כולל את גרסת ה-uber-jar של שירות האתחול של האביב בשכבה אחת. זו הגישה הפשוטה ביותר ליצירת קונטיינרים של קובצי Docker, אבל יש לה כמה חסרונות, במיוחד כשמשווים בין זמנים חוזרים שבהם יחסי התלות יציבים יחסית. חששות מסוג זה הם הסיבה לכך שהשיטה הזו ליצירת קונטיינרים נחשבת למתקדמת יותר. עם זאת, אם תכתבו קובץ Docerfile משלכם, תוכלו ליהנות משליטה מלאה על קובץ האימג' הבסיסי ולגשת ליתרונות הביצועים של כתיבת תמונה עם שכבות בקפידה.

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

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

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

gcloud builds submit --tag LOCATION-docker.pkg.dev/PROJECT_ID/REPOSITORY/IMAGE_NAME

מחליפים את הערכים הזמניים לשמירת מקום (placeholder) בפקודה שלמעלה בערכים הבאים:

  • LOCATION: המיקום האזורי או מרובה האזורים של המאגר.
  • PROJECT_ID: מזהה הפרויקט ב-Cloud.
  • REPOSITORY: שם המאגר ב-Artifact Registry.
  • IMAGE_NAME: השם של קובץ האימג' בקונטיינר.

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

בסוף ה-Codelab הזה, האפליקציה שלך אמורה להיראות זהה לזו שמופיעה בתיקייה mod4-migrate-to-cloud-run.

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

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

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

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

אופציונלי: ניקוי ו/או השבתה של השירות

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

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

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

בעיות/משוב על Codelabs עם מודול ההעברה של App Engine

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

מקורות מידע בנושא העברה

מקורות מידע אונליין

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

App Engine

מידע אחר בענן

סרטונים

רישיון

היצירה הזו בשימוש ברישיון Creative Commons Attribution 2.0 גנרי.