Linux har mange ansigter: hvordan man arbejder på enhver distribution

Linux har mange ansigter: hvordan man arbejder på enhver distribution

Det er ingen nem opgave at oprette et backup-program, der fungerer på enhver distribution. For at sikre, at Veeam Agent til Linux fungerer på distributioner fra Red Hat 6 og Debian 6 til OpenSUSE 15.1 og Ubuntu 19.04, skal du løse en række problemer, især i betragtning af, at softwareproduktet indeholder et kernemodul.

Artiklen er lavet på baggrund af materialer fra en tale på konferencen Linux Peter 2019.

Linux er ikke kun et af de mest populære operativsystemer. Grundlæggende er dette en platform, på grundlag af hvilken du kan lave noget unikt, noget helt dit eget. Takket være dette har Linux mange distributioner, der adskiller sig i deres sæt af softwarekomponenter. Og her opstår et problem: For at et softwareprodukt kan fungere på enhver distribution, skal du tage højde for hver enkelts egenskaber.

Pakkeansvarlige. .deb vs. .rpm

Lad os starte med det åbenlyse problem med at distribuere produktet på tværs af forskellige distributioner.
Den mest typiske måde at distribuere softwareprodukter på er at lægge pakken på et lager, så pakkehåndteringen indbygget i systemet kan installere den derfra.
Vi har dog to populære pakkeformater: rpm и deb. Det betyder, at alle skal støtte.

I en verden af ​​deb-pakker er kompatibilitetsniveauet fantastisk. Den samme pakke installerer og fungerer lige godt på både Debian 6 og Ubuntu 19.04. Standarderne for processen med at bygge pakker og arbejde med dem, som er fastlagt i gamle Debian-distributioner, forbliver relevante i det nymodens Linux Mint og det elementære OS. Derfor er en deb-pakke for hver hardwareplatform tilstrækkelig i tilfælde af Veeam Agent til Linux.

Men i rpm-pakkernes verden er forskellene store. For det første på grund af det faktum, at der er to fuldstændig uafhængige distributører, Red Hat og SUSE, for hvilke kompatibilitet er helt unødvendig. For det andet har disse distributører distributionssæt fra disse. støttende og eksperimenterende. Der er heller ikke behov for kompatibilitet mellem dem. Det viste sig, at el6, el7 og el8 har deres egne pakker. Separat pakke til Fedora. Pakker til SLES11 og 12 og en separat til openSUSE. Hovedproblemet er afhængigheder og pakkenavne.

Afhængighedsproblem

Desværre ender de samme pakker ofte under forskellige navne i forskellige distributioner. Nedenfor er en delvis liste over veeam-pakkeafhængigheder.

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 afhængigheder unik for distributionen.

Hvad der bliver værre er, når en opdateret version begynder at gemme sig under det gamle pakkenavn.

Eksempel:

Pakken er blevet opdateret i Fedora 24 forbandelser fra version 5 til version 6. Vores produkt blev bygget med version 5 for at sikre kompatibilitet med ældre distributioner. For at bruge den gamle 5. version af biblioteket på Fedora 24, var jeg nødt til at bruge pakken ncurses-compat-libs.

Som et resultat er der to pakker til Fedora, med forskellige afhængigheder.

Yderligere mere interessant. Efter den næste distributionsopdatering, pakken ncurses-compat-libs med version 5 af biblioteket viser det sig at være utilgængelig. Det er dyrt for en distributør at trække gamle biblioteker ind i en ny version af distributionen. Efter nogen tid gentog problemet sig i SUSE-distributioner.

Som følge heraf måtte nogle distributioner droppe deres eksplicitte afhængighed af ncurses-libs, og reparer produktet, så det kan fungere med enhver version af biblioteket.

Forresten, i version 8 af Red Hat er der ikke længere en metapakke python, som refererede til det gode gamle python 2.7. der er python2 и python3.

Alternativ til pakkeadministratorer

Problemet med afhængigheder er gammelt og har længe været indlysende. Husk bare afhængighedshelvede.
At kombinere forskellige biblioteker og applikationer, så de alle fungerer stabilt og ikke er i konflikt – faktisk er det den opgave, enhver Linux-distributør forsøger at løse.

Pakkemanageren forsøger at løse dette problem på en helt anden måde. Snappy fra Canonical. Hovedideen: applikationen kører i en sandkasse isoleret og beskyttet fra hovedsystemet. Hvis en applikation kræver biblioteker, leveres de med selve applikationen.

