Images de conteneurs multi-architectures pour les appareils IoT

Ce document constitue la première partie d'une série qui traite de la création d'un pipeline d'intégration continue (CI) automatisé pour créer des images de conteneurs multi-architectures sur Google Cloud. Les concepts expliqués dans ce document s'appliquent à n'importe quel environnement cloud.

La série se compose du présent document et d'un tutoriel d'accompagnement. Ce document explique la structure d'un pipeline permettant de créer des images de conteneurs et en décrit les étapes générales. Le tutoriel vous guide tout au long de la création d'un exemple de pipeline.

Cette série s'adresse aux professionnels de l'informatique qui souhaitent simplifier et optimiser les pipelines complexes pour la création d'images de conteneurs, ou étendre ces pipelines afin de créer des images multi-architectures, et part du principe que vous connaissez bien les technologies cloud et les conteneurs.

Lorsque vous mettez en œuvre un pipeline CI, vous simplifiez vos procédures de compilation d'artefacts. Vous n'avez pas besoin de gérer des outils et du matériel dédiés afin de créer des images de conteneurs pour une architecture donnée. Par exemple, si votre pipeline actuel s'exécute sur une architecture x86_64 et ne produit des images de conteneur que pour cette architecture, vous devrez peut-être gérer des outils et du matériel supplémentaires si vous souhaitez créer des images de conteneurs pour d'autres architectures, telles que pour la famille ARM.

Le domaine Internet des objets (IoT) nécessite souvent des builds multi-architecture. Lorsque vous disposez d'un grand nombre d'appareils avec des piles matérielles et logicielles différentes, le processus de création, de test et de gestion des applications logicielles pour un appareil spécifique devient un véritable défi. L'utilisation d'un processus de compilation multi-architecture permet de simplifier la gestion des applications IoT.

Le défi de la création d'images de conteneurs multi-architectures

Dans la plupart des mises en œuvre, les images de conteneur dépendent de l'architecture. Par exemple, si vous créez une image de conteneur pour l'architecture x86_64, elle ne peut pas s'exécuter sur une architecture de la famille ARM.

Vous pouvez contourner cette limitation de plusieurs manières :

  1. Créer les images de conteneur sur les architectures cibles pour lesquelles vous avez besoin de l'image du conteneur.
  2. Gérer des outils et un parc de matériel dédiés. Votre parc nécessite au moins un appareil pour chaque architecture pour laquelle vous devez créer une image de conteneur.
  3. Créer des images de conteneurs multi-architectures.

La stratégie la plus adaptée dépend de différents facteurs, dont les suivants :

  • Complexité du pipeline
  • Exigences d'automatisation
  • Ressources disponibles pour concevoir, mettre en œuvre et gérer l'environnement de création d'images de conteneurs

Par exemple, si votre environnement d'exécution a un accès limité à une source d'alimentation, vous devrez peut-être créer les images de conteneur dans un environnement distinct de votre environnement d'exécution.

Le schéma suivant illustre les points de décision dans le choix d'une stratégie viable.

Organigramme permettant de déterminer la meilleure stratégie pour créer des images de conteneurs multi-architectures.

Créer les images de conteneur sur les architectures cibles

Une stratégie possible consiste à créer chaque image de conteneur dont vous avez besoin directement dans l'environnement d'exécution compatible avec le conteneur lui-même, comme le montre le schéma suivant.

Chemin de compilation du dépôt de code source vers l'environnement d'exécution.

Pour chaque compilation, procédez comme suit :

  1. Téléchargez le code source de l'image de conteneur à partir d'un dépôt de code source sur chaque appareil de l'environnement d'exécution.
  2. Créez l'image de conteneur dans l'environnement d'exécution.
  3. Stockez l'image de conteneur dans le dépôt d'images de conteneur local à chaque appareil dans l'environnement d'exécution.

L'avantage de cette stratégie est que vous n'avez pas besoin de provisionner et de gérer le matériel en plus de ce dont vous avez besoin pour vos environnements d'exécution. Cette stratégie présente également des inconvénients. Tout d'abord, vous devez répéter le processus de compilation sur chaque instance matérielle de votre environnement d'exécution, et donc gaspiller des ressources. Par exemple, si vous déployez vos charges de travail conteneurisées dans un environnement d'exécution où les appareils n'ont pas accès à une source d'alimentation continue, vous perdez du temps et de l'énergie en exécutant des tâches de compilation sur ces appareils chaque fois que vous devez déployer une nouvelle version d'une charge de travail. En outre, vous devez gérer les outils pour accéder au code source de chaque image de conteneur afin de créer des images de conteneur dans votre environnement d'exécution.

