Linux té moltes cares: com treballar en qualsevol distribució

Linux té moltes cares: com treballar en qualsevol distribució

Crear una aplicació de còpia de seguretat que funcioni en qualsevol distribució no és una tasca fàcil. Per garantir que Veeam Agent per a Linux funcioni en distribucions des de Red Hat 6 i Debian 6, fins a OpenSUSE 15.1 i Ubuntu 19.04, heu de resoldre una sèrie de problemes, sobretot tenint en compte que el producte de programari inclou un mòdul del nucli.

L'article es va crear a partir de materials d'una ponència a la conferència Linux Peter 2019.

Linux no és només un dels sistemes operatius més populars. Essencialment, es tracta d'una plataforma a partir de la qual podeu fer alguna cosa única, alguna cosa pròpia. Gràcies a això, Linux té moltes distribucions que es diferencien pel seu conjunt de components de programari. I aquí sorgeix un problema: perquè un producte de programari funcioni en qualsevol distribució, cal tenir en compte les característiques de cadascun.

Gestors de paquets. .deb vs .rpm

Comencem amb el problema evident de distribuir el producte entre diferents distribucions.
La forma més habitual de distribuir productes de programari és posar el paquet en un dipòsit perquè el gestor de paquets integrat al sistema el pugui instal·lar des d'allà.
Tanmateix, tenim dos formats de paquet populars: rpm и deb. Això vol dir que tothom haurà de donar suport.

Al món dels paquets deb, el nivell de compatibilitat és sorprenent. El mateix paquet s'instal·la i funciona igual de bé tant a Debian 6 com a Ubuntu 19.04. Els estàndards per al procés de creació de paquets i treball amb ells, establerts a les antigues distribucions de Debian, segueixen sent rellevants al nou Linux Mint i al sistema operatiu elemental. Per tant, en el cas de Veeam Agent per a Linux, n'hi ha prou amb un paquet deb per a cada plataforma de maquinari.

Però en el món dels paquets rpm, les diferències són grans. En primer lloc, pel fet que hi ha dos distribuïdors completament independents, Red Hat i SUSE, per als quals la compatibilitat és totalment innecessària. En segon lloc, aquests distribuïdors disposen de kits de distribució. suport i experimental. Tampoc hi ha necessitat de compatibilitat entre ells. Va resultar que el6, el7 i el8 tenen els seus propis paquets. Paquet separat per a Fedora. Paquets per a SLES11 i 12 i un de separat per a openSUSE. El problema principal són les dependències i els noms dels paquets.

Problema de dependència

Malauradament, els mateixos paquets sovint acaben amb diferents noms en diferents distribucions. A continuació es mostra una llista parcial de les dependències del paquet veeam.

Per a EL7:
Per a SLES 12:

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

Com a resultat, la llista de dependències és única per a la distribució.

El que empitjora és quan una versió actualitzada comença a amagar-se sota el nom del paquet antic.

Exemple:

El paquet s'ha actualitzat a Fedora 24 ncurses de la versió 5 a la versió 6. El nostre producte es va crear amb la versió 5 per garantir la compatibilitat amb distribucions anteriors. Per utilitzar la cinquena versió antiga de la biblioteca a Fedora 5, vaig haver d'utilitzar el paquet ncurses-compat-libs.

Com a resultat, hi ha dos paquets per a Fedora, amb dependències diferents.

A més, més interessant. Després de la propera actualització de distribució, el paquet ncurses-compat-libs amb la versió 5 de la biblioteca resulta que no està disponible. És car per a un distribuïdor arrossegar biblioteques antigues a una versió nova de la distribució. Després d'un temps, el problema es va repetir a les distribucions SUSE.

Com a resultat, algunes distribucions van haver d'abandonar la seva dependència explícita ncurses-libs, i arregleu el producte perquè pugui funcionar amb qualsevol versió de la biblioteca.

Per cert, a la versió 8 de Red Hat ja no hi ha un metapaquet pitó, que feia referència al bon vell python 2.7. N’hi ha python2 и pitó3.

Alternativa als gestors de paquets

El problema de les dependències és antic i fa temps que és evident. Només recordeu l'infern de la dependència.
Combinar diverses biblioteques i aplicacions perquè funcionin de manera estable i no entrin en conflicte, de fet, aquesta és la tasca que qualsevol distribuïdor de Linux intenta resoldre.

El gestor de paquets intenta resoldre aquest problema d'una manera completament diferent. Snappy de Canonical. La idea principal: l'aplicació s'executa en un sandbox aïllat i protegit del sistema principal. Si una aplicació requereix biblioteques, aquestes es proporcionen amb l'aplicació mateixa.

