יחידת לימוד 11: מעבר מ-Google App Engine ל-Cloud Functions

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

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

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

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

  • שימוש ב-Cloud Shell
  • הפעלת Google Cloud Translation API
  • אימות בקשות API
  • המרת אפליקציית App Engine קטנה להפעלה ב-Cloud Functions
  • פריסת הקוד ב-Cloud Functions

הדרישות

סקר

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

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

איך היית מדרג את חוויית השימוש שלך ב-Python?

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

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

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

2. רקע

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

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

‫Cloud Functions משמש לפריסת קטע קוד קטן ש:

  • לא חלק מאפליקציה שלמה
  • לא נדרש בסטאק פיתוח שלם
  • נמצאת באפליקציה או בחלק האחורי של אפליקציה אחת לנייד שמתמקדת בדבר אחד

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

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

  • הגדרה/עבודה מקדימה
  • הסרת קובצי תצורה
  • שינוי קבצים של אפליקציות

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

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

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

אם השלמתם את ה-codelab של מודול 2 (והעברתם אותו ל-Python 3), מומלץ להשתמש מחדש באותו פרויקט (ובאותו קוד). אפשר גם ליצור פרויקט חדש לגמרי או להשתמש בפרויקט קיים אחר. מוודאים שלפרויקט יש חשבון לחיוב פעיל עם שירות App Engine מופעל.

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

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

בין אם משתמשים בקוד שלכם או בקוד שלנו, נתחיל עם קוד Python 3 של מודול 2. ב-codelab הזה, מודול 11, מוסבר כל שלב, ובסופו מוצג קוד שדומה למה שמופיע בתיקיית המאגר של מודול 11 (FINISH).

הספרייה של קובצי ההתחלה של מודול 2 של Python 3 (שלכם או שלנו) צריכה להיראות כך:

$ ls
README.md               main.py                 templates
app.yaml                requirements.txt

3. (Re)Deploy baseline app

השלבים הנותרים שצריך לבצע עכשיו:

  1. כדאי להכיר מחדש את כלי שורת הפקודה gcloud
  2. פריסה מחדש של האפליקציה לדוגמה עם gcloud app deploy
  3. אישור שהאפליקציה פועלת ב-App Engine ללא בעיות

אחרי שתבצעו את השלבים האלה, תוכלו להמיר אותה לפונקציה של Cloud Functions.

4. הסרת קובצי תצורה

הקובץ app.yaml הוא ארטיפקט של App Engine שלא נמצא בשימוש ב-Cloud Functions, ולכן צריך למחוק אותו עכשיו. אם לא תעשו את זה או שתשכחו לעשות את זה, לא יקרה שום דבר כי Cloud Functions לא משתמש בזה. זה השינוי היחיד בהגדרות, כי requirements.txt נשאר זהה למה שהוא ממודול 2.

אם אתם מעבירים גם אפליקציית Python 2 App Engine ל-Python 3, מוחקים את appengine_config.py ואת התיקייה lib אם היא קיימת. אלה ארטיפקטים של App Engine שלא נמצאים בשימוש בסביבת זמן הריצה של Python 3.

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

יש רק קובץ אפליקציה אחד, main.py, ולכן כל השינויים שצריך לבצע כדי לעבור ל-Cloud Functions מתרחשים בקובץ הזה.

יבוא

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

מכיוון שסביבות עבודה באינטרנט לא נכללות ב-Cloud Functions, אין ייבוא מ-Flask אלא אם האפליקציה משתמשת בתכונות אחרות של Flask. זה אכן המקרה שלנו, כי עיבוד התבנית עדיין מתבצע אחרי ההמרה לפונקציה, כלומר עדיין נדרשת קריאה ל-flask.render_template(), ולכן צריך לייבא אותה מ-Flask. אם אין מסגרת אינטרנט, אין צורך ליצור מופע של אפליקציית Flask, ולכן אפשר למחוק את app = Flask(__name__). הקוד שלכם ייראה כך, לפני ואחרי החלת השינויים:

לפני:

from flask import Flask, render_template, request
from google.cloud import ndb

app = Flask(__name__)
ds_client = ndb.Client()

