Linux mangfoldig: korleis arbeida på kva som helst distribusjon

Linux mangfoldig: korleis arbeida på kva som helst distribusjon

Å lage ei app for sikkerheitskopiering som fungerer på kva som helst distribusjon er ei krevjande oppgåve. For å sikre at Veeam Agent for Linux fungerer på distribusjonar frå Red Hat 6 til Debian 6, OpenSUSE 15.1 og Ubuntu 19.04, må ein løysa eit spekter av problem, spesielt med tanke på at programvaren inkluderer ein kjerne-modul.

Artikkelen er basert på materiale frå eit foredrag på konferansen LinuxPiter 2019.

Linux er ikkje berre eitt av dei mest populære operativsystema. I utgangspunktet er det ei plattform der ein kan lage noko unikt, noko eige. Takka vere dette har Linux mange distribusjonar som skil seg frå kvarandre ved hjelp av ei rekkje programvarekomponentar. Her oppstår problemet: For at programvaren skal fungere på kva som helst distribusjon, må ein ta omsyn til eigenskapene til kvar enkelt.

Pakkehåndterarar. .deb vs .rpm

La oss byrja med det åpenbare problemet med distribusjon av produktet for ulike distribusjonar.
Den mest vanlege måten å distribuere programvara på er å leggje ut ein pakke i eit repositorium slik at den innebygde pakkehåndteraren i systemet kan installere den derfrå.
Det er imidlertid to populære pakkformat: rpm og deb. Det betyr at vi må støtte kvar enkelt.

I verda av deb-pakkar er kompabiliteten imponerande. Den same pakken installerer og fungerer like godt på både Debian 6 og Ubuntu 19.04. Standardane for pakkeoppretting og arbeid med dei som blei lagt i tidlege Debian-distribusjonar, er fremdeles relevante også i moderne Linux Mint og elementary OS. Difor er det nok med ein deb-pakke for kvar maskinvareplattform for Veeam Agent for Linux.

Derimot er forskjellane i verda av rpm-pakkar store. For det første fordi det finst to heilt uavhengige distribusjonar, Red Hat og SUSE, som ikkje har noko behov for kompabilitet. For det andre har desse distribusjonane både distribusjonar med teknisk støtte og eksperimentelle. Mellom desse er kompabilitet også unødvendig. Det viser seg at vi har eigne pakkar for el6, el7 og el8. I tillegg ein eigen pakke for Fedora. Pakkar for SLES11 og 12 og ein eigen for openSUSE. Hovudproblemet er avhengigheiter og namn på pakkar.

Problemet med avhengigheiter

Dessverre har dei same pakkane ofte ulike namn i forskjellige distribusjonar. Nedenfor er ein ufullstendig liste over avhengigheiter for veeam-pakken.

For EL7:
For SLES 12:

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

Som følger av dette blir avhengighetslisten unik for distribusjonen.

Det blir enda verre når en oppdatert versjon begynner å skjule seg under det gamle pakkenavnet.

Eksempel:

I Fedora 24 ble pakken oppdatert ncurses fra versjon 5 til versjon 6. Vår produkt ble bygget med versjon 5 for å sikre kompatibilitet med gamle distribusjoner. For å bruke den gamle versjon 5 av biblioteket på Fedora 24 måtte man bruke pakken ncurses-compat-libs.

Som et resultat får Fedora to pakker, med forskjellige avhengigheter.

Så blir det mer interessant. Etter en ny oppdatering av distribusjonen blir pakken ncurses-compat-libs med versjon 5 av biblioteket utilgjengelig. For distributøren er det besværlig å trekke gamle biblioteker inn i den nye versjonen av distribusjonen. Etter en tid dukket det samme problemet opp i SUSE-distribusjoner.

Som et resultat måtte man for noen distribusjoner gi opp den eksplisitte avhengigheten fra ncurses-libs, og produktet måtte justeres slik at det kunne fungere med hvilken som helst versjon av biblioteket.