Flatpak giver dig også mulighed for at køre applikationer i en sandkasse ved hjælp af Linux Containers. Sandkasseideen bruges også AppImage.

Disse løsninger giver dig mulighed for at oprette én pakke til enhver distribution. I tilfælde af Flatpak installation og lancering af applikationen er mulig selv uden administratorens viden.

Hovedproblemet er, at ikke alle applikationer kan køre i en sandkasse. Nogle mennesker har brug for direkte adgang til platformen. Jeg taler ikke engang om kernemoduler, som er strengt afhængige af kernen og ikke passer ind i sandkassekonceptet.

Det andet problem er, at distributioner, der er populære i virksomhedsmiljøet fra Red Hat og SUSE, endnu ikke indeholder understøttelse af Snappy og Flatpak.

I denne henseende er Veeam Agent til Linux ikke tilgængelig snapcraft.io slet ikke flathub.org.

For at afslutte spørgsmålet om pakkeadministratorer vil jeg gerne bemærke, at der er en mulighed for at opgive pakkeadministratorer helt ved at kombinere binære filer og et script til at installere dem i én pakke.

En sådan pakke giver dig mulighed for at oprette en fælles pakke til forskellige distributioner og platforme, udføre en interaktiv installationsproces og udføre den nødvendige tilpasning. Jeg har kun stødt på sådanne pakker til Linux fra VMware.

Opdateringsproblem

Linux har mange ansigter: hvordan man arbejder på enhver distribution
Selvom alle afhængighedsproblemer er løst, kan programmet køre anderledes på den samme distribution. Det er et spørgsmål om opdateringer.

Der er 3 opdateringsstrategier:

  • Den enkleste er aldrig at opdatere. Jeg satte serveren op og glemte det. Hvorfor opdatere, hvis alt virker? Problemer begynder første gang, du kontakter support. Skaberen af ​​distributionen understøtter kun den opdaterede udgivelse.
  • Du kan stole på distributøren og konfigurere automatiske opdateringer. I dette tilfælde er et opkald til support sandsynligvis umiddelbart efter en mislykket opdatering.
  • Muligheden for manuel opdatering kun efter at have kørt den på en testinfrastruktur er den mest pålidelige, men dyr og tidskrævende. Ikke alle har råd til det.

Da forskellige brugere bruger forskellige opdateringsstrategier, er det nødvendigt at understøtte både den seneste udgivelse og alle tidligere udgivne. Dette komplicerer både udviklings- og testprocessen og tilføjer hovedpine til supportteamet.

Forskellige hardwareplatforme

Forskellige hardwareplatforme er et problem, der stort set er specifikt for indbygget kode. Som minimum skal du indsamle binære filer for hver understøttet platform.

I Veeam Agent for Linux-projektet kan vi stadig ikke understøtte noget som denne RISC.

Jeg vil ikke dvæle nærmere ved dette spørgsmål. Jeg vil kun skitsere hovedproblemerne: platformafhængige typer, som f.eks size_t, strukturjustering og byterækkefølge.

Statisk og/eller dynamisk linking

Linux har mange ansigter: hvordan man arbejder på enhver distribution
Men spørgsmålet er "Hvordan forbinder man med biblioteker - dynamisk eller statisk?" værd at diskutere.

Som regel bruger C/C++ applikationer under Linux dynamiske links. Dette fungerer godt, hvis applikationen er bygget specifikt til en specifik distribution.

Hvis opgaven er at dække forskellige distributioner med én binær fil, så skal du fokusere på den ældste understøttede distribution. For os er dette Red Hat 6. Den indeholder gcc 4.4, som selv C++11-standarden ikke understøtter fuldt.

Vi bygger vores projekt ved hjælp af gcc 6.3, som fuldt ud understøtter C++14. Naturligvis skal du i dette tilfælde på Red Hat 6 bære libstdc++ og booste biblioteker med dig. Den nemmeste måde er at linke til dem statisk.

Men ak, ikke alle biblioteker kan linkes statisk.

For det første systembiblioteker som f.eks libfuse, libblkid det er nødvendigt at linke dynamisk for at sikre deres kompatibilitet med kernen og dens moduler.

For det andet er der en finesse med licenser.

GPL-licensen giver dig grundlæggende kun mulighed for at linke biblioteker med opensource-kode. MIT og BSD tillader statisk linkning og tillader, at biblioteker inkluderes i et projekt. Men LGPL ser ikke ud til at modsige statisk linkning, men kræver, at de filer, der er nødvendige for at linke, deles.

