ארגז חול

המאמר הזה עוסק בארגז חול ב-Bazel, מתקין את sandboxfs וניפוי באגים בסביבת ארגז החול.

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

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

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

באופן ספציפי יותר, Bazel יוצרת ספריית execroot/ לכל פעולה, המשמשת כספריית העבודה של הפעולה בזמן הביצוע. execroot/ מכיל את כל קובצי הקלט לפעולה, ומשמש כמאגר של הפלט שנוצר. לאחר מכן, בזל משתמשת בשיטה שהוגדרה על ידי מערכת ההפעלה: מאגרים ב-Linux וב-macOS: sandbox-exec כדי להגביל את הפעולה בתוך execroot/.

סיבות לארגז חול

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

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

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

באיזו אסטרטגיית ארגז חול להשתמש

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

השיטה local (שנקראת גם standalone) לא כוללת ארגז חול כלשהו. היא פשוט מפעילה את שורת הפקודה של הפונקציה כאשר הספרייה הפעילה מוגדרת ב-Workspace של סביבת העבודה שלכם.

processwrapper-sandbox היא אסטרטגיית ארגז חול שאינה דורשת תכונות כלשהן של &מירכאות; מתקדם - היא אמורה לפעול בכל מערכת POSIX מחוץ לאריזה. היא יוצרת ספריית ארגז חול שמורכבת מקישורים סמלים שמצביעים על קובצי המקור המקוריים, מפעילה את שורת הפקודה של הפעולה עם ספריית העבודה המוגדרת לספרייה הזו במקום קובץ ה-exe, ולאחר מכן מעבירה את פריטי הפלט הידועים אל מחוץ לארגז החול אל ה-שורש, ומוחקת את ארגז החול. כך לא תינקט פעולה בטעות כדי להשתמש בקובצי קלט שלא הוצהרו, או כדי להוציא את קובץ הפלט מקובצי פלט לא ידועים.

linux-sandbox מתקדם צעד אחד קדימה, ומקיף את processwrapper-sandbox. בדומה למה שקורה ב-Docker, היא משתמשת במרחבי שמות ב-Linux (מרחבי משתמש, הר, PID, רשת ו-IPC) כדי לבודד את הפעולה מהמארח. כלומר, כל מערכת הקבצים היא לקריאה בלבד, מלבד ספריית ארגז החול, כך שהפעולה לא יכולה לשנות בטעות שום דבר במערכת הקבצים של המארח. התכונה הזו מונעת מצבים כמו בדיקת באגים בטעות Rf'ing בספריית $HOME. אפשר גם למנוע את הגישה של הפעולה לרשת. linux-sandbox משתמש במרחבי שמות של PID כדי למנוע לפעולה לראות תהליכים אחרים ולסיים את כל התהליכים (גם daemons) שמופעים בסוף.

darwin-sandbox דומה, אבל ל-macOS. היא משתמשת בכלי sandbox-exec של Apple כדי להגיע בערך פחות או יותר לארגז החול של Linux.

המאפיינים linux-sandbox ו-darwin-sandbox לא פועלים בתרחיש "nested" במגבלות על הגבלות במנגנוני המערכת שסופקו. מכיוון ש-Docker גם משתמשת במרחבי שמות של Linux בקסם המאגר שלה, לא ניתן להריץ בקלות את linux-sandbox בתוך מאגר ב-Docker, אלא אם משתמשים ב-docker run --privileged. ב-macOS, אי אפשר להריץ את sandbox-exec בתוך תהליך שכבר נמצא בארגז חול. לכן, במקרים כאלה, Bazel חוזרת אוטומטית להשתמש ב-processwrapper-sandbox.

אם אתם מעדיפים לקבל שגיאת build - למשל, כדי לא ליצור בטעות שיטת בידינג פחות מחמירה - עליכם לשנות במפורש את רשימת שיטות הביצוע ש-Bazel מנסה להשתמש בהן (לדוגמה, bazel build --spawn_strategy=worker,linux-sandbox).

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

