Linux har många ansikten: hur man arbetar på vilken distribution som helst

Linux har många ansikten: hur man arbetar på vilken distribution som helst

Att skapa en backup-applikation som fungerar på alla distributioner är ingen lätt uppgift. För att säkerställa att Veeam Agent för Linux fungerar på distributioner från Red Hat 6 och Debian 6, till OpenSUSE 15.1 och Ubuntu 19.04, måste du lösa en rad problem, särskilt med tanke på att mjukvaruprodukten innehåller en kärnmodul.

Artikeln skapades utifrån material från ett tal på konferensen Linux Peter 2019.

Linux är inte bara ett av de mest populära operativsystemen. I grund och botten är detta en plattform på grundval av vilken du kan göra något unikt, något eget. Tack vare detta har Linux många distributioner som skiljer sig åt i sin uppsättning mjukvarukomponenter. Och här uppstår ett problem: för att en mjukvaruprodukt ska fungera på någon distribution måste du ta hänsyn till funktionerna hos var och en.

Pakethanterare. .deb kontra .rpm

Låt oss börja med det uppenbara problemet med att distribuera produkten över olika distributioner.
Det vanligaste sättet att distribuera mjukvaruprodukter är att lägga paketet på ett arkiv så att pakethanteraren som är inbyggd i systemet kan installera det därifrån.
Vi har dock två populära paketformat: rpm и deb. Det betyder att alla måste stödja.

I en värld av deb-paket är kompatibilitetsnivån fantastisk. Samma paket installeras och fungerar lika bra på både Debian 6 och Ubuntu 19.04. Standarderna för processen att bygga paket och arbeta med dem, fastställda i gamla Debian-distributioner, är fortfarande relevanta i det nymodiga Linux Mint och det elementära operativsystemet. Därför, i fallet med Veeam Agent för Linux, räcker det med ett deb-paket för varje hårdvaruplattform.

Men i rpm-paketens värld är skillnaderna stora. För det första på grund av att det finns två helt oberoende distributörer, Red Hat och SUSE, för vilka kompatibilitet är helt onödig. För det andra har dessa distributörer distributionssatser från dessa. stödjande och experimentella. Det finns inget behov av kompatibilitet mellan dem heller. Det visade sig att el6, el7 och el8 har sina egna paket. Separat paket för Fedora. Paket för SLES11 och 12 och ett separat för openSUSE. Det största problemet är beroenden och paketnamn.

Beroendeproblem

Tyvärr hamnar samma paket ofta under olika namn i olika distributioner. Nedan finns en ofullständig lista över veeam-paketberoenden.

För EL7:
För SLES 12:

  • libblkid
  • libgcc
  • libstdc ++
  • ncurses-libs
  • fuse-libs
  • fil-libs
  • veeamsnap=3.0.2.1185
  • libblkid1
  • libgcc_s1
  • libstdc ++ 6
  • libmagic1
  • libfuse2
  • veeamsnap-kmp=3.0.2.1185

Som ett resultat är listan över beroenden unik för distributionen.

Vad som blir värre är när en uppdaterad version börjar gömma sig under det gamla paketnamnet.

Exempel:

Paketet har uppdaterats i Fedora 24 ncurses från version 5 till version 6. Vår produkt byggdes med version 5 för att säkerställa kompatibilitet med äldre distributioner. För att använda den gamla 5:e versionen av biblioteket på Fedora 24, var jag tvungen att använda paketet ncurses-compat-libs.

Som ett resultat finns det två paket för Fedora, med olika beroenden.

Mer intressant. Efter nästa distributionsuppdatering, paketet ncurses-compat-libs med version 5 av biblioteket visar det sig att det inte är tillgängligt. Det är dyrt för en distributör att dra gamla bibliotek till en ny version av distributionen. Efter en tid upprepade sig problemet i SUSE-distributioner.

Som ett resultat var vissa distributioner tvungna att släppa sitt explicita beroende av ncurses-libs, och fixa produkten så att den kan fungera med alla versioner av biblioteket.

Förresten, i version 8 av Red Hat finns det inte längre ett metapaket pytonorm, som syftade på det gamla goda python 2.7. Det finns python2 и pytonorm3.

Alternativ till pakethanterare

Problemet med beroenden är gammalt och har länge varit uppenbart. Kom bara ihåg beroendehelvetet.
Att kombinera olika bibliotek och applikationer så att de alla fungerar stabilt och inte kommer i konflikt – i själva verket är detta uppgiften som vilken Linux-distributör som helst försöker lösa.