Gérer des parcs d'outils et de matériel dédiés

Une deuxième stratégie possible consiste à gérer un parc de matériel dédié uniquement aux tâches de création d'images de conteneurs. Le schéma suivant illustre l'architecture de cette stratégie.

Chemin de compilation du dépôt de code source vers un environnement de compilation dédié.

Pour chaque compilation, procédez comme suit :

  1. Téléchargez le code source de l'image de conteneur sur un appareil du parc ayant l'architecture matérielle nécessaire et les ressources permettant de créer l'image de conteneur.
  2. Créez l'image du conteneur.
  3. Stockez l'image de conteneur dans un dépôt d'images de conteneurs centralisé.
  4. Téléchargez l'image de conteneur sur chaque appareil de l'environnement d'exécution lorsque vous devez déployer une nouvelle instance de cette image.

Pour cette stratégie, vous provisionnez au moins une instance de chaque architecture matérielle pour laquelle vous devez créer des images de conteneur. Dans un environnement de production complexe, vous pouvez avoir plusieurs instances afin d'augmenter la tolérance aux pannes de l'environnement et réduire les durées de compilation si vous disposez de plusieurs tâches de compilation simultanées.

Cette stratégie présente plusieurs avantages. Tout d'abord, vous ne pouvez exécuter chaque tâche de build qu'une seule fois et stocker l'image de conteneur résultante dans un dépôt d'images de conteneurs centralisé, tel que Container Registry. En outre, vous pouvez exécuter des suites de tests sur les appareils du parc de compilation ressemblant aux architectures matérielles de vos environnements d'exécution. Le principal désavantage de cette stratégie est que vous devez provisionner et gérer une infrastructure et des outils dédiés pour exécuter les tâches de création d'images de conteneurs. Généralement, de par sa conception, chaque tâche de build ne consomme pas beaucoup de ressources ni de temps. Par conséquent, cette infrastructure est inactive la plupart du temps.

Créer des images de conteneurs multi-architectures

Dans cette troisième stratégie, vous utilisez un pipeline à usage général pour créer des images de conteneurs multi-architectures, comme le montre le schéma suivant.

Chemin de compilation du dépôt de code source vers le pipeline multi-architecture à usage général.

Pour chaque compilation, procédez comme suit :

  1. Téléchargez le code source de l'image du conteneur.
  2. Créez l'image du conteneur.
  3. Stockez l'image de conteneur dans un dépôt d'images de conteneurs centralisé.
  4. Téléchargez l'image de conteneur sur chaque appareil de l'environnement d'exécution lorsque vous devez déployer une nouvelle instance de cette image.

Le principal avantage de cette stratégie est que vous n'avez pas à provisionner ni à gérer de matériel ou d'outils dédiés. Par exemple, vous pouvez utiliser vos pipelines et vos outils d'intégration continue/de déploiement continu (CI/CD) existants pour créer des images de conteneurs multi-architectures. Vous pouvez également bénéficier de meilleures performances avec une architecture matérielle à usage général, telle que x86_64, par rapport à une architecture à faible consommation énergétique, que l'on retrouve par exemple dans la famille ARM.

Cette stratégie peut également faire partie d'une initiative plus large dans laquelle vous adopterez les principes du DevOps. Vous pouvez par exemple mettre en œuvre un pipeline CI/CD pour du matériel spécialisé.

Mettre en œuvre un pipeline pour créer des images de conteneurs multi-architectures

Dans cette section, nous décrivons à titre de référence une mise en œuvre d'un pipeline CI/CD suivant la troisième stratégie : créer des images de conteneurs multi-architectures.

La mise en œuvre de référence comprend les composants suivants :

  • Un dépôt de code source afin de gérer le code source pour les images de conteneurs. Par exemple, vous pouvez utiliser Cloud Source Repositories ou des dépôts GitLab.
  • Un environnement d'exécution CI/CD pour créer des images de conteneurs, tel que Cloud Build.
  • Une plate-forme permettant de gérer les conteneurs et les images de conteneurs compatibles avec les images de conteneurs multi-architecture, telle que Docker.
  • Un registre d'images de conteneurs tel que Container Registry. Si vous souhaitez stocker vos images de conteneurs plus près des nœuds où elles sont nécessaires, vous pouvez exécuter un registre d'images de conteneurs, tel que Docker Registry, directement dans votre environnement actuel.

