שלום Cloud Run עם Python

1. מבוא

96d07289bb51daa7.png

Cloud Run היא פלטפורמת מחשוב מנוהלת שמאפשרת להריץ קונטיינרים ללא שמירת מצב, שניתן להפעיל באמצעות בקשות HTTP. הוא מבוסס על פרויקט הקוד הפתוח Knative, ומאפשר ניידות של עומסי העבודה בפלטפורמות השונות. Cloud Run הוא ללא שרת (serverless): הוא מפשט את כל ניהול התשתית, כך שאתם יכולים להתמקד במה שהכי חשוב – פיתוח אפליקציות מעולות.

מטרת המדריך הזה היא ליצור אפליקציית אינטרנט פשוטה ולפרוס אותה ל-Cloud Run.

2. הגדרה ודרישות

הגדרת סביבה בקצב עצמאי

  1. נכנסים למסוף Google Cloud ויוצרים פרויקט חדש או עושים שימוש חוזר בפרויקט קיים. אם אין לכם עדיין חשבון Gmail או חשבון Google Workspace, עליכם ליצור חשבון.

fbef9caa1602edd0.png

a99b7ace416376c4.png

5e3ff691252acf41.png

  • Project name הוא השם המוצג של המשתתפים בפרויקט. זו מחרוזת תווים שלא משמשת את Google APIs. תמיד אפשר לעדכן.
  • Project ID הוא ייחודי בכל הפרויקטים ב-Google Cloud ואי אפשר לשנות אותו (אי אפשר לשנות אותו אחרי שמגדירים אותו). מסוף Cloud יוצר מחרוזת ייחודית באופן אוטומטי; בדרך כלל לא מעניין אותך מה זה. ברוב ה-codelabs תצטרכו להפנות למזהה הפרויקט שלכם (בדרך כלל מזוהה כ-PROJECT_ID). אם המזהה שנוצר לא מוצא חן בעיניכם, אתם יכולים ליצור מזהה אקראי אחר. לחלופין, אפשר לנסות שם משלך ולראות אם הוא זמין. לא ניתן לשנות אותו אחרי השלב הזה, והוא נשאר למשך הפרויקט.
  • לידיעתך, יש ערך שלישי, Project Number, שבו משתמשים בחלק מממשקי ה-API. מידע נוסף על כל שלושת הערכים האלה זמין במסמכי התיעוד.
  1. בשלב הבא צריך להפעיל את החיוב במסוף Cloud כדי להשתמש במשאבים או בממשקי API של Cloud. מעבר ב-Codelab הזה לא יעלה הרבה כסף, אם בכלל. כדי להשבית משאבים ולא לצבור חיובים מעבר למדריך הזה, אתם יכולים למחוק את המשאבים שיצרתם או למחוק את הפרויקט. משתמשים חדשים ב-Google Cloud זכאים להשתתף בתוכנית תקופת ניסיון בחינם בשווי 1,200 ש"ח.

הפעלת Cloud Shell

אומנם אפשר להפעיל את Google Cloud מרחוק מהמחשב הנייד, אבל במדריך הזה משתמשים ב-Cloud Shell, סביבת שורת הפקודה שפועלת ב-Cloud.

הפעלת Cloud Shell

  1. במסוף Cloud, לוחצים על Activate Cloud Shell 853e55310c205094.png.

3c1dabeca90e44e5.png

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

9c92662c6a846a5c.png

ההקצאה וההתחברות ל-Cloud Shell נמשכת כמה דקות.

9f0e51b578fecce5.png

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