Pakethanteraren försöker lösa detta problem på ett helt annat sätt. Snappy från Canonical. Huvudidén: applikationen körs i en sandlåda isolerad och skyddad från huvudsystemet. Om en applikation kräver bibliotek, levereras de med själva applikationen.

Flatpak låter dig också köra applikationer i en sandlåda med Linux-behållare. Sandlådeidén används också AppImage.

Dessa lösningar låter dig skapa ett paket för vilken distribution som helst. I fall att Flatpak installation och start av applikationen är möjlig även utan administratörens vetskap.

Det största problemet är att inte alla applikationer kan köras i en sandlåda. Vissa människor behöver direkt tillgång till plattformen. Jag pratar inte ens om kärnmoduler, som är strikt beroende av kärnan och inte passar in i sandlådekonceptet.

Det andra problemet är att distributioner som är populära i företagsmiljön från Red Hat och SUSE ännu inte innehåller stöd för Snappy och Flatpak.

I detta avseende är Veeam Agent för Linux inte tillgänglig snapcraft.io inte alls www.flathub.org.

För att avsluta frågan om pakethanterare, skulle jag vilja notera att det finns ett alternativ att överge pakethanterare helt och hållet genom att kombinera binära filer och ett skript för att installera dem i ett paket.

En sådan bunt låter dig skapa ett gemensamt paket för olika distributioner och plattformar, utföra en interaktiv installationsprocess, utföra nödvändig anpassning. Jag har bara stött på sådana paket för Linux från VMware.

Uppdateringsproblem

Linux har många ansikten: hur man arbetar på vilken distribution som helst
Även om alla beroendeproblem är lösta kan programmet köras annorlunda på samma distribution. Det är en fråga om uppdateringar.

Det finns 3 uppdateringsstrategier:

  • Det enklaste är att aldrig uppdatera. Jag satte upp servern och glömde bort det. Varför uppdatera om allt fungerar? Problem börjar första gången du kontaktar supporten. Skaparen av distributionen stöder endast den uppdaterade versionen.
  • Du kan lita på distributören och ställa in automatiska uppdateringar. I det här fallet kommer troligen ett samtal till supporten omedelbart efter en misslyckad uppdatering.
  • Alternativet att manuellt uppdatera endast efter att ha körts på en testinfrastruktur är det mest pålitliga, men dyrt och tidskrävande. Alla har inte råd.

Eftersom olika användare använder olika uppdateringsstrategier är det nödvändigt att stödja både den senaste versionen och alla tidigare släppta. Detta komplicerar både utvecklings- och testprocessen och skapar huvudvärk för supportteamet.

Olika hårdvaruplattformar

Olika hårdvaruplattformar är ett problem som till stor del är specifikt för inbyggd kod. Som ett minimum måste du samla binärer för varje plattform som stöds.

I Veeam Agent for Linux-projektet kan vi fortfarande inte stödja något liknande denna RISC.

Jag kommer inte att uppehålla mig i denna fråga i detalj. Jag kommer bara att beskriva huvudproblemen: plattformsberoende typer, som t.ex size_t, strukturjustering och byteordning.

Statisk och/eller dynamisk länkning

Linux har många ansikten: hur man arbetar på vilken distribution som helst
Men frågan är "Hur länkar man till bibliotek - dynamiskt eller statiskt?" värt att diskutera.

Som regel använder C/C++-applikationer under Linux dynamisk länkning. Detta fungerar utmärkt om applikationen är byggd specifikt för en specifik distribution.

Om uppgiften är att täcka olika distributioner med en binär fil måste du fokusera på den äldsta distributionen som stöds. För oss är detta Red Hat 6. Den innehåller gcc 4.4, som inte ens C++11-standarden stöder fullt.

Vi bygger vårt projekt med hjälp av gcc 6.3, som fullt ut stöder C++14. Naturligtvis, i det här fallet, på Red Hat 6 måste du bära med dig libstdc++ och förstärka biblioteken. Det enklaste sättet är att länka till dem statiskt.

Men tyvärr kan inte alla bibliotek länkas statiskt.

För det första systembibliotek som t.ex libfuse, libblkid det är nödvändigt att länka dynamiskt för att säkerställa deras kompatibilitet med kärnan och dess moduler.

För det andra finns det en subtilitet med licenser.

GPL-licensen tillåter dig i princip att länka bibliotek endast med öppen källkod. MIT och BSD tillåter statisk länkning och tillåter att bibliotek inkluderas i ett projekt. Men LGPL verkar inte motsäga statisk länkning, utan kräver att filerna som behövs för länkning delas.

