Linux a plusieurs visages : comment travailler sur n'importe quelle distribution

Linux a plusieurs visages : comment travailler sur n'importe quelle distribution

Créer une application de sauvegarde qui fonctionne sur n'importe quelle distribution n'est pas une tâche facile. Pour garantir que Veeam Agent pour Linux fonctionne sur les distributions de Red Hat 6 et Debian 6 à OpenSUSE 15.1 et Ubuntu 19.04, vous devez résoudre une série de problèmes, d'autant plus que le produit logiciel inclut un module de noyau.

L'article a été créé sur la base des éléments d'un discours prononcé à la conférence Linux Pierre 2019.

Linux n'est pas seulement l'un des systèmes d'exploitation les plus populaires. Il s’agit essentiellement d’une plateforme sur la base de laquelle vous pouvez créer quelque chose d’unique, quelque chose qui vous est propre. Grâce à cela, Linux dispose de nombreuses distributions qui diffèrent par leur ensemble de composants logiciels. Et là se pose un problème : pour qu'un produit logiciel fonctionne sur n'importe quelle distribution, il faut prendre en compte les caractéristiques de chacune.

Gestionnaires de paquets. .deb contre .rpm

Commençons par le problème évident de la distribution du produit entre différentes distributions.
La manière la plus courante de distribuer des produits logiciels consiste à placer le package dans un référentiel afin que le gestionnaire de packages intégré au système puisse l'installer à partir de là.
Cependant, nous avons deux formats de packages populaires : rpm и deb. Cela signifie que tout le monde devra soutenir.

Dans le monde des packages Deb, le niveau de compatibilité est incroyable. Le même package s'installe et fonctionne aussi bien sur Debian 6 que sur Ubuntu 19.04. Les normes pour le processus de création de paquets et leur utilisation, établies dans les anciennes distributions Debian, restent pertinentes dans le nouveau Linux Mint et le système d'exploitation élémentaire. Par conséquent, dans le cas de Veeam Agent pour Linux, un package deb pour chaque plate-forme matérielle est suffisant.

Mais dans le monde des packages RPM, les différences sont grandes. Premièrement, du fait qu'il existe deux distributeurs totalement indépendants, Red Hat et SUSE, pour lesquels la compatibilité est totalement inutile. Deuxièmement, ces distributeurs disposent de kits de distribution. support et expérimental. Il n’y a pas non plus besoin de compatibilité entre eux. Il s'est avéré que el6, el7 et el8 ont leurs propres packages. Package séparé pour Fedora. Packages pour SLES11 et 12 et un package séparé pour openSUSE. Le principal problème concerne les dépendances et les noms de packages.

Problème de dépendance

Malheureusement, les mêmes packages finissent souvent sous des noms différents dans différentes distributions. Vous trouverez ci-dessous une liste partielle des dépendances des packages Veeam.

Pour EL7 :
Pour SLES12 :

  • libblkid
  • libgcc
  • libstdc++
  • ncurses-libs
  • fusible-libs
  • fichier-libs
  • veeamsnap=3.0.2.1185
  • libblkid1
  • libgcc_s1
  • libstdc + + 6
  • libmagique1
  • libfuse2
  • veeamsnap-kmp=3.0.2.1185

Par conséquent, la liste des dépendances est unique pour la distribution.

Ce qui empire, c'est lorsqu'une version mise à jour commence à se cacher sous l'ancien nom du package.

Exemple:

Le package a été mis à jour dans Fedora 24 ncurses de la version 5 à la version 6. Notre produit a été construit avec la version 5 pour assurer la compatibilité avec les anciennes distributions. Pour utiliser l'ancienne 5ème version de la bibliothèque sur Fedora 24, j'ai dû utiliser le package ncurses-compat-libs.

En conséquence, il existe deux packages pour Fedora, avec des dépendances différentes.

Encore plus intéressant. Après la prochaine mise à jour de la distribution, le package ncurses-compat-libs avec la version 5 de la bibliothèque, elle s'avère indisponible. Il est coûteux pour un distributeur de glisser d'anciennes bibliothèques dans une nouvelle version de la distribution. Après un certain temps, le problème s'est répété dans les distributions SUSE.

