عیب یابی Bazel Remote Execution با Docker Sandbox

ساخت‌های Bazel که به‌صورت محلی موفق می‌شوند، ممکن است هنگام اجرا از راه دور به دلیل محدودیت‌ها و الزاماتی که بر ساخت‌های محلی تأثیر نمی‌گذارند، با شکست مواجه شوند. متداول ترین علل چنین خرابی هایی در تطبیق قوانین Bazel برای اجرای از راه دور توضیح داده شده است.

این صفحه نحوه شناسایی و حل و فصل رایج‌ترین مشکلاتی را که در اجرای از راه دور ایجاد می‌شوند با استفاده از ویژگی Docker sandbox توضیح می‌دهد که محدودیت‌هایی برابر با محدودیت‌های اجرای از راه دور بر روی ساخت اعمال می‌کند. این به شما امکان می دهد بدون نیاز به سرویس اجرای از راه دور، بیلد خود را عیب یابی کنید.

ویژگی Docker sandbox محدودیت های اجرای از راه دور را به شرح زیر تقلید می کند:

  • عملیات ساخت در ظروف زنجیره ابزار اجرا می شود. می توانید از همان کانتینرهای زنجیره ابزار برای اجرای ساخت خود به صورت محلی و از راه دور از طریق یک سرویس پشتیبانی از اجرای از راه دور کانتینری استفاده کنید.

  • هیچ داده خارجی از مرز ظرف عبور نمی کند. فقط ورودی‌ها و خروجی‌های اعلام شده به صراحت وارد و خارج می‌شوند و تنها پس از تکمیل موفقیت‌آمیز عملیات ساخت مرتبط.

  • هر عمل در یک ظرف تازه اجرا می شود. یک ظرف جدید و منحصر به فرد برای هر اقدام ساخت ایجاد شده ایجاد می شود.

با استفاده از یکی از روش های زیر می توانید این مشکلات را برطرف کنید:

  • عیب یابی به صورت بومی با این روش، Bazel و اکشن های ساخت آن به صورت بومی روی ماشین محلی شما اجرا می شوند. ویژگی Docker sandbox محدودیت هایی را بر روی ساخت اعمال می کند که برابر با محدودیت های اجرای از راه دور است. با این حال، این روش ابزارهای محلی، وضعیت‌ها و داده‌های نشت‌شده در ساخت شما را شناسایی نمی‌کند که باعث ایجاد مشکلاتی در اجرای از راه دور می‌شود.

  • عیب یابی در کانتینر داکر. با این روش، Bazel و اقدامات ساخت آن در داخل یک کانتینر Docker اجرا می‌شوند، که به شما امکان می‌دهد تا ابزارها، وضعیت‌ها و داده‌های نشت‌شده از ماشین محلی به داخل ساختمان را شناسایی کنید، علاوه بر اعمال محدودیت‌هایی برابر با محدودیت‌های اجرای از راه دور. این روش بینشی در مورد ساخت شما فراهم می کند حتی اگر بخش هایی از بیلد با شکست مواجه شوند. این روش آزمایشی است و به طور رسمی پشتیبانی نمی شود.

پیش نیازها

قبل از شروع عیب یابی، اگر قبلاً این کار را نکرده اید، موارد زیر را انجام دهید:

  • Docker را نصب کنید و مجوزهای لازم برای اجرای آن را پیکربندی کنید.
  • Bazel 0.14.1 یا بالاتر را نصب کنید. نسخه های قبلی از ویژگی Docker sandbox پشتیبانی نمی کنند.
  • همانطور که در اینجا توضیح داده شده است، مخزن bazel-toolchains را که به آخرین نسخه منتشر شده پین ​​شده است، به فایل WORKSPACE ساخت خود اضافه کنید .
  • برای فعال کردن این ویژگی، پرچم‌ها را به فایل .bazelrc . خود اضافه کنید. اگر فایلی وجود ندارد در دایرکتوری ریشه پروژه Bazel خود ایجاد کنید. پرچم های زیر یک نمونه مرجع هستند. لطفاً آخرین فایل .bazelrc را در مخزن bazel-toolchains ببینید و مقادیر پرچم های تعریف شده در آنجا را برای پیکربندی docker-sandbox کپی کنید.
# Docker Sandbox Mode
build:docker-sandbox --host_javabase=<...>
build:docker-sandbox --javabase=<...>
build:docker-sandbox --crosstool_top=<...>
build:docker-sandbox --experimental_docker_image=<...>
build:docker-sandbox --spawn_strategy=docker --strategy=Javac=docker --genrule_strategy=docker
build:docker-sandbox --define=EXECUTOR=remote
build:docker-sandbox --experimental_docker_verbose
build:docker-sandbox --experimental_enable_docker_sandbox