Flatpak també us permet executar aplicacions en una caixa de sorra mitjançant contenidors Linux. També s'utilitza la idea de la caixa de sorra AppImage.

Aquestes solucions us permeten crear un paquet per a qualsevol distribució. En cas de Flatpak La instal·lació i el llançament de l'aplicació és possible fins i tot sense el coneixement de l'administrador.

El principal problema és que no totes les aplicacions es poden executar en una caixa de sorra. Algunes persones necessiten accés directe a la plataforma. Ni tan sols estic parlant dels mòduls del nucli, que depenen estrictament del nucli i no encaixen en el concepte sandbox.

El segon problema és que les distribucions populars a l'entorn empresarial de Red Hat i SUSE encara no tenen suport per a Snappy i Flatpak.

En aquest sentit, Veeam Agent per a Linux no està disponible snapcraft.io no del tot flathub.org.

Per concloure la pregunta sobre els gestors de paquets, m'agradaria assenyalar que hi ha una opció per abandonar completament els gestors de paquets combinant fitxers binaris i un script per instal·lar-los en un sol paquet.

Aquest paquet us permet crear un paquet comú per a diferents distribucions i plataformes, dur a terme un procés d'instal·lació interactiu, realitzant la personalització necessària. Només he trobat aquests paquets per a Linux de VMware.

Problema d'actualització

Linux té moltes cares: com treballar en qualsevol distribució
Fins i tot si es resolen tots els problemes de dependència, el programa pot funcionar de manera diferent a la mateixa distribució. És qüestió d'actualitzacions.

Hi ha 3 estratègies d'actualització:

  • El més senzill és no actualitzar mai. Vaig configurar el servidor i me'n vaig oblidar. Per què actualitzar si tot funciona? Els problemes comencen la primera vegada que contacteu amb l'assistència. El creador de la distribució només admet la versió actualitzada.
  • Podeu confiar en el distribuïdor i configurar actualitzacions automàtiques. En aquest cas, és probable que una trucada al suport sigui immediatament després d'una actualització sense èxit.
  • L'opció d'actualització manual només després d'executar-la en una infraestructura de prova és la més fiable, però costosa i requereix molt de temps. No tothom s'ho pot permetre.

Com que diferents usuaris utilitzen estratègies d'actualització diferents, és necessari donar suport tant a la darrera versió com a totes les publicades anteriorment. Això complica tant el procés de desenvolupament com de prova i afegeix maldecaps a l'equip de suport.

Varietat de plataformes de maquinari

Les diferents plataformes de maquinari són un problema que és en gran part específic del codi natiu. Com a mínim, heu de recollir binaris per a cada plataforma compatible.

Al projecte Veeam Agent per a Linux, encara no podem donar suport a res com aquest RISC.

No m'atendré en aquest tema en detall. Només exposaré els principals problemes: tipus que depenen de la plataforma, com ara size_t, l'alineació de l'estructura i l'ordre dels bytes.

Enllaç estàtic i/o dinàmic

Linux té moltes cares: com treballar en qualsevol distribució
Però la pregunta és "Com enllaçar amb biblioteques, de forma dinàmica o estàtica?" val la pena discutir.

Per regla general, les aplicacions C/C++ sota Linux utilitzen enllaços dinàmics. Això funciona molt bé si l'aplicació està creada específicament per a una distribució específica.

Si la tasca és cobrir diverses distribucions amb un fitxer binari, haureu de centrar-vos en la distribució compatible més antiga. Per a nosaltres, això és Red Hat 6. Conté gcc 4.4, que fins i tot l'estàndard C++11 no és compatible. completament.

Construïm el nostre projecte utilitzant gcc 6.3, que és totalment compatible amb C++14. Naturalment, en aquest cas, a Red Hat 6 heu de portar la libstdc++ i augmentar les biblioteques amb vosaltres. La manera més senzilla és enllaçar-los de manera estàtica.

Però, per desgràcia, no totes les biblioteques es poden enllaçar estàticament.

En primer lloc, biblioteques del sistema com ara libfuse, libblkid cal enllaçar dinàmicament per garantir la seva compatibilitat amb el nucli i els seus mòduls.

En segon lloc, hi ha una subtilesa amb les llicències.

La llicència GPL bàsicament us permet enllaçar biblioteques només amb codi de codi obert. MIT i BSD permeten l'enllaç estàtic i permeten incloure biblioteques en un projecte. Però la LGPL no sembla contradir l'enllaç estàtic, sinó que requereix que els fitxers necessaris per a l'enllaç siguin compartits.