En conséquence, certaines distributions ont dû abandonner leur dépendance explicite à l'égard de ncurses-libs, et corrigez le produit afin qu'il puisse fonctionner avec n'importe quelle version de la bibliothèque.

D'ailleurs, dans la version 8 de Red Hat, il n'y a plus de méta-paquet python, qui faisait référence au bon vieux python 2.7. Il y a python2 и python3.

Alternative aux gestionnaires de packages

Le problème des dépendances est ancien et évident depuis longtemps. N'oubliez pas l'enfer de la dépendance.
Combiner diverses bibliothèques et applications afin qu'elles fonctionnent toutes de manière stable et sans conflit - en fait, c'est la tâche que tout distributeur Linux essaie de résoudre.

Le gestionnaire de paquets essaie de résoudre ce problème d'une manière complètement différente. brusque de Canonique. L'idée principale : l'application s'exécute dans un sandbox isolé et protégé du système principal. Si une application nécessite des bibliothèques, celles-ci sont fournies avec l'application elle-même.

Flatpak vous permet également d'exécuter des applications dans un bac à sable à l'aide de conteneurs Linux. L'idée du bac à sable est également utilisée AppImage.

Ces solutions vous permettent de créer un package pour n'importe quelle distribution. En cas de Flatpak l’installation et le lancement de l’application sont possibles même à l’insu de l’administrateur.

Le principal problème est que toutes les applications ne peuvent pas s’exécuter dans un bac à sable. Certaines personnes ont besoin d’un accès direct à la plateforme. Je ne parle même pas des modules du noyau, qui dépendent strictement du noyau et ne rentrent pas dans le concept sandbox.

Le deuxième problème est que les distributions populaires dans l'environnement d'entreprise de Red Hat et SUSE ne prennent pas encore en charge Snappy et Flatpak.

À cet égard, Veeam Agent pour Linux n'est pas disponible snapcraft.io pas sur flathub.org.

Pour conclure la question sur les gestionnaires de packages, je voudrais noter qu'il existe une option permettant d'abandonner complètement les gestionnaires de packages en combinant des fichiers binaires et un script pour les installer dans un seul package.

Un tel bundle vous permet de créer un package commun pour différentes distributions et plates-formes, d'effectuer un processus d'installation interactif et d'effectuer la personnalisation nécessaire. Je n'ai rencontré que de tels packages pour Linux de VMware.

Problème de mise à jour

Linux a plusieurs visages : comment travailler sur n'importe quelle distribution
Même si tous les problèmes de dépendance sont résolus, le programme peut s'exécuter différemment sur la même distribution. Il s'agit de mises à jour.

Il existe 3 stratégies de mise à jour :

  • Le plus simple est de ne jamais mettre à jour. J'ai configuré le serveur et je l'ai oublié. Pourquoi mettre à jour si tout fonctionne ? Les problèmes commencent dès la première fois que vous contactez l’assistance. Le créateur de la distribution ne prend en charge que la version mise à jour.
  • Vous pouvez faire confiance au distributeur et mettre en place des mises à jour automatiques. Dans ce cas, un appel au support est probable immédiatement après une mise à jour infructueuse.
  • L’option de mise à jour manuelle uniquement après l’avoir exécutée sur une infrastructure de test est la plus fiable, mais elle est coûteuse et prend du temps. Tout le monde ne peut pas se le permettre.

Étant donné que différents utilisateurs utilisent des stratégies de mise à jour différentes, il est nécessaire de prendre en charge à la fois la dernière version et toutes les versions antérieures. Cela complique à la fois le processus de développement et de test et ajoute des maux de tête à l'équipe d'assistance.

Variété de plates-formes matérielles

Les différentes plates-formes matérielles constituent un problème largement spécifique au code natif. Au minimum, vous devez collecter les binaires pour chaque plateforme prise en charge.

Dans le projet Veeam Agent pour Linux, nous ne pouvons toujours pas prendre en charge ce RISC.

