1. מבוא

Eventarc מאפשר לחבר בקלות שירותי Cloud Run לאירועים ממגוון מקורות. הוא מאפשר לכם לבנות ארכיטקטורות מבוססות-אירועים שבהן מיקרו-שירותים (microservices) מצומדים בצורה חלשה ומפוזרים. הוא מטפל בשליחת אירועים, באספקתם, באבטחה, בהרשאה ובטיפול בשגיאות.
Workflows היא פלטפורמת תזמור מנוהלת במלואה שמבצעת שירותים בסדר שאתם מגדירים: תהליך עבודה. תהליכי העבודה האלה יכולים לשלב שירותים שמתארחים ב-Cloud Run או ב-Cloud Functions, שירותי Google Cloud כמו Cloud Vision AI ו-BigQuery, וכל API מבוסס-HTTP.
ב-codelab הזה תבנו תזמור של מיקרו-שירותים מבוססי-אירועים לעיבוד תמונות. תשתמשו ב-Workflows כדי לתזמן את הסדר, את הקלט ואת הפלט של 4 פונקציות של Cloud Functions לעיבוד תמונות. לאחר מכן תפעילו את התזמור כדי להגיב לאירועים ב-Cloud Storage בצורה בצימוד חלש באמצעות Eventarc.
בסופו של דבר, תהיה לכם ארכיטקטורה גמישה אך מובנית ללא שרת לעיבוד תמונות.

מה תלמדו
- סקירה כללית על Eventarc ו-Workflows
- איך פורסים שירותי Cloud Functions
- איך מתזמרים שירותים באמצעות Workflows
- איך גורמים ל-Workflows להגיב לאירועים ב-Cloud Storage באמצעות Eventarc
2. הגדרה ודרישות
הגדרת סביבה בקצב עצמי
- נכנסים ל-מסוף Google Cloud ויוצרים פרויקט חדש או משתמשים בפרויקט קיים. אם עדיין אין לכם חשבון Gmail או Google Workspace, אתם צריכים ליצור חשבון.



- שם הפרויקט הוא השם המוצג של הפרויקט הזה למשתתפים. זו מחרוזת תווים שלא נמצאת בשימוש ב-Google APIs. תמיד אפשר לעדכן את המיקום.
- מזהה הפרויקט הוא ייחודי לכל הפרויקטים ב-Google Cloud, והוא קבוע (אי אפשר לשנות אותו אחרי שהוא מוגדר). מסוף Cloud יוצר באופן אוטומטי מחרוזת ייחודית, ובדרך כלל לא צריך לדעת מה היא. ברוב ה-Codelabs, תצטרכו להפנות למזהה הפרויקט (בדרך כלל מסומן כ-
PROJECT_ID). אם אתם לא אוהבים את המזהה שנוצר, אתם יכולים ליצור מזהה אקראי אחר. אפשר גם לנסות שם משתמש משלכם ולבדוק אם הוא זמין. אי אפשר לשנות את ההגדרה הזו אחרי השלב הזה, והיא תישאר לאורך הפרויקט. - לידיעתכם, יש ערך שלישי, מספר פרויקט, שחלק מממשקי ה-API משתמשים בו. במאמרי העזרה מפורט מידע נוסף על שלושת הערכים האלה.
- בשלב הבא, תצטרכו להפעיל את החיוב במסוף Cloud כדי להשתמש במשאבי Cloud או בממשקי API של Cloud. השלמת ה-codelab הזה לא תעלה לכם הרבה, אם בכלל. כדי להשבית את המשאבים ולמנוע חיובים נוספים אחרי שתסיימו את המדריך הזה, תוכלו למחוק את המשאבים שיצרתם או למחוק את הפרויקט. משתמשים חדשים ב-Google Cloud זכאים לתוכנית תקופת ניסיון בחינם בשווי 300$.
הפעלת Cloud Shell
אפשר להפעיל את Google Cloud מרחוק מהמחשב הנייד, אבל ב-codelab הזה תשתמשו ב-Google Cloud Shell, סביבת שורת פקודה שפועלת בענן.
ב-מסוף Google Cloud, לוחצים על סמל Cloud Shell בסרגל הכלים שבפינה הימנית העליונה:

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