Generellt sett kommer dynamisk länkning att hindra dig från att behöva tillhandahålla någonting.

Bygga C/C++-applikationer

För att bygga C/C++-applikationer för olika plattformar och distributioner räcker det att välja eller bygga en lämplig version av gcc och använda korskompilatorer för specifika arkitekturer och sätta ihop hela uppsättningen av bibliotek. Detta arbete är ganska genomförbart, men ganska besvärligt. Och det finns ingen garanti för att den valda kompilatorn och biblioteken kommer att tillhandahålla en fungerande version.

En uppenbar fördel: infrastrukturen är avsevärt förenklad, eftersom hela byggprocessen kan slutföras på en maskin. Dessutom räcker det att samla en uppsättning binärer för en arkitektur och du kan paketera dem i paket för olika distributioner. Så här byggs veeam-paket för Veeam Agent för Linux.

I motsats till detta alternativ kan du helt enkelt förbereda en bygggård, det vill säga flera maskiner för montering. Varje sådan maskin kommer att tillhandahålla applikationskompilering och paketmontering för en specifik distribution och en specifik arkitektur. I det här fallet utförs sammanställningen med hjälp av de medel som utarbetats av distributören. Det vill säga, steget att förbereda kompilatorn och välja bibliotek är eliminerat. Dessutom kan byggprocessen enkelt parallelliseras.

Det finns dock en nackdel med detta tillvägagångssätt: för varje distribution inom samma arkitektur måste du samla din egen uppsättning binära filer. En annan nackdel är att ett så stort antal maskiner måste underhållas och en stor mängd diskutrymme och RAM måste allokeras.

Så här kompileras KMOD-paket av veeamsnap-kärnmodulen för Red Hat-distributioner.

Öppna Byggtjänst

Kollegor från SUSE försökte implementera en medelväg i form av en speciell tjänst för att kompilera applikationer och sätta ihop paket - openbuildservice.

I huvudsak är det en hypervisor som skapar en virtuell maskin, installerar alla nödvändiga paket i den, kompilerar applikationen och bygger paketet i denna isolerade miljö, varefter den virtuella maskinen släpps.

Linux har många ansikten: hur man arbetar på vilken distribution som helst

Schemaläggaren som implementeras i OpenBuildService kommer att avgöra hur många virtuella maskiner den kan starta för optimal paketbyggnadshastighet. Den inbyggda signeringsmekanismen signerar paketen och laddar upp dem till det inbyggda arkivet. Det inbyggda versionskontrollsystemet sparar historiken över ändringar och byggen. Allt som återstår är att helt enkelt lägga till dina källor till detta system. Du behöver inte ens ställa in servern själv, du kan använda en öppen.

Det finns dock ett problem: en sådan skördare är svår att passa in i den befintliga infrastrukturen. Till exempel behövs inte versionskontroll, vi har redan våra egna för källkoder. Vår signaturmekanism är annorlunda: vi använder en speciell server. Ett förråd behövs inte heller.

Dessutom är stöd för andra distributioner – till exempel Red Hat – implementerat ganska dåligt, vilket är förståeligt.

Fördelen med en sådan tjänst är snabb support för nästa version av SUSE-distributionen. Innan det officiella tillkännagivandet av releasen läggs de paket som krävs för montering upp på ett offentligt arkiv. En ny visas i listan över tillgängliga distributioner på OpenBuildService. Vi markerar rutan och den läggs till i byggplanen. Att lägga till en ny version av distributionen görs alltså med nästan ett klick.

I vår infrastruktur, med hjälp av OpenBuildService, samlas hela mängden KMP-paket av veeamsnap-kärnmodulen för SUSE-distributioner.

Därefter skulle jag vilja uppehålla mig vid problem som är specifika för kärnmoduler.

kärna ABI

Linux-kärnmoduler har historiskt distribuerats i källform. Faktum är att skaparna av kärnan inte belastar sig själva med oro för att stödja ett stabilt API för kärnmoduler, och speciellt på binär nivå, vidare kallad kABI.

För att bygga en modul för en vaniljkärna behöver du definitivt rubrikerna för just den här kärnan, och den fungerar bara på den här kärnan.

DKMS låter dig automatisera processen att bygga moduler när du uppdaterar kärnan. Som ett resultat av detta använder användare av Debians arkiv (och dess många släktingar) kärnmoduler antingen från distributörens arkiv eller kompilerade från källkod med DKMS.

