יצירת תזמור מבוסס-אירועים באמצעות Eventarc ו-Workflows

1. מבוא

cb762f29e9183a3f.png 1c05e3d0c2bd2b45.png a03f943ca09ac4c.png

בעזרת Eventarc קל לקשר בין שירותי Cloud Run לאירועים ממגוון מקורות. הוא מאפשר לפתח ארכיטקטורות מבוססות-אירועים שבהן מיקרו-שירותים (microservices) בצימוד חלש ומפוזרים. הוא מטפל בהטמעת נתונים של אירועים, בשליחה, באבטחה, בהרשאה ובטיפול בשגיאות.

Workflows היא פלטפורמת תזמור מנוהלת שמפעילה שירותים לפי הסדר שבו הגדרתם: תהליך עבודה. תהליכי העבודה האלה יכולים לשלב שירותים שמתארחים ב-Cloud Run או ב-Cloud Functions, בשירותי Google Cloud כמו Cloud Vision AI ו-BigQuery, וכל API מבוסס-HTTP.

ב-Codelab הזה תבנה תזמור מבוסס-אירועים של מיקרו-שירותים (microservices) כדי לעבד תמונות. אתם תשתמשו בתהליכי עבודה כדי לתזמר את הסדר, הקלט והפלט של 4 פונקציות עיבוד תמונות ב-Cloud Functions. לאחר מכן תפעילו את התזמור להגיב לאירועי Cloud Storage בצימוד חלש עם Eventarc.

בסופו של דבר תהיה לכם ארכיטקטורה גמישה אך ללא שרת (serverless), לעיבוד תמונות.

e372ceed8c26c5fb.png

מה תלמדו

  • סקירה כללית של Eventarc ו-Workflows
  • איך פורסים שירותי Cloud Functions
  • איך לתזמר שירותים באמצעות תהליכי עבודה
  • איך לגרום ל-Workflows להגיב לאירועים ב-Cloud Storage באמצעות Eventarc

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

הגדרת סביבה בקצב אישי

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

b35bf95b8bf3d5d8.png

a99b7ace416376c4.png

bd84a6d3004737c5.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 מרחוק מהמחשב הנייד, אבל ב-Codelab הזה משתמשים ב-Google Cloud Shell, סביבת שורת הפקודה שפועלת ב-Cloud.

במסוף Google Cloud, לוחצים על הסמל של Cloud Shell בסרגל הכלים שבפינה השמאלית העליונה:

55efc1aaa7a4d3ad.png

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

7ffe5cbb04455448.png

למכונה הווירטואלית הזו נטען כל כלי הפיתוח הדרושים. יש בה ספריית בית בנפח מתמיד של 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. סקירה כללית של הארכיטקטורה

הארכיטקטורה של האפליקציה היא:

6aa6fbc7721dd6b6.png

  1. התמונה נשמרת בקטגוריית קלט שיוצרת אירוע יצירה ב-Cloud Storage.
  2. אירוע היצירה ב-Cloud Storage נקרא על ידי Eventarc באמצעות טריגר של Cloud Storage, ומועבר אל Workflows בתור CloudEvent.
  3. בשלב הראשון של תהליך העבודה, הכלי Filter (סינון), שהוא שירות של Cloud Functions, משתמש ב-Vision API כדי לבדוק אם התמונה בטוחה. אם התמונה בטוחה, תהליך העבודה ממשיך לשלבים הבאים.
  4. בשלב השני של תהליך העבודה, Labeler, שירות של Cloud Functions, מחלץ תוויות של התמונה באמצעות Vision API ושומר את התוויות בקטגוריית הפלט.
  5. בשלב השלישי, Resizer, שירות אחר של פונקציה של Cloud Functions, משנה את גודל התמונה באמצעות ImageSharp ושומר את התמונה שגודלה השתנה בקטגוריית הפלט.
  6. בשלב האחרון, Watermark, שירות נוסף של פונקציה של Cloud Functions, מוסיף סימן מים של תוויות מ-Labeler לתמונה שגודלה השתנה באמצעות ImageSharp ושומר את התמונה בקטגוריית הפלט.

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

4. יצירת קטגוריות

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

מריצים את הפקודה הבאה ב-Cloud Shell:

REGION=us-central1
BUCKET1=$PROJECT_ID-images-input
BUCKET2=$PROJECT_ID-images-output

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 ולהפעיל אותן:

76a218568982c90c.png

9. הגדרה ופריסה של תהליך העבודה

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

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

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, תהליכי עבודה מחזירים את קוד סטטוס ה-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

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

92cf4e758bdc3dde.png

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 כדי שאפשר יהיה להשתמש בחשבון השירות כדי להפעיל תהליכי עבודה מ-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:

14330c4fa2451bc0.png

11. בדיקת צינור עיבוד הנתונים

צינור עיבוד התמונות מוכן לקבלת אירועים מ-Cloud Storage. כדי לבדוק את צינור עיבוד הנתונים, מעלים תמונה לקטגוריית הקלט:

gsutil cp beach.jpg gs://$BUCKET1

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

36d07cb63c39e7d9.png

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

229200c79d989c25.png

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

gsutil ls gs://$BUCKET2

gs://$PROJECT_ID-images-output/beach-400x400-watermark.jpeg
gs://$PROJECT_ID-images-output/beach-400x400.png
gs://$PROJECT_ID-images-output/beach-labels.txt

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

75f3c0019ca842ce.jpeg

12. מזל טוב

כל הכבוד, סיימת את ה-Codelab!

הנושאים שטיפלנו בהם

  • סקירה כללית של Eventarc ו-Workflows
  • איך פורסים שירותי Cloud Functions
  • איך לתזמר שירותים באמצעות תהליכי עבודה
  • איך לגרום ל-Workflows להגיב לאירועים ב-Cloud Storage באמצעות Eventarc