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
אין צורך לשמור את הקובץ באופן מפורש כי Cloud Editor שומר את השינויים באופן אוטומטי.
גרסה 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.
מבצעים מחדש את ה-build של קובץ האימג' של הקונטיינר ופורסים את האפליקציה בקונטיינר ב-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. יצירה אוטומטית של מאגר התגים
כל זה נשמע נהדר, אבל מה אם אני לא רוצה לחשוב על קובצי Docker ועל קונטיינרים? מה קורה אם, כמו רוב המפתחים, אני רוצה להתמקד רק בכתיבת קוד האפליקציה שלי ולאפשר למישהו אחר לדאוג להעברה שלה לקונטיינר. אז יש לך מזל, כי 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
ההגדרה הזו אומרת למערכת buildback איך להריץ את האפליקציה בקונטיינר שנוצר אוטומטית. עם ההוראות האלה, כבר לא צריך Dockerfile. כדי לוודא זאת, מוחקים את קובץ ה-Dockerfile ומריצים את הפקודה הבאה בטרמינל של Cloud Shell:
gcloud beta run deploy "$APP" \
--source . \
--platform "managed" \
--region "$REGION" \
--allow-unauthenticated
הפקודה הזו דומה לפקודה שהרצתם כדי לפרוס את האפליקציה בשלב הקודם, אבל הפעם החלפתם את האפשרות --image באפשרות --source .. הפקודה gcloud מציינת שרוצים להשתמש ב-Buildpacks כדי ליצור את קובץ אימג' של קונטיינר, על סמך קובצי המקור שנמצאים בספרייה הנוכחית (הסימן dot ב---source . הוא קיצור של הספרייה הנוכחית). מכיוון שהשירות מטפל בקובץ אימג' של קונטיינר באופן מרומז, לא צריך לציין קובץ אימג' של קונטיינר בפקודה gcloud הזו.
שוב, כדי לוודא שהפריסה הזו עבדה, לוחצים על Service URL המודגש כדי לפתוח כרטיסייה בדפדפן אינטרנט עם האפליקציה שפועלת, ומוודאים שהשירות מציג את ההודעה Hello from Cloud Run with Buildpacks! (שלום מ-Cloud Run עם 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
כדי להירשם, צריך ללחוץ כאן.