En general, utilitzar enllaços dinàmics evitarà que hagis de proporcionar res.

Construcció d'aplicacions C/C++

Per crear aplicacions C/C++ per a diferents plataformes i distribucions, n'hi ha prou amb seleccionar o construir una versió adequada de gcc i utilitzar compiladors creuats per a arquitectures específiques i muntar tot el conjunt de biblioteques. Aquest treball és bastant factible, però força problemàtic. I no hi ha cap garantia que el compilador i les biblioteques seleccionats proporcionin una versió viable.

Un avantatge evident: la infraestructura està molt simplificada, ja que tot el procés de construcció es pot completar en una màquina. A més, n'hi ha prou amb recollir un conjunt de binaris per a una arquitectura i els podeu empaquetar en paquets per a diferents distribucions. Així és com es creen els paquets veeam per a Veeam Agent per a Linux.

A diferència d'aquesta opció, simplement podeu preparar una granja de construcció, és a dir, diverses màquines per al muntatge. Cada màquina d'aquest tipus proporcionarà la compilació d'aplicacions i el muntatge de paquets per a una distribució específica i una arquitectura específica. En aquest cas, la compilació es realitza mitjançant els mitjans elaborats pel distribuïdor. És a dir, s'elimina l'etapa de preparació del compilador i selecció de biblioteques. A més, el procés de creació es pot paral·lelitzar fàcilment.

Tanmateix, aquest enfocament té un inconvenient: per a cada distribució dins de la mateixa arquitectura, haureu de recollir el vostre propi conjunt de fitxers binaris. Un altre desavantatge és que cal mantenir un nombre tan gran de màquines i assignar una gran quantitat d'espai en disc i memòria RAM.

Així és com es compilen els paquets KMOD del mòdul del nucli veeamsnap per a les distribucions de Red Hat.

Servei de construcció oberta

Els companys de SUSE van intentar implementar un terme mitjà en forma d'un servei especial per compilar aplicacions i muntar paquets: servei de construcció oberta.

Essencialment, és un hipervisor que crea una màquina virtual, hi instal·la tots els paquets necessaris, compila l'aplicació i construeix el paquet en aquest entorn aïllat, després del qual s'allibera la màquina virtual.

Linux té moltes cares: com treballar en qualsevol distribució

El planificador implementat a OpenBuildService determinarà quantes màquines virtuals pot llançar per a una velocitat òptima de creació de paquets. El mecanisme de signatura integrat signarà els paquets i els carregarà al repositori integrat. El sistema de control de versions integrat desarà l'historial de canvis i compilacions. Només queda afegir les vostres fonts a aquest sistema. Ni tan sols cal que configureu el servidor vosaltres mateixos; podeu utilitzar-ne un de obert.

Hi ha, però, un problema: una recol·lectora d'aquest tipus és difícil d'encaixar a la infraestructura existent. Per exemple, el control de versions no és necessari; ja tenim el nostre propi per als codis font. El nostre mecanisme de signatura és diferent: fem servir un servidor especial. Tampoc cal un repositori.

A més, el suport per a altres distribucions, per exemple, Red Hat, s'implementa força malament, cosa que és comprensible.

L'avantatge d'aquest servei és el suport ràpid per a la següent versió de la distribució SUSE. Abans de l'anunci oficial del llançament, els paquets necessaris per al muntatge es publiquen en un repositori públic. Apareix un de nou a la llista de distribucions disponibles a OpenBuildService. Marquem la casella i s'afegeix al pla de construcció. Així, afegir una nova versió de la distribució es fa amb gairebé un clic.

A la nostra infraestructura, utilitzant OpenBuildService, s'ajunta tota la varietat de paquets KMP del mòdul del nucli veeamsnap per a distribucions SUSE.

A continuació, m'agradaria detenir-me en els problemes específics dels mòduls del nucli.

nucli ABI

Històricament, els mòduls del nucli de Linux s'han distribuït en forma font. El fet és que els creadors del nucli no es carreguen amb la preocupació de donar suport a una API estable per als mòduls del nucli, i especialment a nivell binari, més conegut com a kABI.

Per crear un mòdul per a un nucli de vainilla, definitivament necessiteu les capçaleres d'aquest nucli en particular, i només funcionarà en aquest nucli.

DKMS us permet automatitzar el procés de creació de mòduls quan actualitzeu el nucli. Com a resultat, els usuaris del dipòsit de Debian (i dels seus nombrosos parents) utilitzen mòduls del nucli ja sigui del dipòsit del distribuïdor o compilats des de la font mitjançant DKMS.

