תמונה יומית: שיעור Lab 5 – ניקוי לאחר מחיקת התמונה

1. סקירה כללית

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

d93345bfc235f81e.png

מה תלמדו

  • Cloud Run
  • Cloud Storage
  • Cloud Firestore
  • Eventarc

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

הגדרת סביבה בקצב עצמאי

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

96a9c957bc475304.png

b9a10ebdf5b5a448.png

a1e3c01a38fa61c2.png

  • Project name הוא השם המוצג של המשתתפים בפרויקט. זו מחרוזת תווים שלא נעשה בה שימוש ב-Google APIs, ואפשר לעדכן אותה בכל שלב.
  • Project ID חייב להיות ייחודי בכל הפרויקטים ב-Google Cloud ואי אפשר לשנות אותו (אי אפשר לשנות אותו אחרי שמגדירים אותו). מסוף Cloud יוצר מחרוזת ייחודית באופן אוטומטי; בדרך כלל לא מעניין אותך מה זה. ברוב ה-Codelabs תצטרכו להפנות אל מזהה הפרויקט (ובדרך כלל הוא מזוהה כ-PROJECT_ID), כך שאם הוא לא מוצא חן בעיניכם, תוכלו ליצור פרויקט אקראי אחר או לנסות בעצמכם ולבדוק אם הוא זמין. ואז המכשיר 'קפוא' לאחר יצירת הפרויקט.
  • יש ערך שלישי, Project Number, שחלק מממשקי ה-API משתמשים בו. מידע נוסף על כל שלושת הערכים האלה זמין במסמכי התיעוד.
  1. בשלב הבא צריך להפעיל את החיוב במסוף Cloud כדי להשתמש במשאבים או בממשקי API של Cloud. מעבר ב-Codelab הזה לא אמור לעלות הרבה, אם בכלל. כדי להשבית את המשאבים ולא לצבור חיובים מעבר למדריך הזה, פועלים לפי ההנחיות לניקוי בסוף ה-Codelab. משתמשים חדשים ב-Google Cloud זכאים להצטרף לתוכנית תקופת ניסיון בחינם בשווי 1,200 ש"ח.

הפעלת Cloud Shell

אומנם אפשר להפעיל את Google Cloud מרחוק מהמחשב הנייד, אבל ב-Codelab הזה משתמשים ב-Google Cloud Shell, סביבת שורת הפקודה שפועלת ב-Cloud.

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

bce75f34b2c53987.png

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

f6ef2b5f13479f3a.png

למכונה הווירטואלית הזו נטען כל כלי הפיתוח הדרושים. יש בה ספריית בית בנפח מתמיד של 5GB והיא פועלת ב-Google Cloud, מה שמשפר משמעותית את ביצועי הרשת והאימות. כל העבודה בשיעור ה-Lab הזה יכולה להתבצע באמצעות דפדפן בלבד.

3. מבוא ל-Eventarc

בעזרת Eventarc אפשר לחבר בקלות בין שירותי Cloud Run לאירועים ממגוון מקורות. הוא מטפל בהטמעת נתונים של אירועים, בשליחה, באבטחה, בהרשאה ובטיפול בשגיאות.

776ed63706ca9683.png

אפשר לשרטט אירועים ממקורות של Google Cloud ומאפליקציות מותאמות אישית שמפרסמים ב-Cloud Pub/Sub ולשלוח אותם ל-sinks ב-Google Cloud Run.

אירועים ממגוון מקורות ב-Google Cloud מועברים באמצעות יומני ביקורת של Cloud. זמן האחזור והזמינות של העברת אירועים מהמקורות האלה קשורים לאלו של יומני הביקורת של Cloud. בכל פעם שאירוע ממקור של Google Cloud מופעל, נוצרת רשומה תואמת ביומן הביקורת של Cloud.

אפליקציות מותאמות אישית שמפרסמים ב-Cloud Pub/Sub יכולות לפרסם הודעות בנושא Pub/Sub שהן מגדירות בכל פורמט.

טריגרים של אירועים הם מנגנון הסינון שמציין אילו אירועים צריך לשלוח לכל sink.

כל האירועים מועברים בפורמט CloudEvents v1.0 לצורך יכולת פעולה הדדית בין שירותים.

4. לפני שמתחילים

הפעלת ממשקי API

שירות Eventarc נדרש כדי להפעיל את שירות Cloud Run. צריך לוודא שהיא מופעלת:

gcloud services enable eventarc.googleapis.com

הפעולה אמורה להסתיים בהצלחה:

Operation "operations/acf.5c5ef4f6-f734-455d-b2f0-ee70b5a17322" finished successfully.

הגדרה של חשבונות שירות

חשבון שירות המחשוב שמוגדר כברירת מחדל ישמש בטריגרים. מקצים את התפקיד eventarc.eventReceiver לחשבון השירות שמשמש כברירת מחדל ב-Compute Engine:

PROJECT_NUMBER=$(gcloud projects describe $GOOGLE_CLOUD_PROJECT --format='value(projectNumber)')