המכונה הווירטואלית הזו כוללת את כל הכלים שדרושים למפתחים. יש בה ספריית בית בנפח מתמיד של 5GB והיא פועלת ב-Google Cloud, מה שמשפר מאוד את הביצועים והאימות ברשת. אפשר לבצע את כל העבודה ב-codelab הזה בדפדפן. לא צריך להתקין שום דבר.
הגדרת gcloud
ב-Cloud Shell, מגדירים את מזהה הפרויקט ואת האזור שבו רוצים לפרוס את האפליקציה. שומרים אותם כמשתנים PROJECT_ID ו-REGION. אפשר לעיין במיקומים של Cloud Functions כדי לראות את האזורים הזמינים.
PROJECT_ID=your-project-id gcloud config set project $PROJECT_ID
קבלת קוד המקור
קוד המקור של האפליקציה נמצא בתיקייה processing-pipelines במאגר eventarc-samples.
משכפלים את המאגר:
git clone https://github.com/GoogleCloudPlatform/eventarc-samples.git
עוברים לתיקייה eventarc-samples/processing-pipelines:
cd eventarc-samples/processing-pipelines
3. סקירה כללית של הארכיטקטורה
זו הארכיטקטורה של האפליקציה:

- תמונה נשמרת בקטגוריית קלט שיוצרת אירוע יצירה ב-Cloud Storage.
- אירוע היצירה ב-Cloud Storage נקרא על ידי Eventarc באמצעות טריגר של Cloud Storage ומועבר אל Workflows כ-CloudEvent.
- בשלב הראשון של תהליך העבודה, Filter, שירות Cloud Functions, משתמש ב-Vision API כדי לקבוע אם התמונה בטוחה. אם התמונה בטוחה, כלי Workflows ממשיך לשלבים הבאים.
- בשלב השני של תהליך העבודה, Labeler, שירות Cloud Functions, מחלץ תוויות של התמונה באמצעות Vision API ושומר את התוויות בדלי הפלט.
- בשלב השלישי, Resizer, שירות נוסף של Cloud Functions, משנה את גודל התמונה באמצעות ImageSharp ושומר את התמונה שגודלה שונה בדלי הפלט.
- בשלב האחרון, Watermarker, שירות נוסף של Cloud Functions, מוסיף סימן מים של תוויות מ-Labeler לתמונה שגודלה שונה באמצעות ImageSharp ושומר את התמונה בדלי הפלט.
האפליקציה מופעלת על ידי אירוע ב-Cloud Storage, ולכן היא מבוססת על אירועים. עיבוד התמונות מתבצע בתהליך עבודה, ולכן זהו תזמור. בסופו של דבר, מדובר בתזמור מבוסס-אירועים של ארכיטקטורה גמישה אך מובנית בלי שרת (serverless), לעיבוד תמונות.
4. יצירת קטגוריות
יוצרים באקט קלט שבו המשתמשים יכולים להעלות את התמונות, ובאקט פלט שבו צינור העיבוד של התמונות יכול לשמור את התמונות המעובדות.
מריצים את הפקודה הבאה ב-Cloud Shell:
REGION=us-central1 BUCKET1=$PROJECT_ID-images-input-$RANDOM BUCKET2=$PROJECT_ID-images-output-$RANDOM gsutil mb -l $REGION gs://$BUCKET1 gsutil mb -l $REGION gs://$BUCKET2
5. פריסת שירות המסננים
נתחיל בפריסת השירות הראשון. שירות Cloud Functions מקבל את פרטי הדלי והקובץ, קובע אם התמונה בטוחה באמצעות Vision API ומחזיר את התוצאה.
קודם כל, מפעילים את השירותים הנדרשים ל-Cloud Functions gen2 ול-Vision API:
gcloud services enable \ artifactregistry.googleapis.com \ cloudbuild.googleapis.com \ cloudfunctions.googleapis.com \ run.googleapis.com \ vision.googleapis.com
בתיקייה ברמה העליונה processing-pipelines, פורסים את השירות:
SERVICE_NAME=filter gcloud functions deploy $SERVICE_NAME \ --gen2 \ --allow-unauthenticated \ --runtime dotnet3 \ --trigger-http \ --region=$REGION \ --entry-point Filter.Function \ --set-build-env-vars GOOGLE_BUILDABLE=image-v3/filter/csharp
אחרי שמבצעים פריסה של הפונקציה, מגדירים את כתובת ה-URL של השירות במשתנה. נצטרך אותה בהמשך:
FILTER_URL=$(gcloud functions describe $SERVICE_NAME --region=$REGION --gen2 --format 'value(serviceConfig.uri)')
6. פריסת שירות לסימון תוויות
שירות Cloud Functions השני מקבל את פרטי הקטגוריה והקובץ, מחלץ את התוויות של התמונה באמצעות Vision API ושומר את התוויות בקטגוריית הפלט.
בתיקייה ברמה העליונה processing-pipelines, פורסים את השירות:
SERVICE_NAME=labeler gcloud functions deploy $SERVICE_NAME \ --gen2 \ --allow-unauthenticated \ --runtime dotnet3 \ --trigger-http \ --region=$REGION \ --set-env-vars BUCKET=$BUCKET2 \ --entry-point Labeler.Function \ --set-build-env-vars GOOGLE_BUILDABLE=image-v2/labeler/csharp
אחרי שפורסים את הפונקציה, מגדירים את כתובת ה-URL של השירות במשתנה. נצטרך אותה בהמשך:
LABELER_URL=$(gcloud functions describe $SERVICE_NAME --region=$REGION --gen2 --format 'value(serviceConfig.uri)')
7. פריסת שירות לשינוי גודל
שירות Cloud Functions מקבל את פרטי הקטגוריה והקובץ, משנה את גודל התמונה באמצעות ImageSharp ושומר את התמונה בקטגוריית הפלט.
בתיקייה ברמה העליונה processing-pipelines, פורסים את השירות:
SERVICE_NAME=resizer gcloud functions deploy $SERVICE_NAME \ --gen2 \ --allow-unauthenticated \ --runtime dotnet3 \ --trigger-http \ --region=$REGION \ --set-env-vars BUCKET=$BUCKET2 \ --entry-point Resizer.Function \ --set-build-env-vars GOOGLE_BUILDABLE=image-v2/resizer/csharp \ --timeout=120s
שימו לב לערך timeout של 2 דקות, כדי לאפשר לפונקציה של שינוי הגודל זמן נוסף לעיבוד.
אחרי שמבצעים פריסה של הפונקציה, מגדירים את כתובת ה-URL של השירות במשתנה. נצטרך אותה בהמשך:
RESIZER_URL=$(gcloud functions describe $SERVICE_NAME --region=$REGION --gen2 --format 'value(serviceConfig.uri)')
8. פריסת שירות לסימון מים
שירות Cloud Functions מקבל את המידע על הקטגוריה, הקובץ והתוויות, קורא את הקובץ, מוסיף את התוויות כסימן מים לתמונה באמצעות ImageSharp ושומר את התמונה בקטגוריית הפלט.
בתיקייה ברמה העליונה processing-pipelines, פורסים את השירות:
SERVICE_NAME=watermarker gcloud functions deploy $SERVICE_NAME \ --gen2 \ --allow-unauthenticated \ --runtime dotnet3 \ --trigger-http \ --region=$REGION \ --set-env-vars BUCKET=$BUCKET2 \ --entry-point Watermarker.Function \ --set-build-env-vars GOOGLE_BUILDABLE=image-v2/watermarker/csharp
אחרי שמבצעים פריסה של הפונקציה, מגדירים את כתובת ה-URL של השירות במשתנה. נצטרך אותה בהמשך:
WATERMARKER_URL=$(gcloud functions describe $SERVICE_NAME --region=$REGION --gen2 --format 'value(serviceConfig.uri)')
בשלב הזה, כל ארבע הפונקציות של Cloud Functions צריכות להיות פרוסות ופעילות:

9. הגדרה ופריסה של תהליך עבודה
אפשר להשתמש בתהליכי עבודה כדי לשלב שירותים של סינון, הוספת תוויות, שינוי גודל והוספת סימן מים לתהליך עבודה. תהליכי העבודה יתזמנו את הקריאות לשירותים האלה בסדר ובפרמטרים שנגדיר.
קודם כל, מפעילים את השירותים הנדרשים ל-Workflows:
gcloud services enable \ workflows.googleapis.com \ workflowexecutions.googleapis.com
הגדר
Workflows מקבלת CloudEvent כפרמטר. הנתונים האלה יגיעו מ-Eventarc אחרי שניצור טריגר. בשני השלבים הראשונים, Workflows מתעד את האירוע ומחלץ ממנו את פרטי הקטגוריה והקובץ:
main:
params: [event]
steps:
- log_event:
call: sys.log
args:
text: ${event}
severity: INFO
- extract_bucket_and_file:
assign:
- bucket: ${event.data.bucket}
- file: ${event.data.name}
בשלב filter, Workflows מבצע קריאה לשירות הסינון שפרסנו קודם. לאחר מכן, המערכת מתעדת ובודקת את בטיחות הקובץ:
- filter:
call: http.post
args:
url: FILTER_URL # TODO: Replace
auth:
type: OIDC
body:
bucket: ${bucket}
file: ${file}
result: filterResponse
- log_safety:
call: sys.log
args:
text: ${filterResponse.body.safe}
severity: INFO
- check_safety:
switch:
- condition: ${filterResponse.body.safe == true}
next: label
next: end
בשלב label, כלי Workflows מבצע קריאה לשירות התיוג ומתעד את התגובה (3 התוויות העליונות):
- label:
call: http.post
args:
url: LABELER_URL # TODO: Replace
auth:
type: OIDC
body:
bucket: ${bucket}
file: ${file}
result: labelResponse
בשלב resize, כלי Workflows מבצע קריאה לשירות שינוי הגודל ומתעד את התגובה (המאגר והקובץ של התמונה שגודלה שונה):
- resize:
call: http.post
args:
url: RESIZER_URL # TODO: Replace
auth:
type: OIDC
body:
bucket: ${bucket}
file: ${file}
result: resizeResponse
בשלב watermark, כלי Workflows קורא לשירות של סימון המים עם התמונה והתוויות שגודלן שונה, ומתעד את התוצאה (התמונה שגודלה שונה וסומנה בסימן מים):
- watermark:
call: http.post
args:
url: WATERMARKER_URL # TODO: Replace
auth:
type: OIDC
body:
bucket: ${resizeResponse.body.bucket}
file: ${resizeResponse.body.file}
labels: ${labelResponse.body.labels}
result: watermarkResponse
בשלב final, כלי Workflows מחזיר את קוד סטטוס של HTTP משירותי התיוג, שינוי הגודל והוספת סימן המים:
- final:
return:
label: ${labelResponse.code}
resize: ${resizeResponse.code}
watermark: ${watermarkResponse.code}
פריסה
לפני שמפעילים את תהליך העבודה, צריך לוודא שכתובות ה-URL של השירות הוחלפו בכתובות ה-URL של הפונקציות שהופעלו, באופן ידני או באמצעות sed:
בתוך תיקיית הרמה העליונה processing-pipelines, עוברים לתיקייה image-v3 שבה נמצא הקובץ workflows.yaml:
cd image-v3/
מריצים את הפקודה sed כדי להחליף את כתובות ה-URL של placeholder בכתובות ה-URL בפועל של השירותים שנפרסו:
sed -i -e "s|FILTER_URL|${FILTER_URL}|" workflow.yaml
sed -i -e "s|LABELER_URL|${LABELER_URL}|" workflow.yaml
sed -i -e "s|RESIZER_URL|${RESIZER_URL}|" workflow.yaml
sed -i -e "s|WATERMARKER_URL|${WATERMARKER_URL}|" workflow.yaml
פורסים את תהליך העבודה:
WORKFLOW_NAME=image-processing
gcloud workflows deploy $WORKFLOW_NAME \
--source=workflow.yaml \
--location=$REGION
אחרי כמה שניות, תראו שהתהליך העסקי נפרס במסוף:

