沙箱機制

回報問題 查看原始碼 夜間 7.2 7.1 7.0 6.5 6.4

本文會介紹 Bazel 中的沙箱機制、安裝 sandboxfs 及偵錯 實作沙箱環境

「沙箱」是一種權限限制策略,可將程序 或系統中的資源至於 Bazel,這代表系統會限制 系統存取權。

Bazel 的檔案系統沙箱會在僅工作目錄中執行處理程序 包含已知的輸入內容,因此編譯器和其他工具不會看到來源 使用者不得存取這些檔案,除非他們知道這些檔案的絕對路徑。

沙箱機制無法以任何方式隱藏主機環境。程序可自由地 存取檔案系統中的所有檔案。但在支援使用者的平台上 命名空間,程序無法修改工作目錄以外的任何檔案。 這可確保建構圖表沒有隱藏依附元件 會影響版本的可重現性

具體來說,Bazel 會為每個動作建構 execroot/ 目錄。 做為動作在執行時間execroot/ 包含動作的所有輸入檔案,且可做為任何 輸出內容Bazel 接著會使用作業系統提供的技術 Linux 和 macOS 上的 sandbox-exec 容器,以便限制在 execroot/

採用沙箱機制的原因

  • 如未宣告動作沙箱,Bazel 無法得知工具是否使用未宣告的 (在該檔案的依附元件中,沒有明確列出的檔案) 動作)。當其中一個未宣告的輸入檔案變更時,Bazel 仍會 認為建構是最新版本,不會重新建立動作。這可以 進而產生錯誤的漸進式建構作業

  • 若是以不正確的方式重複使用快取項目,將會在遠端快取期間發生問題。A 罩杯 如果共用快取中有錯誤的快取項目,會影響專案的每位開發人員, 並清除整個遠端快取並非可行的解決方案。

  • 沙箱機制會模仿遠端執行的行為 (如果建構能順利運作) 也支援遠端執行藉由 遠端執行上傳所有必要檔案 (包括本機工具),您可以 相較於 2018 年, 不必在每次安裝時 試用新的編譯器,或變更現有工具。

採用的沙箱策略

利用 策略標記。使用 sandboxed 策略會讓 Bazel 從下列一種沙箱實作項目中選擇一種 偏好作業系統專屬的沙盒,而不是普通的通用沙箱。 永久工作站會在您通過測試時,在一般沙箱中執行 --worker_sandboxing 旗標。

local (又稱為 standalone) 策略並非執行任何類型的沙箱作業。 它只會執行動作的指令列,並將工作目錄設定為 工作區的執行者

processwrapper-sandbox 是不需要任何測試機制的沙箱策略 「進階」功能 - 立即適用於任何現成的 POSIX 系統,這項服務 會建立沙箱目錄,包含指向原始版本的符號連結 來源檔案,使用工作目錄集執行動作的指令列 移至這個目錄 (而非 execroot),再移動已知的輸出構件 並刪除沙箱。這樣一來, 操作,導致您誤以為 減少輸出檔案的 execroot

linux-sandbox 更進一步,奠基於 processwrapper-sandbox。與 Docker 的功能類似 Linux 命名空間 (User、掛接、PID、網路和 IPC 命名空間) 以便隔離 動作。也就是說,這麼做會將整個檔案系統設為唯讀, ,因此該動作不會意外修改 主機檔案系統這可避免錯誤測試等情況意外觸發 -rf 是您的 $HOME 目錄。或者,您也可以防止動作 存取網路linux-sandbox 會使用 PID 命名空間防止動作 偵測其他處理程序及穩定終止所有程序 (即使是 Daemon 也不例外) 延伸至結尾。

darwin-sandbox 很類似,但適用於 macOS。使用 Apple 的「sandbox-exec」工具 執行的實作效果大致與 Linux 沙箱相同

linux-sandboxdarwin-sandbox 都不適用於「巢狀」 因作業平台所提供機制的限制 有些人會將 Cloud Storage 視為檔案系統 但實際上不是由於 Docker 也會使用 Linux 命名空間來發揮容器神奇效果 無法在 Docker 容器中執行 linux-sandbox,除非您使用 docker run --privileged。在 macOS 上,您無法在 sandbox-exec 已加上沙箱的處理程序因此,在這類情況下 會自動改回使用 processwrapper-sandbox

這樣會發生建構錯誤,例如避免不小心使用 執行策略較不嚴格的執行策略 — 明確修改執行清單 Bazel 嘗試使用的策略 (例如 bazel build --spawn_strategy=worker,linux-sandbox)。

動態執行通常需要在本機執行時採用沙箱機制。如要停用, 傳遞 --experimental_local_lockfree_output 標記。動態執行,不發出任何通知 沙箱的永久工作站

採用沙箱機制的缺點

  • 沙箱作業需要額外的設定及拆解成本。這筆費用有多大 實際速度取決於許多因素,包括構建形狀 也能確保主機 OS 的效能對 Linux 來說,沙箱版本極少發生 因此運作速度會減慢一些設定--reuse_sandbox_directories可 可減少設定及成本

  • 沙箱機制實際上會有效停用工具的所有快取。你可以 使用永久工作站即可減少這種情況, 以及效能低弱的沙箱保證成本

  • 多重工作站」需要明確的工作站支援 沙箱模式不支援多工沙箱的工作站將 動態執行下的單面工作站,可能會耗用額外的記憶體。

沙盒

sandboxfs 是 FUSE 檔案系統,可以公開 不會造成時間懲處Bazel 使用 sandboxfs 會立即產生每個動作的 execroot/,避免 發出數千個系統呼叫請注意,execroot/ 內之後的 I/O 可能會 但由於 FUSE 負擔,因此速度較慢。

安裝 Sandboxf

請按照下列步驟安裝 sandboxfs,並使用 它:

下載

下載並安裝 sandboxfs 後,sandboxfs 二進位檔就會位於 PATH 中。

執行 sandboxfs

  1. (僅限 macOS) 安裝 OSXFUSE
  2. (僅限 macOS) 執行:

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

    請在安裝完成後和每次重新啟動後完成這項操作,以便確保 核心 macOS 系統服務可透過沙箱運作。

  3. 使用 --experimental_use_sandboxfs 執行 Bazel 建構作業。

    bazel build target --experimental_use_sandboxfs
    

疑難排解

如果看到 local,而不是 darwin-sandboxlinux-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 停用沙箱: genrules,--spawn_strategy=local 則適用於其他規則。

建構失敗的詳細偵錯資訊

如果建構失敗,請使用 --verbose_failures--sandbox_debug Bazel 會顯示建構失敗時的確切執行指令,包括 用來設定沙箱

錯誤訊息範例:

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,因為它會隨著時間填滿磁碟。