Cette architecture de référence utilise Moby BuildKit et QEMU pour créer des images de conteneur Docker multi-architectures. Dans ce cas, Moby BuildKit détecte automatiquement les architectures disponibles via l'émulation matérielle QEMU et charge automatiquement les binaires appropriés enregistrés dans la fonctionnalité binfmt_misc du noyau Linux.

Le schéma suivant illustre la pile technique responsable de chaque création d'image de conteneur multi-architecture compatible avec cette architecture de référence.

Composants associés à cette architecture de référence multi-architecture.

Comme cette architecture de référence utilise des fichiers manifestes d'images Docker, vous n'avez pas besoin de fournir un tag d'image de conteneur pour chaque architecture matérielle cible. Vous pouvez utiliser le même tag pour plusieurs architectures. Par exemple, si vous créez la version 1.0.0 d'une image de conteneur multi-architecture, vous n'avez pas besoin d'un tag unique pour chaque architecture matérielle, tel que 1.0.0-x86_64, ou 1.0.0_ARMv7 Vous utilisez le même tag 1.0.0 pour toutes les architectures matérielles que vous créez, et vous utilisez des fichiers manifestes d'images Docker pour identifier correctement chaque image de conteneur.

L'exemple suivant montre le fichier manifeste de l'image Alpine Linux officielle, où vous trouverez des informations sur les architectures compatibles avec une version particulière de cette image de conteneur :

{
   "schemaVersion": 2,
   "mediaType": "application/vnd.docker.distribution.manifest.list.v2+json",
   "manifests": [
      {
         "mediaType": "application/vnd.docker.distribution.manifest.v2+json",
         "size": 528,
         "digest": "sha256:ddba4d27a7ffc3f86dd6c2f92041af252a1f23a8e742c90e6e1297bfa1bc0c45",
         "platform": {
            "architecture": "amd64",
            "os": "linux"
         }
      },
      {
         "mediaType": "application/vnd.docker.distribution.manifest.v2+json",
         "size": 528,
         "digest": "sha256:401f030aa35e86bafd31c6cc292b01659cbde72d77e8c24737bd63283837f02c",
         "platform": {
            "architecture": "arm",
            "os": "linux",
            "variant": "v7"
         }
      },
      {
         "mediaType": "application/vnd.docker.distribution.manifest.v2+json",
         "size": 528,
         "digest": "sha256:2c26a655f6e38294e859edac46230210bbed3591d6ff57060b8671cda09756d4",
         "platform": {
            "architecture": "arm64",
            "os": "linux"
         }
      }
   ]
}

Lorsque vous concevez un pipeline automatisé pour la création d'images de conteneurs, nous vous recommandons d'inclure des suites de tests complètes validant la conformité aux exigences de chaque image de conteneur. Par exemple, vous pouvez utiliser des outils tels que Chef InSpec, Serverspec et RSpec pour exécuter des suites de tests de conformité sur vos images de conteneurs parmi les tâches du pipeline de compilation.

Optimiser le pipeline pour créer des images de conteneurs

Après avoir validé et consolidé les pipelines pour la création de vos images de conteneurs, vous optimisez les pipelines. La section Migration vers Google Cloud : optimiser votre environnement contient des conseils sur l'optimisation de votre environnement. Cette section décrit une structure d'optimisation que vous pouvez adopter pour améliorer l'efficacité de votre environnement par rapport à son état actuel. En suivant le framework d'optimisation, vous passez par plusieurs itérations dans lesquelles vous modifiez l'état de votre environnement.

L'une des premières activités de chaque itération d'optimisation consiste à établir un ensemble d'exigences et d'objectifs pour cette itération. Vous pourriez par exemple avoir besoin de moderniser vos processus de déploiement, en passant de processus de déploiement manuels à des processus entièrement automatisés et conteneurisés. Pour en savoir plus sur la modernisation de vos processus de déploiement, consultez la page Migration vers Google Cloud : passer des déploiements manuels aux déploiements automatisés en conteneurs.

Étape suivante