מידע על Codelab זה
1. מבוא
אפשר להשתמש ב-Workflows כדי ליצור תהליכי עבודה ללא שרת שמקשרים בין סדרה של משימות ללא שרת בסדר שאתם מגדירים. אתם יכולים לשלב את העוצמה של ממשקי ה-API של Google Cloud, מוצרים ללא שרת כמו Cloud Functions ו-Cloud Run וקריאות לממשקי API חיצוניים כדי ליצור אפליקציות גמישות ללא שרת.
תהליכי עבודה לא דורשים ניהול תשתית, והם מותאמים בצורה חלקה לפי הביקוש, כולל התאמה לירידה בביקוש עד לאפס. מודל התמחור של תשלום לפי שימוש מאפשר לכם לשלם רק על זמן הביצוע.
ב-codelab הזה תלמדו איך לחבר שירותים שונים של Google Cloud וממשקי API חיצוניים מסוג HTTP לתהליכי עבודה. באופן ספציפי יותר, תקשרו בין שני שירותי Cloud Functions ציבוריים, שירות Cloud Run פרטי אחד וממשק API חיצוני וציבורי מסוג HTTP לתהליך עבודה.
מה תלמדו
- העקרונות הבסיסיים של תהליכי עבודה.
- איך מחברים פונקציות ציבוריות של Cloud Functions לתהליכי עבודה.
- איך לקשר שירותים פרטיים של Cloud Run ל-Workflows.
- איך מחברים ממשקי HTTP API חיצוניים לתהליכי עבודה.
2. הגדרה ודרישות
הגדרת סביבה בקצב אישי
- נכנסים למסוף Cloud ויוצרים פרויקט חדש או משתמשים מחדש בפרויקט קיים. (אם עדיין אין לכם חשבון Gmail או G Suite, עליכם ליצור חשבון).
חשוב לזכור את מזהה הפרויקט, שהוא שם ייחודי לכל הפרויקטים ב-Google Cloud (השם שלמעלה כבר נלקח ולא יתאים לכם, סליחה!). בהמשך נתייחס אליו כ-PROJECT_ID
.
- בשלב הבא, תצטרכו להפעיל את החיוב במסוף Cloud כדי להשתמש במשאבים של Google Cloud.
השלמת הקודלאב הזה לא אמורה לעלות הרבה, אם בכלל. חשוב לפעול לפי ההוראות בקטע 'ניקוי', שבו מוסבר איך להשבית את המשאבים כדי שלא תחויבו אחרי סיום המדריך. משתמשים חדשים ב-Google Cloud זכאים להשתתף בתוכנית תקופת ניסיון בחינם בסך 300$.
הפעלת Cloud Shell
אפשר להפעיל את Google Cloud מרחוק מהמחשב הנייד, אבל בסדנת הקוד הזו נשתמש ב-Google Cloud Shell, סביבת שורת פקודה שפועלת ב-Cloud.
במסוף GCP, לוחצים על סמל Cloud Shell בסרגל הכלים שבפינה הימנית העליונה:
ההקצאה והחיבור לסביבת העבודה אמורים להימשך רק כמה רגעים. בסיום, אמור להופיע משהו כזה:
המכונה הווירטואלית הזו כוללת את כל הכלים הדרושים למפתחים. יש בה ספריית בית בנפח מתמיד של 5GB והיא פועלת ב-Google Cloud, משפרת מאוד את ביצועי הרשת ואת האימות. כל העבודה בשיעור ה-Lab הזה יכולה להתבצע באמצעות דפדפן בלבד.
3. סקירה כללית על תהליכי עבודה
היסודות
תהליך עבודה מורכב מסדרה של שלבים שמתוארים באמצעות תחביר מבוסס-YAML של תהליכי עבודה. זוהי ההגדרה של תהליך העבודה. הסבר מפורט על תחביר ה-YAML של תהליכי העבודה זמין בדף חומר עזר בנושא תחביר.
כשיוצרים תהליך עבודה, הוא מופעל, כך שהוא מוכן לביצוע. ביצוע הוא הפעלה יחידה של הלוגיקה הכלולה בהגדרה של תהליך עבודה. כל ההפעלות של תהליכי העבודה הן עצמאיות, והמוצר תומך במספר גדול של הפעלות בו-זמנית.
הפעלת שירותים
ב-codelab הזה תתחברו לשירותי Cloud Functions ו-Cloud Run באמצעות תהליכי עבודה. תשתמשו גם ב-Cloud Build וב-Cloud Storage במהלך פיתוח השירותים.
מפעילים את כל השירותים הנדרשים:
gcloud services enable \ cloudfunctions.googleapis.com \ run.googleapis.com \ workflows.googleapis.com \ cloudbuild.googleapis.com \ storage.googleapis.com
בשלב הבא, תקשרו בין שתי פונקציות של Cloud Functions בתהליך עבודה.
4. פריסת הפונקציה הראשונה ב-Cloud Functions
הפונקציה הראשונה היא מחולל מספרים אקראיים ב-Python.
יוצרים ספרייה לקוד הפונקציה ועוברים אליה:
mkdir ~/randomgen cd ~/randomgen
יוצרים קובץ main.py
בתיקייה עם התוכן הבא:
import random, json from flask import jsonify def randomgen(request): randomNum = random.randint(1,100) output = {"random":randomNum} return jsonify(output)
כשהיא מקבלת בקשת HTTP, הפונקציה הזו יוצרת מספר אקראי בין 1 ל-100 ומחזירה אותו בפורמט JSON לשולח הקריאה.
הפונקציה מסתמכת על Flask לעיבוד HTTP, ואנחנו צריכים להוסיף את זה כיחסי תלות. יחסי התלות ב-Python מנוהלים באמצעות pip ומפורטים בקובץ מטא-נתונים שנקרא requirements.txt
.
יוצרים קובץ requirements.txt
באותה ספרייה עם התוכן הבא:
flask>=1.0.2
פורסים את הפונקציה עם טריגר HTTP ועם בקשות לא מאומתות שמותר להן לפעול באמצעות הפקודה הבאה:
gcloud functions deploy randomgen \ --runtime python312 \ --trigger-http \ --allow-unauthenticated
אחרי הפריסה, אפשר לראות את כתובת ה-URL של הפונקציה בנכס url
שמוצג במסוף או באמצעות הפקודה gcloud functions describe
.
אפשר גם להיכנס לכתובת ה-URL של הפונקציה באמצעות הפקודה הבאה של curl
:
curl $(gcloud functions describe randomgen --format='value(url)')
הפונקציה מוכנה לתהליך העבודה.
5. פריסת פונקציית Cloud Functions שנייה
הפונקציה השנייה היא מכפיל. הוא מכפיל את הקלט שהתקבל ב-2.
יוצרים ספרייה לקוד הפונקציה ועוברים אליה:
mkdir ~/multiply cd ~/multiply
יוצרים קובץ main.py
בתיקייה עם התוכן הבא:
import random, json from flask import jsonify def multiply(request): request_json = request.get_json() output = {"multiplied":2*request_json['input']} return jsonify(output)
כשהיא מקבלת בקשת HTTP, הפונקציה הזו מחלצת את input
מגוף ה-JSON, מכפילה אותו ב-2 ומחזירה אותו בפורמט JSON למבצע הקריאה.
יוצרים את אותו קובץ requirements.txt
באותה ספרייה עם התוכן הבא:
flask>=1.0.2
פורסים את הפונקציה עם טריגר HTTP ועם בקשות לא מאומתות שמותר להן לפעול באמצעות הפקודה הבאה:
gcloud functions deploy multiply \ --runtime python312 \ --trigger-http \ --allow-unauthenticated
אחרי הפריסה של הפונקציה, אפשר גם להיכנס לכתובת ה-URL הזו של הפונקציה באמצעות הפקודה curl
הבאה:
curl $(gcloud functions describe multiply --format='value(url)') \ -X POST \ -H "content-type: application/json" \ -d '{"input": 5}'
הפונקציה מוכנה לתהליך העבודה.
6. חיבור של שתי פונקציות Cloud
בתהליך העבודה הראשון, מחברים את שתי הפונקציות.
יוצרים קובץ workflow.yaml
עם התוכן הבא.
- randomgenFunction: call: http.get args: url: https://<region>-<project-id>.cloudfunctions.net/randomgen result: randomgenResult - multiplyFunction: call: http.post args: url: https://<region>-<project-id>.cloudfunctions.net/multiply body: input: ${randomgenResult.body.random} result: multiplyResult - returnResult: return: ${multiplyResult}
בתהליך העבודה הזה, מקבלים מספר אקראי מהפונקציה הראשונה ומעבירים אותו לפונקציה השנייה. התוצאה היא המספר האקראי המוכפל.
פורסים את תהליך העבודה הראשון:
gcloud workflows deploy workflow --source=workflow.yaml
מריצים את תהליך העבודה הראשון:
gcloud workflows execute workflow
אחרי שמפעילים את תהליך העבודה, אפשר לראות את התוצאה על ידי העברת מזהה הביצוע שצוין בשלב הקודם:
gcloud workflows executions describe <your-execution-id> --workflow workflow
הפלט יכלול את result
ואת state
:
result: '{"body":{"multiplied":108},"code":200 ... } ... state: SUCCEEDED
7. חיבור HTTP API חיצוני
בשלב הבא תתחברו ל-math.js כשירות חיצוני בתהליך העבודה.
ב-math.js אפשר להעריך ביטויים מתמטיים באופן הבא:
curl https://api.mathjs.org/v4/?'expr=log(56)'
הפעם נשתמש במסוף Cloud כדי לעדכן את תהליך העבודה שלנו. מחפשים את Workflows
במסוף Google Cloud:
מאתרים את תהליך העבודה ולוחצים על הכרטיסייה Definition
:
עורכים את הגדרת תהליך העבודה וכוללים קריאה ל-math.js
.
- randomgenFunction: call: http.get args: url: https://<region>-<project-id>.cloudfunctions.net/randomgen result: randomgenResult - multiplyFunction: call: http.post args: url: https://<region>-<project-id>.cloudfunctions.net/multiply body: input: ${randomgenResult.body.random} result: multiplyResult - logFunction: call: http.get args: url: https://api.mathjs.org/v4/ query: expr: ${"log(" + string(multiplyResult.body.multiplied) + ")"} result: logResult - returnResult: return: ${logResult}
תהליך העבודה מעביר עכשיו את הפלט של פונקציית המכפלה לקריאה של פונקציית יומן ב-math.js
.
ממשק המשתמש ינחה אתכם לערוך ולפרוס את תהליך העבודה. אחרי הפריסה, לוחצים על Execute
כדי להריץ את תהליך העבודה. יוצגו פרטי הביצוע:
שימו לב לקוד הסטטוס 200
ול-body
בפלט של פונקציית היומן.
השלבת שירות חיצוני בתהליך העבודה שלנו, מגניב!
8. פריסת שירות ב-Cloud Run
בחלק האחרון, משלימים את תהליך העבודה באמצעות קריאה לשירות Cloud Run פרטי. המשמעות היא שצריך לאמת את תהליך העבודה כדי לקרוא לשירות Cloud Run.
שירות Cloud Run מחזיר את math.floor
של המספר שהוענק.
יוצרים ספרייה לקוד השירות ועוברים אליה:
mkdir ~/floor cd ~/floor
יוצרים קובץ app.py
בתיקייה עם התוכן הבא:
import json import logging import os import math from flask import Flask, request app = Flask(__name__) @app.route('/', methods=['POST']) def handle_post(): content = json.loads(request.data) input = float(content['input']) return f"{math.floor(input)}", 200 if __name__ != '__main__': # Redirect Flask logs to Gunicorn logs gunicorn_logger = logging.getLogger('gunicorn.error') app.logger.handlers = gunicorn_logger.handlers app.logger.setLevel(gunicorn_logger.level) app.logger.info('Service started...') else: app.run(debug=True, host='0.0.0.0', port=int(os.environ.get('PORT', 8080)))
Cloud Run פורס קונטיינרים, לכן צריך Dockerfile
והקונטיינר צריך להתחבר למשתנה הסביבה 0.0.0.0
ו-PORT
, ולכן הקוד שלמעלה.
כשהיא מקבלת בקשת HTTP, הפונקציה הזו מחלצת את input
מגוף ה-JSON, קוראת ל-math.floor ומחזירה את התוצאה למבצע הקריאה.
באותה ספרייה, יוצרים את Dockerfile
הבא:
# Use an official lightweight Python image. # https://hub.docker.com/_/python FROM python:3.7-slim # Install production dependencies. RUN pip install Flask gunicorn # Copy local code to the container image. WORKDIR /app COPY . . # Run the web service on container startup. Here we use the gunicorn # webserver, with one worker process and 8 threads. # For environments with multiple CPU cores, increase the number of workers # to be equal to the cores available. CMD exec gunicorn --bind 0.0.0.0:8080 --workers 1 --threads 8 app:app
יצירת הקונטיינר:
export SERVICE_NAME=floor gcloud builds submit --tag gcr.io/${GOOGLE_CLOUD_PROJECT}/${SERVICE_NAME}
אחרי שתבנו את הקונטיינר, תוכלו לפרוס אותו ב-Cloud Run. שימו לב לסימון no-allow-unauthenticated
. כך מוודאים שהשירות מקבל רק קריאות מאומתות:
gcloud run deploy ${SERVICE_NAME} \ --image gcr.io/${GOOGLE_CLOUD_PROJECT}/${SERVICE_NAME} \ --platform managed \ --no-allow-unauthenticated
אחרי הפריסה, השירות מוכן לתהליך העבודה.
9. חיבור שירות Cloud Run
כדי שתוכלו להגדיר ל-Workflows לבצע קריאה לשירות Cloud Run הפרטי, עליכם ליצור חשבון שירות לשימוש ב-Workflows:
export SERVICE_ACCOUNT=workflows-sa gcloud iam service-accounts create ${SERVICE_ACCOUNT}
מקצים לחשבון השירות את התפקיד run.invoker
. כך חשבון השירות יוכל לקרוא לשירותי Cloud Run מאומתים:
gcloud projects add-iam-policy-binding ${GOOGLE_CLOUD_PROJECT} \ --member "serviceAccount:${SERVICE_ACCOUNT}@${GOOGLE_CLOUD_PROJECT}.iam.gserviceaccount.com" \ --role "roles/run.invoker"
מעדכנים את הגדרת תהליך העבודה ב-workflow.yaml
כך שתכלול את שירות Cloud Run. שימו לב שגם לכלול את השדה auth
כדי לוודא ש-Workflows מעביר את אסימון האימות בקריאות שלו לשירות Cloud Run:
- randomgenFunction: call: http.get args: url: https://<region>-<project-id>.cloudfunctions.net/randomgen result: randomgenResult - multiplyFunction: call: http.post args: url: https://<region>-<project-id>.cloudfunctions.net/multiply body: input: ${randomgenResult.body.random} result: multiplyResult - logFunction: call: http.get args: url: https://api.mathjs.org/v4/ query: expr: ${"log(" + string(multiplyResult.body.multiplied) + ")"} result: logResult - floorFunction: call: http.post args: url: https://floor-<random-hash>.run.app auth: type: OIDC body: input: ${logResult.body} result: floorResult - returnResult: return: ${floorResult}
מעדכנים את תהליך העבודה. הפעם מעבירים את חשבון השירות:
gcloud workflows deploy workflow \ --source=workflow.yaml \ --service-account=${SERVICE_ACCOUNT}@${GOOGLE_CLOUD_PROJECT}.iam.gserviceaccount.com
מריצים את תהליך העבודה:
gcloud workflows execute workflow
אחרי כמה שניות תוכלו לעיין בהפעלה של תהליך העבודה כדי לראות את התוצאה:
gcloud workflows executions describe <your-execution-id> --workflow workflow
הפלט יכלול את המספרים השלמים result
ו-state
:
result: '{"body":"5","code":200 ... } ... state: SUCCEEDED
10. מעולה!
כל הכבוד על השלמת ה-Codelab.
מה עסקנו בו
- העקרונות הבסיסיים של תהליכי עבודה.
- איך מחברים פונקציות ציבוריות של Cloud Functions לתהליכי עבודה.
- איך לקשר שירותים פרטיים של Cloud Run ל-Workflows.
- איך מחברים ממשקי HTTP API חיצוניים לתהליכי עבודה.