Generelt vil brug af dynamiske links forhindre dig i at skulle levere noget.

Opbygning af C/C++ applikationer

For at bygge C/C++-applikationer til forskellige platforme og distributioner er det nok at vælge eller bygge en passende version af gcc og bruge krydskompilatorer til specifikke arkitekturer og samle hele sættet af biblioteker. Dette arbejde er ganske muligt, men ret besværligt. Og der er ingen garanti for, at den valgte compiler og biblioteker vil levere en brugbar version.

En åbenlys fordel: Infrastrukturen er meget forenklet, da hele byggeprocessen kan gennemføres på én maskine. Derudover er det nok at samle ét sæt binære filer til én arkitektur, og du kan pakke dem ind i pakker til forskellige distributioner. Sådan er veeam-pakker bygget til Veeam Agent til Linux.

I modsætning til denne mulighed kan du blot forberede en byggegård, det vil sige flere maskiner til montering. Hver sådan maskine vil levere applikationskompilering og pakkesamling til en specifik distribution og en specifik arkitektur. I dette tilfælde udføres kompilering ved hjælp af de midler, der er udarbejdet af distributøren. Det vil sige, at stadiet med at forberede compileren og vælge biblioteker er elimineret. Derudover kan byggeprocessen let paralleliseres.

Der er dog en ulempe ved denne tilgang: for hver distribution inden for den samme arkitektur skal du samle dit eget sæt af binære filer. En anden ulempe er, at et så stort antal maskiner skal vedligeholdes, og en stor mængde diskplads og RAM skal allokeres.

Sådan kompileres KMOD-pakker af veeamsnap-kernemodulet til Red Hat-distributioner.

Åbn Build Service

Kolleger fra SUSE forsøgte at implementere en mellemvej i form af en speciel service til kompilering af applikationer og samling af pakker - openbuildservice.

Grundlæggende er det en hypervisor, der opretter en virtuel maskine, installerer alle de nødvendige pakker i den, kompilerer applikationen og bygger pakken i dette isolerede miljø, hvorefter den virtuelle maskine frigives.

Linux har mange ansigter: hvordan man arbejder på enhver distribution

Scheduleren implementeret i OpenBuildService vil bestemme, hvor mange virtuelle maskiner den kan starte for optimal pakkeopbygningshastighed. Den indbyggede signeringsmekanisme vil signere pakkerne og uploade dem til det indbyggede lager. Det indbyggede versionskontrolsystem gemmer historikken for ændringer og builds. Tilbage er blot at tilføje dine kilder til dette system. Du behøver ikke engang selv at konfigurere serveren; du kan bruge en åben.

Der er dog et problem: sådan en høstmaskine er svær at passe ind i den eksisterende infrastruktur. For eksempel er versionskontrol ikke nødvendig; vi har allerede vores egen til kildekoder. Vores signaturmekanisme er anderledes: vi bruger en speciel server. Et depot er heller ikke nødvendigt.

Derudover er understøttelse af andre distributioner - for eksempel Red Hat - implementeret ret dårligt, hvilket er forståeligt.

Fordelen ved en sådan service er hurtig support til den næste version af SUSE-distributionen. Inden den officielle meddelelse om udgivelsen bliver de pakker, der er nødvendige for samling, lagt ud på et offentligt lager. En ny vises på listen over tilgængelige distributioner på OpenBuildService. Vi markerer boksen, og den tilføjes til byggeplanen. Tilføjelse af en ny version af distributionen sker således med næsten et klik.

I vores infrastruktur, ved hjælp af OpenBuildService, samles hele rækken af ​​KMP-pakker af veeamsnap-kernemodulet til SUSE-distributioner.

Dernæst vil jeg gerne dvæle ved problemer, der er specifikke for kernemoduler.

kerne ABI

Linux-kernemoduler er historisk blevet distribueret i kildeform. Faktum er, at skaberne af kernen ikke belaster sig selv med bekymringen om at understøtte en stabil API til kernemoduler, og især på det binære niveau, videre omtalt som kABI.

For at bygge et modul til en vaniljekerne har du helt sikkert brug for overskrifterne på denne særlige kerne, og det vil kun fungere på denne kerne.

DKMS giver dig mulighed for at automatisere processen med at bygge moduler, når du opdaterer kernen. Som et resultat heraf bruger brugere af Debian-depotet (og dets mange slægtninge) kernemoduler enten fra distributørens lager eller kompileret fra kilde ved hjælp af DKMS.