Tanmateix, aquesta situació no s'adapta especialment al segment Enterprise. Els distribuïdors de codi propietari volen distribuir el producte com a binaris compilats.

Els administradors no volen mantenir les eines de desenvolupament als servidors de producció per motius de seguretat. Els distribuïdors de Linux empresarials com Red Hat i SUSE van decidir que podrien donar suport a kABI estable per als seus usuaris. El resultat van ser paquets KMOD per a Red Hat i paquets KMP per a SUSE.

L'essència d'aquesta solució és bastant simple. Per a una versió específica de la distribució, l'API del nucli està congelada. El distribuïdor afirma que utilitza el nucli, per exemple, 3.10, i només fa correccions i millores que no afecten les interfícies del nucli, i els mòduls recollits per al primer nucli es poden utilitzar per a tots els següents sense recompilar.

Red Hat reclama la compatibilitat de kABI per a la distribució durant tot el seu cicle de vida. És a dir, el mòdul muntat per a rhel 6.0 (lançament el novembre de 2010) també hauria de funcionar a la versió 6.10 (lançament el juny de 2018). I això són gairebé 8 anys. Naturalment, aquesta tasca és bastant difícil.
Hem registrat diversos casos en què el mòdul veeamsnap va deixar de funcionar a causa de problemes de compatibilitat amb kABI.

Després que el mòdul veeamsnap, compilat per a RHEL 7.0, resultés incompatible amb el nucli de RHEL 7.5, però es va carregar i es va garantir que bloquejaria el servidor, vam abandonar completament l'ús de la compatibilitat kABI per a RHEL 7.

Actualment, el paquet KMOD per a RHEL 7 conté un conjunt per a cada versió de llançament i un script que carrega el mòdul.

SUSE va abordar la tasca de compatibilitat kABI amb més cura. Proporcionen compatibilitat amb kABI només dins d'un paquet de servei.

Per exemple, el llançament de SLES 12 va tenir lloc el setembre de 2014. I SLES 12 SP1 ja era el desembre de 2015, és a dir, ha passat una mica més d'un any. Tot i que ambdues versions utilitzen el nucli 3.12, són incompatibles amb kABI. Òbviament, mantenir la compatibilitat kABI durant només un any és molt més fàcil. El cicle anual d'actualització del mòdul del nucli no hauria de causar problemes als creadors de mòduls.

Com a resultat d'aquesta política de SUSE, no hem registrat cap problema amb la compatibilitat de kABI al nostre mòdul veeamsnap. És cert que el nombre de paquets per a SUSE és gairebé un ordre de magnitud més gran.

Pedaços i backports

Tot i que els distribuïdors intenten garantir la compatibilitat amb kABI i l'estabilitat del nucli, també intenten millorar el rendiment i eliminar els defectes d'aquest nucli estable.

Al mateix temps, a més del seu propi "treballar amb errors", els desenvolupadors del nucli empresarial de Linux monitoren els canvis al nucli de vainilla i els transfereixen al seu "estable".

De vegades això en porta a de nous errades.

A la darrera versió de Red Hat 6, es va cometre un error en una de les actualitzacions menors. Va conduir al fet que el mòdul veeamsnap estava garantit per bloquejar el sistema quan es va publicar la instantània. Després d'haver comparat les fonts del nucli abans i després de l'actualització, vam descobrir que el backport era el culpable. Es va fer una correcció similar a la versió 4.19 del nucli de vainilla. És només que aquesta correcció va funcionar bé al nucli de vainilla, però en transferir-lo a la 2.6.32 "estable", va sorgir un problema amb el bloqueig de spin.

Per descomptat, tothom sempre té errors, però valia la pena arrossegar el codi de la 4.19 a la 2.6.32, arriscant l'estabilitat?... No n'estic segur...

El pitjor és quan el màrqueting s'implica en l'estira-i-arronsa entre "estabilitat" i "modernització". El departament de màrqueting necessita que el nucli de la distribució actualitzada sigui estable, d'una banda, i alhora millor en rendiment i tenir noves característiques. Això porta a compromisos estranys.

Quan vaig intentar construir un mòdul al nucli 4.4 des de SLES 12 SP3, em va sorprendre trobar-hi funcionalitat de vanilla 4.8. Al meu entendre, la implementació d'E/S de bloc del nucli 4.4 de SLES 12 SP3 és més semblant al nucli 4.8 que la versió anterior del nucli estable 4.4 de SLES12 SP2. No puc jutjar quin percentatge de codi es va transferir del nucli 4.8 a SLES 4.4 per a SP3, però ni tan sols puc trucar al nucli el mateix 4.4 estable.