Denna situation passar dock inte särskilt Enterprise-segmentet. Proprietära koddistributörer vill distribuera produkten som kompilerade binärer.

Administratörer vill inte behålla utvecklingsverktyg på produktionsservrar av säkerhetsskäl. Enterprise Linux-distributörer som Red Hat och SUSE beslutade att de kunde stödja stabil kABI för sina användare. Resultatet blev KMOD-paket för Red Hat och KMP-paket för SUSE.

Kärnan i denna lösning är ganska enkel. För en specifik version av distributionen är kärnans API fryst. Distributören uppger att han använder kärnan, till exempel 3.10, och gör endast korrigeringar och förbättringar som inte påverkar kärnans gränssnitt, och modulerna som samlas in för den allra första kärnan kan användas för alla efterföljande utan omkompilering.

Red Hat hävdar kABI-kompatibilitet för distributionen under hela dess livscykel. Det vill säga, den sammansatta modulen för rhel 6.0 (släpp november 2010) bör också fungera på version 6.10 (släpp juni 2018). Och det här är nästan 8 år. Naturligtvis är denna uppgift ganska svår.
Vi har registrerat flera fall där veeamsnap-modulen slutade fungera på grund av kABI-kompatibilitetsproblem.

Efter att veeamsnap-modulen, kompilerad för RHEL 7.0, visade sig vara inkompatibel med kärnan från RHEL 7.5, men den laddades och garanterades krascha servern, övergav vi användningen av kABI-kompatibilitet för RHEL 7 helt.

För närvarande innehåller KMOD-paketet för RHEL 7 en sammansättning för varje releaseversion och ett skript som laddar modulen.

SUSE närmade sig uppgiften med kABI-kompatibilitet mer noggrant. De tillhandahåller kABI-kompatibilitet endast inom ett servicepaket.

Till exempel släpptes SLES 12 i september 2014. Och SLES 12 SP1 var redan i december 2015, det vill säga lite mer än ett år har gått. Även om båda utgåvorna använder 3.12-kärnan, är de kABI-inkompatibla. Uppenbarligen är det mycket lättare att upprätthålla kABI-kompatibilitet i bara ett år. Den årliga uppdateringscykeln för kärnmodulen bör inte orsaka problem för modulskapare.

Som ett resultat av denna SUSE-policy har vi inte registrerat ett enda problem med kABI-kompatibilitet i vår veeamsnap-modul. Det är sant att antalet paket för SUSE är nästan en storleksordning större.

Patchar och bakportar

Även om distributörer försöker säkerställa kABI-kompatibilitet och kärnstabilitet, försöker de också förbättra prestandan och eliminera defekter i denna stabila kärna.

Samtidigt, förutom sitt eget "arbete med fel", övervakar utvecklarna av Linux-företagets kärna förändringar i vaniljkärnan och överför dem till sin "stabila" kärna.

Ibland leder detta till nya misstag.

I den senaste versionen av Red Hat 6 gjordes ett misstag i en av de mindre uppdateringarna. Det ledde till att veeamsnap-modulen garanterat kraschade systemet när ögonblicksbilden släpptes. Efter att ha jämfört kärnkällorna före och efter uppdateringen, fick vi reda på att backporten var skyldig. En liknande korrigering gjordes i vaniljkärnversion 4.19. Det är bara det att den här fixen fungerade bra i vaniljkärnan, men när den överfördes till den "stabila" 2.6.32, uppstod ett problem med spinlocket.

Alla har förstås alltid fel, men var det värt att dra koden från 4.19 till 2.6.32, riskera stabilitet?.. Jag är inte säker...

Det värsta är när marknadsföring blir involverad i dragkampen mellan "stabilitet" och "modernisering". Marknadsavdelningen behöver kärnan i den uppdaterade distributionen för att å ena sidan vara stabil och samtidigt vara bättre på prestanda och ha nya funktioner. Detta leder till konstiga kompromisser.

När jag försökte bygga en modul på kärnan 4.4 från SLES 12 SP3 blev jag förvånad över att hitta funktionalitet från vanilla 4.8 i den. Enligt min åsikt är block-I/O-implementeringen av 4.4-kärnan från SLES 12 SP3 mer lik 4.8-kärnan än den tidigare versionen av den stabila 4.4-kärnan från SLES12 SP2. Jag kan inte bedöma vilken procentandel av koden som överfördes från kärnan 4.8 till SLES 4.4 för SP3, men jag kan inte ens kalla kärnan för samma stabila 4.4.

