1. מבוא
סקירה כללית
שירותים של Cloud Run מתאימים לקונטיינרים שפועלים ללא הגבלת זמן להאזנה לבקשות HTTP, ואילו משימות ב-Cloud Run מתאימות יותר לקונטיינרים שמסיימים לפעול (כרגע עד 24 שעות) ולא שולחים בקשות. לדוגמה, עיבוד רשומות ממסד נתונים, עיבוד רשימת קבצים מקטגוריה של Cloud Storage או פעולה ממושכת, כמו חישוב Pi, יהיו אפשרויות טובות אם הן מיושמות כמשימה ב-Cloud Run.
למשימות אין אפשרות למלא בקשות או להאזין לשקע. המשמעות היא שבניגוד לשירותי Cloud Run, משימות לא יכולות לאגד שרת אינטרנט. במקום זאת, קונטיינרים של משימות צריכים לצאת אחרי שהם הושלמו.
במשימות של Cloud Run, אפשר להריץ מספר עותקים של הקונטיינר במקביל על ידי ציון מספר משימות. כל משימה מייצגת עותק פעיל אחד של מאגר התגים. אפשר להשתמש במספר משימות אם כל משימה יכולה לעבד קבוצת משנה של הנתונים בנפרד. לדוגמה, אם עיבוד של 10,000 רשומות מ-Cloud SQL או 10,000 קבצים מ-Cloud Storage, יכול להתבצע מהר יותר כש-10 משימות מעבדות 1,000 רשומות או קבצים, כל אחת במקביל.
השימוש במשימות של Cloud Run כולל תהליך דו-שלבי:
- יצירת משימה: כולל כל ההגדרות שדרושות להרצת המשימה, כמו קובץ האימג' בקונטיינר, האזור ומשתני הסביבה.
- הרצת המשימה: הפעולה הזו יוצרת ביצוע חדש של המשימה. אפשר גם להגדיר את המשימה כך שתפעל לפי לוח זמנים באמצעות Cloud Scheduler.
בשיעור ה-Codelab הזה, קודם כול תצטרכו לחקור אפליקציה של Node.js כדי לצלם צילומי מסך של דפי אינטרנט ולאחסן אותם ב-Cloud Storage. לאחר מכן, אתם יוצרים קובץ אימג' של קונטיינר לאפליקציה, מריצים אותה במשימות של Cloud Run, מעדכנים את המשימה כדי לעבד דפי אינטרנט נוספים ומריצים את המשימה לפי לוח זמנים באמצעות Cloud Scheduler.
מה תלמדו
- איך משתמשים באפליקציה כדי ליצור צילומי מסך של דפי אינטרנט.
- איך לפתח קובץ אימג' של קונטיינר לאפליקציה.
- איך ליצור משימה ב-Cloud Run לאפליקציה.
- איך להריץ את האפליקציה כמשימה של Cloud Run.
- איך מעדכנים את המשימה.
- איך לתזמן את המשימה באמצעות Cloud Scheduler.
2. הגדרה ודרישות
הגדרת סביבה בקצב אישי
- נכנסים למסוף Google Cloud ויוצרים פרויקט חדש או עושים שימוש חוזר בפרויקט קיים. אם אין לכם עדיין חשבון Gmail או חשבון Google Workspace, עליכם ליצור חשבון.
- Project name הוא השם המוצג של המשתתפים בפרויקט. זו מחרוזת תווים שלא משמשת את Google APIs. תמיד אפשר לעדכן.
- Project ID הוא ייחודי בכל הפרויקטים ב-Google Cloud ואי אפשר לשנות אותו (אי אפשר לשנות אותו אחרי שמגדירים אותו). מסוף Cloud יוצר מחרוזת ייחודית באופן אוטומטי; בדרך כלל לא מעניין אותך מה זה. ברוב ה-codelabs תצטרכו להפנות למזהה הפרויקט שלכם (בדרך כלל מזוהה כ-
PROJECT_ID
). אם המזהה שנוצר לא מוצא חן בעיניכם, אתם יכולים ליצור מזהה אקראי אחר. לחלופין, אפשר לנסות שם משלך ולראות אם הוא זמין. לא ניתן לשנות אותו אחרי השלב הזה, והוא נשאר למשך הפרויקט. - לידיעתך, יש ערך שלישי, Project Number, שבו משתמשים בחלק מממשקי ה-API. מידע נוסף על כל שלושת הערכים האלה זמין במסמכי התיעוד.
- בשלב הבא צריך להפעיל את החיוב במסוף Cloud כדי להשתמש במשאבים או בממשקי API של Cloud. מעבר ב-Codelab הזה לא יעלה הרבה כסף, אם בכלל. כדי להשבית משאבים ולא לצבור חיובים מעבר למדריך הזה, אתם יכולים למחוק את המשאבים שיצרתם או למחוק את הפרויקט. משתמשים חדשים ב-Google Cloud זכאים להשתתף בתוכנית תקופת ניסיון בחינם בשווי 1,200 ש"ח.
הפעלת Cloud Shell
אומנם אפשר להפעיל את Google Cloud מרחוק מהמחשב הנייד, אבל ב-Codelab הזה משתמשים ב-Google Cloud Shell, סביבת שורת הפקודה שפועלת ב-Cloud.
במסוף Google Cloud, לוחצים על הסמל של Cloud Shell בסרגל הכלים שבפינה השמאלית העליונה:
נדרשים רק כמה דקות כדי להקצות את הסביבה ולהתחבר אליה. בסיום התהליך, אתם אמורים לראות משהו כזה:
למכונה הווירטואלית הזו נטען כל כלי הפיתוח הדרושים. יש בה ספריית בית בנפח מתמיד של 5GB והיא פועלת ב-Google Cloud, מה שמשפר משמעותית את ביצועי הרשת והאימות. כל העבודה ב-Codelab הזה יכולה להתבצע בתוך דפדפן. אתה לא צריך להתקין שום דבר.
הגדרת gcloud
ב-Cloud Shell, מגדירים את מזהה הפרויקט ואת האזור שבו רוצים לפרוס את המשימה ב-Cloud Run. שומרים אותם כמשתנים מסוג PROJECT_ID
ו-REGION
. בעתיד תוכלו לבחור אזור מתוך אחד מהמיקומים של Cloud Run.
PROJECT_ID=[YOUR-PROJECT-ID] REGION=us-central1 gcloud config set core/project $PROJECT_ID
הפעלת ממשקי API
מפעילים את כל השירותים הנחוצים:
gcloud services enable \ artifactregistry.googleapis.com \ cloudbuild.googleapis.com \ run.googleapis.com
3. קבל את הקוד
קודם כול אתם משתמשים באפליקציית Node.js כדי לצלם צילומי מסך של דפי אינטרנט ולאחסן אותם ב-Cloud Storage. לאחר מכן תיצרו קובץ אימג' של קונטיינר לאפליקציה ותריצו אותו כמשימה ב-Cloud Run.
מ-Cloud Shell, מריצים את הפקודה הבאה כדי לשכפל את הקוד של האפליקציה מהמאגר הזה:
git clone https://github.com/GoogleCloudPlatform/jobs-demos.git
עוברים לספרייה שמכילה את האפליקציה:
cd jobs-demos/screenshot
אתם אמורים לראות את פריסת הקובץ הבאה:
screenshot | ├── Dockerfile ├── README.md ├── screenshot.js ├── package.json
הנה תיאור קצר של כל קובץ:
screenshot.js
מכיל את קוד Node.js של האפליקציה.package.json
מגדיר את יחסי התלות של הספרייה.Dockerfile
מגדיר את קובץ האימג' של הקונטיינר.
4. לבדיקת הקוד
כדי לעיין בקוד, אפשר להשתמש בכלי המובנה לעריכת טקסט. לשם כך, לוחצים על הלחצן Open Editor
בחלק העליון של החלון של Cloud Shell.
הנה הסבר קצר על כל קובץ.
screenshot.js
קודם כול, screenshot.js
מוסיף את Puppeteer ו-Cloud Storage כתלות. Puppeteer היא ספריית Node.js שבה משתמשים כדי ליצור צילומי מסך של דפי אינטרנט:
const puppeteer = require('puppeteer'); const {Storage} = require('@google-cloud/storage');
יש פונקציית initBrowser
כדי לאתחל את 'יצירת בוב', ואת הפונקציה takeScreenshot
לצילום מסך של כתובת URL מסוימת:
async function initBrowser() { console.log('Initializing browser'); return await puppeteer.launch(); } async function takeScreenshot(browser, url) { const page = await browser.newPage(); console.log(`Navigating to ${url}`); await page.goto(url); console.log(`Taking a screenshot of ${url}`); return await page.screenshot({ fullPage: true }); }
בשלב הבא יש פונקציה שמאפשרת לקבל או ליצור קטגוריה של Cloud Storage, ועוד פונקציה להעלאת צילום מסך של דף אינטרנט לקטגוריה:
async function createStorageBucketIfMissing(storage, bucketName) { console.log(`Checking for Cloud Storage bucket '${bucketName}' and creating if not found`); const bucket = storage.bucket(bucketName); const [exists] = await bucket.exists(); if (exists) { // Bucket exists, nothing to do here return bucket; } // Create bucket const [createdBucket] = await storage.createBucket(bucketName); console.log(`Created Cloud Storage bucket '${createdBucket.name}'`); return createdBucket; } async function uploadImage(bucket, taskIndex, imageBuffer) { // Create filename using the current time and task index const date = new Date(); date.setMinutes(date.getMinutes() - date.getTimezoneOffset()); const filename = `${date.toISOString()}-task${taskIndex}.png`; console.log(`Uploading screenshot as '${filename}'`) await bucket.file(filename).save(imageBuffer); }
לבסוף, הפונקציה main
היא נקודת הכניסה:
async function main(urls) { console.log(`Passed in urls: ${urls}`); const taskIndex = process.env.CLOUD_RUN_TASK_INDEX || 0; const url = urls[taskIndex]; if (!url) { throw new Error(`No url found for task ${taskIndex}. Ensure at least ${parseInt(taskIndex, 10) + 1} url(s) have been specified as command args.`); } const bucketName = process.env.BUCKET_NAME; if (!bucketName) { throw new Error('No bucket name specified. Set the BUCKET_NAME env var to specify which Cloud Storage bucket the screenshot will be uploaded to.'); } const browser = await initBrowser(); const imageBuffer = await takeScreenshot(browser, url).catch(async err => { // Make sure to close the browser if we hit an error. await browser.close(); throw err; }); await browser.close(); console.log('Initializing Cloud Storage client') const storage = new Storage(); const bucket = await createStorageBucketIfMissing(storage, bucketName); await uploadImage(bucket, taskIndex, imageBuffer); console.log('Upload complete!'); } main(process.argv.slice(2)).catch(err => { console.error(JSON.stringify({severity: 'ERROR', message: err.message})); process.exit(1); });
שימו לב לדברים הבאים לגבי ה-method main
:
- כתובות ה-URL מועברות כארגומנטים.
- שם הקטגוריה מועבר כמשתנה הסביבה
BUCKET_NAME
שהוגדר על ידי המשתמש. שם הקטגוריה צריך להיות ייחודי באופן גלובלי בכל מוצרי Google Cloud. - משתנה סביבה
CLOUD_RUN_TASK_INDEX
מועבר על ידי משימות ב-Cloud Run. משימות ב-Cloud Run יכולות להריץ מספר עותקים של האפליקציה כמשימות ייחודיות.CLOUD_RUN_TASK_INDEX
מייצג את האינדקס של המשימה שפועלת. ברירת המחדל של הערך היא אפס כשהקוד מופעל מחוץ למשימות של Cloud Run. כשהאפליקציה פועלת כמספר משימות, כל משימה/מאגר תגים אוספים את כתובת ה-URL שעליה הם אחראים, מצלמים את המסך ושומרים את התמונה בקטגוריה.
package.json
הקובץ package.json
מגדיר את האפליקציה ומציין את יחסי התלות של Cloud Storage ושל Puppeteer:
{ "name": "screenshot", "version": "1.0.0", "description": "Create a job to capture screenshots", "main": "screenshot.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1" }, "author": "Google LLC", "license": "Apache-2.0", "dependencies": { "@google-cloud/storage": "^5.18.2", "puppeteer": "^13.5.1" } }
Dockerfile
השדה Dockerfile
מגדיר את קובץ האימג' של הקונטיינר של האפליקציה עם כל הספריות ויחסי התלות הנדרשים:
FROM ghcr.io/puppeteer/puppeteer:16.1.0 COPY package*.json ./ RUN npm ci --omit=dev COPY . . ENTRYPOINT ["node", "screenshot.js"]
5. פריסת משימה
לפני שיוצרים משימה, צריך ליצור חשבון שירות שבו תשתמשו להפעלת המשימה.
gcloud iam service-accounts create screenshot-sa --display-name="Screenshot app service account"
מקצים לחשבון השירות את התפקיד storage.admin
כדי שיהיה אפשר להשתמש בו ליצירת קטגוריות ואובייקטים.
gcloud projects add-iam-policy-binding $PROJECT_ID \ --role roles/storage.admin \ --member serviceAccount:screenshot-sa@$PROJECT_ID.iam.gserviceaccount.com
עכשיו אתם מוכנים לפרוס משימה ב-Cloud Run שכוללת את ההגדרות הנדרשות כדי להריץ את המשימה.
gcloud beta run jobs deploy screenshot \ --source=. \ --args="https://example.com" \ --args="https://cloud.google.com" \ --tasks=2 \ --task-timeout=5m \ --region=$REGION \ --set-env-vars=BUCKET_NAME=screenshot-$PROJECT_ID \ --service-account=screenshot-sa@$PROJECT_ID.iam.gserviceaccount.com
הפעולה הזו משתמשת בפריסה מבוססת מקור ויוצרת משימה ב-Cloud Run בלי לבצע אותה.
שימו לב איך דפי האינטרנט מועברים כארגומנטים. שם הקטגוריה לשמירת צילומי המסך מועבר כמשתנה סביבה.
אפשר להריץ מספר עותקים של הקונטיינר במקביל על ידי ציון מספר משימות שירוצו באמצעות הדגל --tasks
. כל משימה מייצגת עותק פעיל אחד של מאגר התגים. אפשר להשתמש במספר משימות אם כל משימה יכולה לעבד קבוצת משנה של הנתונים בנפרד. כדי לאפשר זאת, כל משימה מודעת לאינדקס שלה, שמאוחסן במשתנה הסביבה CLOUD_RUN_TASK_INDEX
. הקוד הוא זה שקובע איזו משימה תטפל בקבוצת המשנה של הנתונים. שימו לב ל---tasks=2
בדוגמה הזו. כך אפשר לוודא שהופעלו שני מאגרים עבור שתי כתובות ה-URL שאנחנו רוצים לעבד.
כל משימה יכולה להימשך עד 24 שעות. אפשר להקטין את הזמן הקצוב לתפוגה באמצעות הדגל --task-timeout
, כפי שעשינו בדוגמה הזו. כל המשימות צריכות להצליח כדי שהמשימה תושלם. כברירת מחדל, לא יתבצע ניסיון חוזר למשימות שנכשלו. אתם יכולים להגדיר שמשימות יקבלו ניסיון חוזר אם הן ייכשלו. אם משימה מסוימת חורגת ממספר הניסיונות החוזרים שלה, כל המשימה תיכשל.
כברירת מחדל, המשימה תרוץ עם כמה שיותר משימות במקביל. זה יהיה שווה למספר המשימות למשימה, עד 100. מומלץ להגדיר גישה נמוכה יותר המקבילה למשימות שניגשות לקצה עורפי עם יכולת התאמה מוגבלת. לדוגמה, מסד נתונים שתומך במספר מוגבל של חיבורים פעילים. אפשר להפחית את המקבילות עם הדגל --parallelism
.
6. הפעלת משימה
לפני שמריצים את המשימה, צריך לרשום את המשימה כדי לראות שהיא נוצרה:
gcloud run jobs list ✔ JOB: screenshot REGION: us-central LAST RUN AT: CREATED: 2022-02-22 12:20:50 UTC
מריצים את המשימה באמצעות הפקודה הבאה:
gcloud run jobs execute screenshot --region=$REGION
הפעולה הזו תבצע את המשימה. אפשר להציג רשימה של ניסיונות הפעלה נוכחיים וקודמים:
gcloud run jobs executions list --job screenshot --region=$REGION ... JOB: screenshot EXECUTION: screenshot-znkmm REGION: $REGION RUNNING: 1 COMPLETE: 1 / 2 CREATED: 2022-02-22 12:40:42 UTC
מתארים את הביצוע. אתם אמורים לראות סימן וי ירוק ואת ההודעה tasks completed successfully
:
gcloud run jobs executions describe screenshot-znkmm --region=$REGION ✔ Execution screenshot-znkmm in region $REGION 2 tasks completed successfully Image: $REGION-docker.pkg.dev/$PROJECT_ID/containers/screenshot at 311b20d9... Tasks: 2 Args: https://example.com https://cloud.google.com Memory: 1Gi CPU: 1000m Task Timeout: 3600s Parallelism: 2 Service account: 11111111-compute@developer.gserviceaccount.com Env vars: BUCKET_NAME screenshot-$PROJECT_ID
אתם יכולים גם להיכנס לדף המשימות ב-Cloud Run במסוף Cloud כדי לראות את הסטטוס:
אם בודקים את הקטגוריה של Cloud Storage, אמורים לראות את שני קובצי צילומי המסך שנוצרו:
לפעמים צריך לעצור הפעלה לפני שהיא מסתיימת – אולי כי הבנתם שצריך להריץ את המשימה עם פרמטרים שונים או שיש שגיאה בקוד, ואתם לא רוצים לנצל זמן מחשוב מיותר.
כדי להפסיק את הביצוע של המשימה, צריך למחוק את הביצוע:
gcloud run jobs executions delete screenshot-znkmm --region=$REGION
7. עדכון משרה
גרסאות חדשות של הקונטיינר לא יאספו באופן אוטומטי על ידי משימות של Cloud Run בהפעלה הבאה. אם משנים את הקוד של המשימה, צריך ליצור מחדש את הקונטיינר ולעדכן את המשימה. שימוש בתמונות מתויגות יעזור לך לזהות איזו גרסה של התמונה נמצאת בשימוש כרגע.
באופן דומה, צריך לעדכן גם את המשימה אם רוצים לעדכן חלק ממשתני ההגדרה. ההפעלות הבאות של המשימה יתבססו על ההגדרות החדשות של הקונטיינר והתצורה.
מעדכנים את המשימה ומשנים את הדפים שהאפליקציה מצלמת בהם צילומי מסך בדגל --args
. צריך לעדכן גם את הדגל --tasks
כך שישקף את מספר הדפים.
gcloud run jobs update screenshot \ --args="https://www.pinterest.com" \ --args="https://www.apartmenttherapy.com" \ --args="https://www.google.com" \ --region=$REGION \ --tasks=3
מריצים את המשימה שוב. הזמן הזה עובר בדגל --wait
כדי להמתין שההפעלות יסתיימו:
gcloud run jobs execute screenshot --region=$REGION --wait
אחרי כמה שניות אמורים להופיע עוד 3 צילומי מסך שנוספו לקטגוריה:
8. תזמון משימה
עד עכשיו הרצת משימות באופן ידני. בתרחיש בעולם האמיתי, סביר להניח שתרצו להריץ משימות בתגובה לאירוע או לפי לוח זמנים. בואו נראה איך להריץ את משימת צילום המסך לפי לוח זמנים באמצעות Cloud Scheduler.
קודם כל צריך לוודא ש-Cloud Scheduler API מופעל:
gcloud services enable cloudscheduler.googleapis.com
נכנסים לדף הפרטים של המשימות ב-Cloud Run ולוחצים על הקטע Triggers
:
לוחצים על Add Scheduler Trigger
:
בפינה השמאלית תיפתח חלונית. יוצרים משימת תזמון שתרוץ מדי יום בשעה 9:00 עם ההגדרות האישיות האלה ובוחרים באפשרות Continue
:
בדף הבא, בוחרים את חשבון שירות המחשוב שמוגדר כברירת מחדל ואז בוחרים באפשרות Create
:
עכשיו אתם אמורים לראות שנוצר טריגר חדש של Cloud Scheduler:
לוחצים על View Details
כדי לעבור לדף Cloud Scheduler.
אפשר להמתין עד 9:00 עד שהמתזמן ייכנס לתוקף, או להפעיל את Cloud Scheduler באופן ידני על ידי בחירה באפשרות Force Run
:
לאחר מספר שניות אתם אמורים לראות שהמשימה Cloud Scheduler בוצעה בהצלחה:
אמורים להופיע גם 3 צילומי מסך נוספים שנוספו על ידי השיחה מ-Cloud Scheduler:
9. מזל טוב
כל הכבוד, סיימת את ה-Codelab!
ניקוי (אופציונלי)
כדי להימנע מחיובים, מומלץ לנקות משאבים.
אם אין לכם צורך בפרויקט, אפשר פשוט למחוק את הפרויקט:
gcloud projects delete $PROJECT_ID
אם אתם צריכים את הפרויקט, תוכלו למחוק משאבים בנפרד.
מוחקים את קוד המקור:
rm -rf ~/jobs-demos/
מוחקים את המאגר של Artifact Registry:
gcloud artifacts repositories delete containers --location=$REGION
מוחקים את חשבון השירות:
gcloud iam service-accounts delete screenshot-sa@$PROJECT_ID.iam.gserviceaccount.com
מחיקת המשימה ב-Cloud Run:
gcloud run jobs delete screenshot --region=$REGION
מחיקת המשימה של Cloud Scheduler:
gcloud scheduler jobs delete screenshot-scheduler-trigger --location=$REGION
מוחקים את הקטגוריה של Cloud Storage:
gcloud storage rm --recursive gs://screenshot-$PROJECT_ID
הנושאים שטיפלנו בהם
- איך משתמשים באפליקציה כדי ליצור צילומי מסך של דפי אינטרנט.
- איך לפתח קובץ אימג' של קונטיינר לאפליקציה.
- איך ליצור משימה ב-Cloud Run לאפליקציה.
- איך להריץ את האפליקציה כמשימה של Cloud Run.
- איך מעדכנים את המשימה.
- איך לתזמן את המשימה באמצעות Cloud Scheduler.