אחרי ההתחברות ל-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`
  1. מריצים את הפקודה הבאה ב-Cloud Shell כדי לוודא שהפקודה ב-gcloud יודעת על הפרויקט שלכם:
gcloud config list project

פלט הפקודה

[core]
project = <PROJECT_ID>

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

gcloud config set project <PROJECT_ID>

פלט הפקודה

Updated property [core/project].

3. הפעלת ממשקי ה-API

באמצעות Cloud Shell, מפעילים את ממשקי ה-API של Artifact Registry, Cloud Build ו-Cloud Run:

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

בעקבות זאת תופיע הודעת הצלחה שדומה להודעה הבאה:

Operation "operations/..." finished successfully.

עכשיו אפשר להתחיל לעבוד ולכתוב את האפליקציה...

4. כתיבת האפליקציה

בשלב הזה תיצרו אפליקציה פשוטה של Python מבוססת Flask שמגיבה לבקשות HTTP.

ספריית העבודה

משתמשים ב-Cloud Shell כדי ליצור ספריית עבודה בשם helloworld-python ולעבור אליה:

mkdir ~/helloworld-python
cd ~/helloworld-python

main.py

יוצרים קובץ בשם main.py:

touch main.py

עורכים את הקובץ באמצעות עורך שורת הפקודה המועדף עליכם (nano, vim או emacs) או לוחצים על הלחצן של Cloud Shell Editor:

10af7b1a6240e9f4.gif

כדי לערוך את הקובץ ישירות באמצעות Cloud Shell Editor, משתמשים בפקודה הבאה:

cloudshell edit main.py

main.py

from flask import Flask, request

app = Flask(__name__)


@app.get("/")
def hello():
    """Return a friendly HTTP greeting."""
    who = request.args.get("who", default="World")
    return f"Hello {who}!\n"


if __name__ == "__main__":
    # Development only: run "python main.py" and open http://localhost:8080
    # When deploying to Cloud Run, a production-grade WSGI HTTP server,
    # such as Gunicorn, will serve the app.
    app.run(host="localhost", port=8080, debug=True)

הקוד הזה יוצר שירות אינטרנט בסיסי שמגיב לבקשות HTTP GET באמצעות הודעה ידידותית.

requirements.txt

כדי להגדיר את יחסי התלות, מוסיפים קובץ בשם requirements.txt:

touch requirements.txt

כדי לערוך את הקובץ ישירות באמצעות Cloud Shell Editor, משתמשים בפקודה הבאה:

cloudshell edit requirements.txt

requirements.txt

# https://pypi.org/project/flask
Flask==3.0.2

# https://pypi.org/project/gunicorn
gunicorn==21.2.0

Procfile

לסיום, צריך להוסיף קובץ בשם Procfile כדי לציין איך האפליקציה תוצג:

touch Procfile

כדי לערוך את הקובץ ישירות באמצעות Cloud Shell Editor, משתמשים בפקודה הבאה:

cloudshell edit Procfile

Procfile

web: gunicorn --bind :$PORT --workers 1 --threads 8 --timeout 0 main:app

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

ls

הרשימה אמורה לכלול את הקבצים הבאים:

main.py  Procfile  requirements.txt

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

5. בדיקת האפליקציה

כדי לבדוק את האפליקציה, יוצרים סביבה וירטואלית:

virtualenv venv

מפעילים את הסביבה הווירטואלית:

source venv/bin/activate

מתקינים את יחסי התלות:

pip install -r requirements.txt

אמורה להופיע הודעת אישור כמו:

...
Successfully installed Flask ... gunicorn ...

מפעילים את האפליקציה:

python main.py

הרישומים מראים שאתה במצב פיתוח:

 * Serving Flask app 'main'
 * Debug mode: on
   WARNING: This is a development server.
   Do not use it in a production deployment.
   Use a production WSGI server instead.
 * Running on http://localhost:8080
   Press CTRL+C to quit
...

בחלון Cloud Shell, לוחצים על הסמל Web Preview ובוחרים באפשרות Preview on port 8080:

6c9ff9e5c692c58e.gif

אמור להיפתח חלון דפדפן שבו מוצגת ההודעה Hello World!.

אפשר גם לפתוח סשן נוסף של Cloud Shell (כרטיסיית טרמינל חדשה) על ידי לחיצה על הסמל + ושליחת בקשת אינטרנט לאפליקציה שפועלת באופן מקומי:

curl localhost:8080

התשובה הבאה אמורה להתקבל:

Hello World!

כשמסיימים, חוזרים לסשן הראשי של Cloud Shell ומפסיקים את הפקודה python main.py עם CTRL+C.

יוצאים מהסביבה הווירטואלית:

deactivate

לבסוף, מסירים את ספריית הסביבה הווירטואלית:

rm -r venv/

האפליקציה פועלת כצפוי: בואו נפרוס אותה...

6. פריסה ב-Cloud Run

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

REGION="europe-west9"

צריך לוודא שאתם עדיין נמצאים בספריית העבודה:

ls

הרשימה אמורה לכלול את הקבצים הבאים:

main.py  Procfile  requirements.txt

פורסים את האפליקציה ב-Cloud Run:

gcloud run deploy helloworld-python \
  --source . \
  --platform managed \
  --region $REGION \
  --allow-unauthenticated
  • אפשר להגדיר אזור ברירת מחדל באמצעות הפקודה הבאה: gcloud config set run/region $REGION
  • אפשר גם להפוך את Cloud Run למנוהל כברירת מחדל באמצעות הפקודה הבאה: gcloud config set run/platform managed
  • האפשרות --allow-unauthenticated הופכת את השירות לזמין לציבור. כדי למנוע בקשות לא מאומתות, צריך להשתמש בפונקציה --no-allow-unauthenticated במקום זאת.

בפעם הראשונה תופיע הנחיה ליצור מאגר של Artifact Registry. צריך להקיש על Enter כדי לאמת:

Deploying from source requires an Artifact Registry Docker repository to store
built containers. A repository named [cloud-run-source-deploy] in region [REGION]
will be created.

Do you want to continue (Y/n)?

הפעולה הזו מפעילה את ההעלאה של קוד המקור למאגר Artifact Registry ואת ה-build של קובץ האימג' בקונטיינר:

Building using Buildpacks and deploying container ...
* Building and deploying new service... Building Container.           
  OK Creating Container Repository...
  OK Uploading sources...
  * Building Container... Logs are available at ...

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

...
OK Building and deploying new service... Done.
  OK Creating Container Repository...
  OK Uploading sources...
  OK Building Container... Logs are available at ...
  OK Creating Revision... Creating Service.
  OK Routing traffic...
  OK Setting IAM Policy...
Done.
Service [SERVICE]... has been deployed and is serving 100 percent of traffic.
Service URL: https://SERVICE-PROJECTHASH-REGIONID.a.run.app

אפשר למצוא את כתובת ה-URL של השירות באמצעות הפקודה הבאה:

SERVICE_URL=$( \
  gcloud run services describe helloworld-python \
  --platform managed \
  --region $REGION \
  --format "value(status.url)" \
)
echo $SERVICE_URL

זה אמור להיראות כך:

https://helloworld-python-PROJECTHASH-REGIONID.a.run.app

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

c836b93e5601e2cf.gif

אפשר גם לשלוח קריאה לאפליקציה מ-Cloud Shell:

curl $SERVICE_URL?who=me

הנה הודעת הפתיחה הצפויה:

Hello me!

מעולה! פרסתם עכשיו אפליקציה ב-Cloud Run. Cloud Run מגדיל את קובץ האימג' של הקונטיינר באופן אוטומטי ואופקי כדי לטפל בבקשות שהתקבלו, ואז מקטין את הפוטנציאל כשהביקוש יורד. התשלום הוא רק על המעבד (CPU), הזיכרון והרשת שנצרכו במהלך הטיפול בבקשה.

7. הסרת המשאבים

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

כדי למחוק את מאגר קובצי האימג' בקונטיינר:

gcloud artifacts repositories delete cloud-run-source-deploy \
  --location $REGION

כדי למחוק את השירות Cloud Run:

gcloud run services delete helloworld-python \
  --platform managed \
  --region $REGION

כדי למחוק את הפרויקט ב-Google Cloud:

  1. מאחזרים את מזהה הפרויקט הנוכחי:
PROJECT_ID=$(gcloud config get-value core/project)
  1. צריך לוודא שזה הפרויקט שרוצים למחוק:
echo $PROJECT_ID
  1. מוחקים את הפרויקט:
gcloud projects delete $PROJECT_ID

8. מעולה!

96d07289bb51daa7.png

יצרתם אפליקציית אינטרנט פשוטה ופרסתם אותה ב-Cloud Run!

מידע נוסף

רישיון

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