Det mest obehagliga med detta är att när du skriver en modul som skulle fungera lika bra på olika kärnor, kan du inte längre lita på kärnversionen. Man måste också ta hänsyn till fördelningen. Det är bra att man ibland kan engagera sig i en definition som dyker upp tillsammans med ny funktionalitet, men denna möjlighet dyker inte alltid upp.

Som ett resultat blir koden övervuxen med konstiga villkorliga kompileringsdirektiv.

Det finns också patchar som ändrar det dokumenterade kärn-API:et.
Jag stötte på distributionen KDE neon 5.16 och blev mycket förvånad över att se att lookup_bdev-anropet i denna kärnversion ändrade listan med indataparametrar.

För att få ihop det var jag tvungen att lägga till ett skript till makefilen som kontrollerar om lookup_bdev-funktionen har en maskparameter.

Signering av kärnmoduler

Men låt oss återgå till frågan om paketdistribution.

En av fördelarna med stabil kABI är att kärnmoduler kan signeras som en binär fil. I det här fallet kan utvecklaren vara säker på att modulen inte har skadats av misstag eller avsiktligt modifierats. Du kan kontrollera detta med kommandot modinfo.

Red Hat- och SUSE-distributioner låter dig kontrollera modulens signatur och ladda den endast om motsvarande certifikat är registrerat i systemet. Certifikatet är den publika nyckel som modulen är signerad med. Vi distribuerar det som ett separat paket.

Problemet här är att certifikat antingen kan byggas in i kärnan (distributörer använder dem) eller måste skrivas till EFI icke-flyktigt minne med hjälp av ett verktyg mokutil. Verktyg mokutil När du installerar ett certifikat kräver det att du startar om systemet och, även innan operativsystemets kärna laddas, uppmanas administratören att tillåta laddning av ett nytt certifikat.

Att lägga till ett certifikat kräver alltså fysisk administratörsåtkomst till systemet. Om maskinen är placerad någonstans i molnet eller helt enkelt i ett fjärrserverrum och åtkomsten endast sker via nätverket (till exempel via ssh), kommer det att vara omöjligt att lägga till ett certifikat.

EFI på virtuella maskiner

Trots det faktum att EFI länge har stötts av nästan alla moderkortstillverkare, när du installerar ett system, kanske administratören inte tänker på behovet av EFI, och det kan vara inaktiverat.

Inte alla hypervisorer stöder EFI. VMWare vSphere stöder EFI från och med version 5.
Microsoft Hyper-V fick också EFI-stöd från och med Hyper-V för Windows Server 2012R2.

Men i standardkonfigurationen är denna funktion inaktiverad för Linux-maskiner, vilket innebär att certifikatet inte kan installeras.

I vSphere 6.5, ställ in alternativet säkra Boot endast möjligt i den gamla versionen av webbgränssnittet, som körs via Flash. Webbgränssnittet på HTML-5 ligger fortfarande långt efter.

Experimentella distributioner

Och slutligen, låt oss överväga frågan om experimentella distributioner och distributioner utan officiellt stöd. Å ena sidan är det osannolikt att sådana distributioner finns på seriösa organisationers servrar. Det finns inget officiellt stöd för sådana distributioner. Ge därför dem. Produkten kan inte stödjas på en sådan distribution.

Sådana distributioner blir dock en bekväm plattform för att testa nya experimentella lösningar. Till exempel, Fedora, OpenSUSE Tumbleweed eller Unstable versioner av Debian. De är ganska stabila. De har alltid nya versioner av program och alltid en ny kärna. Om ett år kan denna experimentella funktion hamna i en uppdaterad RHEL, SLES eller Ubuntu.

Så om något inte fungerar på en experimentell distribution är detta en anledning att ta reda på problemet och lösa det. Du måste vara beredd på att denna funktion snart kommer att dyka upp på användarnas produktionsservrar.

Du kan studera den aktuella listan över officiellt stödda distributioner för version 3.0 här. Men den verkliga listan över distributioner som vår produkt kan fungera på är mycket bredare.

Personligen var jag intresserad av experimentet med Elbrus OS. Efter att ha slutfört veeam-paketet var vår produkt installerad och fungerade. Jag skrev om detta experiment på Habré i artikeln.

Jo, stödet för nya distributioner fortsätter. Vi väntar på att version 4.0 ska släppas. Beta är på väg att dyka upp, så håll utkik Vad är nytt!

Källa: will.com

Lägg en kommentar