اگر قوانین شما به ابزارهای اضافی نیاز دارد، موارد زیر را انجام دهید:

  1. با نصب ابزارها با استفاده از Dockerfile و ساختن تصویر به صورت محلی، یک ظرف Docker سفارشی ایجاد کنید.

  2. مقدار پرچم --experimental_docker_image در بالا را با نام تصویر ظرف سفارشی خود جایگزین کنید.

عیب یابی به صورت بومی

این روش Bazel و تمام اقدامات ساخت آن را مستقیماً بر روی ماشین محلی اجرا می‌کند و روشی قابل اعتماد برای تأیید موفقیت ساخت شما در صورت اجرای از راه دور است.

با این حال، با این روش، ابزارها، باینری‌ها و داده‌های نصب‌شده محلی ممکن است به داخل بیلد شما نشت کنند، به خصوص اگر از قوانین WORKSPACE به سبک پیکربندی استفاده کند. چنین نشت هایی باعث ایجاد مشکلاتی در اجرای از راه دور می شود. برای شناسایی آنها، علاوه بر عیب یابی بومی، در ظرف داکر عیب یابی کنید.

مرحله 1: ساخت را اجرا کنید

  1. پرچم --config=docker-sandbox را به دستور Bazel که ساخت شما را اجرا می کند اضافه کنید. مثلا:

    bazel --bazelrc=.bazelrc build --config=docker-sandbox target
    
  2. بیلد را اجرا کنید و منتظر بمانید تا کامل شود. به دلیل ویژگی Docker sandbox، ساخت تا چهار برابر کندتر از حد معمول اجرا می شود.

ممکن است با خطای زیر مواجه شوید:

ERROR: 'docker' is an invalid value for docker spawn strategy.

اگر انجام دادید، بیلد را دوباره با پرچم --experimental_docker_verbose اجرا کنید. این پرچم پیام های خطای پرمخاطب را فعال می کند. این خطا معمولاً به دلیل نصب معیوب Docker یا عدم وجود مجوز برای اجرای آن در حساب کاربری فعلی ایجاد می شود. برای اطلاعات بیشتر به مستندات Docker مراجعه کنید. اگر مشکلات همچنان ادامه داشت، به سراغ عیب‌یابی در ظرف Docker بروید.

مرحله 2: مشکلات شناسایی شده را حل کنید

موارد زیر متداول‌ترین مشکلاتی است که با آن مواجه می‌شوید و راه‌حل‌های آن‌ها را بررسی می‌کنید.

  • یک فایل، ابزار، باینری یا منبعی که توسط درخت runfiles Bazel ارجاع داده شده است وجود ندارد. . تأیید کنید که تمام وابستگی های اهداف آسیب دیده به صراحت اعلام شده است. برای اطلاعات بیشتر به مدیریت وابستگی های ضمنی مراجعه کنید.

  • فایل، ابزار، باینری یا منبعی که توسط یک مسیر مطلق یا متغیر PATH ارجاع داده شده است، وجود ندارد. تأیید کنید که همه ابزارهای مورد نیاز در ظرف ابزار زنجیره نصب شده اند و از قوانین زنجیره ابزار برای اعلام درست وابستگی هایی که به منبع گم شده اشاره می کنند استفاده کنید. برای اطلاعات بیشتر به فراخوانی ابزارهای ساخت از طریق قوانین زنجیره ابزار مراجعه کنید.

  • اجرای باینری با شکست مواجه می شود. یکی از قوانین ساخت، ارجاع به یک باینری ناسازگار با محیط اجرا (کانتینر Docker) است. برای اطلاعات بیشتر به مدیریت باینری های وابسته به پلت فرم مراجعه کنید. اگر نمی توانید مشکل را حل کنید، برای راهنمایی با bazel-discuss@google.com تماس بگیرید.

  • فایلی از @local-jdk وجود ندارد یا باعث ایجاد خطا می شود. باینری های جاوا در دستگاه محلی شما در حالی که با آن ناسازگار هستند به داخل بیلد نشت می کنند. به جای @local_jdk از java_toolchain در قوانین و اهداف خود استفاده کنید. در صورت نیاز به راهنمایی بیشتر با bazel-discuss@google.com تماس بگیرید.

  • سایر خطاها برای دریافت راهنمایی با bazel-discuss@google.com تماس بگیرید.

عیب یابی در کانتینر داکر

با این روش، Bazel در داخل یک کانتینر میزبان Docker اجرا می‌شود و اقدامات ساخت Bazel در داخل کانتینرهای زنجیره ابزار منفرد ایجاد شده توسط ویژگی Docker sandbox اجرا می‌شود. جعبه شنی برای هر اقدام ساخت، یک محفظه زنجیره ابزار کاملاً جدید ایجاد می کند و تنها یک عمل در هر ظرف زنجیره ابزار اجرا می شود.