10. יצירת טריגר
אחרי פריסת תהליך העבודה, השלב האחרון הוא לקשר אותו לאירועים ב-Cloud Storage באמצעות טריגר Eventarc.
הגדרה חד פעמית
קודם מפעילים את השירותים הנדרשים ל-Eventarc:
gcloud services enable \ eventarc.googleapis.com
יוצרים חשבון שירות שישמש בטריגר Eventarc.
SERVICE_ACCOUNT=eventarc-trigger-imageproc-sa gcloud iam service-accounts create $SERVICE_ACCOUNT \ --display-name="Eventarc trigger image processing service account"
מקצים את התפקיד workflows.invoker, כדי שאפשר יהיה להשתמש בחשבון השירות להפעלת Workflows מ-Eventarc:
gcloud projects add-iam-policy-binding $PROJECT_ID \ --role roles/workflows.invoker \ --member serviceAccount:$SERVICE_ACCOUNT@$PROJECT_ID.iam.gserviceaccount.com
מקצים את התפקיד eventarc.eventReceiver כדי שאפשר יהיה להשתמש בחשבון השירות
טריגר של Cloud Storage:
gcloud projects add-iam-policy-binding $PROJECT_ID \ --role roles/eventarc.eventReceiver \ --member serviceAccount:$SERVICE_ACCOUNT@$PROJECT_ID.iam.gserviceaccount.com
מקצים את התפקיד pubsub.publisher לחשבון השירות של Cloud Storage. ההרשאה הזו נדרשת לטריגר Cloud Storage של Eventarc:
STORAGE_SERVICE_ACCOUNT="$(gsutil kms serviceaccount -p $PROJECT_ID)"
gcloud projects add-iam-policy-binding $PROJECT_ID \
--member serviceAccount:$STORAGE_SERVICE_ACCOUNT \
--role roles/pubsub.publisher
יצירה
מריצים את הפקודה הבאה כדי ליצור טריגר. הטריגר הזה מסנן אירועים של יצירת קבצים חדשים מקטגוריית הקלט של Cloud Storage ומעביר אותם אל זרימת העבודה שהגדרנו קודם:
TRIGGER_NAME=trigger-image-processing gcloud eventarc triggers create $TRIGGER_NAME \ --location=$REGION \ --destination-workflow=$WORKFLOW_NAME \ --destination-workflow-location=$REGION \ --event-filters="type=google.cloud.storage.object.v1.finalized" \ --event-filters="bucket=$BUCKET1" \ --service-account=$SERVICE_ACCOUNT@$PROJECT_ID.iam.gserviceaccount.com
אפשר לראות שהטריגר נוצר ומוכן בקטע Eventarc במסוף Cloud:

11. בדיקת הפייפליין
צינור העיבוד של התמונות מוכן לקבל אירועים מ-Cloud Storage. כדי לבדוק את צינור העיבוד, מעלים תמונה לקטגוריית הקלט:
gsutil cp beach.jpg gs://$BUCKET1
מיד אחרי העלאת התמונה, אמורה להופיע הפעלה של תהליכי עבודה במצב פעיל:

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

אם תציגו את התוכן של דלי הפלט, תראו את התמונה שגודלה שונה, את התמונה שגודלה שונה ונוסף לה סימן מים, ואת התוויות של התמונה:
gsutil ls gs://$BUCKET2 gs://$PROJECT_ID-images-output-$RANDOM/beach-400x400-watermark.jpeg gs://$PROJECT_ID-images-output-$RANDOM/beach-400x400.png gs://$PROJECT_ID-images-output-$RANDOM/beach-labels.txt
כדי לבדוק, אפשר לפתוח את התמונה שגודלה שונה ואת התמונה עם סימן המים כדי לראות את התוצאה:

12. מזל טוב
כל הכבוד, סיימתם את ה-Codelab!
מה נכלל
- סקירה כללית על Eventarc ו-Workflows
- איך פורסים שירותי Cloud Functions
- איך מתזמרים שירותים באמצעות Workflows
- איך גורמים ל-Workflows להגיב לאירועים ב-Cloud Storage באמצעות Eventarc