Chapitre 4 : DevOps vu par les équipes opérations

La gestion opérationnelle des services d’infrastructure est un élément clé du succès d’une application.

Il intéressant de constater que les pionniers du DevOps avaient un profil plus orienté administration système et réseau que développeur. Les principes de l’agile concernaient tous les acteurs du cycle de développement logiciel (développeurs, analystes métier, testeurs, DBA, responsables qualité…) sauf les équipes opérations. À l’origine, il s’agissait donc d’abord d’appliquer cette vision au domaine d’expertise des responsables opérationnels et de mettre en avant les vertus d’une infrastructure agile.

Mais, notamment, sous l’influence de Patrick Debois, la démarche s’est enrichie d’une dimension nouvelle ciblant à un alignement entre les métiers Dev et les métiers Ops, par l’application des principes Lean. En parallèle, la virtualisation et le cloud ont accéléré le développement de solutions techniques ciblant l’application des bonnes pratiques associées à la démarche DevOps.

La vision du DevOps pour les équipes des opérations s’inscrit donc sur plusieurs axes : une évolution de l’organisation et du métier des opérations, les concepts liés à la mise en œuvre d’une infrastructure agile, le rôle du cloud dans cette évolution, et les multiples technologies et produits qui la rendent possible.

Comme pour le développeur, la mise en œuvre d’une démarche DevOps par les opérations suppose l’acquisition de nouvelles compétences et s’inscrit dans de nouveaux processus organisationnels plus collaboratifs associés à de nouvelles méthodes de travail et de nouveaux outils.

DevOps pour les opérations : la culture avant la technique…

De même que pour le développeur, la transformation DevOps des équipes de gestion opérationnelle suppose un fort changement sur le plan culturel. Ces équipes se doivent d’accorder un niveau plus élevé de confiance aux autres acteurs, en leur déléguant l’accès aux ressources du système d’information. Elles doivent également s’inscrire dans un cycle d’apprentissage et d’amélioration en continu, pour acquérir de nouvelles compétences jusque-là réservées au monde des développeurs et partager leurs outils et leur processus. Ces équipes auront également à prouver leur capacité à prendre des risques avec une vision positive de l’échec, et à s’impliquer sur la réduction des délais, l’optimisation des coûts par l’automatisation et la mise en place de systèmes permettant de remonter de l’information en continu.

Dans la suite de ce chapitre, notre objectif est de montrer le rôle de ces équipes dans la mise en place du processus de continuous delivery en collaboration avec les développeurs. De même que dans le précédent chapitre, notre discours aura une forte connotation technique. Mais là encore, il ne faudra pas perdre de vue, que pour ces équipes, DevOps signifie d’abord un changement de culture…

Une organisation bâtie en silos et qui isole chacun dans un périmètre bien restreint de responsabilité inhibe toute initiative destinée à rendre l’infrastructure plus agile. D’un point de vue organisationnel, une des évolutions majeures de DevOps est la suppression des verrous établis jusqu’alors pour éviter un risque d’erreur lié à un manque de rigueur présumé chez le développeur. Certes, en interdisant au développeur telle ou telle action, on ajoute des niveaux de protection interne au système, mais le résultat est aux antipodes des principes du DevOps : le développeur n’est pas tenté de comprendre ce qui se passe au- delà de son périmètre d’action puisque les opérations lui interdisent de le faire…

Au-delà des contraintes qu’ils occasionnent (délais, frustrations…), ces obstacles sont manifestement le reflet d’un manque de confiance des opérations. Ils doivent donc être progressivement éliminés en accompagnant leur disparition par une sensibilisation sur l’extension des responsabilités de chacun.

Les multiples phases d’un cycle de production logicielle classique sont fréquemment cloisonnées entre les différents rôles. D’une certaine façon, les équipes de gestion opérationnelles assurent le lien entre les multiples acteurs du système d’information, par la mise à disposition des environnements requis par chacun des acteurs et sont donc au cœur de ce processus de collaboration.

Elles sont donc très logiquement devenues responsables de l’automatisation des processus permettant de déployer l’application sur les différentes plateformes. L’objectif est de gagner en agilité, mais aussi de faire en sorte que les équipes opérations n’aient plus à intervenir sur les processus récurrents, ce qui implique la mise en place d’un système de délégation des autorisations vers une multiplicité de rôles au sein de l’organisation pour déclencher des déploiements à la demande.

L’ensemble de ces éléments (automatisation, définition de niveaux de délégation, voire de quotas de ressources) constitue un modèle des services proposés par les équipes de gestion opérationnelle. L’aboutissement de ce modèle est fonction de son niveau d’industrialisation. Les équipes de gestion des opérations ont pour mission de proposer l’équivalent d’un catalogue de services répertoriant l’ensemble des actions et des possibilités permettant d’homogénéiser les besoins des utilisateurs voire de les limiter.

Dans certains cas, ce catalogue pourra être matérialisé par l’ouverture de souscriptions dédiées sur le contrat d’un fournisseur de services cloud.

Le rôle de l’administrateur système DevOps est donc de mettre à disposition de l’ensemble des acteurs du système un certain nombre de capacités avec un niveau d’automatisation, et un accès en libre-service qui permette à chacun de travailler avec plus d’autonomie sans pour autant remettre en cause les principes de contrôle et de sécurité des services d’infrastructures concernés. Avec l’avènement des technologies d’automatisation et de virtualisation, l’administrateur système est, dans une certaine mesure, lui-même devenu un développeur capable d’automatiser telle ou telle séquence d’opérations afin qu’elle s’exécute avec le minimum d’interventions manuelles.

Les systèmes d’exploitation proposent des langages de programmation système permettant d’automatiser un certain nombre de tâches. Il s’agit en général de langage de scripting, comme bash pour Linux ou Windows PowerShell. À ces langages nativement proposés sur ces systèmes viennent s’ajouter des solutions de configuration système souvent issues du monde open source, comme nous le verrons par la suite.

L’administrateur système DevOps se doit donc d’acquérir une réelle expertise sur les multiples solutions de scripting qui lui permettent de déployer les infrastructures dont il a la charge. Au même titre que les développeurs, il a donc besoin d’un environnement qui leur permette de développer, gérer en version, tester et exécuter son code d’infrastructure afin de valider la création d’environnements dotés de l’ensemble des prérequis de configuration et d’instrumentation.

Avant DevOps, l’infrastructure d’un système d’information apparaissait alors comme une composante complexe, aux multiples ramifications et dépendances, associées à des processus souvent long et coûteux, bref, un paquebot plutôt difficile à manœuvrer. Les pionniers du mouvement DevOps ont donc souhaité faire évoluer ce modèle en s’inspirant des concepts agiles. Toutefois, plutôt que de se lancer dans une périlleuse transposition à l’identique des principes du Manifeste, ils ont préféré en retenir certains et les adapter au domaine de la gestion des opérations.

Plus concrètement, il s’agissait avant tout de repenser le rôle des équipes opérationnelles au sein du système d’information et de mettre en place le socle permettant de faire évoluer une infrastructure, de façon progressive et itérative, avec des capacités plus élevées, tout en gardant le contrôle de l’ensemble des ressources et processus associés.

ITIL (Information Technology Infrastructure Library) est un standard qui a été créé à l’initiative du CCTA (Central Computer and Telecommunications Agency), organisme gouvernemental anglais, afin de définir un ensemble de règles pour gérer l’infrastructure et les opérations. ITIL n’est pas le seul framework ITSM (Information Technology Service Management) : il y en a d’autres comme le standard ISO/IEC 20000 qui permet de certifier les services informatiques des organisations ou MOF (Microsoft Operation Framework). Mais il s’agit d’une référence pour la communauté de gestion de services de l’IT. Dans sa troisième version, ITIL est d’ailleurs particulièrement adapté au développement de processus conformes à la norme ISO/IEC 20000.

De prime abord, ITIL peut sembler en contradiction avec les principes de l’agilité et par extension avec la démarche DevOps. En réalité, loin d’être antagonistes, ITIL et DevOps se complètent sur bien des points.

ITIL a pour objectif de rationaliser la gestion des services informatiques autour de grandes fonctions et de processus standardisés. Il intègre de multiples « bonnes pratiques » plus ou moins adaptées ou pertinentes, selon le contexte et l’évolution générale des technologies.

La démarche DevOps s’accompagne aussi de « bonnes pratiques » mais comme nous l’avons vu, ses objectifs sont différents. Pour autant, elle ne remet pas en cause la gestion en services préconisée par ITIL, ni même les processus qui peuvent les composer. Au contraire, DevOps s’appuie sur plusieurs de ces services : par exemple, certains processus d’ITIL sont directement au cœur de la boucle de feedback DevOps. Le Service Desk est l’oreille du client dans une démarche DevOps et la gestion des incidents et des problèmes font partie intégrante de la philosophie de collaboration de la démarche. Enfin le modèle hub-and-spoke du cycle de services ITIL n’est pas si éloigné du modèle d’organisation DevOps en hubs de service que nous étudierons plus en détail dans le chapitre 6 DevOps vu par le management.