gcloud projects add-iam-policy-binding $GOOGLE_CLOUD_PROJECT \
    --member serviceAccount:$PROJECT_NUMBER-compute@developer.gserviceaccount.com \
    --role roles/eventarc.eventReceiver

מקצים את התפקיד pubsub.publisher לחשבון השירות של Cloud Storage. זה נדרש לטריגר של Eventarc Cloud Storage:

SERVICE_ACCOUNT=$(gsutil kms serviceaccount -p $PROJECT_NUMBER)

gcloud projects add-iam-policy-binding $PROJECT_NUMBER \
    --member serviceAccount:$SERVICE_ACCOUNT \
    --role roles/pubsub.publisher

אם הפעלת את חשבון השירות של Pub/Sub ב-8 באפריל 2021 או לפני כן, מקצים את התפקיד iam.serviceAccountTokenCreator לחשבון השירות של Pub/Sub:

gcloud projects add-iam-policy-binding $PROJECT_ID \
  --member serviceAccount:service-$PROJECT_NUMBER@gcp-sa-pubsub.iam.gserviceaccount.com \
  --role roles/iam.serviceAccountTokenCreator

5. שכפול הקוד

משכפלים את הקוד, אם עדיין לא עשיתם זאת ב-Code Lab הקודם:

git clone https://github.com/GoogleCloudPlatform/serverless-photosharing-workshop

עכשיו אפשר לעבור לספרייה שמכילה את השירות:

cd serverless-photosharing-workshop/services/garbage-collector/nodejs

תהיה לכם פריסת קבצים הבאה עבור השירות:

services
 |
 ├── garbage-collector
      |
      ├── nodejs
           |
           ├── index.js
           ├── package.json

בתיקייה יש 3 קבצים:

  • הקוד index.js מכיל את הקוד Node.js
  • package.json מגדיר את יחסי התלות של הספרייה

6. לבדיקת הקוד

תלות

הקובץ package.json מגדיר את יחסי התלות הנדרשים של הספריות:

{
  "name": "garbage_collector_service",
  "version": "0.0.1",
  "main": "index.js",
  "scripts": {
    "start": "node index.js"
  },
  "dependencies": {
    "cloudevents": "^4.0.1",
    "express": "^4.17.1",
    "@google/events": "^3.1.0",
    "@google-cloud/firestore": "^4.9.9",
    "@google-cloud/storage": "^5.8.3"
  }
}

כדי למחוק תמונות בתוך Cloud Storage, אנחנו נעזרים בספריית Cloud Storage. אנחנו מצהירים על תלות ב-Cloud Firestore וגם למחוק מטא-נתונים של תמונות שאחסנו בעבר. בנוסף, אנחנו מסתמכים על CloudEvents SDK ועל ספריות האירועים של Google כדי לקרוא את אירועי CloudEvents שנשלחים על ידי Eventarc. Express היא מסגרת אינטרנט מסוג JavaScript / Node. 'Blubbird' משמשת לטיפול בהבטחות.

index.js

בואו נבחן מקרוב את הקוד index.js שלנו:

const express = require('express');
const {Storage} = require('@google-cloud/storage');
const Firestore = require('@google-cloud/firestore');
const { HTTP } = require("cloudevents");
const {toStorageObjectData} = require('@google/events/cloud/storage/v1/StorageObjectData');

כדי שהתוכנית שלנו תפעל, אנחנו דורשים את יחסי התלות השונים שדרושים כדי להפעיל את התוכנית: Express היא מסגרת האינטרנט שבה נשתמש ב-Node, Blubbird היא ספרייה לטיפול בהבטחות JavaScript, אחסון ו-Firestore מיועדים לעבודה בהתאמה עם Google Cloud Storage (קטגוריות התמונות שלנו) ו-Cloud Firestore. בנוסף, אנחנו דורשים ש-CloudEvent יקרא את CloudEvent שנשלח על ידי Eventarc StoreObjectData מספריית האירועים של Google כדי לקרוא את גוף האירוע של Cloud Storage של ה-CloudEvent.

const app = express();
app.use(express.json());

app.post('/', async (req, res) => {
    try {
        const cloudEvent = HTTP.toEvent({ headers: req.headers, body: req.body });
        console.log(cloudEvent);


        /* ... */

    } catch (err) {
        console.log(`Error: ${err}`);
        res.status(500).send(err);
    }
});

למעלה מופיע המבנה של ה-handler של הצמתים: האפליקציה שלנו מגיבה לבקשות HTTP POST. הוא קורא את ה-CloudEvent מבקשת ה-HTTP ואנחנו מבצעים קצת טיפול בשגיאות במקרה שמשהו משתבש. עכשיו נסתכל מה נמצא בתוך המבנה הזה.

השלב הבא הוא אחזור וניתוח של גוף ה-CloudEvent ואחזור שם האובייקט:

const storageObjectData = toStorageObjectData(cloudEvent.data);
console.log(storageObjectData);

const objectName = storageObjectData.name;

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

try {
    await storage.bucket(bucketThumbnails).file(objectName).delete();
    console.log(`Deleted '${objectName}' from bucket '${bucketThumbnails}'.`);
}
catch(err) {
    console.log(`Failed to delete '${objectName}' from bucket '${bucketThumbnails}': ${err}.`);
}

