Linux har mange ansikter: hvordan jobbe med enhver distribusjon

Linux har mange ansikter: hvordan jobbe med enhver distribusjon

Det er ingen enkel oppgave å lage en sikkerhetskopiapplikasjon som fungerer på enhver distribusjon. For å sikre at Veeam Agent for Linux fungerer på distribusjoner fra Red Hat 6 og Debian 6, til OpenSUSE 15.1 og Ubuntu 19.04, må du løse en rekke problemer, spesielt med tanke på at programvareproduktet inkluderer en kjernemodul.

Artikkelen ble laget basert på materiale fra en tale på konferansen Linux Peter 2019.

Linux er ikke bare et av de mest populære operativsystemene. I hovedsak er dette en plattform på grunnlag av hvilken du kan lage noe unikt, noe eget. Takket være dette har Linux mange distribusjoner som er forskjellige i deres sett med programvarekomponenter. Og her oppstår et problem: For at et programvareprodukt skal fungere på en hvilken som helst distribusjon, må du ta hensyn til funksjonene til hver.

Pakkeforvaltere. .deb vs. .rpm

La oss starte med det åpenbare problemet med å distribuere produktet på tvers av forskjellige distribusjoner.
Den mest typiske måten å distribuere programvareprodukter på er å legge pakken på et depot slik at pakkebehandleren som er innebygd i systemet kan installere den derfra.
Vi har imidlertid to populære pakkeformater: rpm и deb. Det betyr at alle må støtte.

I en verden av deb-pakker er kompatibilitetsnivået fantastisk. Den samme pakken installeres og fungerer like bra på både Debian 6 og Ubuntu 19.04. Standardene for prosessen med å bygge pakker og jobbe med dem, nedfelt i gamle Debian-distribusjoner, forblir relevante i det nymotens Linux Mint og elementære OS. Derfor, i tilfellet med Veeam Agent for Linux, er én deb-pakke for hver maskinvareplattform tilstrekkelig.

Men i rpm-pakkenes verden er forskjellene store. For det første på grunn av det faktum at det er to helt uavhengige distributører, Red Hat og SUSE, som kompatibilitet er helt unødvendig for. For det andre har disse distributørene distribusjonssett fra disse. støtte og eksperimentelle. Det er heller ikke behov for kompatibilitet mellom dem. Det viste seg at el6, el7 og el8 har egne pakker. Separat pakke for Fedora. Pakker for SLES11 og 12 og en separat for openSUSE. Hovedproblemet er avhengigheter og pakkenavn.

Avhengighetsproblem

Dessverre havner de samme pakkene ofte under forskjellige navn i forskjellige distribusjoner. Nedenfor er en delvis liste over veeam-pakkeavhengigheter.

For EL7:
For 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 et resultat er listen over avhengigheter unik for distribusjonen.

Det som blir verre er når en oppdatert versjon begynner å gjemme seg under det gamle pakkenavnet.

Eksempel:

Pakken har blitt oppdatert i Fedora 24 forbannelser fra versjon 5 til versjon 6. Vårt produkt ble bygget med versjon 5 for å sikre kompatibilitet med eldre distribusjoner. For å bruke den gamle 5. versjonen av biblioteket på Fedora 24, måtte jeg bruke pakken ncurses-compat-libs.

Som et resultat er det to pakker for Fedora, med forskjellige avhengigheter.

Mer interessant. Etter neste distribusjonsoppdatering, pakken ncurses-compat-libs med versjon 5 av biblioteket viser det seg å være utilgjengelig. Det er dyrt for en distributør å dra gamle biblioteker inn i en ny versjon av distribusjonen. Etter en tid gjentok problemet seg i SUSE-distribusjoner.

Som et resultat måtte noen distribusjoner droppe sin eksplisitte avhengighet av ncurses-libs, og fiks produktet slik at det kan fungere med alle versjoner av biblioteket.

Forresten, i versjon 8 av Red Hat er det ikke lenger en metapakke python, som refererte til det gode gamle python 2.7... det er python2 и python3.

Alternativ til pakkeforvaltere

Problemet med avhengigheter er gammelt og har lenge vært åpenbart. Bare husk avhengighetshelvete.
Å kombinere ulike biblioteker og applikasjoner slik at de alle fungerer stabilt og ikke kommer i konflikt – faktisk er dette oppgaven enhver Linux-distributør prøver å løse.

Pakkebehandleren prøver å løse dette problemet på en helt annen måte. Snappy fra Canonical. Hovedideen: applikasjonen kjører i en sandkasse isolert og beskyttet fra hovedsystemet. Hvis en applikasjon krever biblioteker, leveres de med selve applikasjonen.