Néanmoins, les pratiques DevOps sont susceptibles de faire évoluer ou remplacer les bonnes pratiques incluses dans la boîte à outils ITIL, sans remettre en cause la logique ou l’esprit initial. Ainsi, DevOps peut intégrer de nouveaux rôles qui n’existent pas dans ITIL ou faire faire évoluer les rôles et les responsabilités de chacun, en décloisonnant tel ou tel silo organisationnel. Avec DevOps, l’importance et la visibilité de certains processus, comme la supervision, la gestion d’incidents ou la gestion du changement diffère également. D’autres processus doivent évoluer, comme par exemple, la mise en production avec l’augmentation de la fréquence de déploiement.

Cet impact de DevOps sur l’implémentation d’ITIL ne les rend pas incompatibles, au contraire, l’amélioration continue (Continual Service Improvement) est inscrite au cœur des principes ITIL (un autre point commun avec DevOps d’ailleurs). Il suffit pour s’en convaincre de se pencher sur l’évolution d’ITIL entre la version 2 et la version 3. Lors de cette évolution, certains processus ont été complètement refondus et parfois simplifiés. De nouveaux processus que nous qualifierons de plus agiles ont été intégrés, comme le Service Catalog par exemple. Des fonctions communes à DevOps, telle que la gestion des applications, ont été ajoutées, en sus du Service Desk.

Enfin, la logique du do fast, check fast and fix fast propre à la philosophie DevOps influe sur la façon de mettre en œuvre ITIL, en focalisant l’attention sur les résultats des processus plutôt que sur leurs pré-requis. Réussir à implémenter une démarche DevOps en complément d’une approche ITIL permet d’atteindre un vrai objectif de fiabilité en disposant d’opérations agiles et robustes et garantie la réussite d’une collaboration avec les développeurs comme avec les métiers.

Le poste du développeur ne constitue que la première brique de l’infrastructure hébergeant le cycle de développement d’une application qui suppose la mise en œuvre de multiples plates-formes : plate-forme de test, d’intégration, de pré-production, de production. Chacun de ces environnements doit refléter l’environnement de production. À chaque instant, il doit pouvoir être rapidement cloné (par exemple, pour vérifier le comportement d’un correctif à chaud).

Cloner un environnement implique d’être en mesure de le provisionner (c’est-à-dire de mettre à disposition les ressources matérielles correspondantes), et de le configurer avec le déploiement de l’ensemble des caractéristiques systèmes et applicatives requises. Ces opérations peuvent être automatisées en utilisant différentes techniques de scripting que nous verrons dans la suite de ce chapitre. Il devient donc aujourd’hui possible de développer le code qui construit l’infrastructure et de mettre en application de nombreuses bonnes pratiques et outils issus de l’expérience du développement (notamment le versioning dans un contrôle de code source). Il devient également possible de procéder à un retour arrière à chaque incrément de l’évolution d’une infrastructure.

L’infrastructure as code devient alors un élément essentiel pour permettre aux équipes de gestion opérationnelle de proposer des services d’infrastructure adaptés à la vitesse du monde d’aujourd’hui.

L’automatisation désigne en général l’implémentation d’une tâche spécifique dans un langage (qui le plus souvent est un langage de script). Par exemple, le déploiement d’une machine virtuelle sur un hyperviseur est une tâche de type automatisation.

L’orchestration cible un processus complet. Il s’agit surtout d’une question d’échelle. Reprenons l’exemple de la machine virtuelle. Ce type de tâche est rarement isolé : on peut donc légitimement s’attendre à ce que la demande de création de la machine virtuelle soit associée à d’autres tâches comme la configuration de la ou les interfaces réseau de la machine, l’attribution d’adresses IP, le nom DNS, les disques attachés, la configuration des accès SSH ou RDP pour une connexion distante…

Fig. 4.1 représente une orchestration elle-même composée de multiples tâches de provisioning et de configuration

Le cloud par la mise en œuvre de technologies liées à la virtualisation (machine, réseau, stockage) et à ses promesses en termes de scalabilité représente sans conteste un formidable accélérateur dans l’évolution technologique qui accompagne la transformation DevOps des équipes de gestion opérationnelle.

D’après le NIST (National Institute of Standards and Technology), les attributs qui définissent le cloud computing sont la mutualisation des ressources, l’accès aux ressources en mode libre-service, l’accès à un réseau ubiquitaire, l’élasticité des ressources, et la facturation à l’usage… Les quatre premières de ces caractéristiques sont particulièrement adaptées à la mise en œuvre d’une infrastructure plus agile. À ce titre, le cloud qu’il soit public ou privé, peut grandement faciliter la mise en œuvre de DevOps sur le plan technique.

Durant la dernière décennie, une grande variété d’environnements pour l’exécution des applications a été mise à disposition des entreprises. Ces environnements peuvent être proposés selon plusieurs modèles de services cloud : IaaS (Infrastructure-as-a-service), PaaS (Plateform-as-a-service) et SaaS (Software-as-a-service). Ces différents types de cloud délivrent de multiples niveaux d’automatisation, et à ce titre ont un impact différent sur le rôle des opérations. Le schéma de la figure 4.2 illustre les différences liées aux options de service en précisant les services automatisés (dits managés) et facturés par un fournisseur tiers, et en signalant les services gérés par les équipes de gestion opérationnelle.

Fig. 4.2  Les différents modèles de services

Services IaaS et gestion opérationnelle

Les services IaaS permettent de se libérer de certaines des préoccupations associées à la fourniture physique ou virtuelle en permettant de provisionner à la demande des machines virtuelles dont le format est standardisé. C’est encore le modèle de service le plus fréquemment utilisé de nos jours et celui avec lequel les équipes de gestion opérationnelle ont sans doute le plus d’affinité. La valeur ajoutée de l’administrateur système DevOps est alors de personnaliser les machines virtuelles et de créer des environnements dédiés, ou de construire de nouveaux processus automatisés sur la base de ces services IaaS. En soi, il constitue déjà une rupture par rapport à un modèle de gestion opérationnelle plus ancien (avec des responsabilités cloisonnées entre systèmes, réseaux, stockage…).

Services PaaS et gestion opérationnelle

