שמירה מרחוק במטמון

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

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

סקירה כללית

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

תוכלו להגדיר שרת כמטמון מרוחק עבור פלטי build, שהם פלטי הפעולה. הפלטים האלה מכילים רשימה של שמות קובצי פלט וגיבובים של התוכן שלהם. בעזרת מטמון מרוחק, אפשר לעשות שימוש חוזר בפלטי build מ-build של משתמש אחר, במקום ליצור כל פלט חדש באופן מקומי.

כדי להשתמש במטמון מרוחק:

  • הגדרת שרת כשרת העורפי של המטמון
  • יש להגדיר את ה-build של Bazel להשתמש במטמון המרוחק
  • להשתמש ב-Bazel בגרסה 0.10.0 ואילך

המטמון המרוחק מאחסן שני סוגי נתונים:

  • מטמון הפעולות, שהוא מפה של גיבובי פעולות עבור מטא-נתונים של תוצאות הפעולה.
  • חנות שניתנת לתוכן (CAS) של קובצי פלט.

חשוב לזכור שהמטמון המרוחק שומר גם את ה-stdout וה-stderr לכל פעולה. לכן, מומלץ לבדוק את ה-stdout/stderr של Bazel לצורך הערכת היטים במטמון.

איך גרסת build משמשת לשמירה במטמון במטמון

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

  • קריאה וכתיבה במטמון המרוחק
  • קריאה ו/או כתיבה במטמון המרוחק למעט יעדים ספציפיים
  • קריאה רק מהמטמון המרוחק
  • לא להשתמש בכלל במטמון המרוחק

כשאתם מריצים גרסת build של Bazel שאפשר לקרוא ולכתוב במטמון המרוחק, ה-build צריך לבצע את השלבים הבאים:

  1. Bazel יוצרת גרף של יעדים שצריך ליצור, ולאחר מכן יוצרת רשימה של פעולות נדרשות. בכל אחת מהפעולות האלה בוצעה הצהרה על קלט ושמות קבצים.
  2. Bazel בודקת אם יש במכשיר שלכם פלטי build קיימים ונעשה בהם שימוש חוזר במוצאים.
  3. Bazel בודק אם יש פלט קיים במטמון. אם הפלט נמצא, Bazel מאחזר את הפלט. זהו היט מטמון.
  4. עבור פעולות נדרשות שלא נמצאו בהן הפלט, בזל מבצע את הפעולות באופן מקומי ויוצר את פלטי ה-build הנדרשים.
  5. פלטי build חדשים מועלים למטמון המרוחק.

הגדרת שרת כקצה העורפי למטמון

עליך להגדיר שרת כדי שישמש כשרת הקצה העורפי למטמון. שרת HTTP/1.1 יכול להתייחס לנתונים של Bazel' כבייטים אטומים ושל כל כך הרבה שרתים קיימים שיכולים לשמש כשרת עורפי לשמירה במטמון. Bazel's פרוטוקול HTTP לשמירה במטמון הוא פרוטוקול שעוזר לשמור במטמון מרוחק.

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

  • מהירות הרשת. לדוגמה, אם הצוות נמצא באותו משרד, ייתכן שתרצו להריץ שרת מקומי משלכם.
  • אבטחה. המטמון הבינארי מרחוק יכלול את הקבצים הבינאריים שלכם, ולכן הוא צריך להיות מאובטח.
  • קל לנהל. לדוגמה: שירות Google Cloud Storage הוא שירות מנוהל.

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

nginx

nginx הוא שרת אינטרנט בקוד פתוח. עם [WebDAV מודול] שלו, אפשר להשתמש בו כמטמון מרוחק עבור Bazel. ב-Debian וב-Ubuntu אפשר להתקין את החבילה nginx-extras. ב-macOS nginx זמינה דרך Homebrew:

brew tap denji/nginx
brew install nginx-full --with-webdav

לפניכם הגדרה לדוגמה של nginx. לתשומת ליבכם: תצטרכו לשנות את /path/to/cache/dir לספרייה חוקית שבה ל-nginx יש הרשאה לכתוב ולקרוא. אם יש לך קובצי פלט גדולים יותר, ייתכן שתצטרכו לשנות את האפשרות client_max_body_size לערך גדול יותר. השרת ידרוש הגדרות אחרות, כמו אימות.

הגדרה לדוגמה של הקטע server ב-nginx.conf:

location /cache/ {
  # The path to the directory where nginx should store the cache contents.
  root /path/to/cache/dir;
  # Allow PUT
  dav_methods PUT;
  # Allow nginx to create the /ac and /cas subdirectories.
  create_full_put_path on;
  # The maximum size of a single file.
  client_max_body_size 1G;
  allow all;
}

