Co je to opakovatelná sestava?
Deterministická stavba nebo reprodukovatelná stavba jsou trochu odlišné, ale z tohoto článku je lze chápat jako totéž.
Reprodukovatelné stavby označujíVíce spuštění procesu sestavování se stejným vstupem a prostředím může vést ke stejným výsledkům。 Tato technologie je důležitá pro vývoj softwaru, distribuci a ověřování bezpečnosti.
Sestava je reprodukovatelná, pokud poskytuje úplně stejný výstup bez ohledu na to, kdy a kde je spuštěna. Bez ohledu na to, na kterém počítači běžíte, v jakou denní dobu a jaké externí služby přistupujete přes síť, reprodukovatelné sestavy produkují stejný bajt po bajtu výstup. To je skvělé jak pro vývoj (protože reprodukovatelné sestavy se snadno sdílejí mezi různými vývojářskými zařízeními), tak pro produkci (protože je snadné zajistit, že výsledky reprodukovatelných sestavení nebyly upraveny – stačí znovu spustit sestavení na svém počítači a ověřit, že výsledky jsou konzistentní!). jsou velmi užitečné.
Tři pilíře opakovatelných sestav
Pilíř 1: Opakovatelné buildy
Opakovatelnost sestavení se týká toho, co se děje přímo se strojem. Pokud jsou naše vstupy pro sestavení dostupné a nic se ve světě kolem nás nemění, generuje naše sestava stejný výstup při opakování?
Deterministický plán instalace
Prvním, nejjednodušším a nejzřetelnějším požadavkem v opakovatelném buildu je deterministický plán instalace závislostí.
Ve většině jazyků je to tak jednoduché, jako zkontrolovat zamčený soubor. Moderní nástroje pro sestavování často umožňují projektům vyjadřovat přímé požadavky na závislosti jako omezení a poté tato omezení vyřešit za účelem vytvoření plánu instalace (seznam názvů závislostí a párů verzí k instalaci). Mnoho těchto nástrojů také generuje zámkové soubory pro sériové instalační plány. Vývojáři mohou tyto zámkové soubory odevzdat do správy verzí, aby budoucí verze používaly stejné názvy závislostí a verze.
Všimněte si, že deterministický přístup potřebujeme i v samotném sestavování závislostí (nejen ve výběru verzí), a deterministický plán instalace nám to neumožňuje!
Deterministická konstrukce
Jakmile víme, co postavit, naše samotná sestava (včetně našeho vlastního kódu a sestavení závislostního kódu) musí být skutečně deterministická.
To nemusí být problém u projektů bez kroku kompilace! Například projekt Node se všemi závislostmi je čistě JavaScript a není potřeba žádná další práce k dosažení efektivní deterministity.
U projektů, které zahrnují kroky kompilace nebo překladu (source-to-source kompilace), je zajištění determinismu zdaleka nejtěžší částí tvorby reprodukovatelné sestavy. Proces kompilace může implicitně zavést nedeterminismus několika způsoby, včetně:
- Turing-kompletní programové build skripty mohou libovolně měnit zkompilovaný výstup.
- Post-instalační skripty, které spoléhají na vyhledávání spustitelného souborového systému nebo síťové volání.
- C vazby na systémově instalovaný balík, kde vazby na různých systémech s různými hlavičkami mohou produkovat různé výstupy.
- Kroky k vytvoření souboru, který čte mimo kontrolu verzí.
- Vytvořte kroky pro generování časových značek pomocí systémového času.
- Kroky k vytvoření závislostí, které nejsou vyjádřeny v plánu instalace síťového stažení (například stažení závislosti NPM z GitHubu pro cacheovaný binární build vázaný na C).
- Změňte chování na základě aktuálně nastavené proměnné prostředí, ale neodesílejte sestavu s konfigurací proměnné prostředí.
Ne všechna tato chování nutně přinášejí nejistotu, pokud jsou správně nastavena, ale správné nastavení procesu stavby může být složité a obtížné. Například si můžete přečíst tento blogový příspěvek o nejistotě v Chromium buildech. Mnoho z těchto problémů lze zmírnit kontrolou místního stavebního prostředí, o kterém budeme mluvit v následující části.
Pilíř 2: Neměnné prostředí
I u opakovatelných sestavení musíme zajistit, aby se vstupy pro sestavení nemění. Často to znamená, že chceme stavět na neměnném snímku našeho okolí.
Neměnné lokální prostředí
Jak jsme zmínili výše, běžným zdrojem nejistoty sestavení je spoléhání se na "závislosti", které build nástroj nezachytává. Nejčastějšími příklady jsou systémové knihovny s omezením C, ale i další místní environmentální faktory, jako jsou nastavení proměnných prostředí a soubory mimo rozsah správy verzí, mohou sestavení ovlivnit.
Jednoduchý způsob, jak tento problém zmírnit, je spustit build v známém, neměnném kontejneru. Například kontejnerový runtime jako Docker pomáhá zajistit, že všichni používají stejné systémové závislosti, stejné proměnné prostředí a běží na stejném souborovém systému. Navíc je snadné ověřit, že obsah kontejneru odpovídá známému dobrému stavebnímu kontejneru, a pokud je to potřeba, lze kontejner snadno zcela odstranit z obrazu známého dobrého a znovu vytvořit.
Všimněte si, že jsme velmi jasní ohledně známých kontejnerů nebo známých obrazů kontejnerů. Nestačí jen poslat Dockerfile! Proč? Protože samotný Dockerfile nepopisuje plně reprodukovatelný build proces pro Docker obrazy, protože neběží v neměnném globálním prostředí.
Neměnné globální prostředí
Build systémy často komunikují s externími službami, aby dokončily úkoly jako je řešení verzí a stahování závislostí. Ale externí služby se často mění.
Spuštění instalačních nodejů Apt dnes vám dá jiné výsledky než loni, a pravděpodobně i příští rok budou jiné výsledky. Proto samotné Dockerfile nedokážou popsat reprodukovatelné sestavy – spuštění stejného Dockerfile v různých časových okamžicích vytvoří různé výstupy buildů!
Jednoduché řešení je konfigurovat sestavení kdykoli je to možné, specifikovat přesnou verzi (ideálně také přesný hash obsahu), aby budoucí sestavy používaly stejnou verzi jako aktuální sestavení. Ale externí služby mohou také nečekaně změnit své chování – skutečně pesimistická reprodukovatelná sestava spustí interní obraz s co nejvíce síťovými zdroji.
Pilíř 3: Dostupnost zdrojů
Řekněme, že naše stavba je opakovatelná a svět pod našimi nohama se nemění. Teď už jen potřebujeme přístup k vstupu k buildu. Zdá se to jednoduché, že? Dobře......
Registr někdy selže
Většina vývojářů Node zažila alespoň jeden výpadek NPM, během kterého je narušen build pipeline bez cacheování nebo zrcadlení NPM balíčků. Mnoho vývojářů Node také zažilo odstranění left-padů a fakerů, což vážně poškodilo ekosystém NPM a v podstatě vedlo k výpadku.
Jediný spolehlivý způsob, jak takové poruchy sestavení zmírnit, je spustit vlastní zrcadlový systém v registru balíčků. Když nejsou dostupné externí služby, obraz může zůstat online; Když oficiální registr smaže starý balíček, zrcadlový systém může nadále poskytovat služby. Stejný princip platí i pro jiné vzdálené služby: pokud nespouštíte vlastní image, dostupnost build pipeline je srovnatelná pouze s dostupností jeho služeb.
Volba provozovat image služby je vždy citlivá výměna. Na jedné straně mají registry jako NPM specializované inženýrské a provozní týmy, které mají odborné znalosti k udržení těchto systémů v provozu. Na druhou stranu je mnohem snazší spustit malý obraz pro malou sadu závislostí než všechny NPM obrazy. Měli byste činit zrcadelní rozhodnutí na základě specifik každé služby, s ohledem na spolehlivost historických externích služeb a dostupnost sestav a personální potřeby vašeho týmu.
Dodavatelé zajišťují maximální dostupnost
Jednoduchý způsob, jak zajistit maximální dostupnost závislostí vašeho projektu, je přidat je k vašemu dodavateli. Většina správců balíčků podporuje nějakou formu "vendoringu", což znamená, že místo spoléhání na stahování z externích služeb ukládáme zdrojový kód závislostí do správy verzí, který koexistuje společně se zdrojovým kódem. Například v Node to může vypadat jako zavázání node_modules do správy zdrojových kódů.
I když toto řešení není dokonalé (záleží na tom, jak je váš dodavatel a projekt nastavený, což může značně zatížit správu verzí), často je to nejjednodušší a nejjednodušší řešení pro maximální dostupnost.
Odkaz:
Přihlášení k hypertextovému odkazu je viditelné.
Přihlášení k hypertextovému odkazu je viditelné. |