Forresten, i Red Hat versjon 8 finnes ikke lenger meta-pakken python, som refererte til den gamle gode python 2.7. Det finnes python2 og python3.

Alternativ til pakkebehandlerne

Problemet med avhengigheter er gammelt og åpenbart. Bare minn om Dependency hell.
Å samle ulike biblioteker og applikasjoner slik at de alle fungerer stabilt og ikke konflikter — dette er utvilsomt oppgaven enhver Linux-distributør prøver å løse.

Helt annerledes forsøker pakkebehandleren Snappy fra Canonical. Hovedideen: applikasjonen kjøres i en isolert og beskyttet sandkasse fra hovedsystemet. Hvis applikasjonen trenger biblioteker, leveres de sammen med selve applikasjonen.

Flatpak lar også kjøre applikasjoner i sandkassen ved bruk av Linux Containers. Ideen om sandkasse brukes også av AppImage.

Disse løsningene gjør det mulig å lage én pakke for alle distribusjoner. Når det gjelder Flatpak kan installasjon og kjøring av applikasjonen skje selv uten administratorens viten.

Hovedproblemet er at ikke alle applikasjoner kan fungere i sandkassen. Noen trenger direkte tilgang til plattformen. Jeg nevner ikke engang kjerne-moduler som er sterkt avhengige av kjernen og ikke passer inn i sandkasse-konseptet.

Det andre problemet er at de populære distribusjonene fra Red Hat og SUSE i enterprise-miljøet fortsatt ikke støtter Snappy og Flatpak.

Som følge av dette er Veeam Agent for Linux verken tilgjengelig på snapcraft.io eller på flathub.org.

For å avslutte spørsmålet om pakkeadministratorer vil jeg bemerke at det er et alternativ å helt slutte å bruke pakkeadministratorer, og i stedet samle binærfiler og skripter for installasjon i én pakke.

En slik pakke gjør det mulig å lage én felles pakke for forskjellige distribusjoner og plattformer, og gjennomføre en interaktiv installasjonsprosess med nødvendig tilpasning. Jeg har bare sett slike pakker for Linux fra VMware.

Problemet med oppdateringer

Linux mangfoldig: korleis arbeida på kva som helst distribusjon
Selv om alle avhengighetsproblemer er løst, kan programmet oppføre seg ulikt på samme distribusjon. Det skyldes oppdateringene.

Det finnes 3 strategier for oppdateringer:

  • Den enkleste er å aldri oppdatere. Du konfigurerer serveren og glemmer den. Hvorfor oppdatere når alt fungerer? Problemer begynner så snart du tar kontakt med supporttjenesten. Distribusjonens utvikler støtter kun den oppdaterte versjonen.
  • Du kan stole på distributøren og sette opp automatiske oppdateringer. I så fall er det sannsynlig at du må ringe supporten umiddelbart etter en mislykket oppdatering.
  • Alternativet med manuell oppdatering kun etter testing i testinfrastrukturen er det sikreste, men det er dyrt og arbeidstungt. Langt fra alle har råd til det.

Siden forskjellige brukere anvender forskjellige oppdateringsstrategier, må både den nyeste utgivelsen og alle tidligere utgivelser støttes. Dette kompliserer både utviklingsprosessen og testingen, og gir supporttjenesten mer hodebry.

Mangfold av maskinvareplattformer

Ulike maskinvareplattformer er et problem som i stor grad er spesifikt for native-kode. Minst må man bygge binærfiler for hver støttet plattform.

I prosjektet Veeam Agent for Linux klarer vi ennå ikke å støtte noe som helst RISC-relatert.

Jeg vil ikke gå i dybden på dette temaet. Jeg vil bare nevne de viktigste problemene: plattformavhengige typer, som size_t, strukturjustering og byte-rekkefølge.

Statisk og/eller dynamisk lenking