בשלב האחרון, מוחקים את המטא-נתונים של התמונה גם מאוסף Firestore:

try {
    const pictureStore = new Firestore().collection('pictures');
    const docRef = pictureStore.doc(objectName);
    await docRef.delete();

    console.log(`Deleted '${objectName}' from Firestore collection 'pictures'`);
}
catch(err) {
    console.log(`Failed to delete '${objectName}' from Firestore: ${err}.`);
}

res.status(200).send(`Processed '${objectName}'.`);

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

app.listen(PORT, () => {
    if (!bucketThumbnails) throw new Error("BUCKET_THUMBNAILS not set");
    console.log(`Started service on port ${PORT}`);
});

7. בדיקה מקומית

מומלץ לבדוק את הקוד באופן מקומי כדי לוודא שהוא פועל לפני הפריסה בענן.

בתוך התיקייה garbage-collector/nodejs, מתקינים יחסי תלות של npm ומפעילים את השרת:

export BUCKET_THUMBNAILS=thumbnails-$GOOGLE_CLOUD_PROJECT

npm install; npm start

אם הכול תקין, צריך להפעיל את השרת ביציאה 8080:

Started service on port 8080

כדי לצאת מהמצב הזה, אפשר להשתמש בCTRL-C.

8. פיתוח ופריסה ל-Cloud Run

לפני הפריסה ב-Cloud Run, צריך להגדיר את האזור של Cloud Run לאחד מהאזורים והפלטפורמות הנתמכים כ-managed:

REGION=europe-west1
gcloud config set run/region $REGION
gcloud config set run/platform managed

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

gcloud config list

...
[run]
platform = managed
region = europe-west1

במקום לפתח ולפרסם את קובץ האימג' של הקונטיינר באמצעות Cloud Build באופן ידני, אתם יכולים גם להסתמך על Cloud Run כדי ליצור בשבילכם את קובץ האימג' של הקונטיינר באמצעות Google Cloud Buildpacks.

מריצים את הפקודה הבאה כדי ליצור את קובץ האימג' בקונטיינר באמצעות Google Cloud Buildpack ולאחר מכן פורסים את קובץ האימג' בקונטיינר ל-Cloud Run:

SERVICE_NAME=garbage-collector-service

gcloud run deploy $SERVICE_NAME \
    --source . \
    --no-allow-unauthenticated \
    --update-env-vars BUCKET_THUMBNAILS=$BUCKET_THUMBNAILS

שימו לב לדגל –-source. הפעולה הזו מסמן ל-Cloud Run להשתמש ב-Google Cloud Buildpacks כדי ליצור קובץ אימג' בקונטיינר ללא Dockerfile.. הדגל --no-allow-unauthenticated הופך את שירות Cloud Run לשירות פנימי שיופעל רק על ידי חשבונות שירות ספציפיים. לאחר מכן, יוצרים טריגר עם חשבון שירות המחשוב שמוגדר כברירת מחדל, שיש לו את התפקיד run.invoker לקריאה לשירותים פנימיים של Cloud Run.

9. יצירת טריגר

ב-Eventarc, טריגר מגדיר איזה שירות יקבל את סוגי האירועים. במקרה כזה, אתם רוצים שהשירות יקבל אירועים כשקובץ נמחק בקטגוריה.

מגדירים את מיקום הטריגר באותו אזור שבו נמצאת קטגוריית התמונות שהועלתה:

gcloud config set eventarc/location eu

יצירת טריגר של AuditLog כדי לסנן לפי אירועי storage.objects.delete ולשלוח לשירות Cloud Run:

BUCKET_IMAGES=uploaded-pictures-$GOOGLE_CLOUD_PROJECT

gcloud eventarc triggers create trigger-$SERVICE_NAME \
  --destination-run-service=$SERVICE_NAME \
  --destination-run-region=$REGION \
  --event-filters="type=google.cloud.storage.object.v1.deleted" \
  --event-filters="bucket=$BUCKET_IMAGES" \
  --service-account=$PROJECT_NUMBER-compute@developer.gserviceaccount.com

אפשר לוודא שהטריגר נוצר באמצעות הפקודה הבאה:

gcloud eventarc triggers list

10. בדיקת השירות

כדי לבדוק אם השירות פועל, עוברים לקטגוריה uploaded-pictures ומוחקים אחת מהתמונות. אתם אמורים לראות ביומנים של השירות שנמחק את התמונה הרלוונטית בקטגוריה thumbnails וגם את המסמך שלו נמחק מהאוסף pictures של Firestore.

519abf90e7ea4d12.png

11. הסרת המשאבים (אופציונלי)

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

מוחקים את השירות:

gcloud run services delete $SERVICE_NAME -q

מוחקים את הטריגר של Eventarc:

gcloud eventarc triggers delete trigger-$SERVICE_NAME -q

לחלופין, אפשר למחוק את הפרויקט כולו:

gcloud projects delete $GOOGLE_CLOUD_PROJECT

12. מעולה!

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

אילו נושאים דיברנו?

  • Cloud Run
  • Cloud Storage
  • Cloud Firestore
  • Eventarc