El més desagradable d'això és que quan escriu un mòdul que funcioni igual de bé en diferents nuclis, ja no pots confiar en la versió del nucli. També cal tenir en compte la distribució. És bo que de vegades et puguis involucrar en una definició que apareix juntament amb una nova funcionalitat, però aquesta oportunitat no sempre apareix.

Com a resultat, el codi s'omple de estranyes directives de compilació condicional.

També hi ha pedaços que canvien l'API del nucli documentada.
Em vaig trobar amb la distribució Neó de KDE 5.16 i em va sorprendre molt veure que la crida lookup_bdev en aquesta versió del nucli canviava la llista de paràmetres d'entrada.

Per ajuntar-ho, vaig haver d'afegir un script al makefile que comprova si la funció lookup_bdev té un paràmetre de màscara.

Signatura de mòduls del nucli

Però tornem al tema de la distribució de paquets.

Un dels avantatges de kABI estable és que els mòduls del nucli es poden signar com a fitxer binari. En aquest cas, el desenvolupador pot estar segur que el mòdul no s'ha fet malbé o modificat intencionadament. Podeu comprovar-ho amb l'ordre modinfo.

Les distribucions Red Hat i SUSE us permeten comprovar la signatura del mòdul i carregar-la només si el certificat corresponent està registrat al sistema. El certificat és la clau pública amb la qual es signa el mòdul. El distribuïm com a paquet a part.

El problema aquí és que els certificats es poden incorporar al nucli (els distribuïdors els utilitzen) o s'han d'escriure a la memòria no volàtil EFI mitjançant una utilitat. mokutil. Utilitat mokutil Quan instal·leu un certificat, cal que reinicieu el sistema i, fins i tot abans de carregar el nucli del sistema operatiu, demana a l'administrador que permeti la càrrega d'un nou certificat.

Per tant, afegir un certificat requereix accés d'administrador físic al sistema. Si la màquina es troba en algun lloc del núvol o simplement en una sala de servidors remota i l'accés només es fa a través de la xarxa (per exemple, mitjançant ssh), serà impossible afegir un certificat.

EFI en màquines virtuals

Malgrat que EFI fa temps que és compatible amb gairebé tots els fabricants de plaques base, en instal·lar un sistema, és possible que l'administrador no pensi en la necessitat d'EFI i es pot desactivar.

No tots els hipervisors admeten EFI. VMWare vSphere admet EFI a partir de la versió 5.
Microsoft Hyper-V també va obtenir suport EFI començant per Hyper-V per a Windows Server 2012R2.

Tanmateix, a la configuració predeterminada, aquesta funcionalitat està desactivada per a les màquines Linux, el que significa que el certificat no es pot instal·lar.

A vSphere 6.5, configureu l'opció Arranjament segur només és possible a la versió antiga de la interfície web, que s'executa mitjançant Flash. La interfície d'usuari web en HTML-5 encara està molt enrere.

Distribucions experimentals

I finalment, considerem el tema de les distribucions experimentals i les distribucions sense suport oficial. D'una banda, és poc probable que aquestes distribucions es trobin als servidors d'organitzacions serioses. No hi ha suport oficial per a aquestes distribucions. Per tant, proporcioneu-los. El producte no pot ser compatible amb aquesta distribució.

Tanmateix, aquestes distribucions es converteixen en una plataforma convenient per provar noves solucions experimentals. Per exemple, les versions Fedora, OpenSUSE Tumbleweed o Unstable de Debian. Són força estables. Sempre tenen noves versions de programes i sempre un nou nucli. En un any, aquesta funcionalitat experimental pot acabar en un RHEL, SLES o Ubuntu actualitzat.

Per tant, si alguna cosa no funciona en una distribució experimental, aquesta és una raó per esbrinar el problema i resoldre'l. Heu d'estar preparat per al fet que aquesta funcionalitat apareixerà aviat als servidors de producció dels usuaris.

Podeu estudiar la llista actual de distribucions oficialment compatibles per a la versió 3.0 aquí. Però la llista real de distribucions sobre les quals pot funcionar el nostre producte és molt més àmplia.

Personalment, m'interessava l'experiment amb el sistema operatiu Elbrus. Després de finalitzar el paquet veeam, el nostre producte es va instal·lar i funcionava. Vaig escriure sobre aquest experiment a Habré a article.

Bé, el suport per a noves distribucions continua. Estem esperant el llançament de la versió 4.0. La beta està a punt d'aparèixer, així que estigueu atents que hi ha de nou!

Font: www.habr.com

Afegeix comentari