Flatpak lar deg også kjøre applikasjoner i en sandkasse ved hjelp av Linux-beholdere. Sandkasseideen brukes også AppImage.

Disse løsningene lar deg lage én pakke for enhver distribusjon. I tilfelle Flatpak installasjon og lansering av applikasjonen er mulig selv uten administratorens viten.

Hovedproblemet er at ikke alle applikasjoner kan kjøres i en sandkasse. Noen mennesker trenger direkte tilgang til plattformen. Jeg snakker ikke engang om kjernemoduler, som er strengt avhengige av kjernen og ikke passer inn i sandkassekonseptet.

Det andre problemet er at distribusjoner som er populære i bedriftsmiljøet fra Red Hat og SUSE ennå ikke inneholder støtte for Snappy og Flatpak.

I denne forbindelse er ikke Veeam Agent for Linux tilgjengelig snapcraft.io ikke på www.flathub.org.

For å konkludere med spørsmålet om pakkebehandlere, vil jeg merke at det er et alternativ å forlate pakkebehandlere helt ved å kombinere binære filer og et skript for å installere dem i én pakke.

En slik pakke lar deg lage en felles pakke for forskjellige distribusjoner og plattformer, utføre en interaktiv installasjonsprosess, utføre nødvendig tilpasning. Jeg har bare møtt slike pakker for Linux fra VMware.

Oppdateringsproblem

Linux har mange ansikter: hvordan jobbe med enhver distribusjon
Selv om alle avhengighetsproblemer er løst, kan programmet kjøre annerledes på samme distribusjon. Det er et spørsmål om oppdateringer.

Det er 3 oppdateringsstrategier:

  • Det enkleste er å aldri oppdatere. Jeg satte opp serveren og glemte det. Hvorfor oppdatere hvis alt fungerer? Problemer begynner første gang du kontakter support. Skaperen av distribusjonen støtter kun den oppdaterte utgivelsen.
  • Du kan stole på distributøren og sette opp automatiske oppdateringer. I dette tilfellet er det sannsynligvis en oppfordring til støtte umiddelbart etter en mislykket oppdatering.
  • Muligheten for manuell oppdatering først etter å ha kjørt den på en testinfrastruktur er den mest pålitelige, men dyr og tidkrevende. Ikke alle har råd til det.

Siden forskjellige brukere bruker forskjellige oppdateringsstrategier, er det nødvendig å støtte både den siste utgivelsen og alle tidligere utgitte. Dette kompliserer både utviklings- og testprosessen og legger til hodepine for støtteteamet.

Ulike maskinvareplattformer

Ulike maskinvareplattformer er et problem som stort sett er spesifikt for innfødt kode. Som et minimum må du samle binærfiler for hver støttet plattform.

I Veeam Agent for Linux-prosjektet kan vi fortsatt ikke støtte noe lignende RISC.

Jeg vil ikke gå nærmere inn på dette spørsmålet. Jeg vil bare skissere hovedproblemene: plattformavhengige typer, som f.eks size_t, strukturjustering og byte-rekkefølge.

Statisk og/eller dynamisk kobling

Linux har mange ansikter: hvordan jobbe med enhver distribusjon
Men spørsmålet er "Hvordan koble til biblioteker - dynamisk eller statisk?" verdt å diskutere.

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

Hvis oppgaven er å dekke ulike distribusjoner med én binær fil, så må du fokusere på den eldste støttede distribusjonen. For oss er dette Red Hat 6. Den inneholder gcc 4.4, som selv ikke C++11-standarden støtter fullt.

Vi bygger prosjektet vårt ved å bruke gcc 6.3, som fullt ut støtter C++14. Naturligvis, i dette tilfellet, på Red Hat 6 må du ha med deg libstdc++ og øke bibliotekene. Den enkleste måten er å koble til dem statisk.

Men dessverre, ikke alle biblioteker kan kobles statisk.

For det første systembiblioteker som f.eks libfuse, libblkid det er nødvendig å koble dynamisk for å sikre deres kompatibilitet med kjernen og dens moduler.

For det andre er det en finesse med lisenser.

GPL-lisensen lar deg i utgangspunktet bare koble biblioteker med åpen kildekode. MIT og BSD tillater statisk kobling og lar biblioteker inkluderes i et prosjekt. Men LGPL ser ikke ut til å motsi statisk kobling, men krever at filene som er nødvendige for kobling deles.

Generelt sett vil bruk av dynamisk kobling hindre deg i å måtte gi noe.

