1. מבוא
למה כל כך קשה לנהל אפליקציות?
סיבה חשובה אחת היא שמפתחים נדרשים לעיתים קרובות להיות אדמינים של המערכת במשרה חלקית. כדאי לעיין ברשימה (החלקית) הבאה של נושאים שחשוב לקחת בחשבון כשמפתחים, פורסים ומנהלים אפליקציית אינטרנט מודרנית ברמת ייצור :

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

במילים אחרות, זו המהות של Cloud Run – אתם יכולים להתמקד באפליקציה שלכם, ולהשאיר את כל הניהול והתחזוקה למישהו אחר, כלומר ל-Google, שהשקיעה מיליוני שעות בשיפור ובהשבחה של הכישורים שלה בתחום הזה.
בנוסף לאתגרים הניהוליים שצוינו למעלה, צריך להתמודד גם עם:
- תלויות – הסביבה שבה האפליקציה פועלת צריכה להיות זהה ככל האפשר לסביבה שבה היא נבדקה. ההגדרה הזו יכולה לכלול כמה מימדים, כולל מערכת הפעלה, ספריות תמיכה, מהדר או מתורגמן שפה, הגדרת חומרה ועוד הרבה גורמים אחרים.
- הפצה – המעבר מגרסה מקומית של אפליקציה לגרסה שמשותפת באופן נרחב באינטרנט דורש לעיתים קרובות שינוי בסביבת זמן הריצה, קפיצה משמעותית במורכבות ועקומת למידה תלולה.
Cloud Run מטפל בבעיות האלה ובעוד הרבה בעיות אחרות בשבילכם. אבל במקום להסתמך על המילה שלי, בואו ניצור אפליקציית ענן ביחד ונראה כמה קל לעבור מסביבת פיתוח מקומית לאפליקציית ענן ברמת ייצור בכמה שלבים פשוטים.
מה עושים...
- תבנו אפליקציית אינטרנט פשוטה ותוודאו שהיא פועלת כמו שצריך בסביבת הפיתוח.
- לאחר מכן תעברו לגרסה מבוססת-קונטיינר של אותה אפליקציה. במהלך התהליך תלמדו מה המשמעות של קונטיינר ומה היתרונות שלו.
- לבסוף, תפרסו את האפליקציה בענן ותראו כמה קל לנהל את שירות Cloud Run באמצעות שורת הפקודה ומסוף Google Cloud.
מה תלמדו...
- איך יוצרים אפליקציית שרת אינטרנט פשוטה ב-Python
- איך לארוז את האפליקציה בקונטיינר Docker שפועל בכל מקום
- איך פורסים את האפליקציה בענן כדי שכל אחד יוכל לנסות את היצירה החדשה
- איך לפשט עוד יותר את השלבים שלמעלה באמצעות Buildpacks
- איך משתמשים בכלי שורת הפקודה של Google Cloud ובממשק המשתמש של מסוף Cloud בדפדפן
מה צריך...
- דפדפן אינטרנט
- חשבון Google
שיעור ה-Lab הזה מיועד למפתחים בכל הרמות, כולל מתחילים. למרות שתשתמשו ב-Python, לא צריך להכיר את התכנות ב-Python כדי להבין מה קורה, כי נסביר את כל הקוד שבו תשתמשו.
2. טיפים להגדרה

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



חשוב לזכור את מזהה הפרויקט, שהוא שם ייחודי בכל הפרויקטים ב-Google Cloud (השם שלמעלה כבר תפוס ולא יתאים לכם, מצטערים!). בהמשך ה-codelab הזה נתייחס אליו כאל PROJECT_ID.
- לאחר מכן, תצטרכו להפעיל את החיוב ב-Cloud Console כדי להשתמש במשאבים של Google Cloud.
העלות של התרגול הזה לא אמורה להיות גבוהה, ואולי אפילו לא תצטרכו לשלם בכלל. חשוב לפעול לפי ההוראות בקטע 'ניקוי' כדי להשבית את המשאבים, וכך לא תחויבו אחרי שתסיימו את המדריך הזה. משתמשים חדשים ב-Google Cloud זכאים לתוכנית תקופת ניסיון בחינם בשווי 300$.
הפעלת Cloud Shell
בשיעור ה-Lab הזה תעבדו בסשן של Cloud Shell, שהוא מתורגמן פקודות שמתארח במכונה וירטואלית שפועלת בענן של Google. אפשר להריץ את הקטע הזה בקלות במחשב שלכם, אבל השימוש ב-Cloud Shell מאפשר לכולם גישה לחוויה שניתנת לשחזור בסביבה עקבית. אחרי הסדנה, אתם מוזמנים לנסות שוב את החלק הזה במחשב שלכם.

הפעלת Cloud Shell
- ב-Cloud Console, לוחצים על Activate Cloud Shell
.

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

הקצאת המשאבים והחיבור ל-Cloud Shell נמשכים רק כמה רגעים.

