La conteneurisation est une technologie qui permet aux développeurs de rassembler tous les éléments d'un logiciel ou d'une application sous la forme de code à exécuter en tant qu'images non modifiables dans des environnements informatiques isolés. Ces images d'application conteneurisée contiennent l'ensemble des fichiers, configurations, bibliothèques et fichiers binaires nécessaires à l'exécution d'une application donnée. L'exécution d'un conteneur ne dépend par conséquent que du noyau du système d'exploitation hôte, dans la mesure où les moteurs de conteneurisation comme Docker Engine font office d'interface entre le runtime et ce noyau.
Cet article se penche sur le rôle de la conteneurisation d'applications dans le domaine des déploiements logiciels, y compris sur ce qui la distingue de la virtualisation appliquée aux systèmes d'exploitation, sur la manière de l'utiliser et sur les avantages à l'utiliser.
Conteneurisation et virtualisation
Si les machines virtuelles (VM) constituent elles aussi un moyen d'isoler un système, elles présentent des différences majeures par rapport aux conteneurs d'application. Bien plus lourdes, elles peuvent aussi prendre en charge des workloads plus gourmands en ressources, sachant qu'elles sont conçues pour émuler des systèmes entiers et pas seulement des applications individuelles.
Les VM sont capables d'émuler ou de virtualiser des systèmes informatiques entiers, noyau de système d'exploitation compris, ce qui permet à une même machine hôte d'exécuter une ou plusieurs machines virtuelles invitées. Ces dernières sont gérées par un hyperviseur qui coordonne le système de fichiers et les ressources matérielles de la machine hôte.
Pourquoi exécuter une, voire plusieurs, machines virtuelles sur une machine hôte ? La capacité à héberger sur une seule machine toute une série de workloads et cas d'usage différents par l'intermédiaire de machines virtuelles invitées offre aux entreprises et aux fournisseurs de services cloud énormément de flexibilité quant à l'utilisation des ressources.
Si une machine physique puissante peut, dans un premier temps, nécessiter un certain portefeuille de machines virtuelles, la capacité à mettre ces ressources à l'échelle et à adapter leurs propriétés à mesure que les besoins de l'entreprise ou que l'architecture évoluent, sans nécessairement avoir à investir dans du nouveau matériel, se transforme ensuite en avantage certain, aussi bien pour les fournisseurs de services cloud que pour les utilisateurs qui gèrent leurs propres datacenters.
Avantages de la conteneurisation d'application
Développer ses logiciels dans des environnements conteneurisés présente plusieurs avantages par rapport au modèle plus traditionnel qui consiste simplement à empaqueter le code d'une application et à l'exécuter directement sur le système hôte. De la même manière que les machines virtuelles offrent souplesse et flexibilité de mise à l'échelle aux fournisseurs de services cloud et aux datacenters, l'utilisation de la conteneurisation pour conditionner et exécuter les applications logicielles présente des avantages similaires, et bien d'autres.
Portabilité
Les dépendances en dehors du conteneur étant minimes, l'application conteneurisée peut fonctionner de façon fiable dans différents environnements. Un exemple qui illustre parfaitement ce principe est le modèle side-car au sein d'une architecture en microservices. Dans celui-ci, une fonction généralisée, comme la collecte de mesures ou l'enregistrement de services, s'exécute en tant que processus aux côtés d'une série de services distincts. La conteneurisation permet d'encapsuler les dépendances de ce processus side-car, en éliminant la nécessité qu'elles soient préalablement installées sur l'hôte. La cohérence entre les environnements de développement, de test et de production est un autre des avantages offerts par la portabilité des applications conteneurisées.
Déclarativité
La possibilité de définir les dépendances d'une application dans son code de manière déclarative offre un meilleur contrôle sur l'environnement d'exécution. En effet, les applications qui dépendent des paquets installés au niveau de l'hôte s'exposent aux problèmes de compatibilité et aux erreurs d'exécution inattendues, en particulier si l'application doit être exécutée dans différents environnements ou si ceux-ci sont instables.
Rapidité et portabilité
En introduisant un modèle universel, l'exécution des applications dans des conteneurs isolés, qui englobent toutes les dépendances nécessaires, élimine de nombreux problèmes pour les développeurs. Les progiciels ne sont plus couplés au système d'exploitation de l'hôte, ce qui simplifie la gestion des dépendances. La cohérence de l'exécution conteneurisée profite également au cycle de développement, puisqu'elle permet aux logiciels d'être exécutés de manière fiable à la fois dans les environnements de développement, de test et de production.
Isolation des défaillances et contrôles de sécurité
Les applications conteneurisées étant associées à un processus isolé, les autres conteneurs exécutés ne seront pas impactés en cas de panne irréversible de l'un d'eux. Par ailleurs, les conteneurs peuvent être intégrés aux règles de sécurité de l'hôte, tandis que les éléments virtualisés offrent une isolation des ressources physiques, capable de bloquer l'accès de code malveillant.
Des contrôles de sécurité supplémentaires peuvent également être ajoutés par le biais de configurations de conteneur spécifiques, afin de limiter l'accès aux ressources et d'activer des règles de sécurité complémentaires. Pour autant, les conteneurs ne constituent pas en eux-mêmes une protection complète contre les menaces de sécurité, et la possibilité de composer plusieurs images dans un seul conteneur augmente la surface d'exposition aux risques lorsqu'il est fait usage d'images tiers.
Utilisation efficace des ressources et des serveurs
Dans la mesure où ils mobilisent le noyau du système d'exploitation de l'hôte avec des images qui ne contiennent que le strict nécessaire de l'application, les conteneurs sont moins lourds que les machines virtuelles. Cela conduit à une empreinte allégée et à la possibilité d'exécuter de manière flexible plusieurs conteneurs au sein d'un même environnement informatique, avec pour résultat une utilisation plus efficace des ressources.
Dans tout contexte informatique (virtuel, physique ou autre), la portabilité et le caractère isolé des conteneurs d'application font qu'ils peuvent être et sont exécutés simultanément et de façon modulable. Machines virtuelles et conteneurisation ne sont pas incompatibles et sont souvent utilisées conjointement. L'une des tendances dans l'industrie consiste d'ailleurs, pour les éditeurs de logiciels cloud native, à exécuter leurs applications sur les machines virtuelles de fournisseurs de services cloud.
L'émergence de plateformes comme Kubernetes contribue elle aussi à renforcer l'efficacité liée à l'utilisation des conteneurs via la dissociation et l'isolement des applications de l'infrastructure sous-jacente, et l'affectation groupée de conteneurs sur des clusters de serveurs. Cela offre des opportunités d'optimisation des ressources bien plus flexibles qu'avec les machines virtuelles et facilite la gestion de l'infrastructure pour les développeurs.
Fonctionnement de la conteneurisation
Ce qui suit est un résumé schématique de ce à quoi ressemble un flux de conteneurisation d'une application logicielle.
Le cycle de développement d'une application conteneurisée compte approximativement trois étapes.
Développement
Le développement d'une application et l'élaboration de son code source impliquent de définir les dépendances de cette application dans un fichier image conteneur de type Dockerfile. L'approche traditionnelle de gestion du code source se prête particulièrement bien à la conteneurisation, dans la mesure où l'ensemble de la configuration du conteneur est stockée en tant que code, généralement auprès du code source de l'application. Il arrive, par exemple lors de l'utilisation de Docker Engine, que la conteneurisation d'une application existante ne nécessite que l'ajout et la configuration d'un Dockerfile, et l'association des dépendances au code source.
Conception
Cette étape consiste à créer et à publier l'image dans un référentiel de conteneurs où elle ne pourra plus être modifiée et où elle sera versionnée et tramée. Une fois qu'une application comprend un fichier de définition d'image de type Dockerfile et qu'elle est configurée pour installer et tirer les dépendances requises dans une image, viennent les phases de matérialisation et de stockage de cette image. Cela peut se faire en local ou dans un référentiel distant dans lequel l'image sera référencée et téléchargeable.
Déploiement
Pour terminer, l'application conteneurisée est déployée et exécutée localement, dans des pipelines CI/CD ou dans des environnements de test, de simulation ou de production. Dès qu'une image publiée est accessible par un environnement, elle devient alors un élément exécutable exploitable. Pour reprendre l'exemple de Docker Engine, l'environnement cible qui exécutera le conteneur devra disposer de Docker Daemon, un service de longue date destiné à gérer la création et l'exécution des processus de conteneurisation. L'interface de ligne de commande de Docker permet d'exécuter manuellement ou par programmation l'application conteneurisée.
Les technologies de conteneurisation ainsi que les méthodes et plateformes d'orchestration des conteneurs sont nombreuses et chaque entreprise devrait procéder à une évaluation minutieuse pour décider quelle technologie adopter. Notons toutefois que l'Open Container Initiative, projet en partie fondé par l'équipe Docker, travaille à l'élaboration de normes et de spécifications industrielles autour des runtimes et images de conteneur.
Conteneurisation et architecture en microservices
Alors que l'exploitation de services monolithiques présente des avantages, comme l'uniformité des outils, la réduction de la latence de certaines opérations, et la simplification de l'observabilité et du déploiement, de nombreuses applications complexes sont divisées en plus petits éléments, ou services, qui interagissent entre eux sous la forme de modèles dénommés architectures en microservices. La manière dont ces architectures sont conçues et dont les monolithes sont divisés en microservices est un sujet complexe en soi, qui n'entre pas dans le propos de cet article. Cependant, cela démontre clairement la pertinence et les avantages de la conteneurisation d'applications dans le cadre du déploiement et de l'hébergement de microservices.
Imaginez-vous une application monolithique qui gère des requêtes web en les traitant selon une logique métier, tout en assurant la connexion avec la couche de base de données. À mesure que la complexité de chaque couche augmente, l'entreprise juge judicieux de diviser cette application en trois services distincts : un service web, un service d'API logique de base et un service de base de données.
Au lieu d'exécuter de lourds et importants processus sur des machines virtuelles, l'entreprise décide ensuite de conteneuriser ces applications distinctes qui touchent chacune à des questions très larges et précises. Cette approche lui laisse même la possibilité de choisir entre gérer chaque service spécialisé dans ses propres clusters élastiques de machines virtuelles en mettant à l'échelle le nombre de conteneurs de chaque VM, ou bien utiliser une plateforme comme Kubernetes pour simplifier la gestion de son infrastructure.
Une option adaptée à vos besoins ?
La convivialité des technologies de conteneurisation modernes comme Docker facilite leur intégration dans le cadre d'une preuve de concept. Si vous avez la possibilité d'introduire la conteneurisation dans votre cycle de déploiement logiciel de manière itérative, par exemple en conteneurisant un service unique ou bien annexe, cela peut être un bon moyen d'acquérir de l'expérience quant au fonctionnement de la technologie et d'éclairer une prise de décision.
Si la conteneurisation peut dans certains cas apparaître comme l'option toute trouvée, faire un choix n'est pas toujours aussi évident, et cela dépend de la taille et de la portée de votre entreprise. L'introduction et l'adoption d'une nouvelle technologie, aussi conviviale soit-elle pour les développeurs, demande une compréhension de ses avantages, mais aussi des compromis associés, notamment en ce qui concerne l'observabilité et la sécurité.
Cela étant, la conteneurisation reste soutenue par une importante et croissante communauté de développeurs, et les premières données tendent à indiquer qu'elle prend le chemin de la norme industrielle. Si vous en êtes aux premiers stades du développement de votre logiciel ou si vous partez d'une page blanche, la conteneurisation pourrait s'avérer une option intéressante, qui vous permettrait de tirer parti de certaines des dernières avancées technologiques en matière de développement et de déploiement.