Denne situation passer dog ikke særligt godt til Enterprise-segmentet. Proprietære kodedistributører ønsker at distribuere produktet som kompilerede binære filer.

Administratorer ønsker ikke at beholde udviklingsværktøjer på produktionsservere af sikkerhedsmæssige årsager. Enterprise Linux-distributører som Red Hat og SUSE besluttede, at de kunne understøtte stabil kABI for deres brugere. Resultatet var KMOD-pakker til Red Hat og KMP-pakker til SUSE.

Essensen af ​​denne løsning er ret enkel. For en specifik version af distributionen er kerne-API'en frosset. Distributøren oplyser, at han bruger kernen, f.eks. 3.10, og laver kun rettelser og forbedringer, der ikke påvirker kernegrænsefladerne, og de moduler, der indsamles til den allerførste kerne, kan bruges til alle efterfølgende uden genkompilering.

Red Hat hævder kABI-kompatibilitet for distributionen gennem hele dens livscyklus. Det vil sige, at det samlede modul til rhel 6.0 (udgivelse november 2010) også skulle fungere på version 6.10 (udgivelse juni 2018). Og det er næsten 8 år. Naturligvis er denne opgave ret vanskelig.
Vi har registreret flere tilfælde, hvor veeamsnap-modulet holdt op med at fungere på grund af problemer med kABI-kompatibilitet.

Efter at veeamsnap-modulet, kompileret til RHEL 7.0, viste sig at være inkompatibelt med kernen fra RHEL 7.5, men det blev indlæst og var garanteret at crashe serveren, opgav vi fuldstændig brugen af ​​kABI-kompatibilitet til RHEL 7.

I øjeblikket indeholder KMOD-pakken til RHEL 7 en samling for hver udgivelsesversion og et script, der indlæser modulet.

SUSE greb opgaven med kABI-kompatibilitet mere omhyggeligt an. De giver kun kABI-kompatibilitet inden for én servicepakke.

For eksempel fandt udgivelsen af ​​SLES 12 sted i september 2014. Og SLES 12 SP1 var allerede i december 2015, det vil sige, at der er gået lidt mere end et år. Selvom begge udgivelser bruger 3.12-kernen, er de kABI-inkompatible. Det er klart, at det er meget nemmere at opretholde kABI-kompatibilitet i blot et år. Den årlige kernemodulopdateringscyklus burde ikke forårsage problemer for modulskabere.

Som et resultat af denne SUSE-politik har vi ikke registreret et eneste problem med kABI-kompatibilitet i vores veeamsnap-modul. Sandt nok er antallet af pakker til SUSE næsten en størrelsesorden større.

Patches og backports

Selvom distributører forsøger at sikre kABI-kompatibilitet og kernestabilitet, forsøger de også at forbedre ydeevnen og eliminere defekter i denne stabile kerne.

Ud over deres eget "arbejde med fejl" overvåger udviklerne af virksomhedens Linux-kernen samtidig ændringer i vaniljekernen og overfører dem til deres "stabile".

Nogle gange fører dette til nye fejl.

I den seneste udgivelse af Red Hat 6 blev der lavet en fejl i en af ​​de mindre opdateringer. Det førte til, at veeamsnap-modulet med garanti ville crashe systemet, når snapshotet blev frigivet. Efter at have sammenlignet kernekilderne før og efter opdateringen, fandt vi ud af, at bagporten var skylden. En lignende rettelse blev lavet i vaniljekerneversion 4.19. Det er bare det, at denne rettelse fungerede fint i vaniljekernen, men da den blev overført til den "stabile" 2.6.32, opstod der et problem med spinlocken.

Selvfølgelig har alle altid fejl, men var det værd at trække koden fra 4.19 til 2.6.32, risikerer stabilitet?.. Jeg er ikke sikker...

Det værste er, når marketing bliver involveret i tovtrækkeriet mellem "stabilitet" og "modernisering". Marketingafdelingen har brug for, at kernen i den opdaterede distribution er stabil på den ene side og samtidig være bedre i ydeevne og have nye funktioner. Dette fører til mærkelige kompromiser.

Da jeg forsøgte at bygge et modul på kerne 4.4 fra SLES 12 SP3, blev jeg overrasket over at finde funktionalitet fra vanilla 4.8 i det. Efter min mening er blok I/O-implementeringen af ​​4.4-kernen fra SLES 12 SP3 mere lig 4.8-kernen end den tidligere udgivelse af den stabile 4.4-kerne fra SLES12 SP2. Jeg kan ikke bedømme, hvor stor en procentdel af koden der blev overført fra kerne 4.8 til SLES 4.4 til SP3, men jeg kan ikke engang kalde kernen den samme stabile 4.4.