Linux mangfoldig: korleis arbeida på kva som helst distribusjon
Spørsmålet «Hvordan skal man lenke med biblioteker - dynamisk eller statisk?» er verdt å diskutere.

Som regel bruker C/C++-applikasjoner på Linux dynamisk linking. Dette fungerer utmerket hvis applikasjonen er bygget spesifikt for en bestemt distribusjon.

Hvis målet er å dekke ulike distribusjoner med én binærfil, må man rette seg etter den eldste støttede distribusjonen. For oss er dette Red Hat 6. Den inneholder gcc 4.4, som ikke engang støtter standard C++11 fullt ut. fullstendig.

Vi bygger prosjektet vårt med gcc 6.3, som støtter C++14 fullt ut. I så fall må vi dra med oss libstdc++ og boost-biblioteket på Red Hat 6. Det enkleste er å linke til dem statisk.

Men dessverre kan ikke alle biblioteker linkes statisk.

For det første må systembiblioteker, som libfuse, libblkid linkes dynamisk for å sikre kompatibilitet med kjernen og dens moduler.

For det andre er det en nyanse med lisenser.

GPL-lisensen tillater i prinsippet å linke biblioteker kun med opensource-kode. MIT og BSD tillater statisk linking og lar inkludere biblioteker i prosjektet. Derimot synes LGPL ikke å motsette seg statisk linking, men krever å gi tilgang til filene som er nødvendige for linking.

Generelt vil bruk av dynamisk linking beskytte mot behovet for å gi noe ut.

Bygging av C/C++-applikasjoner

For å bygge C/C++-applikasjoner for ulike plattformer og distribusjoner, er det tilstrekkelig å finne eller bygge en passende versjon av gcc og bruke krysskompilatorer for spesifikke arkitekturer, samt å samle hele settet av biblioteker. Dette arbeidet er fullt mulig, men ganske tidkrevende. Og det er ingen garantier for at den valgte kompilatoren og bibliotekene vil gi en fungerende variant.

En åpenbar fordel: infrastrukturen blir sterkt forenklet, da hele byggeprosessen kan utføres på én maskin. I tillegg er det tilstrekkelig å samle ett sett av binærfiler for én arkitektur, og så kan de pakkes i pakker for forskjellige distribusjoner. Slik blir veeam-pakkene for Veeam Agent for Linux bygget.

I motsetning til dette alternativet kan man enkelt forberede en bygningsgård, det vil si flere maskiner for bygging. Hver av disse maskinene vil sørge for kompilering av applikasjonen og bygging av pakken for en spesifikk distribusjon og bestemt arkitektur. I så fall utføres kompileringen med de midlene som distribusjonen har forberedt. Med andre ord,forberedelsestrinnet for kompilatoren og valg av biblioteker faller bort. I tillegg kan byggeprosessen enkelt paralleliseres.

Det er imidlertid en ulempe med en slik tilnærming: for hver distribusjon innenfor en arkitektur må man samle sitt eget sett av binærfiler. En annen ulempe er at et så stort antall maskiner må vedlikeholdes, noe som krever mye diskplass og RAM.

Slik blir KMOD-pakkene for veeamsnap-kjernemodulen samlet for Red Hat-distribusjoner.

Open Build Service

Kollegene fra SUSE forsøkte å oppnå en slags gullstandard i form av en spesialtjeneste for kompilering av applikasjoner og bygging av pakker — openbuildservice.

I prinsippet er dette en hypervisor som oppretter en virtuell maskin, installerer alle nødvendige pakker, utfører kompilering av applikasjonen og bygging av pakken i dette isolerte miljøet, hvoretter denne virtuelle maskinen frigjøres.

Linux mangfoldig: korleis arbeida på kva som helst distribusjon