Le Gartner donne la définition suivante du PaaS : « A platform as a service (PaaS) offering, usually depicted in all-cloud diagrams between the SaaS layer above it and the IaaS layer below, is a broad collection of application infrastructure (middleware) services (including application platform, integration, business process management and database services ».

Dans un autre document (PaaS Road Map: A Continent Emerging), le Gartner présente la multiplicité des offres PaaS. Leur dénominateur commun est d’offrir un niveau d’abstraction à de multiples concepts d’infrastructure : modèles d’environnement prédéfinis par plate-forme, approvisionnement sur demande, en libre-service, et automatisé de ces modèles, surveillance des ressources utilisées, gestion élastique des ressources en fonction de leur utilisation, garantie de continuité de service pour les applicatifs hébergés, même en cas de panne matérielle, de mise à jour du système d’exploitation ou de mise à jour de l’applicatif lui-même.

L’objectif du PaaS est de faciliter le développement, le déploiement et l’exécution d’applications et services en focalisant l’investissement sur les données et le code plutôt que la mise en place de l’infrastructure qui les héberge. Pour autant, même si ce modèle décharge l’administrateur système DevOps d’une partie de ses responsabilités, il reste à ce dernier un certain nombre de tâches à accomplir pour en tirer le meilleur parti. Car même si ces services proposent des configurations prédéfinies et des mécanismes intégrés d’autoscaling, il est utile d’automatiser leur création, de tester leur disponibilité, de les intégrer dans un processus les liant à d’autres services pour une gestion commune de leur cycle de vie, de les superviser…

Services SaaS et gestion opérationnelle

Le modèle de cloud le plus visible pour le grand public est le SaaS, modèle dans lequel un vendeur héberge son propre logiciel et le propose à ses clients comme un service accessible via Internet. Salesforce.com, à défaut d’en être l’inventeur a été sans doute été le premier à en avoir réellement démontré la viabilité financière. Même si ce modèle permet de s’affranchir de tout un ensemble de tâches liées à la mise à disposition d’une solution logicielle, il implique souvent les équipes de gestion opérationnelle dans sa mise en œuvre. En effet, ces dernières seront nécessairement amenées à construire de nouveaux processus fondés sur ces services SaaS et à les intégrer aux services existants en prenant en compte différentes problématiques et notamment la gestion d’identité.

L’influence d’une démarche DevOps sur ce type d’intégration se manifestera par le niveau d’automatisation des processus internes et par l’industrialisation du modèle de service associé.

Le cloud propose trois principaux modèles de déploiement : privé, public et hybride. Chaque modèle peut avoir un impact sur la mise à disposition des services avec ou sans intervention des équipes de gestion opérationnelle.

Le cloud privé

L’objectif d’un cloud privé est d’utiliser et de déployer des couches de virtualisation, de provisionnement, d’automatisation et de catalogues de services pour une utilisation interne à l’entreprise. Il peut être déployé et exploité directement par l’entreprise ou par un tiers. Dans les deux cas, il offre un espace très propice à la mise en œuvre d’une infrastructure as code et constitue donc un terrain de jeu idéal pour l’administrateur système DevOps. Au final, il s’agit fréquemment d’en environnement de type IaaS, même s’il existe des exceptions (par exemple, la solution de cloud privé Azure Stack permet d’offrir l’accès à des ressources de type PaaS).

Le cloud public

Un cloud public est un service déployé et géré par des fournisseurs comme Amazon, Google ou Microsoft dans leurs datacenters (ou via des partenaires, comme c’est le cas pour Microsoft en Chine avec 21Vianet). L’infrastructure cloud y est donc mutualisée pour être utilisée par les clients. L’exploitation de la composante non managée, dont le niveau varie selon le type de service (PaaS ou IaaS), est de la responsabilité des clients du fournisseur cloud, qui souvent sont les équipes de gestion opérationnelle. Là encore, l’environnement est particulièrement adapté pour les scénarios de type infrastructure as code. Les processus organisationnels mis en place pour accéder aux ressources cloud par l’ensemble des acteurs du système d’information sont un indicateur significatif du niveau de maturité DevOps des équipes de gestion opérationnelles et plus généralement de l’entreprise.

Le cloud hybride

Le cloud hybride se caractérise par la mise en œuvre d’infrastructures distinctes cloud et à demeure (ou résultant de la composition de multiples cloud). Celles-ci sont liées par des passerelles réseau permettant le bon fonctionnement des applications et l’échange de données. C’est un cas de figure assez fréquent qui suppose une implication forte des équipes de gestion opérationnelle dans l’établissement des connexions entre les différents environnements. Il offre la possibilité de mettre en place des scénarios d’infrastructure agile comme par exemple celui du débordement de ressources sur un cloud public (ou bursting) lorsqu’une entreprise a besoin de ressources supplémentaires (serveurs, stockages, etc.) pour absorber un pic d’utilisation que ne peut supporter son infrastructure à demeure.

La bascule de l’existant vers le cloud doit être mûrement réfléchie. Toutes les applications ne se prêtent pas nécessairement à une stratégie d’évolution vers le cloud. Pour diverses raisons, certains types de service ont vocation à rester à demeure (par exemple les contrôles d’authentification d’accès au réseau, ou la conservation de catégories de données non éligibles à la sortie d’un périmètre géographique précis).

Quoi qu’il en soit, de plus en plus de solutions s’exportent aujourd’hui vers les nuages, partiellement ou dans leur intégralité. De multiples raisons expliquent cette évolution : les capacités en termes de scalabilité ou d’automatisation qu’offre le cloud au regard des limitations de systèmes d’information plus classiques, la mise à disposition de nouveaux types de service apportant clé en main de nouvelles facilités dans de nombreux domaines (y compris ceux liés à la gestion d’identité qui peuvent aujourd’hui tirer parti de l’utilisation de services de IdaaS Identity as a service).

Dans une perspective DevOps, cette évolution vers le cloud se traduit par une transformation significative des équipes de gestion opérationnelle qui se voient ainsi dotées d’un périmètre de responsabilité plus étendu. Concrètement, cette mission suppose l’acquisition de nouvelles compétences portant sur un univers extrêmement riche et requiert la définition des nouveaux processus à destination de l’ensemble des acteurs du système d’information. L’équipe de gestion opérationnelle doit alors assurer le provisioning des plates-formes cloud, la configuration des systèmes, le déploiement des composants applicatifs, la supervision et la maintenance de l’ensemble de l’infrastructure.

Que l’infrastructure d’une application soit déployée à demeure ou dans le cloud, la première étape de sa mise à disposition par les opérations est le provisioning des ressources associées (machines, réseau, stockage). L’administrateur système DevOps aura à cœur d’automatiser les actions correspondantes en offrant la possibilité de déléguer cette capacité à d’autres acteurs du système d’information, en fonction du contexte, tout en la contrôlant. Cette démarche requiert l’utilisation de multiples outils et leur intégration en fonction des environnements dans lesquels ils seront employés.

L’infrastructure physique

Dans bien des situations, l’administrateur système DevOps est encore responsable des choix d’infrastructure matérielle liée au provisioning des environnements sur lesquels vont être déployées les applications. Il lui faut alors décider du constructeur et de la solution entièrement packagée (stockage, serveurs, réseaux) ou suffisamment évolutive pour permettre une mise en œuvre rapide et homogène, en prenant en compte différents critères tels que le prix, les performances, la densité électrique, les flux de climatisation, la duplication des éléments réseaux, la mutualisation de la connectique…

Il doit avoir des compétences étendues sur la configuration matérielle, maîtriser les multiples technologies liées au stockage (SAS, SATA, ISCSI, Fiber Channel…), avoir connaissance des limitations de compatibilité des composants matériels (firmware, drivers…). Il doit avoir de bonnes compétences en réseaux, être capable de définir le nombre d’interfaces physiques des différents réseaux d’un cluster (teaming, multi- VLANS…).

Virtualisation

Suivant la taille de l’entreprise et son historique en termes d’adoption de système de virtualisation, l’administrateur système DevOps doit maîtriser l’utilisation de multiples hyperviseurs. Les hyperviseurs de type 1 (Citrix XenServer, VMWare ESX, ou Microsoft Hyper-V) ou leur équivalent chez les fournisseurs de service cloud offrent des fonctions relativement comparables. Dans la plupart de ces solutions, l’hyperviseur permet l’exécution de la machine virtuelle et sa reconfiguration dynamique en termes de CPU, RAM, ou capacité de stockage.

Avec la virtualisation, le réseau physique peut être partagé entre plusieurs réseaux virtuels isolés les uns des autres avec l’illusion qu’ils sont chacun seul sur ce réseau physique. Les serveurs et les ressources de ces réseaux virtuels (adresses IP, routes…) fonctionnent comme s’ils étaient directement reliés à un réseau physique. Ce type de solution permet de déplacer des VM dans le réseau physique sans avoir à reconfigurer l’adresse IP pour la virtualisation des réseaux ou des VLAN. La virtualisation des adresses IP est réalisée via des mécanismes comme (IP Rewrite) ou des protocoles spécifiques à l’hyperviseur (NV- GRE pour Hyper-V, VXLAN pour VMware).

Virtualisation par container

À la virtualisation des machines, du réseau et du stockage s’ajoute un autre sujet auquel les équipes des opérations doivent aujourd’hui s’intéresser : la virtualisation par container. Cet autre mode de virtualisation, présente des similitudes avec les précédents, notamment pour sa capacité à donner accès à un système d’exploitation à travers le réseau.

La plupart des systèmes d’exploitation offrent des mécanismes de virtualisation : sur UNnix, on parlera des zones Solaris, des jails FreeBSD, ou plus prosaïquement de chroot. Il s’agit d’une opération permettant de modifier le répertoire racine pour un processus système et les sous-processus, ce qui l’empêche d’avoir une visibilité sur d’autres parties du système de fichiers. De même, sur Linux, LXC est un mécanisme qui exploite la fonction cgroup de limitation des ressources (CPU, mémoire, réseau…) complétée par une séparation par espace de nommage ce qui, au final, permet l’isolation complète d’une application. Enfin, Windows Server 2016 propose deux types de containers, les containers Windows qui partagent le même système d’exploitation et les containers Hyper-V plus cloisonnés.

Le processus qui s’exécute au sein d’un container est isolé des autres applications dans un espace de noms virtualisé depuis lequel il accède à un certain nombre de ressources (services, fichiers, réseau) avec l’illusion d’être le seul processus à s’exécuter sur la machine. Ce mécanisme permet de réduire la complexité et la variabilité en favorisant le partage et la réutilisation du container ou de son image, par les développeurs ou par les équipes de gestion opérationnelle. Le partage des ressources entre les containers permet également d’optimiser la consommation des ressources et d’accélérer leur déploiement et leur lancement.

Fig. 4.3  Machine virtuelle et container

Aujourd'hui la virtualisation par les containers suscite un intérêt renouvelé grâce à la solution open source Docker qui propose un framework facilitant leur création et leur distribution. Docker permet de déployer des applications de façon très efficace en offrant des caractéristiques d’isolement similaires à celles d’applications s’exécutant dans des machines virtuelles. Nous reviendrons sur Docker à la fin de cet ouvrage.

Dans une société qui a fait le choix du cloud, qu’il s’agisse d’un cloud public ou d’un cloud privé, il s’agit déjà pour l’administrateur système DevOps de définir les règles qui permettront aux utilisateurs de provisionner les environnements dont ils ont besoin, à partir du portail nativement inclus dans la solution cloud. Dans certains cas, la mise à disposition de ce portail (voire d’extensions de ce portail) ne sera pas suffisante. Il faudra alors envisager le développement de capacités spécifiques qui viendront enrichir le système d’information. Automatiser le provisioning d’une machine dépend directement du type d’environnement ciblé.

Provisioning bare metal

Le provisioning bare metal consiste dans l’installation d’un OS (ou d’un hyperviseur Type 1 directement sur le matériel cible. L’opération peut être réalisé à distance en communicant le contrôleur BMC (Baseboard Management Controller) du serveur cible avec les protocoles IPMI or SMASH. En général ce type de provisioning est proposé à travers les interfaces utilisateurs des solutions de virtualisation.

Provisioning d’environnement virtualisé à demeure

L’automatisation du provisioning d’une machine virtuelle dépend de multiples facteurs. Le développement est fondé sur l’API exposée par l’hyperviseur. Par exemple, supposons qu’il soit nécessaire de provisionner une dizaine de machines virtuelles sur la base d’une image de référence et de les intégrer dans un cluster. Le code suivant présente la syntaxe liée à l’automatisation de ce type de tâche pour un hyperviseur comme hyper-V.

$vhdpath = “C:ClusterStorageVolumeVHD”
$vmnetworkName = “ExternalNetwork”
$memorySize = 4GB
$VmtoCreate = 10
$DiskSize = 100GB
$HypervHost = “hyperviseur” 1..$VmtoCreate | % {
New-VHD -Path $vhdpath”VM00$_.VHDX” -ParentPath $vhdpath”BASE2012.VHDX” -Differencing -SizeBytes
$DiskSize -ComputerName $HypervHost
New-VM -Name VM00$_ -VHDPath $vhdpath”VM00$_.VHDX” -Memory $memorySize -SwitchName
$vmnetworkName -ComputerName $HypervHost Start-VM VM00$_ -ComputerName $HypervHost
Add-ClusterVirtualMachineRole -VirtualMachine VM00$_ -Name VM00$_ -Cluster $ClusterName
}

Sur d’autres hyperviseurs, dans d’autres systèmes d’exploitation, les approches seraient similaires, mais le code serait différent. En effet, quoiqu’elles ciblent le même objectif, les interfaces de programmation exposées par les hyperviseurs KVM (Kernel-based Virtual Machine), ESX, XenServer ou Hyper-V ne correspondent pas à une norme. Dans le cloud privé, l’initiative open source OpenStack tente de proposer un modèle d’unification de ces API. Même si l’idée suscite l’intérêt d’importants acteurs du marché, il reste du chemin à parcourir avant d’unifier le modèle de programmation des environnements virtualisés.

Provisioning d’environnement virtualisé dans le cloud

Il n’y a pas plus d’homogénéité dans le cloud public. En effet, il faut s’adapter aux API de provisioning proposées sur les plates-formes AWS, Google ou Microsoft Azure, pour n’en citer que trois… À défaut d’être identiques, les API de provisioning sont disponibles sur l’ensemble des systèmes d’exploitation (comme par exemple azure-cli sous Unix ou Mac). De ce point de vue, le cas de PowerShell est intéressant car son extensibilité lui permet d’intégrer des commandes qui permettent de manipuler directement des ressources cloud indépendamment du fournisseur de service cloud. Comme on pouvait s’y attendre, ce type d’usage est possible dans le cloud Microsoft avec Azure PowerShell 1.0 (ainsi que dans Azure Automation, une autre facilité à destination des administrateurs système DevOps tournés vers le cloud). Par exemple, sur Microsoft Azure, une opération similaire à l’exemple de provisioning précédent pourrait être réalisée avec le script suivant.

$sqlVms = @()

for($i=1; $i -le 10; $i++)
{
Write-Host “Creating $sqlVMPrefix${i}”
$adminPort = $sqlAdminPort + $i

#create a new VM Config
$newSqlVM = `New-AzureVMConfig -ImageName $WindowsAndSqlServerImageName -InstanceSize $sqlInstanceSize -Name “$sqlVMPrefix$i” `
-AvailabilitySetName $sqlAvailabilitySet -DiskLabel “$sqlVMPrefix${i}os” `
-HostCaching $hostCaching -Label “$sqlVMPrefix${i}” |
Add-AzureProvisioningConfig -WindowsDomain -AdminUsername $adminUsername -Password
$adminPassword `-Domain $domainName -DomainUserName $adminUsername -DomainPassword $adminPassword -JoinDomain $domainName ` -NoRDPEndpoint |
Add-AzureDataDisk -CreateNew -DiskSizeInGB 50 -LUN 0 -DiskLabel “$sqlVMPrefix${i}data1” | Add-AzureEndpoint -LocalPort 3389 -Name “RDP” -Protocol tcp -PublicPort $adminPort |
Set-AzureSubnet  $sqlBackendSubnet
#add the VM config to the collection
$sqlVms += ,$newSqlVM
}

#show the collection
$sqlVms | format-table

#Create the New cloud Service
New-AzureService -ServiceName $sqlServiceName -Location $location

Mais cette ouverture de PowerShell au cloud ne se limite pas à Microsoft Azure : ainsi, les PowerShell AWS Tools permettent également aux développeurs et administrateurs de gérer la plupart des services AWS avec un script PowerShell.

Quoi qu’il en soit, à défaut de disposer d’API identiques, les principes d’invocation de ces multiples API sont relativement similaires. L’essentiel pour l’administrateur système DevOps est de pouvoir être en mesure de scripter et d’automatiser des tâches répétitives de provisioning.

Provisioning de container

Le provisioning de containers Docker requiert la mise à disposition d’un serveur hôte exécutant le moteur Docker sur un server Linux ou Windows Server 2016. Prenons l’exemple d’une machine virtuelle Docker Host Linux hébergée sur Azure. Il existe de multiples façons d’automatiser son provisioning, comme Docker Machine… Cet outil permet de facilement créer des hosts Docker (à demeure ou dans le cloud) et de configurer le client Docker pour qu’il puisse communiquer avec ces serveurs (il génère notamment les certificats et partage les clés assurant la sécurité des échanges).

docker-machine -D create -d azure \
--azure-subscription-id=”<souscription-id>”  \
--azure-docker-port=“2376” \
--azure-publish-settings-file=”<souscription.publishsettingsfile>”   \
--azure-location=“West Europe” \
--azure-password=”<password>”  \
--azure-size=“Small” \
--azure-ssh-port=“22” \
--azure-username=”<username>”  \
<nom de la machine docker host>

L’administrateur DevOps peut ensuite vérifier si le serveur Docker est opérationnel et si la connectivité est effective. De la même façon, il aurait pu provisionner automatiquement un cluster swarm composé de multiples serveurs Docker.

docker info

Containers: 14
 Running: 3
 Paused: 1
 Stopped: 10
Images: 52
Server Version: 1.10.3
Storage Driver: devicemapper
 Pool Name: docker-202:2-25583803-pool
 Pool Blocksize: 65.54 kB
 Base Device Size: 10.74 GB
 Backing Filesystem: xfs
 Data file: /dev/loop0
 Metadata file: /dev/loop1
 Data Space Used: 1.68 GB
 Data Space Total: 107.4 GB

Il est alors possible de rechercher des images dans un dépôt public ou privé, d’en construire de nouvelles et de déployer des containers avec la commande docker run.

Une fois l’environnement déployé, que ce soit à demeure ou dans le cloud, il s’agit maintenant pour l’administrateur DevOps d’automatiser la configuration des différentes ressources liées à la machine cible (système, réseau, management…), d’un point de vue système et applicatif, que ce soit à demeure ou dans le cloud et de s’assurer que le résultat obtenu est conforme à ses objectifs. Pour ce faire de multiples outils s’offrent à lui.

Automatiser le déploiement d’une machine consiste à s’assurer qu'elle dispose de l’ensemble des pré-requis systèmes et applicatifs pour son intégration dans la solution.

Si la machine cible est une machine virtuelle et si l’on souhaite automatiser un déploiement de machines similaires, l’administrateur peut dans un premier temps configurer chacune des composantes de l’environnement cible et documenter les actions correspondantes, puis archiver la machine virtuelle de référence ainsi construite pour en faire un modèle qu'il pourra cloner autant de fois que nécessaire. Dans ce contexte, l’administrateur DevOps doit avoir établi en amont une configuration exhaustive de l’ensemble des composants pour les environnements qui auraient vocation à être répliqués. Il lui faut ensuite les archiver dans des librairies accessibles par les autres acteurs du système d’information. Cette démarche peut s’inscrire dans un scénario de mise à disposition d’environnements de développement et de tests.

Une autre approche consiste à faire en sorte que chaque nouvelle machine virtuelle démarre en se basant sur une image de base du système d’exploitation, et à la configurer par script en fonction d’un état descriptif correspondant à l’ensemble des pré-requis systèmes et applicatifs de l’application. Il devient alors extrêmement simple de répliquer la machine puisque le script de configuration est partagé et géré dans un contrôleur de code source, ce qui de plus a le mérite de documenter l’infrastructure.

Quelle que soit l’approche retenue cette automatisation permet de garantir que les environnements de développement, de test, pré-production ou de production sont identiques et conformes à l’état défini comme étant la référence (qu'il soit scripté ou conservé sous forme d’archivage de modèle de machine virtuelle). Au final, cela se traduit par une diminution du risque d’erreur liée au déploiement sur des plateformes différentes. La responsabilité de l’administrateur DevOps est alors de s’assurer que cette flexibilité se retrouve dans les moyens de mise à disposition de ces environnements que ce soit vis-à- vis de leurs homologues développeurs ou vis-à-vis des services mis en œuvre dans la chaîne de production logicielle.

L’administrateur Système DevOps doit maîtriser les différents gestionnaires de packages correspondant aux systèmes d’exploitation qu'il utilise. En développant des scripts d’interaction avec ces dépôts, il a ainsi la possibilité d’automatiser la configuration des systèmes des environnements dont il a la charge.

Apt-Get

Dans le monde Linux, les administrateurs systèmes DevOps utilisent les gestionnaires de packages tels que YUM, RPM ou APT pour différentes distributions de Linux. L’Advanced Package Tool (APT) est une solution open source qui permet de gérer l’installation et la suppression des logiciels sur de multiples distributions Linux en automatisant la récupération, la configuration et l’installation de logiciels.

L’installation d’un package se fait par une simple commande apt-get sur le nom du package et permet d’obtenir également tous les packages dont dépend le package cible (avec un système de résolution des conflits). L’administrateur système DevOps peut spécifier le chemin d’accès du dépôt apt-get, dans un fichier de configuration, ce qui lui permet également de définir un dépôt privé. Il peut aussi forcer APT à choisir une version spécifique de package (/etc/apt/preferences). La liste des mises à jour peut être téléchargée à l’aide de la commande apt-get update. L’installation correspondante est déclenchée via un apt-get upgrade.

Ces commandes bien connues des administrateurs Linux, car ils les mettent en œuvre régulièrement. Leur usage dans une perspective DevOps peut être étendu par de l’automatisation. Par exemple, un administrateur système DevOps peut décider d’automatiser le téléchargement des mises à jour et faire en sorte d’en être notifié tout en se réservant le droit de décider ou non de leur installation. Pour ce faire, il lui suffit d’installer cron-apt (avec un apt-get install cron-apt), de configurer le fichier /etc/cron-apt/config avec les lignes MAILON=“upgrade” et MAILTO= pour y renseigner son adresse, et de copier le script cron dans le répertoire /etc/cron-apt/action.d/ afin qu'il puisse être périodiquement exécuté.

Chocolatey

Ce type de solution est beaucoup plus récent dans l’histoire de Windows. Le référentiel communautaire Chocolatey est un gestionnaire de packages pour Windows. Il recense aujourd'hui plus de 2930 logiciels uniques. Le fonctionnement de ce dépôt est similaire à ce que propose Apt-Get. Nous l’illustrerons dans son emploi avec PackageManagement, une technologie incluse dans Windows et présentée ci-dessous.

PackageManagement

Dans le monde Windows, il existe de nombreuses technologies d’installations comme par exemple MSI, MSU, APPX… pour ne citer que certaines de celles proposées par Microsoft. L’administrateur DevOps est donc confronté à une difficulté supplémentaire, lorsqu’il souhaite automatiser le déploiement de multiples logiciels. Pour répondre à cette problématique, Windows a récemment intégré un nouveau composant baptisé PackageManagement (initialement appelé OneGet). Il s’agit d’une technologie dont l’objectif est de simplifier la découverte et l’installation de logiciel sur les machines Windows. PackageManagement unifie la gestion de multiples gestionnaires de package via une interface extensible. Il permet de gérer une liste de dépôts de logiciels dans lequel les packages logiciels peuvent être recherchés, acquis puis installés (ou désinstallés) silencieusement à partir d’un ou plusieurs référentiels.

PackageManagement inclut nativement de mulitples providers : Bootstrap (celui qui sait où se procurer d’autre providers), Nuget, MSI, MSU (pour gérer les fichiers de mise à jour de Microsoft), ajout/suppression de programmes et PowerShellGet (pour accéder aux modules PowerShell). Chacun des providers de PackageManagement donne accès à un ou plusieurs référentiels. Ces dépôts peuvent être publics ou privés, accessibles par internet ou uniquement en Intranet. Grâce à l’extensibilité qu'offre le modèle de PackageManagement, il est possible d’ajouter de nouveaux providers, comme Chocolatey.

Le provider vient alors s’ajouter à la liste de l’ensemble des gestionnaires de package (que l’on peut inventorier avec la commande Get-PackageProvider). On peut alors rechercher tout applicatif présent sur le dépôt cible dès lors que l’on connaît son nom, avec la commande Find-Package -Provider chocolatey armclient. Dans cet exemple, le package recherché est armclient, un outil qui permet d’invoquer très simplement l’API Azure Resource Manager, une solution sur laquelle nous reviendrons un peu plus loin dans ce chapitre. Il ne reste plus alors qu'à l’installer, avec la commande Install-Package armclient.

Et bien entendu, ces opérations peuvent être assemblées dans un script afin d’automatiser un processus d’installation. Mais pour ce faire, il faut d’abord décider du choix du langage de script.

Qu'ils ciblent Windows ou Linux, les interpréteurs en ligne de commande font partis des outils incontournables pour l’administrateur système DevOps. Il s’agit pour ce dernier de disposer de commandes qui lui permettent d’interagir avec le système d’exploitation. Il lui faut également pouvoir s’assurer de leur bon fonctionnement par une validation de la syntaxe de l’appel. L’administrateur système a la possibilité de regrouper ces commandes dans un fichier script pour pouvoir les séquencer dans un appel automatisé. Ces scripts peuvent être exécutés manuellement par l’utilisateur ou automatiquement par le système. La plupart des systèmes d’exploitation disposent donc d’un langage de programmation niveau systèmes conçu pour faciliter l'automatisation opérationnelle.

Les langages de script sous Linux

Les systèmes Unix et Linux proposent de multiples interpréteurs en ligne de commande de type script dérivés du Bourne Shell (sh), comme le Korn Shell ou le Bash (Bourne-Again shell) qui intègrent plusieurs optimisations issues du C Shell. Bash est le shell par défaut sur de nombreux Unix open source notamment sur les systèmes GNU/Linux (ainsi que sur Mac OS X, et Cygwin l’un des sous-systèmes Unix de Windows). Bash permet d’ordonnancer l'appel de multiples scripts en offrant la possibilité de rediriger la sortie d’un script vers l’entrée d’un autre script (via la notion de pipe).

À ces interpréteurs s’ajoutent des langages plus puissants comme Perl ou Python, s’inspirant du C, mais avec un mode d’exécution interprété. Quoiqu’ils puissent être utilisés à d’autres fins que dans le cadre d’une démarche infrastructure as code, ils sont très fréquemment utilisés dans ce contexte. Perl (Practical Extraction and Report Language) supporte nativement l’utilisation d’expressions régulières ce qui le prédispose aux traitements de séquences de texte dans les environnements Unix, Linux ou Windows.

Les langages de script sous Windows

Pendant de nombreuses années l'administrateur système Windows a dû se contenter de langages batch permettant d'exécuter différents types de commande (système de fichier, réseau…). L'une de ses valeurs ajoutées était alors plus liée à sa capacité à connaître les subtilités techniques de chacune des versions des systèmes d'exploitation qu'il gérait. Par exemple, d'une version à l'autre de Windows, il y a parfois des changements sur la configuration réseau avec l'activation de certains paramètres qui peuvent influencer (dans un sens ou dans l'autre) les performances réseau (Receive Side Scaling, TCP Chimney Offloading, NetDMA…). Il faut donc connaître la localisation de ces paramètres en base de registre, dans notre exemple (HKEY_LOCAL_MACHINE\SYSTEM\ CurrentControlSet\Services\Tcpip\Parameters) et les commandes pour modifier ces paramètres, comme netsh int tcp set global chimney=disabled. Fort de ce type expertise, l'administrateur système Windows pouvait jouer un rôle déterminant pour configurer les systèmes au mieux de leur capacité, mais était moins susceptible d'automatiser des tâches complexes sur les environnements dont il avait la charge.

Cette situation a radicalement changé avec l’arrivée de PowerShell, un langage de script développé par Microsoft à partir de la version Windows 7, avec comme objectif de

remplacer les langages batch en s’alignant sur les shells Unix ou Linux. Toutefois, PowerShell se distingue en proposant un développement orienté objet plutôt qu’un modèle d’échange fondé sur un flux d’octets entre l’entrée et la sortie d’un composant. De plus, PowerShell est extensible et permet de manipuler en lignes de commande les classes implémentées dans les bibliothèques du framework Microsoft .NET.

Avec cette évolution, l’administrateur système Windows devient lui aussi éligible à la mise en œuvre de certaines des bonnes pratiques DevOps. Il peut utiliser des outils comparables à ceux du développeur. Par exemple, en plus des lignes de commande, PowerShell propose un environnement graphique d’édition de scripts avec debugger intégré, le Windows PowerShell ISE (Integrated Scripting Environment). Il peut archiver ses scripts dans un référentiel de code et les partager avec les autres acteurs du système d’information.

Un script PowerShell (ou un shell Linux) peut être utilisé pour installer un environnement dédié à la configuration.

L’approche programmatique fondée sur l'utilisation de scripts peut être complétée par une approche déclarative pour configurer l’environnement cible en fonction d’une description enregistrée de l’état souhaité d’un ensemble des caractéristiques logicielles. Le langage déclaratif correspondant est implémenté comme un DSL (Domain Specific Langage) décrivant des relations de dépendances entre ressources. De multiples solutions open source de gestion de configuration s’appuient sur ce type de modèle.

Des capacités similaires et des différences

Elles permettent toutes de modéliser et de déployer la configuration d’un ensemble de systèmes, physiques ou virtuels, sur des clouds publics ou privés, sur des systèmes d'exploitation Linux ou Windows. Une de leurs caractéristiques les plus intéressantes est leur idempotence : le mécanisme de configuration a le même effet lorsqu'on l’applique une ou plusieurs fois (ce qu'un simple script ne permettait pas). Leurs différences sont principalement liées à la topologie du modèle d’architecture proposé (serveur central comme le proposent Chef ou Puppet ou pilotage en direct par une solution comme Ansible), à la syntaxe du DSL (approche déclarative ou programmatique), à l’affinité de la solution avec tel ou tel langage ou système d’exploitation et au vocabulaire décrivant les éléments constitutifs de la solution de configuration.

L’administrateur DevOps n’aura pas à les connaître toutes, mais très souvent il procédera à une évaluation de la solution la plus appropriée dans son contexte. Parfois, il sera amené à combiner certaines de ces technologies, comme par exemple : Salt avec DSC.

Puppet

Puppet est fondé selon un modèle client/serveur dans lequel l'agent node installée sur la machine déployée communique périodiquement avec le Puppet Master afin d’obtenir les configurations associées au module correspondant la définition de l'état souhaité. Une fois obtenues ces informations, il suffit alors à l’agent de les appliquer : elles sont fournies sous la forme d'une série d'instructions permettant de configurer le système. Une fois les modifications apportées, l'agent les signale au serveur.

Le code de Puppet est déclaratif. Par exemple si l’on considère le code impératif suivant :

if [0 -ne $(getent passwd stephgou /dev/null)$? ] 
then
  useradd stephgou -gid sysadmin -n
fi

GID=`getent passwd stephgou | awk -F: {'print $4]'` GROUP=`getent group $GID | awk 'F: {'print $1]'`
if [ "$GROUP" != "$GID" ] && ["$GROUP" != "sysadmin" ] 
then
  usermod -gid $GROUP $USER
fi

Le code déclaratif proposé avec Puppet est bien plus concis :

user {'stephgou': 
    ensure => 'present', 
    gid    =>'sysadmin',
}

Chef

Chef opère également en mode client/serveur. La configuration d’un environnement, baptisée recipe, est créée avec le client Chef. Elle résulte de la combinaison d’une série de policies implémentées avec le langage Ruby. Les recipes et autres ressources sont rassemblées dans un package, le Cookbook. Une fois, construit, ce package est centralisé sur le serveur Chef afin d’être déployé sur les machines Nodes liées au même environnement (développement, test, pré-production, production).

Les Nodes exécutent les instructions du package dans le cadre des policies qui ont été définies et vont régulièrement interroger le serveur afin de savoir si des modifications sont à apporter sur la cible.

Fig. 4.8 Composants de la solution de gestion de configuration Chef

Ansible

Ansible est un système complètement décentralisé : c’est la machine sur laquelle Ansible s’exécute qui pilote directement les systèmes distants via le protocole SSH. Il s’appuie sur l’inventaire des machines cibles pour déployer en parallèle ou non les configurations. Les configurations correspondent à des séries d’actions, les recipes que l’on peut regrouper dans un playbook en mode impératif, décrit en YAML. Ces actions peuvent être déclenchées en mode push ou en mode pull (avec la commande ansible-pull). *

Ansible est développé en Python mais peut être étendu avec des modules implémentés sur d’autres langages (Ruby…) disponibles sur la poste de contrôle des déploiements…

La société qui fournit cette solution vient récemment d’être rachetée par Red Hat.

Salt

Salt est un système distribué qui permet d’exécuter depuis le master des commandes impératives ou déclaratives sur des nœuds distants (les minions), individuellement ou selon divers critères de sélection. Les étapes de construction de l’environnement cible sont orchestrées autour d’un bus de communication.

Dans un contexte infrastructure as code, l’administrateur DevOps est confronté aux mêmes problématiques que le développeur. Il doit par exemple pouvoir debugger ses scripts d’automatisation, en les instrumentant, ou lorsque la technologie le permet, en les debuggant. Ainsi, PowerShell offre nativement la possibilité d’être exécuté, en pas à pas, avec une vue sur la pile des appels, les points d'arrêt, les sorties d'erreur. De plus, il peut être étendu avec des modules, comme par exemple DebugPx qui fournit un ensemble de commandes s'appliquant aux scripts et aux modules PowerShell en exploitant et en étendant ces fonctions natives de debugging.

La solution open source Pester, permet d'aller un cran plus loin dans l'application de pratiques issues du monde du développement à l'infrastructure, en offrant à l'administrateur DevOps la possibilité de pratiquer une approche TDD (Test Driven Development : un sujet sur lequel nous reviendrons dans le chapitre 5 lié à la qualité). Pour ce faire, Pester fournit un framework d'exécution de tests unitaires pour exécuter et valider le résultat de l'exécution de commandes ou de modules PowerShell. Il associe de multiples fonctions à une convention de nommage qui lui permet d’avoir connaissance des éléments à tester.

Une fois installé Pester (par exemple via la solution de PackageManagement déjà évoquée avec un Install-Package depuis un provider nuget.org ou Chocolatey), il suffit de lancer la commande New-Fixture pour créer un répertoire incluant deux fichiers, un pour le code qui sera la cible des tests et un fichier pour exécuter ces tests. Ce deuxième fichier, judicieusement suffixé par .Tests, intègre en en-tête trois lignes lui permettant de très simplement établir la liaison avec le premier fichier et destiné à valider la ou les fonctions qui y sont définies. Il implémente ensuite dans un bloc Describe différentes assertions (un terme bien connu des testeurs et des développeurs) qui comparent les valeurs en entrée avec celles qui sont attendues. Il ne reste plus qu'à lancer la commande Invoke-Pester pour exécuter l'ensemble des tests contenus dans le répertoire courant et ses sous-répertoires, et vérifier, en fonction du résultat de l’évaluation de chaque assertion, si le test s'est achevé avec succès ou pas.

Une des difficultés du test d'infrastructure est liée au fait que l’administrateur DevOps interagit avec des ressources dont l'état varie. Par exemple, un fichier peut être déplacé, verrouillé… Pester offre un niveau d'abstraction à partir de fonctions comme Mock donnant notamment la possibilité de les remplacer avec une autre implémentation ou TestDrive, un répertoire qui n'a d'existence que dans le contexte du Describe. Naturellement, l'administrateur DevOps aura tout intérêt à combiner l'usage de cette approche avec d'autres mécanismes déjà évoqués. Le script suivant illustre cette approche pour valider la compilation des ressources DSC associées à la configuration d’un environnement.

{

# Install the IIS role WindowsFeature IIS
{
Ensure  = “Present”
Name    = “Web-Server”
}

# Install the ASP .NET 4.5 role WindowsFeature AspNet45
{
Ensure  = “Present”
Name    = “Web-Asp-Net45”
}
# Stop the default website xWebsite DefaultSite
{
Ensure  = “Present”
Name    = “Default Web Site”
State   = “Stopped”
PhysicalPath  = “C:\inetpub\wwwroot” DependsOn = “[WindowsFeature]IIS”
}

# Copy the website content File WebContent
{
Ensure       = “Present”
SourcePath   =  “C:\users\stephgou\DevOpsWebsite” DestinationPath = “C:\inetpub\DevOps”
Recurse      = $true
Type         = “Directory”
DependsOn    =  “[WindowsFeature]AspNet45”
}

# Create a new website xWebsite DevOpsWebSite
{
Ensure  = “Present”
Name    = “DevOps”
State   = “Started”

Enfin, Pester peut directement être intégré dans les scripts de compilation d’un système d’intégration continue et de release management.

Tous les mécanismes que nous venons de voir s’appliquent également dans le contexte d’une virtualisation par container. En associant ce type d’approche avec l’utilisation d’une solution comme Docker, les différentes étapes de provisioning et configuration deviennent alors encore plus simples à automatiser ce qui facilite les mises à jour et la maintenance. Les équipes de gestion opérationnelle peuvent alors standardiser les environnements pour les équipes de développement, de qualité et de production indépendamment de l’infrastructure sous-jacente.

Les offres de services d’infrastructure cloud permettent de créer à la demande des machines virtuelles Windows ou Linux, à partir de modèles de machines proposés par le fournisseur ou son écosystème, depuis le portail ou un langage de script. Une fois ces machines virtuelles déployées dans le DataCenter cible, il est fréquent de souhaiter compléter leur installation par une configuration complémentaire.

Extension de machines virtuelles

Le fournisseur d’offre cloud propose souvent des mécanismes d’extensibilité permettant de simplifier les diverses opérations de gestion de VM en fonction du système d’exploitation et pouvant être ajoutées, mises à jour ou retirées tout au long de son cycle de vie. En général, ces mécanismes sont également ouverts aux technologies open source de gestion de configuration reconnues par le marché, comme celles que nous avons précédemment évoquées. Ainsi, les machines virtuelles provisionnées dans le cloud peuvent disposer d’un agent de type Chef, Puppet, DSC… dès la phase de provisioning.

Dans le cas d’Azure, un VM agent propose ce type de mécanisme via la notion de VM Extension que l’on peut ajouter manuellement ou par un script. L’administrateur DevOps peut alors associer l’utilisation d’un script de création de machine virtuelle, avec une configuration déclarative, implémentée par exemple avec DSC comme l’illustre l’exemple suivant :

#

# Publish the DSC configuration to Azure
#
Publish-AzureVMDSCConfiguration -ConfigurationPath $resolvePath -StorageContext $storageContext - ContainerName $dscContainerName -Force

#
# Create the VM configuration to use
#
$vmConfig = New-AzureVMConfig -Name $vmName -InstanceSize Small -ImageName $vmImage
$vmConfig = Add-AzureProvisioningConfig -VM $vmConfig -Windows `
-Password $password `
-AdminUsername $userName
#
# Setup the DSC extension
#
$vmConfig = Set-AzureVMDSCExtension -VM $vmConfig -ConfigurationArchive “$configScript.zip” `
-ConfigurationName $dscConfigurationName -ContainerName $dscContainerName

# Add 80 endpoint
$vmConfig = Add-AzureEndpoint -VM $vmConfig -Name “HTTP” -Protocol tcp -LocalPort 80 -PublicPort 80

# Finally create a new VM with the above configuration
New-AzureVM -Location “West Europe” -ServiceName $serviceName -VM $vmConfig -WaitForBoot

# You can use the Azure management portal to examine the VM creation process
# or retrieve the VM object as follows:
$myVM = Get-AzureVM -ServiceName $serviceName -Name $vmName

$status = $myVM | Get-AzureVMDscExtensionStatus

$status

$status.DscConfigurationLog

Ces mécanismes d’extensibilité ne sont pas propres à Microsoft Azure. On les retrouve sur d’autres solutions cloud.

Configuration d’applications composée

Les solutions techniques que nous avons vues jusqu'à présent offrent une forte capacité d’automatisation, mais la gestion des ressources associées (base de données, machine virtuelle, compte de stockage, site web…) reste unitaire. C'est donc à l’administrateur DevOps d'implémenter les scripts permettant d'agréger l'ensemble de ces opérations.

Toutefois, la gestion d’une application composée de plusieurs ressources reste complexe lorsqu'il s'agit de gérer les permissions ou la supervision technique à l'échelle d'un groupe de ressources. C'est pourquoi les fournisseurs de service cloud proposent des mécanismes permettant de créer et gérer des groupes dans lesquels sont intégrés des regroupements de multiples ressources de même type ou non. Dans ce contexte, un groupe de ressources est un conteneur logique destiné à faciliter la gestion du cycle de vie d'un regroupement de multiples ressources, comme dans le cas d'une application construite autour de sites web, de multiples serveurs applicatifs et bases de données.

La solution proposée pour le déploiement et la configuration d'un groupe de ressources est déclarative afin de faciliter la configuration des ressources, de leurs dépendances, de leurs interconnexions, de la gestion d'identité entre ces ressources, et, le cas échéant, de leur facturation. Elle se fonde sur l'utilisation de modèles.

Par exemple, l'offre cloud AWS, propose tout une série de modèles AWS Cloud Formation que l'administrateur DevOps peut bien entendu étendre, avec pour objectif de garantir l'idempotence, simplifier l'orchestration, la gestion du cycle déploiement, ou le retour sur une version antérieure.

Avec Azure Resource Manager, Microsoft propose une démarche très similaire. Comme dans le cas d’AWS, ces templates sont implémentés en JSON et peuvent donc être gérés dans un contrôleur de code source.

L’administrateur système DevOps a également pour objectif d’optimiser les ressources dont il dispose, qu’elles soient à demeure ou dans le cloud.

C’est la dimension Lean de DevOps.

Avant de pouvoir optimiser les ressources, il faut déjà disposer des moyens pour les gérer efficacement et de préférence de façon unifiée, en termes d’outils et d’API. Du côté des solutions commerciales, Microsoft propose une offre baptisée AzureStack qui unifie les services et les API entre cloud privé et cloud public, mais cette unification ne s’étend pas aux offres concurrentes. Côté open source, à l’initiative OpenStack vient s’ajouter la solution Apache Cloud Stack, sans toutefois offrir de compatibilité avec la précédente.

Un premier niveau d’optimisation des ressources peut être assuré par l’automatisation des environnements. Ainsi, dans la plupart des cas, une plate-forme de développement, d’intégration, ou de QA n’a pas vocation à fonctionner 24 heures sur 24. L’administrateur DevOps a donc tout intérêt à définir des plannings de libération de ressources, en particulier si ces ressources sont facturées à la consommation par un fournisseur de service cloud. Et bien entendu, le provisioning/deprovisioning de ces ressources doit être automatisé, ce qui requiert l’utilisation de l’ensemble des technologies que nous avons précédemment évoquées.

Les infrastructures sont soumises à des sollicitations variables, ce qui au-delà des plages de fonctionnement/arrêt, suppose la planification de périodes durant lesquelles davantage d’instances de machines virtuelles devront être démarrées et inversement. Parfois, cette approche par anticipation de la consommation ne suffit pas et il faut mettre en place des moyens techniques permettant d’adapter la puissance de traitement au volume et au nombre des requêtes qui sont soumises sur la plate-forme cible.

Il faut alors disposer de moyens permettant de calibrer l’infrastructure dynamiquement en fonction de la charge à laquelle elle est soumise. Les offres des grands acteurs du cloud public (Google App Engine, AWS, Microsoft Azure) proposent des mécanismes d’autoscaling, a minima sur la partie compute (machine virtuelle, site web…).

Le principe consiste généralement à augmenter le nombre d’instances, en fonction de la charge CPU moyenne sur une période considérée et à diminuer ces instances en prenant en compte une période d’observation plus longue. Ainsi, seule la durée effective de fonctionnement des instances est facturée tout en offrant les meilleurs temps de réponse possibles aux utilisateurs de l’application. Ce type de mécanismes d’autoscaling s’étend maintenant à d’autres types de services comme par exemple les services de base de données avec Azure Database Pools.

Fig. 4.15 Configuration manuelle de l’autoscaling d’une Web App

Ces mécanismes d’autoscaling sont également programmables via API comme nous avons pu le voir précédemment avec le template AWS. L’approche déclarative proposée avec le service NetScaler de Google App Engine serait similaire.

Fig. 4.16 Configuration déclarative de l’AutoScaler de Google App Engine

Comme nous l’avons vu dans le précédent chapitre, une partie de la responsabilité liée à la résilience du système incombe maintenant au développeur DevOps qui a ajouté à ses compétences la connaissance de patterns de gestion de la haute disponibilité de l’application (comme les patterns Retry et Circuit Breaker par exemple).

Bien entendu, l’administrateur DevOps sera lui aussi fortement impliqué dans la démarche accompagnant la conception d’une architecture dite FailSafe que nous avons décrite dans le chapitre 2. Assurer la continuité des services d’une application nécessite une analyse de ses dépendances, de ses composantes critiques et la définition d’objectifs tels que le RPO (Recovery Point Objective : perte de données maximum acceptable suite à un sinistre ou un problème majeur) ou le RTO (Recovery Time Objective : délai maximum acceptable de redémarrage de l’activité suite à un sinistre ou un problème majeur). L’objectif pour l’administrateur DevOps est donc d’intervenir dans la définition du cycle de vie de l’application en production (plan de charge), dans la définition du plan de disponibilité, et dans l’identification des différentes étapes de remédiation. L’ensemble de ces éléments s’inscrivent dans le processus qui permet de déterminer un modèle de résilience pour l’application, qui, dans un monde DevOps a vocation à être partagé entre tous les acteurs du système d’information.

Fig. 4.18 Modèle de résilience : diagramme d’interaction entre composants

À cette démarche, s’ajoutent des pratiques expérimentales qui visent à valider la capacité du système à résister à la défaillance de l’un ou l’autre de ses composants, avec l’exemple de l’introduction volontaire de défauts afin de constater la capacité du système à se remettre en service dans une perspective de garantie de la résilience du système après un dysfonctionnement. Nous reverrons plus en détail cette approche (Fault Injection Testing) dans l’étude du cas Netflix.

Enfin le clustering de services, de bases de données, la géoréplication des données, le load balancing de datacenter (comme par exemple avec Azure Traffic Manager), la migration live d’environnements virtualisés à demeure vers le cloud, sont autant de mécanismes qui participent à la mise en œuvre de solutions permettant d’assurer dans le meilleur des cas la haute disponibilité, et dans le pire, un socle suffisant pour un Plan de continuité d’activité (PCA) acceptable.

DevOps part du principe que la solution finira par rencontrer un dysfonctionnement. Il ne s’agit donc pas de s’affranchir de tout risque d’erreur, car cela reste impossible. Il s’agit de mettre en place des mécanismes permettant d’assurer la remise en fonction du système dans les plus brefs délais. Pour l’administrateur système DevOps, la première étape consiste donc à mettre en place une solution de monitoring, permettant non seulement de déclencher les alertes en cas d’indisponibilité des services, mais également d’anticiper les dysfonctionnements en détectant des franchissements de seuil…

L’ingénieur système DevOps se doit de totalement maîtriser les subtilités des systèmes d’exploitation sur lesquels s’exécuteront les applications, et en particulier d’avoir une connaissance très pointue des mécanismes de journalisation du système. Ces mécanismes peuvent être de très bas niveau. Il faut être en mesure de monitorer le maximum de métriques afin de pouvoir réagir au plus vite en cas de problème. Les métriques d’utilisation de services et de mesure de la performance des services doivent être partagées.

Linux propose nativement un mécanisme de journalisation. Ainsi, le daemon klogd lit les messages du kernel (/proc/kmsg) et les redirige vers le répertoire approprié. Cette approche peut être complétée par l’emploi de syslogd (daemon configurable au niveau utilisateur) pour rediriger ces mêmes messages dans le répertoire /var/log et définir la façon dont ils seront analysés. L’équivalent côté Windows est le mécanisme de journalisation NT Kernel Logger que l’on peut gérer avec des outils comme TraceLog ou TraceView pour activer le suivi d’évènements sur les processus, threads, réseau, I/Os disque… Toutefois, ces services de niveau système doivent être manipulés en ayant connaissance de leurs effets. Par exemple, l’utilisation de syslogd peut conduire à la dégradation des performances du système, si la configuration associée impose de très fréquentes opérations d’écriture sur de nombreux fichiers journaux.

À ces systèmes de journalisation d’évènements système s’ajoutent de nombreux mécanismes de trace de bas niveau (que ce soit pour Linux, Unix ou Windows).

Sous Unix, DTrace est l’un des frameworks d’instrumentation système de référence. Développé à l’origine pour Solaris, il est publié en open source et a été porté sur plusieurs autres systèmes de type Unix. Il s’agit d’un framework global très évolué permettant l’analyse et le suivi système ou applicatif sur les solutions temps réel en production. Il permet ainsi d’obtenir une vue globale des performances du système en cours d’exécution (processeur, mémoires, réseau, I/O disque) et peut naturellement être étendu pour tracer des informations applicatives. Le principe de DTrace consiste à définir des sondes (points d’instrumentation), et à les associer à des actions. Lorsque la condition de déclenchement (démarrage d’un processus, ouverture d’un fichier, exécution d’une ligne de code…) se manifeste, l’action associée est exécutée et les variables liées au contexte de l’appel ou allouées dans la call stack sont capturées pour faciliter une analyse a posteriori par le développeur DevOps.

Linux propose de très nombreux outils de trace intégrés au Kernel, comme ptrace, pour tracer les entrées et sorties de syscall, ftrace capable d’intercepter des évènements en utilisant un système de sonde (tracepoint, kprobes, uprobes), et qui fournit des traces d’évènements avec filtre et timing, ou perf_events pour le profiling CPU.

L’homologue de DTrace sur Linux est SystemTap. À l’origine implémenté sur Red Hat, on le retrouve depuis sur l’ensemble des distributions Linux. Bien qu’il n’offre pas nécessairement autant de possibilités que DTrace, c’est sans doute l’un des outils de trace les plus puissants sur Linux. Il supporte les sondes USDT (User-level Statically Defined Tracing) au même titre que LTTng (Linux Trace Tool Next Generation) qui lui se distingue par ses performances dans la collecte d’évènements.

LTTng est une solution de trace très efficace, surtout lorsqu’on l’associe avec des bases de données de type time series (influxdb, prometheus…) et des dashboards (comme promdash, grafana, kibana…). L’administrateur DevOps a tout intérêt à centraliser les logs des middlewares (apache, mysql, nginx, postgrrsql, php-fpm…), les logs applicatifs et les métriques système (CPU, ram, I/O, hits caches…) dans ces mêmes bases et à les superviser avec ces mêmes outils. L’ensemble de ces logs pourront ainsi être mis à disposition des différents acteurs DevOps (développeurs, opérations, business, management, clients) via des tableaux de bord dédiés.

Que ce soit sous Unix, Linux, ou Windows, la connaissance précise de ces mécanismes et leurs effets permet à l’administrateur DevOps d’échanger avec son homologue développeur pour l’inviter à instrumenter l’application en étant très proche du système. Cette collaboration est d’autant plus nécessaire qu’il n’est pas toujours très simple d’intégrer ces mécanismes dans un processus de développement traditionnel, d’où la nécessité pour l’administrateur système DevOps d’expérimenter pour parvenir à un réel de degré de maîtrise de ces solutions en fonction des systèmes d’exploitation utilisés, sur les infrastructures dont il est responsable.

Dans le cadre d’un processus de continuous delivery, la fréquence de livraison logicielle est fortement réduite, il devient encore plus important de recueillir des informations techniques en phase de tests, mais aussi en production afin de résoudre plus rapidement les problématiques opérationnelles. Il faut pouvoir capturer des données de réseau ou de performance, et établir des corrélations entre les données historiques ou en temps réel, afin d’en tirer le maximum d’informations utiles. Les données qui intéressent les équipes de gestion opérationnelle au premier chef sont celles qui sont liées à la disponibilité du service, à son dimensionnement, à la remontée d’erreurs applicatives, ainsi qu’aux performances des serveurs de l’infrastructure en termes de CPU, mémoire, réseau, I/O disque. Les outils de supervision offrent le suivi de métriques de façon chronologique (time series), et des fonctions d’alerte.

Le niveau de pertinence de ces données est tributaire de celui de l’instrumentation mise en place par le développeur et couplée avec les données nativement capturées par les systèmes. Dans ses activités liées à la supervision, l’administrateur DevOps est amené à utiliser des tableaux de bord pour la visualisation, avec des règles d’acquisition préconfigurées et des algorithmes pour faciliter le capacity planning, le suivi de l’application des mises à jour, la détection de changement ou l’audit de sécurité.

Il existe un grand nombre de logiciels qui offrent ce type de fonctions : des solutions propriétaires comme System Center Operations Manager (SCOM) et Operations Management Suite (OMS) ou open source comme Zabbix, Nagios, Check_MK, Prometheus ainsi que le triptyque issu de la combinaison de Logstash, ElasticSearch et Kibana pour assurer une lecture et une recherche efficace sur les centaines de milliers de lignes de traces log que peuvent générer les services d’une application.

À cela s’ajoute des solutions offrant des fonctions plus spécifiques comme, par exemple, les outils IPAM (IP Address Management Software) qui permettent, au sein d’une organisation, de gérer, superviser et auditer les adresses IP allouées, et d’anticiper un éventuel dépassement de capacité. Parmi elles on peut citer des solutions open source comme GestioIP, IPplan, OpenIPAM, ou des mécanismes nativement intégrés dans le système comme dans le cas de Windows Server.

De nombreuses possibilités s’offrent aujourd’hui à l’administrateur DevOps pour requêter ou étendre les solutions de monitoring avec du code.

Par exemple, l’outil open source Consul permet (par le DNS ou via HTTP) de découvrir et de configurer les services d’une infrastructure. Il offre également un mécanisme de vérification de disponibilité (utilisé pour interrompre le trafic en direction des serveurs considérés comme indisponibles).

Autre exemple, le framework open source de monitoring Shinken.io, extension Python qui permet de bâtir des plugins pour Nagios afin de pouvoir mieux superviser les systèmes cibles. La démarche est complétée par un partage de ces plugins en open source sur GitHub. De même, Microsoft propose la possibilité de bâtir des Management Packs .mpx de monitoring ou d’alerte pour venir enrichir la solution System Center Operation Manager.

En résumé

DevOps représente avant tout une transformation culturelle pour les équipes opérationnelles. DevOps suppose un changement majeur de leur rôle au sein d’une organisation dans laquelle chacun a désormais la possibilité de travailler avec plus d’autonomie, tout en garantissant la sécurité des services d’infrastructures concernés.

L’administrateur système DevOps a pour mission de rendre l’infrastructure plus agile en la dotant de capacités de provisioning d’environnements virtualisés et de leur configuration automatisée. Pour y parvenir, il doit lui aussi devenir un développeur afin de maîtriser les multiples langages lui permettant scripter les différentes opérations liées à l’automatisation, d’utiliser les solutions de packaging et les outils de contrôle du versioning de code.

À cela s’ajoute la nécessité d’optimiser la consommation des ressources, notamment en s’appuyant sur les services d’autoscaling offerts par le cloud. Enfin, l’administrateur système DevOps participe à la mise en place du suivi en continu du comportement de l’application. L’ensemble de ces éléments remettent en perspective le rôle clé de l’administrateur système DevOps dans un processus de continuous delivery et la nécessité pour lui de collaborer encore plus activement avec l’ensemble des acteurs du système d’information, en particulier les développeurs.

Ce site web utilise des cookies. En utilisant le site Web, vous acceptez le stockage de cookies sur votre ordinateur. Vous reconnaissez également que vous avez lu et compris notre politique de confidentialité. Si vous n'êtes pas d'accord, quittez le site.En savoir plus