این روش کنترل دقیق تری بر ابزارهای نصب شده در محیط میزبان فراهم می کند. با جدا کردن اجرای بیلد از اجرای عملیات ساخت آن و به حداقل رساندن ابزار نصب شده، می توانید بررسی کنید که آیا ساخت شما وابستگی به محیط اجرای محلی دارد یا خیر.

مرحله 1: ظرف را بسازید

  1. یک Dockerfile ایجاد کنید که ظرف Docker را ایجاد می کند و Bazel را با حداقل مجموعه ای از ابزارهای ساخت نصب می کند:

    FROM debian:stretch
    
    RUN apt-get update && apt-get install -y apt-transport-https curl software-properties-common git gcc gnupg2 g++ openjdk-8-jdk-headless python-dev zip wget vim
    
    RUN curl -fsSL https://download.docker.com/linux/debian/gpg | apt-key add -
    
    RUN add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/debian $(lsb_release -cs) stable"
    
    RUN apt-get update && apt-get install -y docker-ce
    
    RUN wget https://releases.bazel.build/<latest Bazel version>/release/bazel-<latest Bazel version>-installer-linux-x86_64.sh -O ./bazel-installer.sh && chmod 755 ./bazel-installer.sh
    
    RUN ./bazel-installer.sh
    
  2. کانتینر را به صورت bazel_container :

    docker build -t bazel_container - < Dockerfile
    

مرحله 2: ظرف را راه اندازی کنید

ظرف Docker را با استفاده از دستور زیر راه اندازی کنید. در دستور، مسیر کد منبع را در هاست خود که می خواهید بسازید جایگزین کنید.

docker run -it \
  -v /var/run/docker.sock:/var/run/docker.sock \
  -v /tmp:/tmp \
  -v your source code directory:/src \
  -w /src \
  bazel_container \
  /bin/bash

این دستور کانتینر را به صورت root اجرا می کند، سوکت docker را نقشه برداری می کند و دایرکتوری /tmp را نصب می کند. این به Bazel اجازه می دهد تا سایر کانتینرهای Docker را ایجاد کند و از دایرکتوری های زیر /tmp برای به اشتراک گذاری فایل ها با آن کانتینرها استفاده کند. کد منبع شما در /src در داخل ظرف موجود است.

این دستور عمداً از یک کانتینر پایه debian:stretch شروع می‌شود که شامل باینری‌های ناسازگار با rbe-ubuntu16-04 که به‌عنوان کانتینر زنجیره ابزار استفاده می‌شود. اگر فایل های باینری از محیط محلی به داخل جعبه ابزار نشت کند، باعث ایجاد خطاهای ساخت می شود.

مرحله 3: ظرف را تست کنید

دستورات زیر را از داخل کانتینر Docker اجرا کنید تا آن را آزمایش کنید:

docker ps
bazel version

مرحله 4: ساخت را اجرا کنید

بیلد را مطابق شکل زیر اجرا کنید. کاربر خروجی ریشه است به طوری که مطابق با دایرکتوری است که با همان مسیر مطلق از داخل کانتینر میزبانی که Bazel در آن اجرا می شود، از کانتینرهای زنجیره ابزار ایجاد شده توسط ویژگی Docker sandbox که در آن اقدامات ساخت Bazel در حال اجرا است، قابل دسترسی است، و از ماشین محلی که میزبان و کانتینرهای اکشن روی آن اجرا می شوند.

bazel --output_user_root=/tmp/bazel_docker_root --bazelrc=.bazelrc \ build --config=docker-sandbox target

مرحله 5: مشکلات شناسایی شده را حل کنید

شما می توانید خرابی های ساخت را به صورت زیر حل کنید:

  • اگر ساخت با خطای «فضای دیسک خارج شده» با شکست مواجه شد، می‌توانید این محدودیت را با راه‌اندازی محفظه میزبان با پرچم --memory=XX که XX فضای دیسک تخصیص‌یافته بر حسب گیگابایت است، افزایش دهید. این آزمایشی است و ممکن است منجر به رفتار غیرقابل پیش بینی شود.

  • اگر ساخت در طول مراحل تحلیل یا بارگیری با شکست مواجه شود، یک یا چند قانون ساخت شما که در فایل WORKSPACE اعلام شده است با اجرای از راه دور سازگار نیست. برای دلایل احتمالی و راه‌حل‌ها، به تطبیق قوانین Bazel برای اجرای از راه دور مراجعه کنید.

  • اگر ساخت به هر دلیل دیگری با شکست مواجه شد، مراحل عیب‌یابی را در مرحله 2 ببینید: حل مشکلات شناسایی‌شده .