Planleggeren innebygd i OpenBuildService vil selv avgjøre hvor mange virtuelle maskiner den kan starte for optimal hastighet ved pakkebygging. Den innebygde signeringsmekanismen vil automatisk signere pakkene og legge dem ut på den innebygde lagringsplassen. Det innebygde versjonskontrollsystemet vil lagre historikken for endringer og bygg. Det gjenstår bare å legge inn sine kildefiler i dette systemet. Det er ikke engang nødvendig å sette opp en server selv, man kan bruke den åpne.

Men her er det et problem: en slik kombinasjon passer ikke godt inn i den eksisterende infrastrukturen. For eksempel er versjonskontrollen ikke nødvendig, da vi allerede har vår for kildefilene. Signeringsmekanismen vår er annerledes: en spesiell server benyttes. Lagringsplassen er heller ikke nødvendig.

I tillegg er støtten for andre distribusjoner — for eksempel Red Hat — ganske mager, noe som er forståelig.

Fordelen med en slik tjeneste er rask støtte for den nyeste versjonen av SUSE-distribusjonen. Før den offisielle kunngjøringen om utgivelsen legges nødvendige pakker ut i et offentlig repository. Den nye distribusjonen vises på listen over tilgjengelige distribusjoner i OpenBuildService. Vi setter en hake, og den legges til i byggeplanen. Dermed kan tillegget av en ny distribusjonsversjon gjøres praktisk talt med ett klikk.

I vår infrastruktur, som bruker OpenBuildService, bygges et mangfold av KMP-pakker for veeamsnap-modulen til SUSE-distribusjoner.

Deretter vil jeg gjerne stoppe opp ved spørsmål som er spesifikke for kjernemoduler.

kernel ABI

Linux-kjernemoduler har historisk blitt distribuert som kildekode. Årsaken er at kjernens utviklere ikke tar seg bryet med å opprettholde et stabilt API for kjernemoduler, langt mindre på binært nivå, videre kABI.

For å bygge en modul for det vanlige kjernen, er det nødvendig med header-filer for nettopp denne kjernen, og den vil kun fungere med denne kjernen.

DKMS lar deg automatisere prosessen med å bygge moduler ved oppdatering av kjernen. Som et resultat bruker brukere av Debian-repositoryet (og dets mange slektninger) kjernemoduler enten fra distributørens repository eller bygget fra kildekode ved hjelp av DKMS.

Men slik situasjonen er, tilfredsstiller det ikke Enterprise-segmentet særlig godt. Distribusjoner av proprietær kode ønsker å distribuere produktet i form av ferdigbygde binærfiler.

Administratorer ønsker ikke å ha utviklingsverktøy på produksjonsservere av sikkerhetsmessige årsaker. Distribusjoner av Enterprise Linux – som Red Hat og SUSE – har besluttet at de kan støtte sine brukere med stabil kABI. Som et resultat har KMOD-pakker for Red Hat og KMP-pakker for SUSE dukket opp.

Kjernen i en slik løsning er ganske enkel. For en spesifikk versjon av distribusjonen fryses API-et i kjernen. Distributøren erklærer at de bruker en spesifikk kjerne, for eksempel 3.10, og gjør bare feilrettinger og forbedringer som ikke berører kernelgrensesnittene, og moduler bygget for den aller første kjernen kan brukes for alle påfølgende uten rekompilering.

Red Hat uttaler at kABI-kompatibilitet for distribusjonen gjelder gjennom hele livssyklusen. Det betyr at en bygget modul for rhel 6.0 (utgivelse november 2010) også skal fungere på versjon 6.10 (utgivelse juni 2018). Og dette er nesten 8 år. Naturligvis er dette en ganske vanskelig oppgave.
Vi har registrert flere tilfeller der modulen veeamsnap sluttet å fungere på grunn av problemer med kABI-kompatibiliteten.

Etter at modulen veeamsnap, bygget for RHEL 7.0, viste seg å være inkompatibel med kjernen fra RHEL 7.5, men likevel ble lastet inn og garantert krasjet serveren, forkastet vi bruken av kABI-kompatibilitet for RHEL 7 helt.