המכונה הווירטואלית הזו כוללת את כל הכלים שדרושים למפתחים. יש בה ספריית בית בנפח מתמיד של 5GB והיא פועלת ב-Google Cloud, מה שמשפר מאוד את הביצועים והאימות ברשת. אפשר לבצע את רוב העבודה ב-codelab הזה, אם לא את כולה, באמצעות דפדפן או Chromebook.
אחרי שמתחברים ל-Cloud Shell, אמור להופיע אימות שכבר בוצע ושהפרויקט כבר הוגדר לפי מזהה הפרויקט.
- מריצים את הפקודה הבאה ב-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`
- מריצים את הפקודה הבאה ב-Cloud Shell כדי לוודא שפקודת gcloud מכירה את הפרויקט:
gcloud config list project
פלט הפקודה
[core] project = <PROJECT_ID>
אם לא, אפשר להגדיר אותו באמצעות הפקודה הבאה:
gcloud config set project <PROJECT_ID>
פלט הפקודה
Updated property [core/project].
מגדירים כמה משתני סביבה במסוף כדי להקל על השלבים הבאים:
export PROJ=$GOOGLE_CLOUD_PROJECT export APP=hello export PORT=8080 export REGION="us-central1" export TAG="gcr.io/$PROJ/$APP"
הפעלת ממשקי ה-API
בשלבים הבאים תראו איפה השירותים האלה נדרשים (ולמה), אבל בינתיים, מריצים את הפקודה הזו כדי לתת לפרויקט גישה לשירותים Cloud Build, Container Registry ו-Cloud Run:
gcloud services enable cloudbuild.googleapis.com \
containerregistry.googleapis.com \
run.googleapis.com
אמורה להופיע הודעה על הצלחה, כמו זו:
Operation "operations/acf.cc11852d-40af-47ad-9d59-477a12847c9e" finished successfully.
3. פיתוח אפליקציית אינטרנט פשוטה

כדי להתחיל, לוחצים על הלחצן Open Editor בחלק העליון של חלונית Cloud Shell. כך הוא נראה:

אחרי שתעשו את זה, תועברו לסביבת IDE שדומה ל-Visual Studio Code, שבה תוכלו ליצור פרויקטים, לערוך קוד מקור, להריץ את התוכניות וכו'. אם המסך צפוף מדי, תוכלו להרחיב או לצמצם את קו החלוקה בין המסוף לבין חלון העריכה או חלון הטרמינל. כדי לעשות את זה, צריך לגרור את הקו האופקי שבין שני האזורים האלה, שמודגש כאן:

אפשר לעבור בין העורך לבין הטרמינל בלחיצה על הלחצנים Open Editor ו-Open Terminal, בהתאמה. עכשיו נסו לעבור הלוך ושוב בין שני הסביבות האלה.
לאחר מכן, יוצרים תיקייה לאחסון העבודה במעבדה הזו על ידי בחירה באפשרות File->New Folder (קובץ > תיקייה חדשה), מזינים hello ולוחצים על OK. כל הקבצים שתיצרו בשיעור ה-Lab הזה וכל העבודה שתבצעו ב-Cloud Shell יתבצעו בתיקייה הזו.
עכשיו יוצרים קובץ requirements.txt. הקובץ הזה מציין ל-Python באילו ספריות האפליקציה תלויה. באפליקציית האינטרנט הפשוטה הזו, תשתמשו במודול פופולרי של Python לבניית שרתי אינטרנט שנקרא Flask ובמסגרת של שרת אינטרנט שנקרא gunicorn. בחלון Cloud Editor, לוחצים על התפריט File (קובץ) -> New File (קובץ חדש) כדי ליצור קובץ חדש. כשמופיעה בקשה להזין את השם החדש של הקובץ, מזינים requirements.txt ולוחצים על הלחצן OK. מוודאים שהקובץ החדש מגיע לתיקיית הפרויקט hello.
מזינים את השורות הבאות בקובץ החדש כדי לציין שהאפליקציה תלויה בחבילת Python Flask ובשרת האינטרנט gunicorn.
Flask gunicorn
אין צורך לשמור את הקובץ באופן מפורש כי עורך הענן ישמור את השינויים באופן אוטומטי.
גרסה 1: Hello world!
באמצעות אותה טכניקה, יוצרים קובץ חדש נוסף בשם main.py. זה יהיה קובץ המקור הראשי (והיחיד) של האפליקציה ב-Python. שוב, מוודאים שהקובץ החדש יגיע לתיקיית הפרויקט hello.
מוסיפים את הקוד הבא לקובץ הזה:
from flask import Flask
import os
import random
app = Flask(__name__) # Create a Flask object.
PORT = os.environ.get("PORT") # Get PORT setting from the environment.
# The app.route decorator routes any GET requests sent to the root path
# to this function, which responds with a "Hello world!" HTML document.
@app.route("/", methods=["GET"])
def say_hello():
html = "<h1>Hello world!</h1>"
return html
# This code ensures that your Flask app is started and listens for
# incoming connections on the local interface and port 8080.
if __name__ == "__main__":
app.run(host="0.0.0.0", port=PORT)
חוזרים לטרמינל ועוברים לתיקיית הפרויקט באמצעות הפקודה הבאה:
cd hello
מריצים את הפקודה הבאה כדי להתקין את יחסי התלות של הפרויקט:
pip3 install -r requirements.txt
עכשיו מפעילים את האפליקציה על ידי הרצת הפקודה הבאה בטרמינל:
python3 main.py
בשלב הזה, האפליקציה פועלת במכונה הווירטואלית שמוקדשת לסשן של Cloud Shell. סביבת Cloud Shell כוללת מנגנון proxy שמאפשר לכם לגשת לשרתי אינטרנט (כמו השרת שהפעלתם עכשיו) שפועלים במכונה הווירטואלית מכל מקום באינטרנט.
לוחצים על הלחצן web preview ואז על פריט התפריט Preview on Port 8080, כמו שמוצג כאן:

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

גרסה 2: שיקוף של נתיב כתובת ה-URL
חוזרים אל Cloud Editor (באמצעות הלחצן Open Editor) ומוסיפים תמיכה בהד של סיומת אופציונלית של כתובת URL על ידי עדכון הקובץ main.py באופן הבא:
from flask import Flask
import os
import random
app = Flask(__name__) # Create a Flask object.
PORT = os.environ.get("PORT") # Get PORT setting from environment.
# The app.route decorator routes any GET requests sent to the root path
# to this function, which responds with a "Hello world!" HTML document.
# If something is specified as the URL path (after the '/'), say_hello()
# responds with "Hello X", where X is the string at the end of the URL.
@app.route("/", methods=["GET"])
@app.route("/<name>", methods=["GET"]) # ← NEW
def say_hello(name="world"): # ← MODIFIED
html = f"<h1>Hello {name}!</h1>" # ← MODIFIED
return html
# This code ensures that your Flask app is started and listens for
# incoming connections on the local interface and port 8080.
if __name__ == "__main__":
app.run(host="0.0.0.0", port=PORT)
חוזרים לטרמינל (באמצעות הלחצן Open Terminal) ומזינים control-C (לחיצה ארוכה על מקש Control תוך כדי לחיצה על 'C') כדי לעצור את האפליקציה הפועלת ואז מפעילים אותה מחדש על ידי הזנת:
python3 main.py
שוב, לוחצים על הלחצן web preview ואז על פריט התפריט Preview on Port 8080 כדי לפתוח כרטיסייה בדפדפן אינטרנט עם האפליקציה הפועלת. שוב אמורה להופיע ההודעה Hello world!, אבל עכשיו צריך להחליף את הטקסט של כתובת ה-URL אחרי התו '/' במחרוזת כלשהי (למשל /your-name) ולוודא שמופיע משהו כזה:

גרסה 3: צבעים אקראיים
עכשיו מוסיפים תמיכה בצבעי רקע אקראיים. לשם כך, חוזרים ל-Cloud Editor (באמצעות הלחצן Open Editor) ומעדכנים את הקובץ main.py באופן הבא:
from flask import Flask
import os
import random
app = Flask(__name__) # Create a Flask object.
PORT = os.environ.get("PORT") # Get PORT setting from the environment.
# This function decides whether foreground text should be
# displayed in black or white, to maximize fg/bg contrast.
def set_text_color(rgb): # ← NEW
sum = round( # ← NEW
(int(rgb[0]) * 0.299) # ← NEW
+ (int(rgb[1]) * 0.587) # ← NEW
+ (int(rgb[2]) * 0.114) # ← NEW
) # ← NEW
return "black" if sum > 186 else "white" # ← NEW
# The app.route decorator routes any GET requests sent to the root path
# to this function, which responds with a "Hello world!" HTML document.
# If something is specified as the URL path (after the '/'), say_hello()
# responds with "Hello X", where X is the string at the end of the URL.
# To verify each new invocation of these requests, the HTML document
# includes CSS styling to produce a randomly colored background.
@app.route("/", methods=["GET"])
@app.route("/<name>", methods=["GET"])
def say_hello(name="world"):
bg = random.sample(range(1, 255), 3) # ← NEW
hex = (int(bg[0]) * 256) + (int(bg[1]) * 16) + int(bg[2]) # ← NEW
fg_color = set_text_color(bg) # ← NEW
bg_color = f"#{hex:06x}" # ← NEW
style = f"color:{fg_color}; background-color:{bg_color}" # ← NEW
html = f'<h1 style="{style}">Hello {name}!</h1>' # ← MODIFIED
return html
# This code ensures that your Flask app is started and listens for
# incoming connections on the local interface and port 8080.
if __name__ == "__main__":
app.run(host="0.0.0.0", port=PORT)
חוזרים לטרמינל (באמצעות הלחצן Open Terminal) ומזינים control-C (לחיצה ארוכה על מקש Control תוך כדי לחיצה על 'C') כדי לעצור את האפליקציה הפועלת ואז מפעילים אותה מחדש על ידי הזנת:
python3 main.py
שוב, לוחצים על הלחצן web preview ואז על פריט התפריט Preview on Port 8080 כדי לפתוח כרטיסייה בדפדפן אינטרנט עם האפליקציה הפועלת. אמור להופיע הטקסט שנוצר, עם הסיומת שצוינה או עם מחרוזת ברירת המחדל 'Hello world!', שמוצגת על רקע בצבע אקראי, כמו בדוגמה הבאה:

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

מה זה מאגר תגים?
קונטיינרים באופן כללי, ו-Docker בפרט, מאפשרים לנו ליצור תיבה מודולרית שבה אפשר להריץ אפליקציה עם כל יחסי התלות שלה. התוצאה נקראת קובץ אימג' של קונטיינר. בקטע הזה תיצרו קובץ אימג' של קונטיינר, שבו תשתמשו כדי לארוז את האפליקציה ואת כל התלות שלה.
בשלב הקודם, כשמריצים את האפליקציה בסביבת פיתוח, צריך להריץ את הפקודה pip3 install -r requirements.txt ולוודא שקובץ ה-requirements.txt מכיל את כל הספריות התלויות והגרסאות התואמות שלהן. כשמשתמשים בקונטיינרים, מתקינים את הדרישות האלה כשיוצרים את קובץ האימג' של הקונטיינר, כך שהמשתמש בקונטיינר לא צריך לדאוג להתקנה של שום דבר.
קובץ אימג' של קונטיינר זה יהווה את אבן הבניין הבסיסית לפריסת האפליקציה ב-Cloud Run. אפשר להשתמש בקונטיינרים כמעט בכל שרת וירטואלי או פיזי, ולכן הם מאפשרים לנו לפרוס את האפליקציה שלכם בכל מקום שתרצו, ולהעביר את האפליקציה מספק שירותים אחד לאחר, או משרת מקומי לענן.
קונטיינרים עוזרים להפוך את האפליקציות שלכם ל:
- ניתן לשחזר אותם – הקונטיינרים עצמאיים ושלמים
- ניידות – קונטיינרים הם אבני בניין חוצות-תעשייה, שמאפשרות ניידות של אפליקציות בין ספקי ענן וסביבות שונות
בקיצור, קונטיינרים מאפשרים סוף סוף "לכתוב פעם אחת ולהריץ בכל מקום". יוצא מן הכלל אחד הוא שהמאגר שנוצר מוגבל להרצה בסוג המעבד שבו הוא נוצר, אבל יש דרכים ליצור גרסאות של מאגרים גם עבור תצורות חומרה אחרות.
מספיק דיבורים – בואו ניצור מאגר תגים! תשתמשו בטכנולוגיה ספציפית ליצירת קונטיינר שנקראת Docker.
ב-Cloud Editor, יוצרים קובץ חדש בשם Dockerfile. הקובץ הזה הוא תוכנית ליצירת התמונה. הוא כולל מידע על סביבת ההפעלה וקוד המקור, על אופן ההתקנה של התלויות, על בניית האפליקציה ועל הרצת הקוד.
# Use an official lightweight Python image.
FROM python:3.9-slim
# Copy local code to the container image.
WORKDIR /app
COPY main.py .
COPY requirements.txt .
# Install dependencies into this container so there's no need to
# install anything at container run time.
RUN pip install -r requirements.txt
# Service must listen to $PORT environment variable.
# This default value facilitates local development.
ENV PORT 8080
# Run the web service on container startup. Here you use the gunicorn
# server, with one worker process and 8 threads. For environments
# with multiple CPU cores, increase the number of workers to match
# the number of cores available.
CMD exec gunicorn --bind 0.0.0.0:$PORT --workers 1 --threads 8 --timeout 0 main:app
ב-Cloud Terminal, יוצרים את קובץ האימג' של הקונטיינר באמצעות Cloud Build, על ידי הפעלת הפקודה הבאה:
gcloud builds submit --tag $TAG
אחרי שהתמונה נדחפת למאגר, מוצגת SUCCESS הודעה עם שם התמונה, שצריכה להיראות בערך כך: gcr.io/<project-id>/hello. התמונה מאוחסנת עכשיו ב-Google Container Registry ואפשר להשתמש בה שוב מתי ואיפה שרוצים.
כדי להציג רשימה של כל קובצי האימג' בקונטיינר שמשויכים לפרויקט הנוכחי, משתמשים בפקודה הבאה:
gcloud container images list
עכשיו מריצים ובודקים את האפליקציה באופן מקומי מ-Cloud Shell באמצעות הפקודות docker:
docker run -p $PORT:$PORT -e PORT=$PORT $TAG
האפשרות -p $PORT:$PORT אומרת ל-Docker למפות את היציאה החיצונית $PORT (שמוגדרת ל-8080 למעלה) בסביבת המארח לאותו מספר יציאה בתוך הקונטיינר הפועל. זה מקל על החיים כי קוד השרת שאתם כותבים ומספר היציאה החיצוני שאליו אתם מתחברים כשאתם בודקים את האפליקציה יהיו זהים (8080), אבל אתם יכולים גם להשתמש באפשרות -p כדי למפות כל יציאה חיצונית שרירותית במארח לכל יציאה פנימית רצויה בתוך הקונטיינר.
האפשרות -e PORT=$PORT אומרת ל-Docker להפוך את משתנה הסביבה $PORT (שמוגדר ל-8080 למעלה) לזמין לאפליקציה שפועלת בתוך הקונטיינר.
עכשיו אתם מוכנים לבדוק את האפליקציה על ידי הפניית דפדפן אינטרנט לקוד Python שפועל בתוך הקונטיינר. בחלון Cloud Shell, לוחצים על סמל התצוגה המקדימה של האינטרנט ובוחרים באפשרות 'תצוגה מקדימה ביציאה 8080', כמו בשלב הקודם.
התוצאה אמורה להיראות מוכרת – הטקסט שנוצר אמור להופיע על רקע בצבע אקראי, בדיוק כמו כשמריצים את האפליקציה ישירות במסוף Cloud Shell. טוענים מחדש את הדף כמה פעמים כדי לראות שצבע הרקע האקראי משתנה בכל פעם שנכנסים לאפליקציה.
מעולה! עכשיו הפעלתם גרסה של האפליקציה שלכם בתוך קונטיינר. בקטע הבא, תלמדו איך להפוך את קובץ האימג' של הקונטיינר לאפליקציית אינטרנט באיכות ייצור בלי לגעת בשורת קוד אחת.
5. לענן...

עכשיו, אחרי שיצרתם קונטיינר לאפליקציה, כדאי לשתף את היצירה המדהימה הזו עם שאר העולם, ולכן הגיע הזמן לפרוס אותה בענן. אבל אתם רוצים לעשות איתו יותר מאשר רק לשתף אותו. אתם רוצים לוודא שהיא:
- פועל בצורה מהימנה – אתם מקבלים סבילות אוטומטית לתקלות במקרה של קריסת מחשב שבו האפליקציה פועלת
- התאמה אוטומטית של קנה המידה – האפליקציה תעמוד בקצב של רמות תנועה גבוהות, ותצמצם אוטומטית את טביעת הרגל שלה כשהיא לא בשימוש
- מצמצם את העלויות, כי לא מחייבים אתכם על משאבים שאתם לא משתמשים בהם – אתם מחויבים רק על משאבים שנצרכים בזמן התגובה לתנועה
- אפשר לגשת אליו דרך שם דומיין מותאם אישית – יש לכם גישה לפתרון בלחיצה אחת להקצאת שם דומיין מותאם אישית לשירות
- זמן התגובה מצוין – התגובה במצב התחלתי (cold start) סבירה, אבל אפשר לשפר אותה על ידי הגדרת מופע מינימלי
- תומך בהצפנה מקצה לקצה באמצעות אבטחת אינטרנט רגילה של SSL/TLS – כשפורסים שירות, מקבלים הצפנה רגילה של האינטרנט ואת האישורים הנדרשים המתאימים, בחינם ובאופן אוטומטי
אם פורסים את האפליקציה ב-Google Cloud Run, מקבלים את כל היתרונות שצוינו למעלה ועוד.
פריסת האפליקציה ב-Cloud Run
קודם כל, נשנה את האפליקציה כדי שתוכלו להבחין בין הגרסה החדשה לישנה. כדי לעשות את זה, משנים את הקובץ main.py כך שההודעה שמוצגת כברירת מחדל תשתנה מ-Hello world! ל-Hello from Cloud Run!. במילים אחרות, צריך לשנות את השורה הזו בקובץ main.py מהערך הזה:
def say_hello(name="world"):
לזה:
def say_hello(name="from Cloud Run"):
Cloud Run הוא שירות אזורי, כלומר התשתית שמריצה את שירותי Cloud Run ממוקמת באזור ספציפי ומנוהלת על ידי Google כך שתהיה זמינה באופן יתיר בכל האזורים בתוך אותו אזור. בקטע 'הגדרת החשבון' שלמעלה, הגדרתם אזור ברירת מחדל באמצעות משתנה הסביבה REGION.
כדי לבנות מחדש את קובץ האימג' של הקונטיינר ולפרוס את האפליקציה בקונטיינר ב-Cloud Run, מריצים את הפקודה הבאה:
gcloud builds submit --tag $TAG gcloud run deploy "$APP" \ --image "$TAG" \ --platform "managed" \ --region "$REGION" \ --allow-unauthenticated
- אפשר גם להגדיר אזור ברירת מחדל באמצעות
gcloud config set run/region $REGION. - האפשרות
--allow-unauthenticatedהופכת את השירות לזמין לכולם. כדי למנוע בקשות לא מאומתות, צריך להשתמש במדיניות--no-allow-unauthenticatedבמקום זאת.
התמונה שצוינה כאן היא תמונת ה-Docker שבניתם בשלב האחרון. הודות לשירות Cloud Build, ששמר את האימג' שנוצר ב-Google Container Registry, שירות Cloud Run יכול למצוא אותו ולפרוס אותו בשבילכם.
מחכים כמה רגעים עד שהפריסה תושלם. אם הפעולה בוצעה ללא שגיאות, כתובת ה-URL של השירות מוצגת בשורת הפקודה:
Deploying container to Cloud Run service [hello] in project [PROJECT_ID... ✓ Deploying new service... Done. ✓ Creating Revision... Revision deployment finished. Waiting for health check... ✓ Routing traffic... ✓ Setting IAM Policy... Done. Service [hello] revision [hello-...] has been deployed and is serving 100 percent of traffic. Service URL: https://hello-....a.run.app
אפשר גם לאחזר את כתובת ה-URL של השירות באמצעות הפקודה הבאה:
gcloud run services describe hello \ --platform managed \ --region $REGION \ --format "value(status.url)"
אמור להופיע פלט שדומה לזה:
https://hello-....a.run.app
הקישור הזה הוא כתובת URL ייעודית עם אבטחת TLS לשירות Cloud Run שלכם. הקישור הזה הוא קבוע (כל עוד לא משביתים את השירות) ואפשר להשתמש בו בכל מקום באינטרנט. הוא לא משתמש במנגנון ה-proxy של Cloud Shell שצוין קודם, שהיה תלוי במכונה וירטואלית זמנית.
לוחצים על Service URL המודגש כדי לפתוח כרטיסייה בדפדפן אינטרנט עם האפליקציה שפועלת. התוצאה אמורה להציג את ההודעה "Hello from Cloud Run!" על רקע בצבע אקראי.
מעולה! האפליקציה שלך פועלת עכשיו ב-Google Cloud. האפליקציה שלכם זמינה לציבור, עם הצפנת TLS (HTTPS) והתאמה אוטומטית לעומס לרמות תנועה מדהימות, בלי שתצטרכו לחשוב על זה.
אבל לדעתי אפשר לפשט את התהליך הזה עוד יותר...
6. יצירת מאגר תגים באופן אוטומטי
כל זה נשמע נהדר, אבל מה אם אני לא רוצה לחשוב על קובצי Dockerfile ועל קונטיינרים? מה קורה אם, כמו רוב המפתחים, אני רוצה להתמקד רק בכתיבת קוד האפליקציה שלי ולא רוצה לדאוג להעברת האפליקציה לקונטיינר? אז יש לך מזל כי Cloud Run תומך בתקן קוד פתוח שנקרא Buildpacks, שקיים בדיוק בשביל זה: כדי לאוטומט את תהליך הייצור של קונטיינר מאוסף של קובצי מקור.
שימו לב: יש מקרים שבהם מפתחים מעדיפים להשתמש בקובץ Dockerfile מפורש, למשל אם הם רוצים רמת התאמה אישית גבוהה באופן שבו נוצר הקונטיינר שלהם. אבל במקרים נפוצים כמו התרגיל הזה, חבילות buildpack פועלות בצורה טובה ומונעות את הצורך ליצור Dockerfile באופן ידני. נשנה את הקוד כדי להשתמש ב-Buildpacks.
קודם כל, נשנה את האפליקציה כדי שתוכלו להבחין בין הגרסה החדשה לישנה. כדי לעשות את זה, משנים את הקובץ main.py כך שההודעה שמוצגת כברירת מחדל תשתנה מ-Hello from Cloud Run! ל-Hello from Cloud Run with Buildpacks!. במילים אחרות, צריך לשנות את השורה הזו בקובץ main.py מהערך הזה:
def say_hello(name="from Cloud Run"):
לזה:
def say_hello(name="from Cloud Run with Buildpacks"):
עכשיו ניצור קובץ חדש בשם Procfile כדי להשתמש ב-buildpacks. יוצרים את הקובץ ב-Cloud Editor ומזינים בו את שורת הטקסט הזו:
web: python3 main.py
הפקודה הזו אומרת למערכת buildpack איך להריץ את האפליקציה בקונטיינר שנוצר אוטומטית. עם ההוראה הזו, כבר לא צריך Dockerfile. כדי לוודא זאת, מוחקים את קובץ Docker ומריצים את הפקודה הבאה במסוף Cloud Shell:
gcloud beta run deploy "$APP" \
--source . \
--platform "managed" \
--region "$REGION" \
--allow-unauthenticated
הפקודה הזו דומה לפקודה שהרצתם כדי לפרוס את האפליקציה בשלב הקודם, אבל הפעם החלפתם את האפשרות --image באפשרות --source .. הפקודה הזו אומרת לפקודה gcloud שרוצים שהיא תשתמש ב-Buildpack כדי ליצור את קובץ אימג' של קונטיינר, על סמך קובצי המקור שהיא מוצאת בספרייה הנוכחית (הסימן dot ב---source . הוא קיצור של הספרייה הנוכחית). מכיוון שהשירות מטפל בקובץ האימג' בקונטיינר באופן מרומז, לא צריך לציין קובץ אימג' בפקודה gcloud הזו.
שוב, כדי לוודא שהפריסה הזו עבדה, לוחצים על Service URL המודגש כדי לפתוח כרטיסייה בדפדפן אינטרנט עם האפליקציה הפועלת, ומוודאים שהשירות מציג את ההודעה Hello from Cloud Run with Buildpacks! על רקע בצבע אקראי.
שימו לב שבאמצעות חבילות buildpack ליצירת Dockerfile, צמצמתם את שלושת השלבים הפשוטים לשני שלבים:
- יוצרים אפליקציה בסביבת הפיתוח.
- פריסת בדיוק אותו קוד בענן באמצעות פקודה אחת.
7. האם חייבים להשתמש בשורת הפקודה?
לא! כמו כמעט כל שירות ב-Google Cloud, יש שלוש דרכים ליצור אינטראקציה עם Cloud Run:
- כלי שורת הפקודה gcloud, שראיתם הרגע.
- ממשק משתמש עשיר בדפדפן, דרך Cloud Console, שתומך בסגנון אינטראקציה אינטואיטיבי של הצבעה ולחיצה.
- באופן פרוגרמטי, באמצעות ספריות לקוח של Google שזמינות בשפות פופולריות רבות, כולל Java, C#, Python, Go, Javascript, Ruby, C/C++ ועוד.
נפרוס מופע נוסף של אפליקציית Cloud Run באמצעות ממשק המשתמש של המסוף. עוברים לדף הנחיתה של Cloud Run Service דרך התפריט בפינה הימנית העליונה:

אחרי כן יוצג סיכום של שירותי Cloud Run, כמו בדוגמה הבאה:

כדי להתחיל בתהליך הפריסה, לוחצים על הקישור 'יצירת שירות':

מזינים hello-again כשם השירות, בוחרים בפלטפורמת הפריסה ובאזור שמוגדרים כברירת מחדל ולוחצים על Next (הבא).

מזינים את כתובת ה-URL הזו לקובץ אימג' של קונטיינר: gcr.io/cloudrun/hello, שהוא קונטיינר שנוצר על ידי Google למטרות בדיקה, ולוחצים על התפריט הנפתח 'הגדרות מתקדמות' כדי לראות חלק מההגדרות הרבות שזמינות לכם. הנה כמה דוגמאות לאפשרויות ההתאמה האישית:
- מספר היציאה ונקודת הכניסה לקונטיינר (שיחליפו את נקודת הכניסה שצוינה כשבונים את הקונטיינר)
- חומרה: זיכרון ומספר המעבדים (CPU)
- קנה מידה: מספר המופעים המינימלי והמקסימלי
- משתני סביבה
- אחרים: הגדרת זמן קצוב לתפוגה לבקשה, מספר מקסימלי של בקשות לכל מאגר, HTTP/2
כדי להמשיך בשיחה, לוחצים על הלחצן 'הבא'. בתיבת הדו-שיח הבאה אפשר לציין איך השירות מופעל. בקטע Ingress (תנועה נכנסת), בוחרים באפשרות allow all traffic (אישור של כל התנועה), ובקטע Authentication (אימות), בוחרים באפשרות Allow unauthenticated traffic (אישור של תנועה לא מאומתת).

אלה ההגדרות הכי ליברליות, כי הן מאפשרות לכל אחד לגשת לאפליקציית Cloud Run שלכם מכל מקום באינטרנט הציבורי, בלי לציין פרטי כניסה לאימות. יכול להיות שתרצו להגדיר הגדרות מגבילות יותר לאפליקציה, אבל כדי לפשט את התרגיל הזה, נשתמש בהגדרות האלה.
עכשיו לוחצים על הלחצן Create כדי ליצור את שירות Cloud Run. אחרי כמה שניות, השירות החדש אמור להופיע ברשימת הסיכום של שירותי Cloud Run. בשורה של הסיכום מופיעה הפריסה האחרונה (תאריך/שעה ומי ביצע אותה) יחד עם כמה הגדרות תצורה חשובות. כדי לראות פרטים נוספים על השירות החדש, לוחצים על הקישור של שם השירות.
כדי לאמת את השירות, לוחצים על כתובת ה-URL שמוצגת בחלק העליון של דף הסיכום, כפי שמודגש בדוגמה שלמטה:

אתם אמורים לראות משהו כזה:

אחרי שפורסים שירות חדש של Cloud Run, בוחרים בכרטיסייה REVISIONS כדי לראות כמה דרכים לניהול של כמה פריסות.

כדי לפרוס גרסאות חדשות ישירות מהמסוף, אפשר ללחוץ על הלחצן EDIT & DEPLOY NEW REVISION, כמו שמודגש בצילום המסך לדוגמה שבהמשך:

לוחצים על הלחצן הזה כדי ליצור גרסה חדשה. ליד כתובת ה-URL של מאגר התגים, לוחצים על הלחצן SELECT, כמו שמוצג למטה:

בתיבת הדו-שיח שמופיעה, מחפשים את אפליקציית האינטרנט הפשוטה שפרסתם מ-Cloud Build באמצעות Buildpacks קודם, ואז לוחצים על 'בחירה'. חשוב לבחור את קובץ אימג' של קונטיינר בקטע
gcr.io/<project>/cloud-run-source-deploy
תיקייה , כך:

אחרי שבוחרים את האפשרות הרצויה, גוללים לחלק התחתון של המסך ולוחצים על הלחצן DEPLOY. הפריסה של הגרסה החדשה של האפליקציה הושלמה. כדי לוודא זאת, נכנסים שוב לכתובת ה-URL של השירות ומוודאים שמוצגת אפליקציית האינטרנט הצבעונית 'Hello from Cloud Run with Buildpacks!'.
כפי שאפשר לראות, בכרטיסייה 'עדכונים' מוצג סיכום של כל עדכון שפרסתם, ועכשיו אמורים להופיע שני עדכונים לשירות הזה. כדי לבחור גרסה מסוימת, לוחצים על לחצן האפשרויות שמימין לשם הגרסה. סיכום של פרטי הגרסה יוצג בצד שמאל של המסך. אם תלחצו על הלחצנים האלה, תוכלו לראות ששתי הגרסאות שלכם נגזרות משתי תמונות שונות של מאגר תגים.
הלחצן MANAGE TRAFFIC מאפשר לשנות את אופן ההפצה של בקשות נכנסות שנשלחות לגרסה מסוימת. היכולת הזו לכוונן את כמות התנועה שנשלחת לגרסה מסוימת מאפשרת כמה תרחישי שימוש חשובים:
- בדיקת קנרי של גרסה חדשה של האפליקציה עם חלק קטן מתנועת הגולשים הנכנסת
- להחזיר את התנועה מגרסה בעייתית לגרסה קודמת
- A/B Testing
כך מוצאים את הלחצן MANAGE TRAFFIC:

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

עכשיו לוחצים על הלחצן SAVE (שמירה) ומאמתים את החלוקה של 50/50. כדי לעשות זאת, נכנסים שוב ושוב לכתובת ה-URL של השירות ובודקים שבממוצע, חצי מהבקשות מוגשות על ידי הגרסה הנוכחית ("Hello from Cloud Run with Buildpacks!") וחצי מהבקשות מוגשות על ידי הגרסה הקודמת ("It's running!").
בכרטיסיות אחרות בדף 'פרטי השירות' אפשר לעקוב אחרי הביצועים, התנועה והיומנים, שמספקים תובנות חשובות לגבי מידת המאמץ שמושקעת בשירות ומידת ההצלחה שלו. בכרטיסייה 'הרשאות' אפשר גם לכוונן את הגישה לשירות. כדאי להקדיש כמה רגעים כדי לבדוק את הכרטיסיות בדף הזה ולהבין אילו יכולות זמינות כאן.
ממשק פרוגרמטי
כמו שצוין קודם, יש לכם גם אפשרות ליצור, לפרוס ולנהל את שירותי Cloud Run באופן פרוגרמטי. למשימות ידניות, האפשרות הזו מתקדמת יותר משורת הפקודה או ממסוף האינטרנט, אבל היא בהחלט הדרך המומלצת לאוטומציה של שירותי Cloud Run. יש לכם אפשרות להשתמש בספריות לקוח של Google בכמה שפות תכנות פופולריות.
8. בדיקת האפליקציה
בשלב האחרון, תריצו בדיקת עומס מלאכותית כדי לבדוק את האפליקציה ולראות איך היא מתרחבת בהתאם לביקוש הנכנס. תשתמשו בכלי שנקרא hey, שמותקן מראש ב-Cloud Shell ומאפשר להריץ בדיקות עומס ולהציג את התוצאות.
הרצת הבדיקה
בטרמינל של Cloud Shell, מריצים את הפקודה הבאה כדי להריץ בדיקת עומס:
hey -q 1000 -c 200 -z 30s https://hello-...run.app
הארגומנטים של הפקודה מתפרשים באופן הבא:
-
-q 1000– מנסים להגדיל את העומס לכ-1,000 בקשות לשנייה -
-c 200- הקצאת 200 עובדים מקבילים -
-z 30s– הפעלת בדיקת העומס למשך 30 שניות - חשוב להשתמש בכתובת ה-URL של השירות כארגומנט האחרון בשורת הפקודה הזו
תוצאות הבדיקה אמורות להיראות בערך כך:
Summary:
Total: 30.2767 secs
Slowest: 3.3633 secs
Fastest: 0.1071 secs
Average: 0.1828 secs
Requests/sec: 1087.2387
Total data: 3028456 bytes
Size/request: 92 bytes
Response time histogram:
0.107 [1] |
0.433 [31346] |■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
0.758 [1472] |■■
1.084 [82] |
1.410 [4] |
...
Latency distribution:
...
50% in 0.1528 secs
75% in 0.1949 secs
90% in 0.2442 secs
95% in 0.4052 secs
99% in 0.7062 secs
Details (average, fastest, slowest):
...
req write: 0.0000 secs, 0.0000 secs, 0.0232 secs
resp wait: 0.1824 secs, 0.1070 secs, 3.2953 secs
resp read: 0.0000 secs, 0.0000 secs, 0.0010 secs
Status code distribution:
[200] 32918 responses
מהסיכום הזה אפשר ללמוד כמה דברים מעניינים:
- נשלחו 32,918 בקשות בקצב של בערך 1,000 לשנייה למשך 30 שניות.
- לא היו שגיאות (רק תגובות HTTP 200).
- זמן האחזור הממוצע היה 180 אלפיות השנייה.
- זמן האחזור המינימלי היה 107 אלפיות השנייה, ובמקרה הגרוע ביותר הוא היה 3.3 שניות
- זמן האחזור באחוזון ה-90 היה 244 אלפיות השנייה.
אם בודקים את הכרטיסייה METRICS במסוף Cloud Run, אפשר לראות את הצד של השרת בסיפור הביצועים:

9. ניקוי
ב-Cloud Run לא מחייבים כשלא משתמשים בשירות, אבל יכול להיות שתחויבו על אחסון של קובץ אימג' של קונטיינר.
כדי להימנע מחיובים, אפשר למחוק את הפרויקט ב-GCP. פעולה כזו תפסיק את החיוב על כל המשאבים שנעשה בהם שימוש בפרויקט. אפשרות נוספת היא למחוק את קובץ האימג' של הקונטיינר באמצעות הפקודה הבאה:
gcloud container images delete $TAG
כדי למחוק את שירותי Cloud Run, משתמשים בפקודות הבאות:
gcloud run services delete hello --platform managed --region $REGION --quiet gcloud run services delete hello-again --platform managed --region $REGION --quiet
10. כל הכבוד!

כל הכבוד – יצרתם ופרסתם בהצלחה אפליקציית Cloud Run לייצור. במהלך התהליך למדתם על קונטיינרים ואיך ליצור קונטיינר משלכם. ראיתם כמה קל לפרוס את האפליקציה באמצעות Cloud Run, גם באמצעות כלי שורת הפקודה gcloud וגם באמצעות Cloud Console. עכשיו אתם יודעים איך לשתף את היצירות המדהימות שלכם עם כל העולם!
אני רוצה להשאיר אותך עם שאלה חשובה אחת:
אחרי שהאפליקציה התחילה לפעול בסביבת הפיתוח, כמה שורות קוד היית צריך לשנות כדי לפרוס אותה בענן, עם כל המאפיינים ברמת הייצור שמוצעים על ידי Cloud Run?
התשובה היא אפס. :)
כדאי לעיין ב-Codelabs הבאים…
- איך בונים בוט ל-Slack באמצעות Node.js ב-Cloud Run
- הפעלת Cloud Run באמצעות אירועים מ-Eventarc
- Hello Cloud Run for Anthos Codelab
- פריסה והפעלה של קונטיינר באמצעות Cloud Run ב-Node.js
- Codelabs נוספים בנושא Cloud Run
תכונות מגניבות נוספות שכדאי לנסות...
- פריסה רציפה מ-Git באמצעות Cloud Build
- שימוש בסודות מ-Secret Manager
- היכרות עם WebSockets, HTTP/2 וזרמים דו-כיווניים של gRPC ל-Cloud Run
- Cloud Run min instances: Minimize your serverless cold starts
- הצגת מודעות לתנועה מכמה אזורים
מסמכי עזר...
11. קריאה לפעולה
אם נהניתם מה-codelab הזה ואתם מתכוונים להשקיע עוד זמן בהתנסות מעשית עם Google Cloud, כדאי לכם להצטרף ל-Google Cloud Innovators עוד היום!

התוכנית Google Cloud Innovators היא בחינם וכוללת:
- דיונים בשידור חי, מפגשי שאלות ותשובות ומפגשי תוכנית פעולה כדי ללמוד ישירות מהעובדים של Google
- החדשות האחרונות מ-Google Cloud ישירות לתיבת הדואר הנכנס
- תג דיגיטלי ורקע לשיחות ועידה בווידאו
- 500 קרדיטים לשיעורי Lab ולמידה ב-Skills Boost
לחצו כאן כדי להירשם!