Bygge C/C++-applikasjoner

For å bygge C/C++-applikasjoner for forskjellige plattformer og distribusjoner, er det nok å velge eller bygge en passende versjon av gcc og bruke krysskompilatorer for spesifikke arkitekturer og sette sammen hele settet med biblioteker. Dette arbeidet er ganske gjennomførbart, men ganske plagsomt. Og det er ingen garanti for at den valgte kompilatoren og bibliotekene vil gi en brukbar versjon.

En åpenbar fordel: Infrastrukturen er betydelig forenklet, siden hele byggeprosessen kan fullføres på én maskin. I tillegg er det nok å samle ett sett med binærfiler for én arkitektur, og du kan pakke dem inn i pakker for forskjellige distribusjoner. Dette er hvordan veeam-pakker er bygget for Veeam Agent for Linux.

I motsetning til dette alternativet, kan du ganske enkelt forberede en byggegård, det vil si flere maskiner for montering. Hver slik maskin vil gi applikasjonskompilering og pakkesammenstilling for en spesifikk distribusjon og en spesifikk arkitektur. I dette tilfellet utføres kompilering ved hjelp av midlene utarbeidet av distributøren. Det vil si at trinnet med å forberede kompilatoren og velge biblioteker er eliminert. I tillegg kan byggeprosessen enkelt parallelliseres.

Det er imidlertid en ulempe ved denne tilnærmingen: for hver distribusjon innenfor den samme arkitekturen, må du samle ditt eget sett med binære filer. En annen ulempe er at et så stort antall maskiner må vedlikeholdes og en stor mengde diskplass og RAM må tildeles.

Dette er hvordan KMOD-pakker til veeamsnap-kjernemodulen kompileres for Red Hat-distribusjoner.

Åpne Byggtjeneste

Kolleger fra SUSE prøvde å implementere en mellomting i form av en spesiell tjeneste for å kompilere applikasjoner og sette sammen pakker - openbuildservice.

I hovedsak er det en hypervisor som lager en virtuell maskin, installerer alle nødvendige pakker i den, kompilerer applikasjonen og bygger pakken i dette isolerte miljøet, hvoretter den virtuelle maskinen frigjøres.

Linux har mange ansikter: hvordan jobbe med enhver distribusjon

Planleggeren implementert i OpenBuildService vil bestemme hvor mange virtuelle maskiner den kan starte for optimal pakkebyggingshastighet. Den innebygde signeringsmekanismen vil signere pakkene og laste dem opp til det innebygde depotet. Det innebygde versjonskontrollsystemet vil lagre historikken for endringer og bygg. Alt som gjenstår er å legge til kildene dine i dette systemet. Du trenger ikke engang å sette opp serveren selv; du kan bruke en åpen.

Det er imidlertid et problem: En slik hogstmaskin er vanskelig å passe inn i den eksisterende infrastrukturen. For eksempel er versjonskontroll ikke nødvendig; vi har allerede vår egen for kildekoder. Signaturmekanismen vår er annerledes: vi bruker en spesiell server. Et depot er heller ikke nødvendig.

I tillegg er støtte for andre distribusjoner – for eksempel Red Hat – implementert ganske dårlig, noe som er forståelig.

Fordelen med en slik tjeneste er rask støtte for neste versjon av SUSE-distribusjonen. Før den offisielle kunngjøringen av utgivelsen, legges pakkene som er nødvendige for montering ut på et offentlig depot. En ny dukker opp i listen over tilgjengelige distribusjoner på OpenBuildService. Vi krysser av i boksen og det legges til byggeplanen. Dermed legges en ny versjon av distribusjonen til med nesten ett klikk.

I vår infrastruktur, ved å bruke OpenBuildService, er hele utvalget av KMP-pakker av veeamsnap-kjernemodulen for SUSE-distribusjoner satt sammen.

Deretter vil jeg dvele ved problemer som er spesifikke for kjernemoduler.

kjerne ABI

Linux-kjernemoduler har historisk blitt distribuert i kildeform. Faktum er at skaperne av kjernen ikke belaster seg selv med bekymringen om å støtte et stabilt API for kjernemoduler, og spesielt på binært nivå, videre referert til som kABI.

For å bygge en modul for en vaniljekjerne trenger du definitivt overskriftene til denne spesielle kjernen, og den vil bare fungere på denne kjernen.

DKMS lar deg automatisere prosessen med å bygge moduler når du oppdaterer kjernen. Som et resultat bruker brukere av Debian-depotet (og dets mange slektninger) kjernemoduler enten fra distributørens depot eller kompilert fra kilde ved hjelp av DKMS.