For øyeblikket inneholder KMOD-pakken for RHEL 7 en bygging for hver versjon av utgivelsen og et skript som sørger for lasting av modulen.

SUSE har tatt en mer forsiktig tilnærming til kABI-kompatibilitet. De sikrer kABI-kompatibilitet bare innenfor ett servicepakke.

For eksempel ble utgivelsen SLES 12 lansert i september 2014. Og SLES 12 SP1 kom allerede i desember 2015, altså gikk det litt over ett år. Til tross for at begge utgivelser bruker kjerne 3.12, er de kABI-incompatible. Det er åpenbart at det er betydelig enklere å opprettholde kABI-kompatibilitet i løpet av bare ett år. Et årlig oppdateringssyklus for modulkjernen bør ikke forårsake problemer for modulskaperne.

Som et resultat av denne politikken fra SUSE har vi ikke registrert noen problemer med kABI-kompatibilitet med vår modul veeamsnap. Faktisk er antallet pakker for SUSE nesten på nivå med en orden større.

Patch og bakporter

Selv om distributørene prøver å sikre kABI-kompatibilitet og stabilitet i kjernen, prøver de også å forbedre ytelsen og rette opp feil i denne stabile kjernen.

I tillegg til sitt eget "arbeid med feil" følger utviklerne av enterprise linux-kjernen med på endringene i vaniljekjernen og overfører dem til sin "stabile".

Noen ganger fører dette til nye feil.

I den siste utgivelsen av Red Hat 6 ble det gjort en feil i en av de mindre oppdateringene. Denne førte til at modulen veeamsnap garantert krasjet systemet ved frigjøring av et snapshot. Etter å ha sammenlignet kildekodene til kjernen før og etter oppdateringen, fant vi ut at det var bakporten som var ansvarlig. En tilsvarende fiks ble utført i vaniljekjernen versjon 4.19. Men i vaniljekjernen fungerte denne fiksen normalt, mens overføringen til det "stabile" 2.6.32 medførte et problem med spin-låsingen.

Selvfølgelig, fejl opstår altid for alle, men var det værd at trække kode fra 4.19 til 2.6.32, risikerende stabiliteten?.. Jeg er ikke sikker…

Det værste er, når marketing også blander sig i det at trække i det stræk, der handler om "stabilitet""modernisering". Marketingafdelingen har brug for, at kernen i den opdaterede distribution er stabil, på den ene side, men samtidig skal den også være bedre i ydeevne og have nye funktioner. Dette fører til mærkelige kompromisser.

Da jeg prøvede at samle modulet på kernen 4.4 fra SLES 12 SP3, blev jeg overrasket over at opdage funktionalitet fra den rene 4.8. Efter min mening ligner implementeringen af blokind- og udgang fra kernen 4.4 fra SLES 12 SP3 mere kernen 4.8 end den tidligere udgave af den stabile 4.4 kerne fra SLES 12 SP2. Jeg vil ikke vurdere, hvad procentdelen af den overførte kode fra kernen 4.8 til SLES' 4.4 for SP3 er, men jeg kan ikke kalde kernen den samme stabile 4.4.

Det mest frustrerende ved at skrive et modul, der fungerer godt på forskellige kerner, er, at man ikke længere kan stole på kerneversionen. Man skal også tage hensyn til distributionen. Heldigvis kan man nogle gange binde sig til en define, som dukker op med den nye funktionalitet, men denne mulighed opstår ikke altid.

Resultatet er, at koden bliver fyldt med bizarre preproces directives.

Der er også patches, der ændrer det dokumenterede API for kernen.
Jeg stødte på distributionen KDE neon 5.16 og blev meget overrasket over at se, at kaldet til lookup_bdev i denne kerneversion havde ændret listen af indparametre.

For at kunne samle det måtte jeg tilføje et script til makefile, der kontrollerede, om der var en mask parameter til funktionen lookup_bdev.

Undertegnelse af kernemoduler