אחרי:

from flask import render_template
from google.cloud import ndb

ds_client = ndb.Client()

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

עדכון החתימה של פונקציית ה-handler הראשית

השינויים שצריך לבצע בחתימת הפונקציה הם:

  1. אחרי שממירים את האפליקציה לפונקציה של Cloud Functions, לא משתמשים יותר ב-Flask, ולכן צריך להסיר את מעצבי המסלולים.
  2. מערכת Cloud Functions מעבירה אוטומטית את אובייקט Request של Flask כפרמטר, לכן צריך ליצור בשבילו משתנה. באפליקציית הדוגמה שלנו, נקרא לה request.
  3. חובה לתת שם לפונקציות של Cloud Functions שפורסו. ה-handler הראשי שלנו נקרא root() ב-App Engine כדי לתאר מה הוא (ה-handler של אפליקציית השורש). כשמדובר ב-Cloud Function, השם הזה פחות מתאים. במקום זאת, נבצע פריסה של Cloud Function עם השם visitme, ולכן צריך להשתמש בשם הזה גם כשם של פונקציית Python. באופן דומה, במודולים 4 ו-5, קראנו לשירות Cloud Run בשם visitme.

כך נראו הדברים לפני העדכונים ואחריהם:

לפני:

@app.route('/')
def root():
    'main application (GET) handler'
    store_visit(request.remote_addr, request.user_agent)
    visits = fetch_visits(10)
    return render_template('index.html', visits=visits)

אחרי:

def visitme(request):
    'main application (GET) handler'
    store_visit(request.remote_addr, request.user_agent)
    visits = fetch_visits(10)
    return render_template('index.html', visits=visits)

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

668f30e3865b27a9.png

פיתוח ובדיקה באופן מקומי

ב-App Engine יש dev_appserver.py שרת פיתוח מקומי, וב-Cloud Functions יש Functions Framework. בעזרת המסגרת הזו, אפשר לפתח ולבדוק באופן מקומי. אפשר לפרוס את הקוד ב-Cloud Functions, אבל אפשר גם לפרוס אותו בפלטפורמות מחשוב אחרות כמו Compute Engine,‏ Cloud Run או אפילו במערכות מקומיות או בענן היברידי שתומכות ב-Knative. בהמשך מופיעים קישורים נוספים ל-Functions Framework.

6. פיתוח ופריסה

הפריסה ב-Cloud Functions שונה מעט מהפריסה ב-App Engine. מכיוון שלא נעשה שימוש בקובצי תצורה מחוץ ל-requirements.txt, צריך לציין מידע נוסף על הקוד בשורת הפקודה. פורסים את הפונקציה החדשה של Cloud Functions שמופעלת באמצעות HTTP ופועלת ב-Python 3.10 באמצעות הפקודה הבאה:

$ gcloud functions deploy visitme --runtime python310 --trigger-http --allow-unauthenticated

הפלט אמור להיראות כך:

Deploying function (may take a while - up to 2 minutes)...⠛
For Cloud Build Logs, visit: https://console.cloud.google.com/cloud-build/builds;region=REGION/f5f6fc81-1bb3-4cdb-8bfe?project=PROJECT_ID
Deploying function (may take a while - up to 2 minutes)...done.
availableMemoryMb: 256
buildId: f5f6fc81-1bb3-4cdb-8bfe
buildName: projects/PROJECT_ID/locations/REGION/builds/f5f6fc81-1bb3-4cdb-8bfe
dockerRegistry: CONTAINER_REGISTRY
entryPoint: visitme
httpsTrigger:
  securityLevel: SECURE_OPTIONAL
  url: https://REGION-PROJECT_ID.cloudfunctions.net/visitme
ingressSettings: ALLOW_ALL
labels:
  deployment-tool: cli-gcloud
name: projects/PROJECT_ID/locations/REGION/functions/visitme
runtime: python310
serviceAccountEmail: PROJECT_ID@appspot.gserviceaccount.com
sourceUploadUrl: https://storage.googleapis.com/uploads-853031211983.REGION.cloudfunctions.appspot.com/8c923758-cee8-47ce-8e97-5720a5301c34.zip
status: ACTIVE
timeout: 60s
updateTime: '2022-05-16T18:28:06.153Z'
versionId: '8'