Denne situasjonen passer imidlertid ikke spesielt godt til Enterprise-segmentet. Proprietære kodedistributører ønsker å distribuere produktet som kompilerte binære filer.

Administratorer ønsker ikke å beholde utviklingsverktøy på produksjonsservere av sikkerhetsgrunner. Enterprise Linux-distributører som Red Hat og SUSE bestemte at de kunne støtte stabil kABI for brukerne sine. Resultatet ble KMOD-pakker for Red Hat og KMP-pakker for SUSE.

Essensen av denne løsningen er ganske enkel. For en spesifikk versjon av distribusjonen er kjerne-API-en frosset. Distributøren oppgir at han bruker kjernen, for eksempel 3.10, og gjør kun rettelser og forbedringer som ikke påvirker kjernegrensesnittene, og modulene som samles inn for den aller første kjernen kan brukes til alle påfølgende uten rekompilering.

Red Hat hevder kABI-kompatibilitet for distribusjonen gjennom hele livssyklusen. Det vil si at den sammensatte modulen for rhel 6.0 (utgivelse november 2010) også skal fungere på versjon 6.10 (utgivelse juni 2018). Og dette er snart 8 år. Naturligvis er denne oppgaven ganske vanskelig.
Vi har registrert flere tilfeller der veeamsnap-modulen sluttet å fungere på grunn av problemer med kABI-kompatibilitet.

Etter at veeamsnap-modulen, kompilert for RHEL 7.0, viste seg å være inkompatibel med kjernen fra RHEL 7.5, men den lastet og var garantert å krasje serveren, forlot vi bruken av kABI-kompatibilitet for RHEL 7 helt.

For øyeblikket inneholder KMOD-pakken for RHEL 7 en sammenstilling for hver utgivelsesversjon og et skript som laster modulen.

SUSE nærmet seg oppgaven med kABI-kompatibilitet mer nøye. De gir kun kABI-kompatibilitet innenfor én oppdateringspakke.

For eksempel fant utgivelsen av SLES 12 sted i september 2014. Og SLES 12 SP1 var allerede i desember 2015, det vil si at det har gått litt mer enn et år. Selv om begge utgivelsene bruker 3.12-kjernen, er de kABI-inkompatible. Å opprettholde kABI-kompatibilitet i bare ett år er åpenbart mye enklere. Den årlige kjernemodulens oppdateringssyklus skal ikke forårsake problemer for modulskapere.

Som et resultat av denne SUSE-policyen har vi ikke registrert et eneste problem med kABI-kompatibilitet i veeamsnap-modulen vår. Riktignok er antallet pakker for SUSE nesten en størrelsesorden større.

Lapper og bakporter

Selv om distributører prøver å sikre kABI-kompatibilitet og kjernestabilitet, prøver de også å forbedre ytelsen og eliminere defekter ved denne stabile kjernen.

Samtidig, i tillegg til sitt eget "arbeid med feil", overvåker utviklerne av Enterprise Linux-kjernen endringer i vaniljekjernen og overfører dem til deres "stabile" en.

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. Det førte til at veeamsnap-modulen garantert krasjet systemet når øyeblikksbildet ble sluppet. Etter å ha sammenlignet kjernekildene før og etter oppdateringen, fant vi ut at bakporten hadde skylden. En lignende løsning ble laget i vaniljekjernen versjon 4.19. Det er bare at denne løsningen fungerte bra i vaniljekjernen, men når den ble overført til "stabil" 2.6.32, oppsto det et problem med spinlocken.

Selvfølgelig har alle alltid feil, men var det verdt å dra koden fra 4.19 til 2.6.32, risikere stabilitet?.. Jeg er ikke sikker...

Det verste er når markedsføring blir involvert i dragkampen mellom «stabilitet» og «modernisering». Markedsavdelingen trenger at kjernen i den oppdaterte distribusjonen skal være stabil på den ene siden og samtidig være bedre i ytelse og ha nye funksjoner. Dette fører til merkelige kompromisser.

Da jeg prøvde å bygge en modul på kjerne 4.4 fra SLES 12 SP3, ble jeg overrasket over å finne funksjonalitet fra vanilla 4.8 i den. Etter min mening er blokk-I/O-implementeringen av 4.4-kjernen fra SLES 12 SP3 mer lik 4.8-kjernen enn den forrige utgivelsen av den stabile 4.4-kjernen fra SLES12 SP2. Jeg kan ikke bedømme hvor stor prosentandel av koden som ble overført fra kjerne 4.8 til SLES 4.4 for SP3, men jeg kan ikke engang kalle kjernen den samme stabile 4.4.