Bazel מרוחק

bazel-remote הוא מטמון build בקוד פתוח שניתן להשתמש בו בתשתית. השימוש בה נמצא בהצלחה בייצור בכמה חברות מאז תחילת 2018. שימו לב שפרויקט Bazel לא מספק תמיכה טכנית לשלט רחוק.

המטמון הזה מאחסן תוכן בדיסק וגם מספק איסוף אשפה כדי לאכוף את מגבלת האחסון העליונה ופריטים נקיים שאינם בשימוש. המטמון זמין כ-[docker image] והקוד שלו זמין ב-GitHub. ממשקי API ל-REST ו-gRPC במטמון נתמכים.

בדף GitHub תמצאו הוראות לשימוש.

Google Cloud Storage

[Google Cloud Storage] היא חנות אובייקטים מנוהלת שמספקת ממשק API ל-HTTP שתואם לפרוטוקול השמירה במטמון מרחוק של Bazel&#39. לשם כך, צריך להיות לכם חשבון Google Cloud שבו החיוב מופעל.

כדי להשתמש ב-Cloud Storage בתור המטמון:

  1. יוצרים קטגוריית אחסון. ודאו שבחרתם מיקום בקטגוריה הקרובה אליכם, כי רוחב הפס חשוב לרשת המטמון המרוחק.

  2. יצירת חשבון שירות ל-Bazel לצורך אימות ב-Cloud Storage. איך יוצרים חשבון שירות?

  3. יש ליצור מפתח JSON סודי ולאחר מכן להעביר אותו ל-Bazel לאימות. מאחסנים את המפתח באופן מאובטח, כי כל מי שיש לו את המפתח יכול לקרוא ולכתוב נתונים שרירותיים מקטגוריית GCS שלכם.

  4. מתחברים ל-Cloud Storage על ידי הוספה של הסימונים הבאים לפקודה Bazel:

    • מעבירים את כתובת ה-URL הבאה ל-Bazel באמצעות הסימון: --remote_cache=https://storage.googleapis.com/bucket-name כאשר bucket-name הוא שם קטגוריית האחסון.
    • עליך להעביר את מפתח האימות באמצעות הסימון: --google_credentials=/path/to/your/secret-key.json, או --google_default_credentials כדי להשתמש באימות אפליקציות.
  5. ניתן להגדיר ב-Cloud Storage מחיקה אוטומטית של קבצים ישנים. לשם כך, קראו את המאמר ניהול מחזורי חיים של אובייקטים.

שרתים אחרים

אתם יכולים להגדיר כל שרת HTTP/1.1 שתומך ב-PUT וב-GET כמטמון העורפי&#39.s. משתמשים דיווחו על הצלחה באמצעות הקצה העורפי במטמון, כמו Hazelcast, Apache httpd ו-AWS S3.

אימות

החל מגרסה 0.11.0, האימות הבסיסי ל-HTTP נוסף ל-Bazel. ניתן להעביר שם משתמש וסיסמה ל-Bazel דרך כתובת האתר של המטמון המרוחק. הסינקציה היא https://username:[email protected]:port/path. חשוב לדעת ש'אימות HTTP בסיסי' משדר שם משתמש וסיסמה בטקסט פשוט ברשת, ולכן חשוב להשתמש בו תמיד ב-HTTPS.

פרוטוקול שמירה במטמון של HTTP

Bazel תומכת במטמון מרוחק באמצעות HTTP/1.1. הפרוטוקול פשוט בצורה קונספט: נתונים בינאריים (BLOB) מועלים דרך בקשות PUT ומורידים אותן באמצעות בקשות GET. המטא-נתונים של תוצאות הפעולה מאוחסנים בנתיב /ac/, וקובצי הפלט מאוחסנים בנתיב /cas/.

לדוגמה, נניח שמטמון מרוחק שפועל מתחת ל-http://localhost:8080/cache. בקשת Bazel להורדה של מטא-נתונים של פעולת פעולה עבור פעולת הגיבוב SHA256 01ba4719... תיראה כך:

GET /cache/ac/01ba4719c80b6fe911b091a7c05124b64eeece964e09c058ef8f9805daca546b HTTP/1.1
Host: localhost:8080
Accept: */*
Connection: Keep-Alive

בקשת Bazel להעלאת קובץ פלט עם גיבוב SHA256 15e2b0d3... ל-CAS תיראה כך:

PUT /cache/cas/15e2b0d3c33891ebb0f1ef609ec419420c20e320ce94c65fbc8c3312448eb225 HTTP/1.1
Host: localhost:8080
Accept: */*
Content-Length: 9
Connection: Keep-Alive