Je ne m'étendrai pas sur cette question en détail. Je me contenterai d'exposer les principaux problèmes : les types dépendants de la plate-forme, tels que size_t, l'alignement de la structure et l'ordre des octets.

Liaison statique et/ou dynamique

Linux a plusieurs visages : comment travailler sur n'importe quelle distribution
Mais la question est « Comment établir des liens avec des bibliothèques – dynamiquement ou statiquement ? » mérite d'être discuté.

En règle générale, les applications C/C++ sous Linux utilisent des liens dynamiques. Cela fonctionne très bien si l'application est conçue spécifiquement pour une distribution spécifique.

Si la tâche consiste à couvrir plusieurs distributions avec un seul fichier binaire, vous devez alors vous concentrer sur la distribution prise en charge la plus ancienne. Pour nous, il s'agit de Red Hat 6. Il contient gcc 4.4, que même le standard C++11 ne prend pas en charge. pleinement.

Nous construisons notre projet en utilisant gcc 6.3, qui prend entièrement en charge C++14. Naturellement, dans ce cas, sur Red Hat 6, vous devez emporter avec vous les bibliothèques libstdc++ et booster. Le moyen le plus simple est de créer un lien vers eux de manière statique.

Mais hélas, toutes les bibliothèques ne peuvent pas être liées de manière statique.

Premièrement, les bibliothèques système telles que libfuse, libblkid il est nécessaire d'effectuer des liaisons dynamiques pour assurer leur compatibilité avec le noyau et ses modules.

Deuxièmement, il y a une subtilité avec les licences.

La licence GPL vous permet essentiellement de lier des bibliothèques uniquement avec du code open source. MIT et BSD autorisent les liaisons statiques et permettent d'inclure des bibliothèques dans un projet. Mais la LGPL ne semble pas contredire le lien statique, mais impose que les fichiers nécessaires au lien soient partagés.

En général, l’utilisation de liens dynamiques vous évitera de devoir fournir quoi que ce soit.

Création d'applications C/C++

Pour créer des applications C/C++ pour différentes plates-formes et distributions, il suffit de sélectionner ou de créer une version appropriée de gcc, d'utiliser des compilateurs croisés pour des architectures spécifiques et d'assembler l'ensemble des bibliothèques. Ce travail est tout à fait réalisable, mais assez gênant. Et rien ne garantit que le compilateur et les bibliothèques sélectionnés fourniront une version exploitable.

Un avantage évident : l'infrastructure est grandement simplifiée, puisque l'ensemble du processus de construction peut être réalisé sur une seule machine. De plus, il suffit de collecter un ensemble de binaires pour une architecture et vous pouvez les regrouper dans des packages pour différentes distributions. C’est ainsi que les packages Veeam sont créés pour Veeam Agent pour Linux.

Contrairement à cette option, vous pouvez simplement préparer une ferme de construction, c'est-à-dire plusieurs machines à assembler. Chacune de ces machines fournira la compilation d'applications et l'assemblage de packages pour une distribution spécifique et une architecture spécifique. Dans ce cas, la compilation est réalisée à l'aide des moyens préparés par le distributeur. Autrement dit, l'étape de préparation du compilateur et de sélection des bibliothèques est éliminée. De plus, le processus de construction peut être facilement parallélisé.

Il y a cependant un inconvénient à cette approche : pour chaque distribution au sein d'une même architecture, vous devrez collecter votre propre ensemble de fichiers binaires. Un autre inconvénient est qu’un grand nombre de machines doivent être entretenues et qu’une grande quantité d’espace disque et de RAM doit être allouée.

C'est ainsi que les packages KMOD du module noyau veeamsnap sont compilés pour les distributions Red Hat.

Ouvrir le service de construction

Des collègues de SUSE ont essayé de mettre en œuvre un terrain d'entente sous la forme d'un service spécial pour compiler des applications et assembler des packages - service de construction ouvert.

Il s'agit essentiellement d'un hyperviseur qui crée une machine virtuelle, y installe tous les packages nécessaires, compile l'application et construit le package dans cet environnement isolé, après quoi la machine virtuelle est libérée.