אחרי שפורסים את הפונקציה, משתמשים בכתובת ה-URL מתוצאת הפריסה ונכנסים לאפליקציה. כתובת ה-URL היא מהצורה: REGION-PROJECT_ID.cloudfunctions.net/visitme. הפלט צריך להיות זהה לזה שקיבלתם כשפרסתם את האפליקציה קודם ב-App Engine:

2732ae9218f011a2.png

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

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

כל הכבוד על ההמרה של אפליקציית App Engine הקטנה הזו לפונקציה של Cloud Functions! תרחיש שימוש מתאים נוסף: פירוק אפליקציית App Engine גדולה ומונוליתית לסדרה של מיקרו-שירותים, שכל אחד מהם הוא Cloud Function. זו טכניקת פיתוח מודרנית יותר שיוצרת רכיב יותר 'plug-and-play' (בסגנון JAM stack). היא מאפשרת לערבב ולהתאים, ולעשות שימוש חוזר בקוד, שהם שני יעדים, אבל יתרון נוסף הוא שהמיקרו-שירותים האלה ימשיכו לעבור ניפוי באגים לאורך זמן, מה שאומר קוד יציב ועלויות תחזוקה נמוכות יותר באופן כללי.

הסרת המשאבים

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

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

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

השלבים הבאים

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

  • מודול 4: מעבר ל-Cloud Run באמצעות Docker
  • העברת האפליקציה לקונטיינר להפעלה ב-Cloud Run באמצעות Docker
  • ההעברה הזו מאפשרת לכם להמשיך להשתמש ב-Python 2.
  • מודול 5: מעבר ל-Cloud Run באמצעות Cloud Buildpacks
  • יצירת קונטיינר לאפליקציה כדי להפעיל אותה ב-Cloud Run באמצעות Cloud Buildpacks
  • לא צריך לדעת שום דבר על Docker, על קונטיינרים או על Dockerfiles.
  • האפליקציה כבר צריכה להיות מועברת ל-Python 3 (Buildpacks לא תומך ב-Python 2)

הרבה מהמודולים האחרים מתמקדים בהסבר למפתחים איך להעביר את השירותים בחבילה של App Engine להחלפות עצמאיות ב-Cloud:

אם יצירת קונטיינרים הפכה לחלק מתהליך העבודה של פיתוח האפליקציה, במיוחד אם היא כוללת צינור עיבוד נתונים של CI/CD (שילוב רציף/העברה או פריסה רציפה), מומלץ לעבור ל-Cloud Run במקום ל-Cloud Functions. במודול 4 מוסבר איך להשתמש ב-Docker כדי להוסיף את האפליקציה למאגר, ובמודול 5 מוסבר איך לעשות את זה בלי מאגרי Docker או בלי ידע ב-Docker או ב-Dockerfiles. המעבר לפלטפורמה אחרת בלי שרת (serverless) הוא אופציונלי, בין אם מדובר ב-Cloud Functions או ב-Cloud Run. מומלץ לבדוק מהן האפשרויות הכי טובות לאפליקציות ולתרחישי השימוש שלכם לפני שמבצעים שינויים.

לא משנה איזה מודול העברה תבחרו, תוכלו לגשת לכל התוכן של Serverless Migration Station (סדנאות קוד, סרטונים, קוד מקור [אם זמין]) במאגר הקוד הפתוח שלו. במאגר README יש גם הנחיות לגבי ההעברות שכדאי לבצע וסדר רלוונטי של מודולי ההעברה.

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

App Engine migration module codelabs issues/feedback

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

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

בטבלה שלמטה מופיעים קישורים לתיקיות של מאגרים למודול 8 (התחלה) ולמודול 9 (סיום). אפשר גם לגשת אליהם ממאגר המידע של כל ההעברות של Codelabs של App Engine, שאפשר לשכפל או להוריד כקובץ ZIP.

Codelab

Python 3

מודול 2

קוד

מודול 11

קוד

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

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

App Engine

Cloud Functions

מידע אחר על Cloud

סרטונים

רישיון

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