חסרונות לארגז חול

  • השימוש בארגז החול כרוך בהגדרה נוספת ובעלויות פירוק. העלות הזו תלויה בגורמים רבים, כולל הצורה של ה-build והביצועים של מערכת ההפעלה של המארח. כשמדובר ב-Linux, גרסאות build בארגז חול מעטות לעיתים רחוקות יותר בכמה אחוזים. הגדרת --reuse_sandbox_directories יכולה לצמצם את ההגדרה ואת פירוק העלויות.

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

  • כדי לעבוד עם Multiplex workers צריך להגדיר תמיכה מפורשת בעובדים בארגז חול. עובדים שלא תומכים בארגז חול עם ארגז חול יכולים לפעול כעובדים חד-פעמיים במסגרת ביצוע דינמי. מצב זה עשוי לעלות יותר זיכרון.

משחקים בסגנון ארגז חול

sandboxfs היא מערכת קבצים בפורמט FUSE שחושפת תצוגה שרירותית של מערכת הקבצים הבסיסית ללא קנסות זמן. Bazel משתמשת ב-sandboxfs כדי ליצור באופן מיידי execroot/ לכל פעולה, וכך מונעת את העלות של אלפי קריאות למערכת. חשוב לשים לב שחיבור I/O נוסף ב-execroot/ עשוי להיות איטי יותר עקב תקורה של FUSE.

התקנת sandboxf

כדי להתקין את sandboxfs ולבצע build של Bazel באמצעות השלבים הבאים:

הורדה

מורידים ומתקינים sandboxfs כדי שהקובץ הבינארי של sandboxfs יסתיים ב-PATH שלך.

הפעלה של sandboxfs

  1. (macOS בלבד) התקנת OSXFUSE.
  2. (macOS בלבד) הפעלה:

    sudo sysctl -w vfs.generic.osxfuse.tunables.allow_other=1
    

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

  3. הפעלת build של Bazel באמצעות --experimental_use_sandboxfs.

    bazel build target --experimental_use_sandboxfs
    

פתרון בעיות

אם במקום local בוצעו darwin-sandbox או linux-sandbox הופיעו הערות לגבי הפעולות שבוצעו, ייתכן שארגז החול הושבת. אפשר להפעיל את --genrule_strategy=sandboxed --spawn_strategy=sandboxed כדי להפעיל אותה.

ניפוי באגים

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

מרחבי שמות מושבתים

בפלטפורמות מסוימות, כמו Google Kubernetes Engine, צמתים של אשכולות או Debian, מרחבי השמות של משתמשים מושבתים כברירת מחדל בשל בעיות אבטחה. אם הקובץ /proc/sys/kernel/unprivileged_userns_clone קיים ומכיל 0, אפשר להפעיל מרחבי שמות של משתמשים באמצעות הפונקציה:

   sudo sysctl kernel.unprivileged_userns_clone=1

כשלים בביצוע כלל

ייתכן שארגז החול לא יבצע כללים בגלל הגדרת המערכת. אם מופיעה הודעה כמו namespace-sandbox.c:633: execvp(argv[0], argv): No such file or directory, אפשר לנסות להשבית את ארגז החול עם --strategy=Genrule=local עבור כללי כלל ואת --spawn_strategy=local עבור כללים אחרים.

ניפוי באגים מפורט במקרה של כשלים ב-build

אם ה-build שלך נכשל, יש להשתמש ב---verbose_failures וב---sandbox_debug כדי לגרום ל-Bazel להציג את הפקודה המדויקת שבה היא פעלה כשה-build נכשל, כולל החלק שמגדיר את ארגז החול.

הודעת שגיאה לדוגמה:

ERROR: path/to/your/project/BUILD:1:1: compilation of rule
'//path/to/your/project:all' failed:

Sandboxed execution failed, which may be legitimate (such as a compiler error),
or due to missing dependencies. To enter the sandbox environment for easier
debugging, run the following command in parentheses. On command failure, a bash
shell running inside the sandbox will then automatically be spawned

namespace-sandbox failed: error executing command
  (cd /some/path && \
  exec env - \
    LANG=en_US \
    PATH=/some/path/bin:/bin:/usr/bin \
    PYTHONPATH=/usr/local/some/path \
  /some/path/namespace-sandbox @/sandbox/root/path/this-sandbox-name.params --
  /some/path/to/your/some-compiler --some-params some-target)

עכשיו תוכלו לבדוק את ספריית ארגז החול שנוצרה ולראות אילו קבצים Bazel יצרו ולהריץ את הפקודה שוב כדי לראות את התנהגותה.

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