Linux a plusieurs visages : comment travailler sur n'importe quelle distribution

Le planificateur implémenté dans OpenBuildService déterminera le nombre de machines virtuelles qu'il peut lancer pour une vitesse de création de packages optimale. Le mécanisme de signature intégré signera les packages et les téléchargera dans le référentiel intégré. Le système de contrôle de version intégré enregistrera l'historique des modifications et des builds. Il ne reste plus qu'à simplement ajouter vos sources à ce système. Vous n’avez même pas besoin de configurer le serveur vous-même : vous pouvez en utiliser un ouvert.

Il y a cependant un problème : une telle abatteuse est difficile à intégrer dans l’infrastructure existante. Par exemple, le contrôle de version n'est pas nécessaire, nous avons déjà le nôtre pour les codes sources. Notre mécanisme de signature est différent : nous utilisons un serveur spécial. Un référentiel n'est pas non plus nécessaire.

De plus, la prise en charge d'autres distributions - par exemple Red Hat - est plutôt mal implémentée, ce qui est compréhensible.

L'avantage d'un tel service est une prise en charge rapide de la prochaine version de la distribution SUSE. Avant l'annonce officielle de la sortie, les packages nécessaires à l'assemblage sont publiés sur un référentiel public. Une nouvelle apparaît dans la liste des distributions disponibles sur OpenBuildService. Nous cochons la case et elle est ajoutée au plan de build. Ainsi, l’ajout d’une nouvelle version de la distribution se fait en quasiment un clic.

Dans notre infrastructure, utilisant OpenBuildService, toute la variété des packages KMP du module noyau veeamsnap pour les distributions SUSE est assemblée.

Ensuite, je voudrais m'attarder sur les problèmes spécifiques aux modules du noyau.

ABI du noyau

Les modules du noyau Linux ont toujours été distribués sous forme source. Le fait est que les créateurs du noyau ne se soucient pas de prendre en charge une API stable pour les modules du noyau, et notamment au niveau binaire, encore appelé kABI.

Pour construire un module pour un noyau Vanilla, vous avez absolument besoin des en-têtes de ce noyau particulier, et cela ne fonctionnera que sur ce noyau.

DKMS vous permet d'automatiser le processus de création de modules lors de la mise à jour du noyau. En conséquence, les utilisateurs du référentiel Debian (et de ses nombreux apparentés) utilisent les modules du noyau soit à partir du référentiel du distributeur, soit compilés à partir des sources à l'aide de DKMS.

Cependant, cette situation ne convient pas particulièrement au segment Entreprises. Les distributeurs de code propriétaire souhaitent distribuer le produit sous forme de binaires compilés.

Les administrateurs ne souhaitent pas conserver les outils de développement sur les serveurs de production pour des raisons de sécurité. Les distributeurs Enterprise Linux tels que Red Hat et SUSE ont décidé qu'ils pouvaient prendre en charge kABI stable pour leurs utilisateurs. Le résultat a été des packages KMOD pour Red Hat et des packages KMP pour SUSE.

L'essence de cette solution est assez simple. Pour une version spécifique de la distribution, l'API du noyau est gelée. Le distributeur déclare qu'il utilise le noyau, par exemple 3.10, et n'apporte que des corrections et des améliorations qui n'affectent pas les interfaces du noyau, et que les modules collectés pour le tout premier noyau peuvent être utilisés pour tous les suivants sans recompilation.

Red Hat revendique la compatibilité kABI pour la distribution tout au long de son cycle de vie. Autrement dit, le module assemblé pour rhel 6.0 (sortie novembre 2010) devrait également fonctionner sur la version 6.10 (sortie juin 2018). Et cela fait presque 8 ans. Naturellement, cette tâche est assez difficile.
Nous avons enregistré plusieurs cas où le module veeamsnap a cessé de fonctionner en raison de problèmes de compatibilité kABI.

Après que le module veeamsnap, compilé pour RHEL 7.0, s'est avéré incompatible avec le noyau de RHEL 7.5, mais qu'il s'est chargé et était garanti de planter le serveur, nous avons complètement abandonné l'utilisation de la compatibilité kABI pour RHEL 7.

