แซนด์บ็อกซ์

วันที่ รายงานปัญหา ดูแหล่งที่มา ตอนกลางคืน · 7.3 · 7.2 · 7.1 · 7.0 · 6.5

บทความนี้กล่าวถึงแซนด์บ็อกซ์ใน Bazel, การติดตั้ง sandboxfs และการแก้ไขข้อบกพร่อง สภาพแวดล้อมแซนด์บ็อกซ์ของคุณ

แซนด์บ็อกซ์เป็นกลยุทธ์สิทธิ์ที่จำกัด ซึ่งแยกกระบวนการออกจาก หรือจากทรัพยากรในระบบ สำหรับ Bazel นี่หมายถึงการจำกัดไฟล์ การเข้าถึงระบบ

แซนด์บ็อกซ์ระบบไฟล์ของ Bazel เรียกใช้กระบวนการในไดเรกทอรีที่ทำงานซึ่ง มีอินพุตที่รู้จักซึ่งคอมไพเลอร์และเครื่องมืออื่นๆ จะไม่เห็นแหล่งที่มา ไฟล์ที่ผู้ใช้ไม่ควรเข้าถึง เว้นแต่จะทราบเส้นทางที่แน่นอนที่เข้าถึง

แซนด์บ็อกซ์ไม่ได้ซ่อนสภาพแวดล้อมของโฮสต์ไม่ว่าในลักษณะใดก็ตาม กระบวนการต่างๆ สามารถทำได้อย่างอิสระ เข้าถึงไฟล์ทั้งหมดในระบบไฟล์ อย่างไรก็ตาม บนแพลตฟอร์มที่รองรับผู้ใช้ เนมสเปซ กระบวนการจะแก้ไขไฟล์นอกไดเรกทอรีที่ใช้งานอยู่ไม่ได้ ซึ่งทำให้กราฟของบิลด์ไม่มีทรัพยากร Dependency ที่ซ่อนอยู่ ส่งผลต่อความสามารถในการทำซ้ำของบิลด์

กล่าวอย่างเจาะจงก็คือ Bazel สร้างไดเรกทอรี execroot/ สำหรับการดำเนินการแต่ละรายการ ซึ่งทำหน้าที่เป็นไดเรกทอรีงานของการดำเนินการ ณ เวลาที่ดำเนินการ execroot/ เก็บไฟล์อินพุตทั้งหมดสำหรับการทำงาน และทำหน้าที่เป็นคอนเทนเนอร์สำหรับ ที่สร้างขึ้น จากนั้น Bazel ใช้เทคนิคที่ระบบปฏิบัติการมีให้ คอนเทนเนอร์บน Linux และ sandbox-exec ใน macOS เพื่อจำกัดการดำเนินการภายใน execroot/

เหตุผลที่ควรใช้แซนด์บ็อกซ์

  • หากไม่มีการดำเนินการแซนด์บ็อกซ์ Bazel จะไม่ทราบหากเครื่องมือใช้เครื่องมือ ไฟล์อินพุต (ไฟล์ที่ไม่ได้แสดงไว้อย่างชัดแจ้งในทรัพยากร Dependency ของ การดำเนินการ) เมื่อไฟล์อินพุตที่ไม่ได้ประกาศมีการเปลี่ยนแปลง Bazel เชื่อว่าบิลด์นี้เป็นเวอร์ชันล่าสุดและไม่ได้สร้างการดำเนินการอีกครั้ง วิธีนี้ ส่งผลให้เกิดบิลด์ที่เพิ่มขึ้นที่ไม่ถูกต้อง

  • การนำรายการแคชมาใช้ซ้ำที่ไม่ถูกต้องจะสร้างปัญหาระหว่างการแคชระยะไกล ต รายการแคชที่ไม่ถูกต้องในแคชที่แชร์จะส่งผลต่อนักพัฒนาซอฟต์แวร์ทุกคนในโปรเจ็กต์ และการล้างข้อมูลแคชระยะไกลทั้งหมดไม่ใช่วิธีแก้ปัญหาที่สามารถทำได้

  • แซนด์บ็อกซ์จะเลียนแบบลักษณะการทำงานของการดำเนินการระยะไกล หากบิลด์ทำงานได้ดี วิธีนี้ก็มีแนวโน้มที่จะใช้กับการดำเนินการระยะไกลได้ โดยการทำให้ การดำเนินการจากระยะไกล อัปโหลดไฟล์ที่จำเป็นทั้งหมด (รวมถึงเครื่องมือในเครื่อง) คุณสามารถ ลดค่าใช้จ่ายในการบำรุงรักษาสำหรับคลัสเตอร์คอมไพล์ได้อย่างมากเมื่อเทียบกับ เพราะไม่ต้องติดตั้งเครื่องมือในเครื่องทุกเครื่องในคลัสเตอร์ทุกครั้งที่คุณ ต้องการลองใช้คอมไพเลอร์ใหม่หรือทำการเปลี่ยนแปลงเครื่องมือที่มีอยู่

