Що таке повторювана збірка?
Детермінована збірка або відтворювана збірка трохи відрізняються, але з цієї статті їх можна розуміти як одне й те саме.
Відтворювані збірки означаютьКілька виконань процесу збірки з однаковим середовищем введення та збірки можуть дати однакові результати。 Ця технологія є важливою для розробки, розповсюдження та валідації безпеки програмного забезпечення.
Збірка відтворюється, якщо дає абсолютно однаковий вихід незалежно від часу і місця запуску. Незалежно від того, на якому комп'ютері ви працюєте, в який час доби і до яких зовнішніх сервісів користуєтеся через мережу, відтворювані збірки дають однаковий вихід байт за байтом. Це чудово як для розробки (бо відтворювані збірки легко ділитися між різними пристроями розробника), так і для продакшну (адже легко переконатися, що результати відтворюваних збірок не були змінені — просто запустіть збірку на своєму комп'ютері і переконайтеся, що результати послідовні!). дуже корисні.
Три стовпи повторюваних збірок
Стовп 1: Повторювані збірки
Повторюваність збірки стосується того, що відбувається з самою машиною для збірки. Якщо наші дані для збірки доступні і нічого не змінюється у світі навколо, чи дає наша збірка той самий результат при повторенні?
Детермінований план встановлення
Перша, найпростіша і найочевидніша вимога у повторюваній збірці — це детермінований план встановлення залежностей.
У більшості мов це так просто, як перевірити заблокований файл. Сучасні інструменти збірки часто дозволяють проєктам виражати прямі вимоги до залежностей як обмеження, а потім розв'язувати ці обмеження для створення плану встановлення (списку імен залежностей і пар версій для встановлення). Багато з цих інструментів також генерують файли блокування для серіалізованих планів встановлення. Розробники можуть подавати ці файли блокування до контролю версій, щоб майбутні збірки використовували ті ж імена залежностей і версії.
Зверніть увагу, що нам також потрібна детермінованість у самій збірці залежностей (а не лише у виборі версії), і детермінований план встановлення не дозволяє нам цього досягти!
Детермінована конструкція
Коли ми знаємо, що будувати, наша збірка (включаючи власний код і код залежностей) має бути детермінованою.
Можливо, це не є проблемою для проєктів без етапу компіляції! Наприклад, проєкт Node з усіма залежностями — це чистий JavaScript, і для досягнення ефективної детермінованості не потрібна додаткова робота.
Для проєктів, які включають етапи компіляції або перекладу (компіляція від джерела до джерела), забезпечення детермінізму є найскладнішою частиною створення відтворюваної збірки. Процес компіляції може неявно вводити недетермінізм різними способами, зокрема:
- Скрипти для побудови програм Тюрінга можуть за бажанням змінювати скомпільований результат.
- Післяінсталяційні скрипти, які базуються на виконуваних файлових пошуках або мережевих викликах.
- C-прив'язка до пакету, встановленого системою, де зв'язки на різних системах з різними заголовками можуть давати різні виходи.
- Кроки для створення файлу, який читається поза контролем версій.
- Побудуйте кроки для генерації часових позначок за системним часом.
- Кроки для створення залежностей, які не виражені в плані встановлення мережі (наприклад, завантажити NPM-залежність з GitHub для кешованої бінарної збірки, що має C-зв'язок).
- Змінюйте поведінку відповідно до поточної змінної середовища, але не подавайте збірку з конфігурацією змінної середовища.
Не всі ці поведінки створюють невизначеність при правильному налаштуванні, але правильне налаштування процесу збірки може бути складним і складним. Наприклад, ви можете прочитати цей блог про невизначеність у збірках Chromium. Багато з цих проблем можна пом'якшити шляхом контролю місцевого будівельного середовища, про що ми розглянемо в наступному розділі.
Стовп 2: Незмінне середовище
Навіть із повторюваними збірками потрібно переконатися, що вхідні дані не змінюються. Часто це означає, що ми хочемо переконатися, що будуємо на незмінному знімку нашого оточення.
Незмінне локальне середовище
Як ми обговорювали вище, поширеною причиною невизначеності збірки є «залежності», які не захоплюються інструментом збірки. Найпоширенішими прикладами є системні бібліотеки з обмеженням C, але й інші локальні фактори середовища, такі як налаштування змінних середовища та файли, що виходять за межі контролю версій, також можуть впливати на збірку.
Простий спосіб зменшити цю проблему — запустити збірку у відомому, незмінному контейнері. Наприклад, контейнерний режим виконання, такий як Docker, допомагає гарантувати, що всі використовують однакові системні залежності, однакові змінні середовища та працюють на одній і тій самій файловій системі. Крім того, легко перевірити, чи вміст контейнера відповідає відомому хорошому контейнеру для збірки, і за потреби контейнер можна легко повністю видалити з відомого образу і відтворити заново.
Зверніть увагу, що ми дуже чітко розуміємо відомі контейнери або відомі зображення контейнерів. Недостатньо просто подати Dockerfile! Чому? Тому що сам Dockerfile не описує повністю відтворюваний процес збірки для образів Docker, бо вони не працюють у незмінному глобальному середовищі.
Незмінне глобальне середовище
Системи збірки часто взаємодіють із зовнішніми сервісами для виконання завдань, таких як розв'язання версій та завантаження залежностей. Але зовнішні сервіси часто змінюються.
Запуск apt install nodejs сьогодні дасть вам інші результати, ніж минулого року, і, ймовірно, наступного року теж будуть інші. Ось чому самі Dockerfiles не можуть описати відтворювані збірки — запуск одного й того ж Dockerfile у різний момент часу дає різні результати збірки!
Просте рішення тут — налаштовувати збірку, коли це можливо, вказуючи точну версію (ідеально — точний хеш контенту), щоб майбутні збірки використовували ту ж версію, що й поточна. Але зовнішні сервіси також можуть несподівано змінити свою поведінку — справді песимістична відтворювана збірка запускає внутрішній образ із максимальною кількістю мережевих ресурсів.
Стовп 3: Доступність ресурсів
Припустимо, наша збірка повторюється, і світ під ногами не змінюється. Все, що нам зараз потрібно — це доступ до введення збірки. Здається, це просто, правда? Ну......
Реєстр іноді виходить з ладу
Більшість розробників Node стикалися з принаймні одним збоєм у NPM, під час якого конвеєр збірки без кешування або дзеркалювання NPM-пакетів порушується. Багато розробників Node також стикалися з видалення лівої панелі та фейкерів, що серйозно пошкодило екосистему NPM і фактично призвело до збою.
Єдиний надійний спосіб уникнути таких зривів — це запустити власне дзеркало реєстру пакетів. Коли зовнішні сервіси недоступні, зображення може залишатися онлайн; Коли офіційний реєстр видаляє старий пакет, дзеркало може продовжувати надавати послуги. Той самий принцип застосовується і до інших віддалених сервісів: якщо ви не запускаєте власний імідж, доступність build pipeline порівнянна лише з доступністю його сервісів.
Вибір запуску сервісного образу завжди є делікатним компромісом. З одного боку, реєстри, такі як NPM, мають спеціалізовані інженерні та операційні команди, які мають експертизу для підтримки цих систем онлайн. З іншого боку, набагато простіше запустити маленьке зображення для невеликої кількості залежностей, ніж усі NPM-образи. Ви повинні приймати відповідні рішення, виходячи з конкретики кожної служби, враховуючи надійність історичних зовнішніх сервісів та доступність вашої команди у збірці та потреби в персоналі.
Постачальники забезпечують максимальну доступність
Простий спосіб забезпечити максимальну доступність залежностей вашого проєкту — додати їх до вашого постачальника. Більшість менеджерів пакетів підтримують певну форму «вендорингу», тобто замість завантаження з зовнішніх сервісів ми зберігаємо вихідний код залежності у контролі версій, співіснуючий із нашим кодом. Наприклад, у Node це може виглядати як комітет node_modules у контроль версій.
Хоча це рішення не ідеальне (залежно від того, як налаштований ваш постачальник і проєкт, що може створювати велике навантаження на контроль версій), часто це найпростіше і найпростіше рішення для максимальної доступності.
Посилання:
Вхід за гіперпосиланням видно.
Вхід за гіперпосиланням видно. |