Actuellement, le package KMOD pour RHEL 7 contient un assembly pour chaque version et un script qui charge le module.

SUSE a abordé la tâche de compatibilité kABI avec plus de soin. Ils fournissent la compatibilité kABI uniquement au sein d’un seul service pack.

Par exemple, la sortie de SLES 12 a eu lieu en septembre 2014. Et SLES 12 SP1 était déjà en décembre 2015, c'est-à-dire qu'un peu plus d'un an s'est écoulé. Même si les deux versions utilisent le noyau 3.12, elles sont incompatibles avec kABI. Évidemment, maintenir la compatibilité kABI pendant seulement un an est beaucoup plus facile. Le cycle annuel de mise à jour des modules du noyau ne devrait pas poser de problèmes aux créateurs de modules.

Grâce à cette politique SUSE, nous n'avons enregistré aucun problème de compatibilité kABI dans notre module veeamsnap. Certes, le nombre de packages pour SUSE est presque d'un ordre de grandeur supérieur.

Correctifs et rétroportages

Bien que les distributeurs tentent d'assurer la compatibilité de kABI et la stabilité du noyau, ils tentent également d'améliorer les performances et d'éliminer les défauts de ce noyau stable.

Dans le même temps, en plus de leur propre « travail sur les erreurs », les développeurs du noyau Linux d'entreprise surveillent les modifications apportées au noyau Vanilla et les transfèrent vers leur noyau « stable ».

Parfois, cela en amène de nouveaux erreurs.

Dans la dernière version de Red Hat 6, une erreur a été commise dans l'une des mises à jour mineures. Cela a conduit au fait que le module veeamsnap était assuré de faire planter le système lorsque l'instantané était publié. Après avoir comparé les sources du noyau avant et après la mise à jour, nous avons découvert que le rétroportage était en cause. Un correctif similaire a été apporté à la version 4.19 du noyau Vanilla. C'est juste que ce correctif a bien fonctionné dans le noyau Vanilla, mais lors de son transfert vers la version "stable" 2.6.32, un problème est survenu avec le spinlock.

Bien sûr, tout le monde a toujours des erreurs, mais cela valait-il la peine de faire glisser le code de la 4.19 à la 2.6.32, au risque de la stabilité ?.. Je ne suis pas sûr...

Le pire, c’est quand le marketing s’implique dans le bras de fer entre « stabilité » et « modernisation ». Le service marketing a besoin que le noyau de la distribution mise à jour soit stable, d'une part, et en même temps qu'il soit plus performant et doté de nouvelles fonctionnalités. Cela conduit à d’étranges compromis.

Lorsque j'ai essayé de créer un module sur le noyau 4.4 à partir de SLES 12 SP3, j'ai été surpris d'y trouver des fonctionnalités de Vanilla 4.8. À mon avis, l'implémentation des E/S en bloc du noyau 4.4 de SLES 12 SP3 est plus similaire au noyau 4.8 que la version précédente du noyau stable 4.4 de SLES12 SP2. Je ne peux pas juger quel pourcentage de code a été transféré du noyau 4.8 vers SLES 4.4 pour SP3, mais je ne peux même pas appeler le noyau le même stable 4.4.

Le plus désagréable, c'est que lors de l'écriture d'un module qui fonctionnerait aussi bien sur différents noyaux, vous ne pouvez plus vous fier à la version du noyau. Il faut également tenir compte de la répartition. C'est bien que parfois vous puissiez vous impliquer dans une définition qui apparaît avec de nouvelles fonctionnalités, mais cette opportunité n'apparaît pas toujours.

En conséquence, le code est envahi par d’étranges directives de compilation conditionnelle.

Il existe également des correctifs qui modifient l'API du noyau documentée.
Je suis tombé sur la distribution KDE néon 5.16 et j'ai été très surpris de voir que l'appel lookup_bdev dans cette version du noyau modifiait la liste des paramètres d'entrée.

Pour y parvenir, j'ai dû ajouter un script au makefile qui vérifie si la fonction lookup_bdev a un paramètre de masque.