Men lad os vende tilbage til spørgsmålet om distributionspakker.

En af fordelene ved stabil kABI er, at kernemoduler i form af binære filer kan signeres. På denne måde kan udvikleren være sikker på, at modulet ikke er blevet beskadiget ved en fejl eller ændret bevidst. Dette kan tjekkes med kommandoen modinfo.

Distributioner som Red Hat og SUSE tillader at kontrollere signaturen på modulet og indlæse det kun, hvis det relevante certifikat er registreret i systemet. Certifikatet er en offentlig nøgle, som modulet bliver signeret med. Vi distribuerer det som en separat pakke.

Problemet her er, at certifikater enten kan være indbyggede i kernen (de anvendes af distributionsudbydere) eller skal skrives til den ikke-flygtige EFI-hukommelse ved hjælp af et værktøj. mokutil. The utility mokutil ved installation af certifikatet kræver det genstart af systemet og tilbydes administratoren at tillade indlæsning af det nye certifikat før indlæsning af operativsystemkernen.

Således kræver tilføjelse af certifikatet fysisk adgang til systemet fra administratoren. Hvis maskinen er placeret et sted i skyen eller blot i en fjern server, hvor adgang kun er muligt via netværket (f.eks. via ssh), kan certifikatet ikke tilføjes.

EFI på virtuelle maskiner

Selvom EFI længe har været understøttet af næsten alle producenter af bundkort, kan administratoren ved installation af systemet måske ikke overveje behovet for EFI, og det kan være deaktiveret.

Ikke alle hypervisorer understøtter EFI. VMWare vSphere understøtter EFI fra version 5.
Microsoft Hyper-V har også fået støtte for EFI, begyndende med Hyper-V for Windows Server 2012R2.

Men i standardkonfigurationen er denne funktionalitet deaktiveret for Linux-maskiner, hvilket betyder, at certifikatet ikke kan installeres.

I vSphere 6.5 kan du indstille muligheden Secure Boot kun i den gamle version af webgrænsefladen, som fungerer gennem Flash. Web UI i HTML-5 er stadig meget bagud.

Eksperimentelle distributioner

Og til sidst vil vi se på spørgsmålet om eksperimentelle distributioner og distributioner uden officiel støtte. På den ene side vil du næppe finde sådanne distributioner på serverne i seriøse organisationer. Der er ikke officiel støtte til sådanne distributioner. Derfor kan teknisk support af produktet ikke ydes på en sådan distribution.

Men sådanne distributioner bliver et praktisk forum til at afprøve nye eksperimentelle løsninger. For eksempel, Fedora, OpenSUSE Tumbleweed eller Unstable-versioner af Debian. De er ret stabile. De har altid nye versioner af programmerne og altid en ny kerne. Om et år kan denne eksperimentelle funktionalitet findes i den opdaterede RHEL, SLES eller Ubuntu.

Så hvis noget ikke virker på en eksperimentel distribution, er det en grund til at undersøge problemet og løse det. Man skal være klar til, at denne funktionalitet snart vil dukke op på production-serverne hos brugerne.

Den eksisterende listen over offisielt støttede distribusjoner for versjon 3.0 kan du studere her. Men den virkelige listen over distribusjoner som produktet vårt kan fungere på, er mye bredere.

Personlig var jeg interessert i et eksperiment med operativsystemet «Elbrus». Etter tilpasning av veeam-pakken ble produktet vårt installert og fungerte. Jeg skrev om dette eksperimentet på Habr i artikkelen.

Støtten for nye distribusjoner fortsetter. Vi venter på at versjon 4.0 skal komme. Betaen bør snart være tilgjengelig, så følg med på whats-new!

Kilde: habr.com

Kjøp pålitelig hosting for nettsteder med DDoS-beskyttelse, VPS VDS-servere 🔥 Kjøp pålitelig hosting for nettsteder med DDoS-beskyttelse, VPS VDS-servere | ProHoster