กลยุทธ์แซนด์บ็อกซ์ที่ควรใช้

คุณสามารถเลือกได้ว่าจะใช้แซนด์บ็อกซ์ประเภทใด (หากมี) ด้วย แฟล็กกลยุทธ์ การใช้ sandboxed ทำให้ Bazel เลือกใช้ แซนด์บ็อกซ์ตามรายการด้านล่างนี้ เลือกใช้แซนด์บ็อกซ์เฉพาะระบบปฏิบัติการมากกว่าแซนด์บ็อกซ์ที่มีคุณลักษณะทั่วไปน้อยกว่า ผู้ปฏิบัติงานถาวรจะเรียกใช้ในแซนด์บ็อกซ์ทั่วไปหากผ่าน ธง --worker_sandboxing

กลยุทธ์ local (หรือที่เรียกว่า standalone) ไม่ได้ใช้แซนด์บ็อกซ์ใดๆ ทั้งสิ้น ไฟล์ดังกล่าวจะเรียกใช้บรรทัดคำสั่งของการดำเนินการโดยมีไดเรกทอรีที่ใช้งานอยู่ที่ตั้งค่าเป็น ผู้บริหารของพื้นที่ทำงาน

processwrapper-sandbox เป็นกลยุทธ์แซนด์บ็อกซ์ที่ "ขั้นสูง" ควรใช้งานกับระบบ POSIX ได้ตั้งแต่แกะกล่อง ทั้งนี้ สร้างไดเรกทอรีแซนด์บ็อกซ์ซึ่งประกอบด้วยลิงก์สัญลักษณ์ที่ชี้ไปยังไดเรกทอรีต้นฉบับ จะเรียกใช้บรรทัดคำสั่งของการดำเนินการพร้อมกับชุดไดเรกทอรีที่ใช้งานได้ ไปยังไดเรกทอรีนี้แทน execroot จากนั้นจะย้ายอาร์ติแฟกต์เอาต์พุตที่รู้จัก ออกจากแซนด์บ็อกซ์ไปยัง execroot และลบแซนด์บ็อกซ์ ซึ่งจะป้องกันไม่ให้ จากการใช้ไฟล์อินพุตที่ไม่ได้ประกาศ โดยไม่ได้ตั้งใจ และ ทิ้งไฟล์เอาต์พุตที่ไม่รู้จักให้กับผู้บริหาร

linux-sandbox ก้าวไปอีกขั้นและต่อยอดมาจาก processwrapper-sandbox โดย Docker จะใช้การทำงานขั้นสูง เนมสเปซของ Linux (เนมสเปซผู้ใช้, ต่อเชื่อม, PID, เครือข่าย และ IPC) เพื่อแยก จากโฮสต์ กล่าวคือ ทำให้ทั้งระบบไฟล์เป็นแบบอ่านอย่างเดียว ยกเว้น สำหรับไดเรกทอรีแซนด์บ็อกซ์ ดังนั้นการทำงาน จึงไม่สามารถแก้ไขข้อมูลใน ระบบไฟล์ของโฮสต์ เพื่อป้องกันสถานการณ์ เช่น การทดสอบข้อบกพร่องโดยไม่ตั้งใจ -กำลังเปิดไดเรกทอรี $HOME ของคุณ นอกจากนี้ คุณยังสามารถป้องกันการดำเนินการจาก ในการเข้าถึงเครือข่าย linux-sandbox ใช้เนมสเปซ PID เพื่อป้องกันการดำเนินการ ไม่ให้เห็นกระบวนการอื่นๆ และฆ่ากระบวนการทั้งหมดได้อย่างน่าเชื่อถือ (รวมถึงดีมอน) ที่เกิดจากการกระทำ)

darwin-sandbox ก็คล้ายๆ กัน แต่สำหรับ macOS ใช้เครื่องมือ sandbox-exec ของ Apple เพื่อให้ได้ผลลัพธ์ใกล้เคียงกับแซนด์บ็อกซ์ของ Linux