Signature des modules du noyau

Mais revenons à la question de la distribution des packages.

L'un des avantages de kABI stable est que les modules du noyau peuvent être signés sous forme de fichier binaire. Dans ce cas, le développeur peut être sûr que le module n'a pas été accidentellement endommagé ou intentionnellement modifié. Vous pouvez vérifier cela avec la commande modinfo.

Les distributions Red Hat et SUSE permettent de vérifier la signature du module et de le charger uniquement si le certificat correspondant est enregistré sur le système. Le certificat est la clé publique avec laquelle le module est signé. Nous le distribuons dans un package séparé.

Le problème ici est que les certificats peuvent être intégrés au noyau (les distributeurs les utilisent) ou doivent être écrits dans la mémoire non volatile EFI à l'aide d'un utilitaire. mokutil. Utilitaire mokutil Lors de l'installation d'un certificat, il vous faut redémarrer le système et, avant même de charger le noyau du système d'exploitation, il invite l'administrateur à autoriser le chargement d'un nouveau certificat.

Ainsi, l'ajout d'un certificat nécessite un accès administrateur physique au système. Si la machine est située quelque part dans le cloud ou simplement dans une salle de serveurs distante et que l'accès se fait uniquement via le réseau (par exemple via ssh), alors il sera impossible d'ajouter un certificat.

EFI sur les machines virtuelles

Bien que l'EFI soit pris en charge depuis longtemps par presque tous les fabricants de cartes mères, lors de l'installation d'un système, l'administrateur peut ne pas penser à la nécessité de l'EFI et celui-ci peut être désactivé.

Tous les hyperviseurs ne prennent pas en charge EFI. VMWare vSphere prend en charge EFI à partir de la version 5.
Microsoft Hyper-V a également obtenu la prise en charge EFI à partir d'Hyper-V pour Windows Server 2012R2.

Cependant, dans la configuration par défaut, cette fonctionnalité est désactivée pour les machines Linux, ce qui signifie que le certificat ne peut pas être installé.

Dans vSphere 6.5, définissez l'option DÉMARRAGE SÉCURISÉ possible uniquement dans l'ancienne version de l'interface web, qui fonctionne via Flash. L'interface utilisateur Web sur HTML-5 est encore loin derrière.

Distributions expérimentales

Et enfin, considérons la question des distributions expérimentales et des distributions sans support officiel. D'une part, il est peu probable que de telles distributions soient trouvées sur les serveurs d'organisations sérieuses. Il n’existe aucun support officiel pour de telles distributions. Par conséquent, fournissez-les. Le produit ne peut pas être pris en charge sur une telle distribution.

Cependant, ces distributions deviennent une plate-forme pratique pour tester de nouvelles solutions expérimentales. Par exemple, les versions Fedora, OpenSUSE Tumbleweed ou Unstable de Debian. Ils sont assez stables. Ils ont toujours de nouvelles versions de programmes et toujours un nouveau noyau. Dans un an, cette fonctionnalité expérimentale pourrait aboutir dans une mise à jour de RHEL, SLES ou Ubuntu.

Donc, si quelque chose ne fonctionne pas sur une distribution expérimentale, c'est une raison pour comprendre le problème et le résoudre. Vous devez vous préparer au fait que cette fonctionnalité apparaîtra bientôt sur les serveurs de production des utilisateurs.

Vous pouvez étudier la liste actuelle des distributions officiellement prises en charge pour la version 3.0 ici. Mais la véritable liste des distributions sur lesquelles notre produit peut fonctionner est bien plus large.

Personnellement, j'étais intéressé par l'expérience avec le système d'exploitation Elbrus. Après avoir finalisé le package Veeam, notre produit a été installé et fonctionnel. J'ai écrit sur cette expérience sur Habré dans article.

Eh bien, la prise en charge des nouvelles distributions continue. Nous attendons la sortie de la version 4.0. La bêta est sur le point d'apparaître, alors gardez l'œil ouvert quoi de neuf!

Source: habr.com

Ajouter un commentaire