0x310x320x330x340x350x360x370x380x39

הפעלת Bazel באמצעות מטמון מרוחק

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

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

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

  • במחשב המקומי שלך
  • בסביבת העבודה של הפרויקט, משותפת עם הצוות
  • במערכת ה-CI

קריאה וכתיבה במטמון המרוחק

בודקים מי יכול לכתוב למטמון המרוחק. אולי כדאי שרק מערכת ה-CI תוכל לכתוב למטמון המרוחק.

צריך להשתמש בסימון הבא כדי לקרוא ממנו ולכתוב במטמון המרוחק:

build --remote_cache=http://your.host:port

בנוסף ל-HTTP, הפרוטוקולים הבאים נתמכים גם: HTTPS, grpc, grpcs.

כדאי להשתמש בסימון הבא בנוסף לסמל שלמעלה כדי לקרוא רק מהמטמון המרוחק:

build --remote_upload_local_results=false

החרגת יעדים ספציפיים משימוש במטמון המרוחק

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

java_library(
    name = "target",
    tags = ["no-cache"],
)

מחיקת תוכן מהמטמון המרוחק

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

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

מומלץ למחוק תוכן מהמטמון כדי:

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

שקעי יוניקס

מטמון ה-HTTP המרוחק תומך בהתחברות לשקעי דומיין ב-Unix. ההתנהגות הזו דומה לסימון --unix-socket ב-curl&#39. יש להשתמש בפרמטרים הבאים כדי להגדיר שקע דומיין Unix:

   build --remote_cache=http://your.host:port
   build --remote_cache_proxy=unix:/path/to/socket

התכונה הזו לא נתמכת ב-Windows.

מטמון אחסון

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

build --disk_cache=path/to/build/cache

ניתן להעביר נתיב ספציפי למשתמש לסימון --disk_cache באמצעות הכינוי ~ (Bazel יחליף את ספריית הבית של המשתמש הנוכחי). פעולה זו שימושית כאשר מפעילים את מטמון הדיסק לכל המפתחים של פרויקט מסוים דרך קובץ .bazelrc.

בעיות ידועות

שינוי קובץ קלט במהלך build

כשקובץ קלט משתנה, גרסת Bazel עשויה להעלות תוצאות לא חוקיות למטמון המרוחק. ניתן להפעיל זיהוי שינויים באמצעות הסימון --experimental_guard_against_concurrent_changes. אין בעיות ידועות, והיא תופעל כברירת מחדל במהדורה עתידית. העדכונים זמינים בכתובת [בעיה מס' 3360]. ככלל, הימנעו משינוי קובצי המקור במהלך build.

משתני סביבה שדלפים לפעולה

הגדרת פעולה מכילה משתני סביבה. זו יכולה להיות בעיה בשיתוף היטים מרוחקים של מטמון בין מחשבים. לדוגמה, סביבות שיש בהן משתנים של $PATH שונים לא ישתפו היטים של מטמון. רק משתני סביבה שמסומנים במפורש ברשימת ההיתרים דרך --action_env כלולים בהגדרה של הפעולה. חבילת Debian/Ubuntu של Bazel'להתקנת /etc/bazel.bazelrc עם רשימת היתרים של משתני סביבה, כולל $PATH. אם אתם מקבלים פחות היטים מהצפוי במטמון, כדאי לבדוק שבסביבה שלכם אין קובץ /etc/bazel.bazelrc ישן.

Bazel לא עוקבת אחרי כלים מחוץ לסביבת העבודה

בשלב הזה, Bazel לא עוקבת אחרי כלים מחוץ לסביבת העבודה. זו יכולה להיות בעיה אם, לדוגמה, פעולה משתמשת במהדר מ-/usr/bin/. לאחר מכן, שני משתמשים שמהדרים שונים מתקינים זה את זה בצורה שגויה, מומלץ לעיין בבעיה מס' 4558 לקבלת עדכונים.

מצב זיכרון מוגבל מצטבר בעת ריצה של גרסאות build בקונטיינרים שלDocker Bazel משתמשת בארכיטקטורת שרת/לקוח גם בעת הרצה בקונטיינר אחד של אביזר עגינה. בצד השרת, Bazel שומרת מצב זיכרון בזיכרון שמאיץ את גרסת ה-build. בעת הפעלת builds מתוך מאגרי עגינה כמו ב-CI, מצב הזיכרון אבד ו-Bazel חייב לבנות אותו מחדש לפני השימוש במטמון המרוחק.