ทั้ง linux-sandbox และ darwin-sandbox ไม่ทำงานใน "ที่ซ้อนกัน" เนื่องจากข้อจำกัดในกลไกของปฏิบัติการ ระบบต่างๆ เนื่องจาก Docker ยังใช้เนมสเปซของ Linux สำหรับความมหัศจรรย์ของคอนเทนเนอร์ด้วย ไม่สามารถเรียกใช้ linux-sandbox ภายในคอนเทนเนอร์ Docker ได้ง่ายๆ เว้นแต่คุณจะใช้ docker run --privileged ใน macOS คุณจะเรียกใช้ sandbox-exec ภายในไฟล์ ที่เป็นแซนด์บ็อกซ์อยู่แล้ว ดังนั้น ในกรณีเหล่านี้ Bazel จะกลับไปใช้ processwrapper-sandbox โดยอัตโนมัติ

หากคุณต้องการได้รับข้อผิดพลาดของบิลด์ เช่น ไม่ได้สร้างด้วย กลยุทธ์การดำเนินการที่เข้มงวดน้อยลง - แก้ไขรายการการดำเนินการอย่างชัดเจน ที่ Bazel พยายามจะใช้ (เช่น bazel build --spawn_strategy=worker,linux-sandbox)

การดำเนินการแบบไดนามิกมักจะต้องใช้แซนด์บ็อกซ์สำหรับการดำเนินการในเครื่อง หากต้องการเลือกไม่ใช้ ส่งแฟล็ก --experimental_local_lockfree_output การดำเนินการแบบไดนามิกโดยไม่มีการแจ้งเตือน สำหรับผู้ปฏิบัติงานถาวร

ข้อเสียของการใช้แซนด์บ็อกซ์

  • แซนด์บ็อกซ์จะมีค่าใช้จ่ายเพิ่มเติมในการตั้งค่าและการทำลาย ค่าใช้จ่ายนี้สูงเพียงใด ขึ้นอยู่กับปัจจัยหลายอย่าง เช่น รูปร่างของสิ่งที่สร้างขึ้น และ ของระบบปฏิบัติการโฮสต์ สำหรับ Linux บิลด์แซนด์บ็อกซ์มักจะ ช้าลง 2-3 เปอร์เซ็นต์ การตั้งค่าให้ --reuse_sandbox_directories สามารถ ลดต้นทุนในการตั้งค่าและการทำลาย

  • แซนด์บ็อกซ์จะปิดใช้แคชที่เครื่องมืออาจมีอย่างมีประสิทธิภาพ คุณสามารถ ลดปัญหานี้ด้วยการใช้ผู้ปฏิบัติงานถาวร ต้นทุนของการรับประกันแซนด์บ็อกซ์ที่มีประสิทธิภาพน้อยกว่า

  • ผู้ปฏิบัติงาน Multiplex ต้องการการสนับสนุนจากผู้ปฏิบัติงานอย่างชัดแจ้ง ที่จะทำแซนด์บ็อกซ์ ผู้ปฏิบัติงานที่ไม่รองรับการทำแซนด์บ็อกซ์แบบมัลติเพล็กซ์จะเรียกใช้ในฐานะ Singleplex อยู่ระหว่างการดำเนินการแบบไดนามิก ซึ่งอาจทำให้ต้องใช้หน่วยความจำเพิ่มเติม

Sandboxfs

sandboxfs เป็นระบบไฟล์ FUSE ที่แสดงมุมมองที่กำหนดเองของ ระบบไฟล์พื้นฐานโดยไม่มีการลงโทษเวลาได้ Bazel ใช้ sandboxfs เพื่อ สร้าง execroot/ สำหรับแต่ละการดำเนินการโดยทันที โดยหลีกเลี่ยงค่าใช้จ่าย ออกการเรียกระบบจำนวนหลายพันครั้ง โปรดทราบว่า I/O เพิ่มเติมภายใน execroot/ อาจ ช้าลงเนื่องจากโอเวอร์เฮดของ FUSE

ติดตั้ง sandboxfs

ใช้ขั้นตอนต่อไปนี้เพื่อติดตั้ง sandboxfs และสร้าง Bazel ด้วย ดังนี้

ดาวน์โหลด

ดาวน์โหลดและติดตั้ง sandboxfs เพื่อให้ไบนารี sandboxfs ลงท้ายด้วย PATH

เรียกใช้ sandboxfs

  1. (macOS เท่านั้น) ติดตั้ง OSXFUSE
  2. (macOS เท่านั้น) เรียกใช้:

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

    คุณจะต้องดำเนินการนี้หลังจากติดตั้ง และหลังจากการรีบูตทุกครั้งเพื่อให้แน่ใจว่า บริการหลักของระบบ macOS ทำงานผ่านแซนด์บ็อกซ์

  3. เรียกใช้บิลด์ 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 สำหรับ 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 เนื่องจากแบตเตอรี่จะเต็มดิสก์เมื่อเวลาผ่านไป