Det mest ubehagelige med dette er at når du skriver en modul som fungerer like godt på forskjellige kjerner, kan du ikke lenger stole på kjerneversjonen. Du må også ta hensyn til fordelingen. Det er bra at du noen ganger kan bli involvert i en definisjon som dukker opp sammen med ny funksjonalitet, men denne muligheten dukker ikke alltid opp.

Som et resultat blir koden overgrodd med rare betingede kompileringsdirektiver.

Det er også patcher som endrer det dokumenterte kjerne-APIet.
Jeg kom over distribusjonen KDE neon 5.16 og ble veldig overrasket over å se at lookup_bdev-kallet i denne kjerneversjonen endret listen over inngangsparametere.

For å få det sammen, måtte jeg legge til et skript til makefilen som sjekker om lookup_bdev-funksjonen har en maskeparameter.

Signering av kjernemoduler

Men la oss gå tilbake til spørsmålet om pakkedistribusjon.

En av fordelene med stabil kABI er at kjernemoduler kan signeres som en binær fil. I dette tilfellet kan utvikleren være sikker på at modulen ikke har blitt skadet ved et uhell eller med vilje modifisert. Du kan sjekke dette med modinfo-kommandoen.

Red Hat- og SUSE-distribusjoner lar deg sjekke modulens signatur og laste den bare hvis det tilsvarende sertifikatet er registrert på systemet. Sertifikatet er den offentlige nøkkelen som modulen er signert med. Vi distribuerer den som en egen pakke.

Problemet her er at sertifikater enten kan bygges inn i kjernen (distributører bruker dem) eller må skrives til EFI ikke-flyktig minne ved hjelp av et verktøy mokutil. Nytte mokutil Når du installerer et sertifikat, krever det at du starter systemet på nytt, og selv før du laster inn operativsystemkjernen, ber administratoren om å tillate lasting av et nytt sertifikat.

Å legge til et sertifikat krever derfor fysisk administratortilgang til systemet. Hvis maskinen er plassert et sted i skyen eller rett og slett i et eksternt serverrom og tilgang kun skjer via nettverket (for eksempel via ssh), vil det være umulig å legge til et sertifikat.

EFI på virtuelle maskiner

Til tross for at EFI lenge har vært støttet av nesten alle hovedkortprodusenter, kan administratoren ikke tenke på behovet for EFI når du installerer et system, og det kan være deaktivert.

Ikke alle hypervisorer støtter EFI. VMWare vSphere støtter EFI fra og med versjon 5.
Microsoft Hyper-V fikk også EFI-støtte fra og med Hyper-V for Windows Server 2012R2.

I standardkonfigurasjonen er imidlertid denne funksjonaliteten deaktivert for Linux-maskiner, noe som betyr at sertifikatet ikke kan installeres.

Angi alternativet i vSphere 6.5 Secure Boot kun mulig i den gamle versjonen av nettgrensesnittet, som kjører via Flash. Web-UI på HTML-5 er fortsatt langt bak.

Eksperimentelle fordelinger

Og til slutt, la oss vurdere spørsmålet om eksperimentelle distribusjoner og distribusjoner uten offisiell støtte. På den ene siden er det usannsynlig at slike distribusjoner finnes på serverne til seriøse organisasjoner. Det er ingen offisiell støtte for slike distribusjoner. Gi dem derfor. Produktet kan ikke støttes på en slik distribusjon.

Imidlertid blir slike distribusjoner en praktisk plattform for å prøve ut nye eksperimentelle løsninger. For eksempel Fedora, OpenSUSE Tumbleweed eller Ustabile versjoner av Debian. De er ganske stabile. De har alltid nye versjoner av programmer og alltid en ny kjerne. Om et år kan denne eksperimentelle funksjonaliteten ende opp i en oppdatert RHEL, SLES eller Ubuntu.

Så hvis noe ikke fungerer på en eksperimentell distribusjon, er dette en grunn til å finne ut av problemet og løse det. Du må være forberedt på at denne funksjonaliteten snart vil vises på brukernes produksjonsservere.

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

Personlig var jeg interessert i eksperimentet med Elbrus OS. Etter å ha fullført veeam-pakken, var produktet vårt installert og fungerte. Jeg skrev om dette eksperimentet på Habré i artikkel.

Vel, støtten for nye distribusjoner fortsetter. Vi venter på at versjon 4.0 skal slippes. Beta er i ferd med å dukke opp, så følg med hva er nytt!

Kilde: www.habr.com

Legg til en kommentar