Det mest ubehagelige ved dette er, at når du skriver et modul, der ville fungere lige godt på forskellige kerner, kan du ikke længere stole på kerneversionen. Du skal også tage højde for fordelingen. Det er godt, at du nogle gange kan blive involveret i en definition, der dukker op sammen med ny funktionalitet, men denne mulighed dukker ikke altid op.

Som et resultat bliver koden overgroet med mærkelige betingede kompileringsdirektiver.

Der er også patches, der ændrer det dokumenterede kerne-API.
Jeg stødte på distributionen KDE neon 5.16 og var meget overrasket over at se, at lookup_bdev-kaldet i denne kerneversion ændrede listen over inputparametre.

For at få det sammen, var jeg nødt til at tilføje et script til makefilen, der kontrollerer om lookup_bdev-funktionen har en maskeparameter.

Signering af kernemoduler

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

En af fordelene ved stabil kABI er, at kernemoduler kan signeres som en binær fil. I dette tilfælde kan udvikleren være sikker på, at modulet ikke er blevet beskadiget ved et uheld eller bevidst ændret. Du kan kontrollere dette med modinfo-kommandoen.

Red Hat og SUSE distributioner giver dig mulighed for at kontrollere modulets signatur og kun indlæse det, hvis det tilsvarende certifikat er registreret på systemet. Certifikatet er den offentlige nøgle, som modulet er signeret med. Vi distribuerer det som en separat pakke.

Problemet her er, at certifikater enten kan indbygges i kernen (distributører bruger dem) eller skal skrives til EFI ikke-flygtig hukommelse ved hjælp af et hjælpeprogram mokutil. Nytte mokutil Når du installerer et certifikat, kræver det, at du genstarter systemet, og selv før indlæsning af operativsystemkernen, beder administratoren om at tillade indlæsning af et nyt certifikat.

Tilføjelse af et certifikat kræver således fysisk administratoradgang til systemet. Hvis maskinen er placeret et sted i skyen eller blot i et eksternt serverrum, og adgangen kun sker via netværket (for eksempel via ssh), så vil det være umuligt at tilføje et certifikat.

EFI på virtuelle maskiner

På trods af at EFI længe har været understøttet af næsten alle bundkortproducenter, tænker administratoren muligvis ikke på behovet for EFI, når du installerer et system, og det kan blive deaktiveret.

Ikke alle hypervisorer understøtter EFI. VMWare vSphere understøtter EFI fra version 5.
Microsoft Hyper-V fik også EFI-understøttelse startende med Hyper-V til Windows Server 2012R2.

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

Indstil indstillingen i vSphere 6.5 Sikker Boot kun muligt i den gamle version af webgrænsefladen, som kører via Flash. Web UI på HTML-5 er stadig langt bagud.

Eksperimentelle fordelinger

Og endelig, lad os overveje spørgsmålet om eksperimentelle distributioner og distributioner uden officiel støtte. På den ene side er det usandsynligt, at sådanne distributioner findes på seriøse organisationers servere. Der er ingen officiel støtte til sådanne distributioner. Giv dem derfor. Produktet kan ikke understøttes på en sådan distribution.

Sådanne distributioner bliver dog en bekvem platform 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 programmer og altid en ny kerne. Om et år kan denne eksperimentelle funktionalitet ende i en opdateret RHEL, SLES eller Ubuntu.

Så hvis noget ikke virker på en eksperimentel fordeling, er dette en grund til at finde ud af problemet og løse det. Du skal være forberedt på, at denne funktionalitet snart vil dukke op på brugernes produktionsservere.

Du kan studere den aktuelle liste over officielt understøttede distributioner til version 3.0 her. Men den reelle liste over distributioner, som vores produkt kan fungere på, er meget bredere.

Personligt var jeg interesseret i eksperimentet med Elbrus OS. Efter at have afsluttet veeam-pakken, var vores produkt installeret og virkede. Jeg skrev om dette eksperiment på Habré i artiklen.

Nå, støtten til nye distributioner fortsætter. Vi venter på, at version 4.0 bliver frigivet. Beta er ved at dukke op, så hold øje hvad er nyt!

Kilde: www.habr.com

Tilføj en kommentar