• La culture DevOps joue le rôle de médiateur entre les deux équipes dev et ops.
L’objectif est de
transformer la tension entre les deux équipes en une collaboration saine.
• Création d’un pipeline automatisé entre les deux équipes appelées CI/CD (continuous
integration/ continious delivery (ou deployement).
• CI/CD vous aide à fournir régulièrement des applications aux clients et à valider la qualité
des logiciels en réduisant au maximum les interventions humaines.
• L'approche CI/CD :
• Vise à livrer fréquemment des applications de haute qualité.
• Automatise et surveille le processus du développement au déploiement.
• L'identification rapide des problèmes réduit les coûts de modification.
• Il existe 3 processus DevOps :
1- Intégration continue (CI) : Consiste à compiler, tester et déployer fréquemment du
code sur un environnement de développement pour détecter les régressions (bugs) tôt
dans le processus de développement.
2- Livraison continue : C’est la progression naturelle de l'Intégration Continue, implique
la construction d'une application de manière à ce qu'elle puisse être déployée en
production à tout moment. (Appliqué à chaque modification apportée par un
programmeur)
3- Déploiement continu : c’est le processus de mise en production d'une application,
exige que les processus d'Intégration Continue et de Livraison Continue aient été réalisés
avec succès
GIT
• Git est un logiciel de gestion de versions décentralisé.
Maven
• C’est un outil de construction de projets (build).
• Permettant :
• Automatisation de tâches récurrentes
• Construction, Compilation des projets
• Gestion des dépendances
• Génération des livrables
• Déploiement d'applications (mvn deploy)
Jenkins
• C’est un outil logiciel open source d’intégration continue
• À chaque modification de code d'une application dans le gestionnaire de configuration,
Jenkins se charge automatiquement de la recompiler, et de la tester
• Jenkins facilite l'intégration continue et la livraison continue dans les projets logiciels en
automatisant les parties liées à la construction, aux tests et au déploiement.
• La configuration d'un projet avec Jenkins implique la création et la configuration d'un job,
qui est le cœur du processus de build. Le processus de création d'un projet Jenkins passe par
trois étapes principales :
• Création du job : Cette étape consiste à créer un nouveau job dans Jenkins pour
représenter le projet. Le job sera responsable de l'ensemble du processus de build.
• Configuration du job : La configuration du job implique la définition des étapes
spécifiques du build, qui sont manipulées à travers des plugins. Les étapes courantes
comprennent la récupération du projet, la compilation, le lancement des tests
unitaires automatiques (JUnit), le lancement des tests de qualité (Sonar), la
préparation de la version à distribuer, etc.
• Lancement du build : Une fois que le job est correctement configuré, vous pouvez
lancer le build, ce qui déclenche l'exécution des étapes définies dans le job.
• Deux méthodes de configuration sont possibles pour mettre en place un
processus de compilation d’un projet : La méthode freestyle et
l’implémentation d’un pipeline
• La méthode freestyle : où la configuration du projet se réalise à travers un formulaire à
remplir.
• L’implémentation d’un pipeline : définit la configuration d’un projet grâce à des
scripts (basé sur Groovy). Cette méthode offre aussi les avantages de permettre de paralléliser les
étapes du projet et offre une meilleure interface pour lire les logs.
Docker
• La virtualisation : La virtualisation est une technologie permettant de créer et d’exécuter une
ou plusieurs représentations virtuelles d’un ordinateur ou de ses différentes ressources sur une
même machine physique.
• Docker est un outil qui peut empaqueter une application et ses dépendances dans un
conteneur isolé, qui pourra être exécuté sur n'importe quel serveur, c’est un outil qui permet
de créer, gérer et exécuter des conteneurs.
Avantages Inconvénients
Flexible : Même les applications les plus La portabilité des containers entre les différents
complexes peuvent être conteneurisées. systèmes d’exploitation (Windows, linux, etc..)
est très délicate.
Léger : Les conteneurs exploitent et partagent le La difficulté de gérer plusieurs conteneurs
noyau hôte, ce qui les rend beaucoup plus simultanément.
efficaces en termes de ressources système que
les machines virtuelles.
Portable : Moins de dépendances avec la Possible failles de sécurité (conteneurs partagent
machine hôte. le même système d’exploitation)
Faiblement couplé : Les conteneurs sont
hautement autonomes et encapsulés
Évolutif : Vous pouvez augmenter et distribuer
automatiquement les répliques de conteneurs
dans un centre de données.
Composants clés de Docker
• Docker Engine : Le composant central de Docker qui permet de créer, gérer et exécuter des
conteneurs.
• Docker Daemon : Le service en arrière-plan qui gère les opérations de conteneurisation sur le
système hôte.
• Docker CLI : L'interface en ligne de commande permettant aux utilisateurs d'interagir avec
Docker.
• Docker API : Une interface de programmation permettant aux applications de communiquer avec
Docker.
• Machine hôte : L'emplacement où les conteneurs Docker s'exécutent, avec un Docker Daemon
installé. Il contient des images en cache et des conteneurs.
• Docker Hub : Un emplacement pour stocker et partager des images Docker, qu'il s'agisse d'un
registre public (Docker Hub) ou privé.
• Images : Des modèles en lecture seule avec des instructions pour créer un conteneur Docker. Les
images peuvent être extraites d'un hub Docker ou modifiées pour créer de nouvelles images.
• Conteneurs : Les instances d'une image Docker exécutée. Toutes les applications et leur
environnement s'exécutent à l'intérieur de ces conteneurs. Les conteneurs sont créés, gérés et
supprimés à l'aide de Docker Desktop ou de la CLI Docker.
Pour importer une image, nous pouvons utiliser les solutions suivantes :
• Docker Hub (importer une image depuis le cloud Docker) : C’est le registre officiel de Docker
c’est un répertoire SaaS (Software as a Service ou logiciel en tant que service) regroupant des
applications containerisés (images).
• Utiliser un fichier DockerFile pour créer une image à travers les commandes : C’est un document
qui contient toutes les commandes qu'un utilisateur pourrait exécuter sur la ligne de commande
pour créer sa propre image.
• Les instructions de base que peut contenir un DockerFile sont les suivantes :
• FROM permet de définir depuis quelle base votre image va être créée
• LABEL permet de définir l’auteur de l’image
• RUN permet de lancer une commande
• ADD permet de copier un fichier depuis la machine hôte ou depuis une URL
• EXPOSE permet d’exposer un port du container vers l’extérieur
• CMD détermine la commande qui sera exécutée lorsque le container démarrera
• ENTRYPOINT permet d’ajouter une commande qui sera exécutée par défaut
• WORKDIR permet de définir le dossier de travail pour toutes les autres commandes
• ENV permet de définir des variables d’environnements
• VOLUMES permet de créer un point de montage qui permettra de persister les données
• À partir d’un registry local (sans accéder au cloud)
• À partir d’un conteneur (Image → Conteneur → Image)
Sonar
Tests dynamiques Tests statiques
Ces tests sont effectués pendant que l'application Ces tests sont effectués sur le code source
est en cours d'exécution pour détecter les avant son exécution. Ils consistent à analyser le
dysfonctionnements, tels que des fonctionnalités code pour détecter les écarts par rapport aux
mal implémentées ou des bases de données bonnes pratiques de développement, tels que
inaccessibles. Un exemple de test dynamique est l'absence de logs ou de commentaires.
le test unitaire (JUnit, par exemple). SonarQube est un outil qui effectue ce type de
tests.
=> Les tests dynamiques sont effectués pendant l'exécution de l'application pour détecter des
dysfonctionnements, tandis que les tests statiques sont réalisés sur le code source pour identifier les
violations des bonnes pratiques de développement. Les deux types de tests sont essentiels pour assurer la
qualité et la fiabilité d'une application.
• SonarQube : c’est un outil de test statique, open source, utilisé pour analyser la qualité du
code source, selon des règles prédéfinies. II permet donc l’inspection en continue de la
qualité de votre code (Code Review automatique).
• Appart la qualité de code, SonarQube s’intéresse à plusieurs aspects, tels que :
• La détection rapide des erreurs
• Les applications durables
• Une meilleure productivité
• La flexibilité
• La réduction des coûts
• L’évaluation de la couverture du code par les tests unitaires
• Des analyses entièrement automatisées (intégration avec Jenkins et Maven)
• SonarQube est un outil qui évalue la qualité du code source, y compris s'il a été testé par des
outils comme JUnit, mais il ne réalise pas l'analyse lui-même. Il repose sur d'autres outils tels
que JaCoCo pour fournir des informations sur la couverture de code.
• Le terme "Code Smells" ne fait pas référence à des bogues, mais à des éléments de code source
qui ne sont pas optimaux et qui peuvent compliquer la compréhension ou la modification du
code.
• SonarQube est un outil précieux pour identifier ces problèmes de qualité du code, notamment les
"Code Smells", et il peut aider les équipes de développement à améliorer la lisibilité, la
maintenabilité et la performance du code source.
Nexus
• Livrable : Un livrable représente le résultat attendu à la clôture d’un projet.
• Release vs Snapshot : Une release est une version fixe d'un projet (Sprint en cas de Scrum).
Une version Snapshot est une version en cours de développement avec une partie des
fonctionnalités à implémenter.
• Nexus est une plateforme de gestion de dépôts d'artéfacts logiciels, fortement liée à Maven
pour simplifier la gestion des composants et des dépendances dans les projets de
développement. C’est un gestionnaire de référentiel qui organise, stocke et distribue les
artefacts nécessaires au développement
• L'intérêt de Nexus est de pouvoir y partager des artéfacts avec les autres développeurs d'un
projet, ou entre plusieurs environnements (Docker).
• Hosted (ce qui nous avons utilisés dans nos projets) : Les dépôts hébergés par Nexus
contentant les livrables créés par les utilisateurs, Nexus est configuré par défaut par les dépôts
hosted suivants :
• Releases : les librairies (artéfacts et autres) stables de l’organisation.
• Snapshots : les librairies (artéfacts et autres) en cours de développement de
l’organisation.
• Proxy : Dépôts dont le serveur Nexus est seulement un relais d’un repository distant. Le
proxy permet d’accélérer le processus de build tout en évitant les téléchargements inutiles sur
internet.
• Virtual : Adaptateur de dépôts au format attendu (structure Maven bien défini par exemple).
• Group : Un regroupement de dépôts sous une même URL afin d’alléger la configuration.
Junit
Les principaux types de tests :
• Test d'intégration : visent à s'assurer du bon fonctionnement de la mise en œuvre conjointe de
plusieurs unités de programme qui ont été testées unitairement au préalable. Ils vérifient la
coordination et la compatibilité des composants logiciels.
• Test de régression : Sont exécutés sur un programme préalablement testé mais ayant subi des
modifications. Ils visent à vérifier que les nouvelles modifications n'ont pas introduit de nouveaux
bugs ou altéré le comportement existant.
• Test de montée en charge : Ces tests de capacité simulent un nombre croissant d'utilisateurs
pour déterminer la charge limite que le système peut supporter. Ils aident à évaluer les
performances et la scalabilité du système.
• Test de sécurité : visent à découvrir les vulnérabilités du système et à s'assurer que les données
et les ressources sont protégées contre d'éventuels intrus.
Dans un pipeline CI/CD, les tests sont intégrés à différentes étapes du processus de développement et de
déploiement :
• Intégration continue : Les tests unitaires et les tests de qualité du code sont recommandés à
cette étape pour garantir que les nouvelles modifications n'ont pas introduit de problèmes.
• Livraison continue : En plus des tests unitaires, des tests d'intégration plus avancés sont
nécessaires pour s'assurer que les composants fonctionnent correctement ensemble.
• Déploiement continu : Dans un environnement de production, des tests plus avancés sont
nécessaires, y compris des tests fonctionnels, de performance et de sécurité, pour garantir la
qualité du livrable.
Le choix d'exécution des tests est fortement lié à la pyramide des tests, où les tests les plus rapides sont
effectués au début du pipeline (intégration continue) et les tests nécessitant plus de temps d'exécution
arrivent plus tard (livraison ou déploiement continue).
En ce qui concerne les tests unitaires, ils visent à vérifier que chaque unité de code logiciel fonctionne
comme prévu. Les tests unitaires sont réalisés par les développeurs et sont essentiels pour garantir la
non-régression, détecter les bugs plus facilement, isoler les fonctions, et suivre l'avancement du
projet.
• Un framework populaire pour les tests unitaires est JUnit, qui permet aux développeurs
d'automatiser les tests et de s'assurer que le code répond toujours aux besoins, même après des
modifications.
• L’annotation RunWith (JUnit invoquera la classe spécifiée dans cette annotation en tant
qu'exécuteur de test au lieu d'exécuter l'exécuteur par défaut.), car elle provient de JUnit 4.
• JUnit 5 offre un certain nombre d'annotations et d'outils pour faciliter la création et l'exécution de
tests unitaires :
• @Test : Cette annotation est utilisée pour marquer une méthode comme étant une
méthode de test. Elle indique que cette méthode doit être exécutée lors de l'exécution des
tests.
• @Order : Permet de définir l'ordre d'exécution des tests. Pour utiliser cette annotation,
vous devez ajouter l'annotation
@TestMethodOrder([Link]) au-dessus de la classe
de test.
• @RepeatedTest (n) : Cette annotation permet d'exécuter une méthode annotée un
nombre spécifié de fois (n). Cela permet de répéter le même test plusieurs fois.
• @BeforeEach / @AfterEach : Ces annotations définissent des méthodes qui sont
exécutées avant et après chaque méthode de test dans la classe. Elles sont utiles pour
l'initialisation et le nettoyage entre les tests.
• @BeforeAll / @AfterAll : Ces annotations sont utilisées pour signaler que les méthodes
statiques annotées doivent être exécutées avant et après l'ensemble des tests annotés avec
@Test dans la classe de test.
• JUnit 5 fournit également des assertions pour valider les résultats des tests :
AssertArrayEquals (expected, actual) : Vérifie l'égalité entre deux tableaux.
AssertEquals(expected, actual) : Vérifie l'égalité entre deux valeurs (entiers, réels, chaînes de
caractères, etc.).
AssertNotEquals (expected, actual) : Vérifie l'inégalité entre deux valeurs.
AssertTrue(condition) : Vérifie qu'une condition est vraie.
AssertFalse(condition) : Vérifie qu'une condition est fausse.
AssertSame (expected, actual) : Vérifie l'égalité entre deux objets.
AssertNotSame (expected, actual) : Vérifie l'inégalité entre deux objets.
AssertAll(executables) : Permet de créer des assertions groupées.
AssertTimeout (timeout, executable) : Affirme que l'exécution d'un code donné se termine
avant une date spécifiée.
• Mockito :
• C’est une bibliothèque qui permet de créer des mocks pour vos tests unitaires, ce qui vous
permet de tester vos classes de manière isolée, même lorsque des dépendances externes ne
sont pas disponibles ou peuvent être lentes. Cela contribue à maintenir des tests unitaires
efficaces et à améliorer la productivité de l'équipe de développement.
• Pour pouvoir utiliser le mock, il suffit d’ajouter au niveau de la classe de test :
@extendwith([Link])
• Les méthodes « when » et « thenReturn » de Mockito permettent de paramétrer le mock en
affirmant que si la méthode findById () est appelée sur la classe (mockée)
• La phase de tests unitaire c’est une phase primordiale dans la réalisation d’un
projet. Un mock est un type de doublure de test simple à créer, et qui vous
permet également de tester comment on interagit avec lui.
Mockito vous permet de définir comment vos mocks doivent se comporter
(avec when) et vérifier si ces mocks sont bien utilisés (avec verify).
Docker compose et volume
• C’est un outil pour définir et exécuter des applications Docker multi-conteneurs. Il repose
sur un fichier YAML qui spécifie les services, la version (obsolète) , réseaux, volumes,
configurations, et secrets nécessaires pour l'application.
En trois étapes, vous pouvez créer et lancer votre application :
• Définir l'environnement avec un DockerFile,
• Spécifier les services dans le fichier [Link],
• Exécuter la commande "docker compose up" pour démarrer l'application.
• Pour pallier au problème de la persistance des données dans les conteneurs Docker, on
utilise Docker Volume.
• Les volumes sont le mécanisme privilégié pour la persistance des données générées et
utilisées par les conteneurs Docker. Ils permettent de stocker des données de manière
permanente, de les réutiliser dans d'autres conteneurs, de les exporter ou de les importer.
Grafana / Prometheus
• Prometheus :
• C’est un système de monitoring basé sur le langage Go, conçu pour surveiller
diverses cibles telles que serveurs, bases de données et machines virtuelles. Il offre
une base de données de séries chronologiques et travaille en double delta, calculant
l'écart de la valeur par rapport à sa valeur précédente pour le suivi des performances.
• Ce système est composé d'une base de données de séries chronologiques, d'un
serveur web et d'un moteur de base de données. Il fonctionne en collectant des
métriques sur des routes spécifiques (IP, URL, etc.), stockant ces données dans sa
base de données interne au format standardisé, et offre un langage de requêtage
appelé PromQL (Prometheus Query Language) pour l'agrégation et l'interrogation des
données en temps réel.
• Grafana :
• C’est un logiciel open source de visualisation et d'analyse qui permet de créer des
visualisations telles que des graphiques, des histogrammes, des tableaux, des points, des
jauges, et plus encore. Il offre des fonctionnalités d'interrogation, de visualisation, d'alerte et
d'exploration de métriques, quel que soit l'endroit où elles sont stockées (Prometheus,
InfluxDB, PostgreSQL, MySQL, Elasticsearch, etc.). Grafana stocke ses données dans une
base de données interne (SQLite)
• Grafana s'appuie sur Node Exporter, un exportateur Prometheus qui expose les métriques
des serveurs Linux. Node Exporter collecte diverses ressources système telles que
l'utilisation de la RAM, du processeur, de la mémoire, de l'espace disque, etc. Ces
métriques sont ensuite visualisées à l'aide de Grafana pour une surveillance et une analyse
efficace.