<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[DevOps, Cloud &amp; Microservices]]></title><description><![CDATA[I am passionate about DevOps ♾️, Cloud ☁️, and Microservices]]></description><link>https://blog.acloud.digital</link><image><url>https://cdn.hashnode.com/res/hashnode/image/upload/v1715150180073/uqfErDCWb.png</url><title>DevOps, Cloud &amp;amp; Microservices</title><link>https://blog.acloud.digital</link></image><generator>RSS for Node</generator><lastBuildDate>Tue, 21 Apr 2026 22:08:01 GMT</lastBuildDate><atom:link href="https://blog.acloud.digital/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[Mise en place d'un pipeline CICD avec Jenkins & Ansible, pour la stack Odoo, PostgreSQL, pgAdmin]]></title><description><![CDATA[LinkedIn | GitLab | GitHub | Credly


1. Introduction
Le déploiement continu et l'intégration continue (CI/CD) sont des pratiques essentielles dans le développement de logiciels modernes, permettant aux équipes de livrer des applications avec plus de...]]></description><link>https://blog.acloud.digital/pipeline-cicd-jenkins-ansible-stack-odoo-postgresql-pgadmin</link><guid isPermaLink="true">https://blog.acloud.digital/pipeline-cicd-jenkins-ansible-stack-odoo-postgresql-pgadmin</guid><category><![CDATA[Jenkins]]></category><category><![CDATA[ansible]]></category><category><![CDATA[Odoo]]></category><category><![CDATA[pgAdmin]]></category><category><![CDATA[PostgreSQL]]></category><category><![CDATA[cicd]]></category><dc:creator><![CDATA[Carlin FONGANG]]></dc:creator><pubDate>Tue, 07 May 2024 19:22:45 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/4XvAZN8_WHo/upload/ac1d9ae57aa779885c82d60ff1bd8972.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<hr />
<blockquote>
<p><a target="_blank" href="https://www.linkedin.com/in/carlinfongang/">LinkedIn</a> | <a target="_blank" href="https://gitlab.com/carlinfongang">GitLab</a> | <a target="_blank" href="https://github.com/carlinfongang">GitHub</a> | <a target="_blank" href="https://www.credly.com/users/carlin-fongang/badges">Credly</a></p>
</blockquote>
<hr />
<h1 id="heading-1-introduction">1. Introduction</h1>
<p>Le déploiement continu et l'intégration continue (CI/CD) sont des pratiques essentielles dans le développement de logiciels modernes, permettant aux équipes de livrer des applications avec plus de rapidité, fiabilité et sécurité. Ce projet vise à établir un pipeline CI/CD utilisant Jenkins et Ansible pour automatiser le déploiement de plusieurs applications, incluant Odoo, PostgreSQL, pgAdmin, et une application web personnalisée nommée ic-webapp.</p>
<h2 id="heading-11-objectifs">1.1. Objectifs</h2>
<p>Le principal objectif de ce lab est de mettre en place une infrastructure automatisée qui permettra non seulement d'accélérer le processus de déploiement des mises à jour logicielles mais aussi de minimiser les risques d'erreurs humaines. Cela sera bénéfique pour améliorer la continuité des opérations commerciales et optimiser la gestion des ressources. Plus précisément, le projet vise à :</p>
<p><strong>- Automatiser :</strong> Automatiser le processus de déploiement des applications pour garantir des livraisons rapides et sans erreur.</p>
<p><strong>- Sécuriser :</strong> Assurer que toutes les configurations et les déploiements se font dans un environnement sécurisé pour protéger les données et les services.</p>
<p><strong>- Documenter :</strong> Fournir une documentation claire et détaillée qui peut être utilisée pour la maintenance et l'évolution future du système.</p>
<h2 id="heading-12-apercu-des-technologies-utilisees">1.2. Aperçu des technologies utilisées</h2>
<p>Pour atteindre ces objectifs, le pipeline CI/CD sera construit en utilisant :</p>
<p><strong>- Jenkins :</strong> Un serveur d'automatisation open source qui offre un large éventail de plugins pour supporter la construction et le déploiement de divers projets logiciels.</p>
<p><strong>- Ansible :</strong> Un outil d'automatisation qui permet de configurer des systèmes, déployer des logiciels, et orchestrer des tâches plus avancées telles que la gestion de la configuration continue.</p>
<p><strong>- Docker :</strong> Utilisé pour la conteneurisation des applications, garantissant ainsi que les logiciels fonctionnent de manière uniforme et cohérente à travers différents environnements de développement et de production.</p>
<p><strong>- Git :</strong> Système de contrôle de version pour gérer les changements dans les documents, les programmes, et d'autres collections d'informations liées au développement du logiciel.</p>
<p><strong>- Terraform :</strong> Terraform est un outil de gestion d'infrastructure sous forme de code (Infrastructure as Code - IaC) développé par HashiCorp.</p>
<h2 id="heading-13-apercu-de-larchitecture">1.3. Aperçu de l'Architecture</h2>
<p>Le pipeline sera configuré pour gérer les déploiements sur trois serveurs différents, chacun hébergé sur le cloud (AWS) ou en On Premises, selon la préférence et les ressources disponibles. Chaque serveur jouera un rôle spécifique dans l'architecture globale :</p>
<p><strong>- Serveur Jenkins :</strong> Gère l'intégration et le déploiement continu des applications.</p>
<p><strong>- Serveur Applications :</strong> Héberge les applications web ic-webapp et pgAdmin.</p>
<p><strong>- Serveur Odoo :</strong> Exécute l'application de gestion Odoo et sa base de données PostgreSQL.</p>
<p><strong>- Un nœud Jenkins :</strong> C'est une instance qui permettra d'étendre les capacités de l'instance Jenkins maître. cet agent permettra d'exécuter les tâches assignées par l'instance maître et permettent une distribution efficace des charges de travail</p>
<p>La documentation suivante détaillera chaque aspect du pipeline, de l'installation et la configuration des outils à la création et l'exécution des scripts de déploiement, en passant par la gestion des erreurs et des versions.</p>
<h1 id="heading-2-prerequis">2. Prérequis</h1>
<p>Avant de mettre en place le pipeline CI/CD avec Jenkins, Docker, Ansible, et Terraform pour le déploiement de la stack Odoo, Postgres, pgAdmin, et une application Python, il est essentiel de s'assurer que tous les prérequis suivants sont correctement installés et configurés :</p>
<h2 id="heading-21-configuration-des-serveurs">2.1. Configuration des serveurs</h2>
<p><strong>1. Serveur Jenkins :</strong> Une instance (AWS t2.medium recommandé) où Jenkins sera installé, qui servira à orchestrer le pipeline CI/CD.</p>
<p><strong>2. Serveur Applications :</strong> Une instance (AWS t2.micro recommandé) pour héberger les applications web vitrine ic-webapp et pgAdmin.</p>
<p><strong>3. Serveur Odoo :</strong> Une instance (AWS t2.micro recommandé) qui sera dédiée à l'application Odoo et la base de donnée sous Postgres.</p>
<p><strong>4. Un nœud Jenkins :</strong> C'est une instance qui permettra d'étendre les capacités de l'instance Jenkins maître. cet agent permettra d'exécuter les tâches assignées par l'instance maître et permettent une distribution efficace des charges de travail</p>
<p>Chaque serveur doit disposer d'une connectivité réseau appropriée (SSH avec clés, acces via le protocole TCP dans les ingress ...).au niveau des <strong>security groups</strong></p>
<h2 id="heading-22-logiciels-necessaires-jenkins-docker-ansible-git">2.2. Logiciels nécessaires (Jenkins, Docker, Ansible, Git)</h2>
<p><strong>1. Jenkins :</strong> Une instance Jenkins doit être préinstallé et configuré pour gérer les jobs et orchestrer le pipeline. &gt;&gt; <a target="_blank" href="https://gitlab.com/CarlinFongang-Labs/jenkins-cicd/lab1-install.git">Comment installer Jenkins</a></p>
<p><strong>2. Docker :</strong> Docker doit être installé sur les instance pour permettre la conteneurisation des applications. Cela inclut Docker Engine et, Docker Compose pour gérer les applications multi-conteneurs (nous utiliserons Ansible pour simplifier cette tache). &gt;&gt; <a target="_blank" href="https://gitlab.com/CarlinFongang-Labs/docker-labs/docker-install.git">Comment installer Docker</a></p>
<p><strong>3. Ansible :</strong> Ansible est utilisé pour l'automatisation de la configuration et du déploiement des applications sur les serveurs. Il doit être installé sur le serveur Jenkins pour exécuter les playbooks. &gt;&gt; <a target="_blank" href="https://gitlab.com/CarlinFongang-Labs/Ansible/lab1-install-ansible.git">Comment installer Ansible</a></p>
<p><strong>4. Git :</strong> Nécessaire pour le versionnage des codes source et des configurations d'infrastructures. Git doit être installé sur le serveur Jenkins pour permettre le clonage des dépôts et la gestion des versions. Terraform (optionnel) : Si utilisé, Terraform doit être configuré pour gérer l'infrastructure sous forme de code, ce qui permet un déploiement et une gestion dynamiques des ressources cloud.</p>
<p><strong>5. Terraform :</strong> (optionnel), installé sur une machine tièrce, nous perettra de provisionner les défferentes instances dont nous aurons besoin. &gt;&gt; <a target="_blank" href="https://gitlab.com/CarlinFongang-Labs/Terraform/lab1-intall-terraform.git">Comment installer Terraform</a></p>
<h2 id="heading-23-connaissances-requises">2.3. Connaissances Requises</h2>
<p><strong>Compréhension de CI/CD :</strong> Une compréhension de base des concepts de l'intégration continue et du déploiement continu.</p>
<p><strong>Base en scriptage :</strong> Connaissance en Bash pour scripts shell et en YAML pour les configurations Docker et Ansible.</p>
<p><strong>Administration système :</strong> Compétences en gestion de systèmes Unix/Linux, notamment pour la configuration réseau, la gestion des processus, et la surveillance.</p>
<p><strong>Gestion de réseau :</strong> Connaissance des concepts réseau de base, essentiels pour configurer correctement les interactions entre les différents services et applications.</p>
<h1 id="heading-3-configuration-de-linfrastructure">3. Configuration de l'Infrastructure</h1>
<h2 id="heading-31-provisionner-des-instances-a-laide-de-terraform-avec-gitlab-comme-outil-de-remote-state">3.1. Provisionner des instances à l'aide de terraform avec gitlab comme outil de remote state</h2>
<p>Dans ce depôt, vous retrouverez des explication sur comment utiliser les modules terraform proposer pour provisionner une instance ec2 en utilisant gitlab comme remote state manager ou même la solution s3 de AWS pour le même rôle :</p>
<p><a target="_blank" href="https://gitlab.com/CarlinFongang-Labs/Terraform/hub/terraform-provide-ec2-instance#remote-state-avec-gitlab">\&gt;&gt; Provisionner une instance ec2 grâce à Terraform</a></p>
<h2 id="heading-32-preparation-de-jenkins">3.2 Préparation de Jenkins</h2>
<h3 id="heading-321-installation-de-jenkins">3.2.1. Installation de Jenkins</h3>
<p>Pour l'installation de Jenkins, se référer à la documentation : <a target="_blank" href="https://gitlab.com/CarlinFongang-Labs/jenkins-cicd/lab1-install.git">Installation de Jenkins sur une instance ec2 (AWS)</a></p>
<h3 id="heading-322-configuration-de-lagent-jenkins-slaves">3.2.2. Configuration de l'agent Jenkins (slaves)</h3>
<p>La configuration des agents Jenkins, également appelés "nœuds" ou "slaves", est une étape cruciale pour étendre les capacités d'un instance Jenkins maître. Ces agents exécutent les tâches assignées par l'instance maître et permettent une distribution efficace des charges de travail, surtout lors de l'exécution de plusieurs jobs ou de jobs particulièrement lourds. La mise en place correcte des agents assure une meilleure scalabilité et optimisation des ressources dans un environnement CI/CD.</p>
<p>Pour mettre en œuvre cette solution, nous allons provisionner, grace à terraform une nouvelle instance qui servira de noeud à l'instance master Jenkins en utilisant le IaaC terraform proposé plus haut, où en <a target="_blank" href="https://gitlab.com/CarlinFongang-Labs/Terraform/lab0-sigup-aws.git">provisionnant une instance manuellement dépuis la console aws</a></p>
<h4 id="heading-installation-de-java"><strong>Installation de Java</strong></h4>
<p>Une fois connecté en ssh à notre instance ec2 qui devra servir de noed, entrez les commandes suivantes depuis le terminal</p>
<pre><code class="lang-bash">sudo apt update
sudo apt install openjdk-11-jdk -y
</code></pre>
<blockquote>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1715108593643/309e90a6-53da-42c4-8cd7-753100af24da.png" alt class="image--center mx-auto" /></p>
</blockquote>
<h3 id="heading-323-configuration-de-jenkins">3.2.3. Configuration de Jenkins</h3>
<h4 id="heading-plugin-requis"><strong>Plugin requis</strong></h4>
<p>Installer le plugins : <strong>SSH Build Agents</strong></p>
<p><strong>Ce plugin permet à Jenkins de se connecter et de lancer des agents sur des machines distantes via SSH.</strong></p>
<blockquote>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1715108693438/e0319987-62c8-4703-bd99-95c79ccc3a28.png" alt class="image--center mx-auto" /></p>
</blockquote>
<h4 id="heading-credentials"><strong>Crédentials</strong></h4>
<ol>
<li><p>Se rendre dans "Manage Jenkins" &gt; "Manage Credentials".</p>
</li>
<li><p>Ajoutez une nouvelle credential de type "SSH Username with private key".</p>
</li>
<li><p>Entrez le nom d'utilisateur de votre instance EC2 et la clé privée que vous avez configurée pour l'accès SSH.</p>
</li>
</ol>
<blockquote>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1715108710740/ca7be9d8-2ebc-489a-bcfc-50bf012e3f95.png" alt="Enregistrement d'un credential sous Jinkins" class="image--center mx-auto" /></p>
</blockquote>
<h4 id="heading-ajouter-un-nouvel-agent"><strong>Ajouter un nouvel agent</strong></h4>
<ol>
<li><p>Allez dans "Manage Jenkins" &gt; "Manage Nodes and Clouds".</p>
</li>
<li><p>Cliquez sur "New Node".</p>
</li>
<li><p>Entrez un nom pour le nœud, sélectionnez "Permanent Agent", puis cliquez sur "Create".</p>
</li>
</ol>
<blockquote>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1715108732493/e19022cf-3ce6-42f9-9f4d-5c408da0cc6e.png" alt class="image--center mx-auto" /></p>
<p><em>Création d'un node sous Jenkins</em></p>
</blockquote>
<p><strong>Configurez les paramètres de l'agent :</strong></p>
<ol>
<li><p>Remote root directory: Un chemin dans lequel Jenkins peut exécuter des builds (/home/ubuntu/jenkins_path).</p>
</li>
<li><p>Labels: Des étiquettes pour identifier l'agent.</p>
</li>
<li><p>Usage: Déterminez comment cet agent sera utilisé (exclusivement ou laissé à Jenkins pour décider).</p>
</li>
<li><p>Launch method: Sélectionnez "Launch agents via SSH".</p>
</li>
<li><p>Host: L'adresse IP ou le DNS de votre instance EC2.</p>
</li>
<li><p>Credentials: Sélectionnez les credentials SSH que vous avez créés.</p>
</li>
<li><p>Host Key Verification Strategy: Choisissez "Non verifying Verification Strategy" pour simplifier, mais pour plus de sécurité, il est recommandé de configurer une stratégie de vérification.</p>
</li>
</ol>
<blockquote>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1715108760042/b3af49e3-5640-4c93-bba7-7565889916ef.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1715108763710/1be459a6-26f2-458f-817a-216250a793fe.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1715108785156/97e0aa0a-ac07-4f7f-bc65-6313d610804a.png" alt class="image--center mx-auto" /></p>
</blockquote>
<h4 id="heading-lancement-de-lagent"><strong>Lancement de l'agent</strong></h4>
<p>Une fois tout configuré, Jenkins essaiera de se connecter à l'instance EC2 et de démarrer l'agent lorsqu'un build doit être exécuté sur ce nœud. Vous pouvez vérifier le statut de l'agent dans la section "Manage Nodes and Clouds" pour vous assurer qu'il est connecté correctement.</p>
<blockquote>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1715108803324/3fedfd38-f17a-455e-876b-116908a1bb35.png" alt class="image--center mx-auto" /></p>
<p><em>Agent Jenkins en ligne</em></p>
</blockquote>
<h2 id="heading-33-configuration-du-gestion-scm">3.3. Configuration du gestion SCM</h2>
<p>se rendre dans l'option ConfigureTools où à l'adresse : <a target="_blank" href="http://public_ip_address_jenkins_instance/configureTools/"><strong>http://public_ip_address_jenkins_instance/configureTools/</strong></a></p>
<p>Mettre à jour le repertoire de git pour la prise en charge du build</p>
<blockquote>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1715108816417/bce6ee01-5468-4a1f-bab2-0e0b6b8dc9eb.png" alt class="image--center mx-auto" /></p>
</blockquote>
<h1 id="heading-4-developpement-du-pipeline-ci">4. Développement du Pipeline (CI)</h1>
<h2 id="heading-41-structure-generale-du-pipeline-stages">4.1. Structure générale du pipeline (stages)</h2>
<p>Structure Générale du Pipeline CI/CD</p>
<p>La mise en place d'un pipeline CI/CD pour la solution <strong>Odoo</strong>, <strong>PostgreSQL</strong>, <strong>pgAdmin</strong>, et une application web vitrine nécessite une structuration claire et détaillée des étapes de build, test, release et déploiement.</p>
<p>Voici un aperçu de la structure générale du pipeline qui sera implémentée dans Jenkins pour automatiser l'ensemble du processus de développement et de déploiement.</p>
<h3 id="heading-stages-du-pipeline">Stages du Pipeline</h3>
<h4 id="heading-initialisation"><strong>Initialisation :</strong></h4>
<p><strong>Checkout :</strong> Récupération du code source depuis le système de gestion de version. <strong>Préparation de l'environnement :</strong> Installation des dépendances nécessaires pour le build et le test.</p>
<h4 id="heading-build"><strong>Build :</strong></h4>
<p><strong>Construction des images Docker :</strong> Pour l'application vitrine une image Docker est construite en utilisant un Dockerfiles spécifique.</p>
<h4 id="heading-tests"><strong>Tests :</strong></h4>
<p><strong>health check :</strong> Exécution d'une commande shell pour vérifier la disponibilité du service une fois le conteneur test lancée.</p>
<h4 id="heading-release"><strong>Release :</strong></h4>
<p>Tagging des images : Attribution de tags à l'images Docker construite, en utilisant un identifiants de version ou des hashes de commit pour la traçabilité de la release. Push des images : Envoi des images vers un registre Docker pour stockage et récupération lors du déploiement.</p>
<h4 id="heading-deploiement"><strong>Déploiement :</strong></h4>
<p>Déploiement : Déploiement de chaque stack (odoo+postgres et pgadmin+ic-webapp) sur les serveurs de production distinct.</p>
<h4 id="heading-integration-et-deploiement-continus"><strong>Intégration et Déploiement Continus</strong></h4>
<p>Le pipeline est conçu pour permettre une intégration et un déploiement continus, où chaque commit dans le dépôt de code (Gitlab) déclenche automatiquement un nouveau cycle de ce pipeline. Cette automatisation assure que toutes les modifications sont rapidement testées et prêtes à être déployées, minimisant ainsi le temps de mise en marché et augmentant la réactivité aux besoins des utilisateurs.</p>
<h2 id="heading-42-details-de-chaque-etape-du-pipeline">4.2. Détails de chaque étape du pipeline</h2>
<h3 id="heading-421-declaration-des-variables">4.2.1 Déclaration des variables</h3>
<p>Dans le Jenkinsfile, la section des variables d'environnement joue un rôle crucial en définissant les paramètres qui seront utilisés à travers les différentes étapes du pipeline.</p>
<pre><code class="lang-yaml">   <span class="hljs-string">environment</span> {
        <span class="hljs-string">IMAGE_NAME</span> <span class="hljs-string">=</span> <span class="hljs-string">"ic-webapp"</span>
        <span class="hljs-string">IMAGE_TAG</span> <span class="hljs-string">=</span> <span class="hljs-string">"latest"</span>
        <span class="hljs-string">LOCAL_TAG</span> <span class="hljs-string">=</span> <span class="hljs-string">"1.0"</span>
        <span class="hljs-string">IP_ANSIBLE</span> <span class="hljs-string">=</span> <span class="hljs-string">"18.211.168.237"</span>
        <span class="hljs-string">IP_ODOO</span> <span class="hljs-string">=</span> <span class="hljs-string">"54.226.148.2"</span>
        <span class="hljs-string">IP_PGADMIN</span> <span class="hljs-string">=</span> <span class="hljs-string">"54.209.185.19"</span>
        <span class="hljs-string">JENKINS_PATH</span> <span class="hljs-string">=</span> <span class="hljs-string">"jenkins_path"</span>
        <span class="hljs-string">USER_SERVER</span> <span class="hljs-string">=</span> <span class="hljs-string">"ubuntu"</span>
        <span class="hljs-string">REPO_ODOO</span> <span class="hljs-string">=</span> <span class="hljs-string">"https://gitlab.com/CarlinFongang-Labs/projet-odoo/deploy-odoo-postgresql-pgadmin/odoo-postgresql-ansible.git"</span>
        <span class="hljs-string">REPO_PGADMIN</span> <span class="hljs-string">=</span> <span class="hljs-string">"https://gitlab.com/CarlinFongang-Labs/projet-odoo/deploy-odoo-postgresql-pgadmin/pgadmin-webapp-with-ansible.git"</span>
    }
    <span class="hljs-string">agent</span> {
        <span class="hljs-string">label</span> <span class="hljs-string">'runner_ec2_aws'</span>
    }
</code></pre>
<p>Voici une explication de chaque variable et son importance dans le processus de CI/CD :</p>
<h4 id="heading-variables-generales"><strong>Variables générales</strong></h4>
<p><strong>IMAGE_NAME:</strong> Nom de l'image Docker qui sera construite et déployée. Cela permet de personnaliser et de reconnaître facilement l'image au sein des registres Docker.</p>
<p><strong>IMAGE_TAG:</strong> Tag de l'image Docker pour la version la plus récente. Utiliser latest permet de s'assurer que la dernière version de l'image est toujours utilisée là où c'est nécessaire.</p>
<p><strong>LOCAL_TAG:</strong> Une version spécifique de l'image, ici "1.0", qui peut être utilisée pour assurer un suivi de versions spécifiques ou pour des déploiements ciblés.</p>
<p><strong>IP_ANSIBLE, IP_ODOO, IP_PGADMIN:</strong> Adresses IP des serveurs sur lesquels les différentes applications seront déployées. Ces adresses permettent à Ansible de cibler correctement les machines pour le déploiement</p>
<h4 id="heading-chemins-et-references"><strong>Chemins et références</strong></h4>
<p><strong>JENKINS_PATH:</strong> Le chemin dans le système de fichiers où Jenkins stocke les données de travail. Cela peut inclure des scripts, des fichiers temporaires ou des configurations spécifiques à Jenkins.</p>
<p><strong>USER_SERVER:</strong> Nom d'utilisateur utilisé pour les connexions SSH lors des déploiements Ansible. Typiquement, ubuntu est le nom d'utilisateur par défaut pour les instances EC2 Ubuntu sur AWS.</p>
<h4 id="heading-references-de-repertoire-git"><strong>Références de répertoire Git</strong></h4>
<p><strong>REPO_ODOO:</strong> URL du dépôt Git contenant les configurations et les scripts Ansible pour déployer l'application Odoo. Ce lien est essentiel pour permettre au pipeline de récupérer les dernières configurations et scripts nécessaires au déploiement. <strong>REPO_PGADMIN:</strong> URL du dépôt Git pour les configurations de pgAdmin. Cela assure que les scripts et configurations nécessaires pour déployer pgAdmin sont accessibles et à jour.</p>
<h4 id="heading-configuration-de-lagent-jenkins"><strong>Configuration de l'agent Jenkins</strong></h4>
<p><strong>agent { label 'runner_ec2_aws' }:</strong> Définit l'agent Jenkins qui exécutera le pipeline. Ici, <strong>runner_ec2_aws</strong> fait référence au label assigné à un notre agents Jenkins configurés précédement et qui fonctionne dans un environnement AWS. Cela garantit que les tâches du pipeline sont exécutées dans l'environnement approprié.</p>
<h3 id="heading-422-build-creation-de-limage-docker">4.2.2. Build: Création de l'image Docker</h3>
<p>La phase de build est une étape crutiale dans notre pipeline CI/CD où le code source de notre application est transformé en un artefact. Pour notre application vitrine, cette phase est orchestrée à l'aide de Docker, qui nous permet de construire une image contenant tout le nécessaire pour exécuter notre application.</p>
<h3 id="heading-423-declaration-des-secrets">4.2.3. Déclaration des secrets</h3>
<p>Pour renseigner des secrets dans Jenkins et les utiliser de manière sécurisée dans des pipelines, nous pouvons configurer et utiliser les secrets comme des mots de passe, des clés SSH, des tokens API, et d'autres informations sensibles :</p>
<p><strong>1: Accéder aux Credentials dans Jenkins</strong> Allez dans le menu principal, cliquez sur "Manage Jenkins". Choisissez "Manage Credentials".</p>
<p><strong>2: Choisir le Scope des Credentials</strong> Sous <strong>"Stores scoped to Jenkins"</strong>, cliquez sur <strong>"(global)"</strong> pour définir les credentials qui sont accessibles à tous les jobs, ou choisissez un domaine spécifique si vous voulez restreindre l'accès à certains jobs ou pipelines.</p>
<p><strong>3: Ajouter un Nouveau Credential</strong></p>
<ul>
<li><p>Cliquez sur "Add Credentials" sur le côté gauche.</p>
</li>
<li><p>Choisissez le type de credentials que vous souhaitez ajouter. Les options courantes incluent :</p>
</li>
<li><p>Username with password – pour les combinaisons nom d'utilisateur/mot de passe.</p>
</li>
<li><p>Secret text – pour les tokens API ou les secrets arbitraires.</p>
</li>
<li><p>SSH Username with private key – pour les connexions SSH sécurisées.</p>
</li>
<li><p>Certificate – pour l'authentification basée sur certificat.</p>
</li>
<li><p>Remplissez les champs nécessaires, tels que :</p>
</li>
<li><p>Scope: Choisissez "Global" (accessible de partout) ou "Jenkins" (limité à des jobs spécifiques).</p>
</li>
<li><p>ID: Laissez ce champ vide pour autogénérer un ID, ou entrez un identifiant personnalisé.</p>
</li>
<li><p>Description: Fournissez une description claire pour identifier ce credential dans la liste.</p>
</li>
<li><p>Username, Password/Secret, Private Key, etc., selon le type de credential ajouté.</p>
</li>
</ul>
<p>\&gt;<a target="_blank" href="https://gitlab.com/CarlinFongang-Labs/jenkins-cicd/projet-jenkins-cicd#6-release-stage">\&gt; Découvrez comment créer un token éphémère Dockerhub</a></p>
<blockquote>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1715108907829/5f3c33c8-9d2e-44d5-8bf6-3b8176c29395.png" alt class="image--center mx-auto" /></p>
</blockquote>
<h4 id="heading-description-du-dockerfile">Description du Dockerfile</h4>
<p>Le Dockerfile défini pour une application utilisant Python 3.6 basé sur une image Alpine Linux, cette image est choisie car offre une grande légèreté et une bonne sécurité. Voici les étapes détaillées du processus de build :</p>
<pre><code class="lang-yaml"><span class="hljs-string">ARG</span> <span class="hljs-string">version="3.6-alpine"</span>
<span class="hljs-string">FROM</span> <span class="hljs-string">python:${version}</span>

<span class="hljs-string">LABEL</span> <span class="hljs-string">desciption="ic-webapp"</span>
<span class="hljs-string">LABEL</span> <span class="hljs-string">maintainer="Carlinfg</span> <span class="hljs-string">&lt;fongangcarlin@gmail.com&gt;"</span>

<span class="hljs-string">WORKDIR</span> <span class="hljs-string">/opt</span>

<span class="hljs-comment"># Installer Flask and git</span>
<span class="hljs-string">RUN</span> <span class="hljs-string">apk</span> <span class="hljs-string">update</span> <span class="hljs-string">&amp;&amp;</span> <span class="hljs-string">\</span>
    <span class="hljs-string">apk</span> <span class="hljs-string">add</span> <span class="hljs-string">--no-cache</span> <span class="hljs-string">git</span> <span class="hljs-string">bash</span> <span class="hljs-string">gawk</span> <span class="hljs-string">&amp;&amp;</span> <span class="hljs-string">\</span>
    <span class="hljs-string">pip</span> <span class="hljs-string">install</span> <span class="hljs-string">Flask</span>

<span class="hljs-string">RUN</span> <span class="hljs-string">git</span> <span class="hljs-string">clone</span> <span class="hljs-string">https://github.com/LaboCloud/ic-webapp.git</span> <span class="hljs-string">/opt</span>


<span class="hljs-comment"># Copy the releases.txt file into the working directory</span>
<span class="hljs-string">COPY</span> <span class="hljs-string">releases.txt</span> <span class="hljs-string">/opt/releases.txt</span>
<span class="hljs-string">COPY</span> <span class="hljs-string">env_vars.sh</span> <span class="hljs-string">/opt/env_vars.sh</span>

<span class="hljs-comment"># Permissions</span>
<span class="hljs-string">RUN</span> <span class="hljs-string">chmod</span> <span class="hljs-string">+x</span> <span class="hljs-string">/opt/env_vars.sh</span> <span class="hljs-string">&amp;&amp;</span> <span class="hljs-string">\</span>
    <span class="hljs-string">chmod</span> <span class="hljs-string">+x</span> <span class="hljs-string">env_vars.sh</span>

<span class="hljs-comment"># Set environment variables</span>
<span class="hljs-string">ENV</span> <span class="hljs-string">ODOO_URL=$ODOO_URL</span>
<span class="hljs-string">ENV</span> <span class="hljs-string">PGADMIN_URL=$PGADMIN_URL</span>

<span class="hljs-comment"># Port</span>
<span class="hljs-string">EXPOSE</span> <span class="hljs-number">8080</span>

<span class="hljs-comment"># Start</span>
<span class="hljs-string">ENTRYPOINT</span> [<span class="hljs-string">"sh"</span>, <span class="hljs-string">"-c"</span>, <span class="hljs-string">"source /opt/env_vars.sh"</span>, <span class="hljs-string">"-s"</span>]
<span class="hljs-string">CMD</span> [<span class="hljs-string">"python"</span>, <span class="hljs-string">"app.py"</span>]
</code></pre>
<p><strong>1. Base et dépendances :</strong></p>
<p><strong>Image de base :</strong> L'image de base est <strong>python:3.6-alpine</strong>. Alpine est choisie pour sa simplicité et sa petite taille.</p>
<p><strong>Installation de Dépendances :</strong> Installation de Git, Bash et Gawk. Ces outils sont nécessaires pour cloner le répertoire du projet et exécuter des scripts shell.</p>
<p><strong>2. Récupération du code source :</strong></p>
<p>Le code source de l'application est cloné depuis un dépôt Git externe directement dans le répertoire de travail <strong>/opt</strong> du conteneur.</p>
<p><strong>3. Configuration de l'environnement :</strong></p>
<p><strong>Fichiers de configuration :</strong> Les fichiers releases.txt et env_<a target="_blank" href="http://vars.sh">vars.sh</a> sont copiés dans le conteneur. Ces fichiers contiennent respectivement les variables de configuration et un script pour initialiser ces variables d'environnement.</p>
<p><strong>Permissions :</strong> Des permissions d'exécution sont attribuées au script env_<a target="_blank" href="http://vars.sh">vars.sh</a> pour assurer sa bonne exécution. Variables d'Environnement : Les variables ODOO_URL et PGADMIN_URL sont définies dans l'environnement du conteneur à partir des valeurs extraites par le script env_<a target="_blank" href="http://vars.sh">vars.sh</a>.</p>
<p><strong>4. Exposition de port et démarrage :</strong></p>
<p>Le port <strong>8080</strong> est exposé pour permettre l'accès à l'application depuis l'extérieur du conteneur.</p>
<p><strong>ENTRYPOINT ["sh", "-c", "source /opt/env_</strong><a target="_blank" href="http://vars.sh"><strong>vars.sh</strong></a><strong>", "-s"] :</strong> Le conteneur est configuré pour exécuter le script env_vars.sh au démarrage, suivi de la commande python <a target="_blank" href="http://app.py">app.py</a> pour démarrer l'application Flask.</p>
<p><strong>Description du script "env_vars.sh"</strong></p>
<p>Ce script Bash, destiné à être utilisé dans notre conteneur, il nous permet de gère les variables d'environnement pour les URL de d'Odoo et pgAdmin, en fonction de leur présence dans un fichier de configuration releases.txt.</p>
<pre><code class="lang-bash">présente brièvement ce script 

<span class="hljs-comment">#!/bin/bash</span>
releases_file_path=<span class="hljs-string">"/opt/releases.txt"</span>

<span class="hljs-keyword">if</span> <span class="hljs-built_in">test</span> -f <span class="hljs-string">"<span class="hljs-variable">$releases_file_path</span>"</span>; <span class="hljs-keyword">then</span>
   <span class="hljs-built_in">export</span> ODOO_URL=$(awk -F <span class="hljs-string">': '</span> <span class="hljs-string">'/ODOO_URL/ {print $2}'</span> <span class="hljs-variable">$releases_file_path</span>)
   <span class="hljs-built_in">export</span> PGADMIN_URL=$(awk -F <span class="hljs-string">': '</span> <span class="hljs-string">'/PGADMIN_URL/ {print $2}'</span> <span class="hljs-variable">$releases_file_path</span>)
<span class="hljs-keyword">else</span>
   <span class="hljs-built_in">echo</span> <span class="hljs-string">"Les URL par défaut des variables ODOO_URL and PGADMIN_URL, vont être utilisées"</span>
<span class="hljs-keyword">fi</span>

<span class="hljs-built_in">exec</span> <span class="hljs-string">"<span class="hljs-variable">$@</span>"</span>
</code></pre>
<p>Une fois les instances destinées à accueillir Odoo et pgAdmin provisionnées et les adresses IP connues, nous pourrons renseigner ces IP/EIP dans le fichier <strong>releases.txt</strong> afin que ces dernieres soient prise en compte et embarquées dans l'image docker lors de la phase de build dans le pipeline Jenkins.</p>
<p>Notre fichier <strong>releases.txt</strong> se présente sous le formation suivant :</p>
<pre><code class="lang-bash">ODOO_URL: http://54.226.148.2:8090
PGADMIN_URL: http://54.209.185.19:8080
VERSION: 2.0
</code></pre>
<p>pour mettre en œuvre la tache de build du Dockerfile préalablement défini dans un pipeline Jenkins, nous allons rédiger un script groovy approprié à cette tâche :</p>
<pre><code class="lang-yaml">        <span class="hljs-string">stage('Build</span> <span class="hljs-string">image')</span> {
            <span class="hljs-string">steps</span> {
                <span class="hljs-string">script</span> {
                    <span class="hljs-string">sh</span> <span class="hljs-string">'which git'</span>
                    <span class="hljs-string">sh</span> <span class="hljs-string">'docker build -t $IMAGE_NAME:$LOCAL_TAG .'</span>
                }
            }
        }
</code></pre>
<h3 id="heading-424-test-dacceptation">4.2.4. Test d'acceptation</h3>
<p>Dans la phase de "Test d'acceptation" de notre pipeline Jenkins, l'application est d'abord déployée dans un environnement de conteneur isolé pour simuler son comportement en production et ensuite testé.</p>
<pre><code class="lang-bash">        stage(<span class="hljs-string">'Run contenair'</span>) {
            //agent { docker { image <span class="hljs-string">'alpine'</span> } }
            steps {
                script {
                    sh <span class="hljs-string">'docker run -d -p 8080:8080 --name $IMAGE_NAME-test $IMAGE_NAME:$LOCAL_TAG'</span>
                    sh <span class="hljs-string">'sleep 5'</span>
                    sh <span class="hljs-string">'sudo apt install curl -y'</span>
                }
            }
        }
        stage(<span class="hljs-string">'Test image'</span>) {
            agent any
            steps {
                script {
                    sh <span class="hljs-string">''</span><span class="hljs-string">'
                        docker ps
                        IP_TEST=$(docker inspect -f '</span>{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}<span class="hljs-string">' "$IMAGE_NAME-test")
                        response=$(curl -s -o /dev/null -w "%{http_code}" "http://$IP_TEST:8080")
                        if [ "$response" -eq 200 ]; then
                            echo "La connexion au conteneur est réussie."
                        else
                            echo "Erreur: La connexion au conteneur a échoué avec le code de réponse HTTP $response."
                        fi
                    '</span><span class="hljs-string">''</span>  
                }
            }
        }
</code></pre>
<p>Voici les étapes principales :</p>
<p><strong>Lancement du conteneur :</strong> Un conteneur Docker est démarré à partir de l'image construite précédemment, exposant l'application sur le port spécifié.</p>
<p><strong>Installation de Curl :</strong> Curl est installé pour faciliter les tests HTTP, permettant de faire des requêtes simples pour tester la connectivité et la réponse de l'application.</p>
<p><strong>Validation du service :</strong></p>
<ul>
<li><p><strong>Récupération de l'IP :</strong> L'adresse IP interne du conteneur est récupérée, ce qui est utilisé pour adresser les requêtes de test.</p>
</li>
<li><p><strong>Requête HTTP :</strong> Une requête HTTP est envoyée à l'application via la commande <strong>Curl</strong>. Le code de réponse <strong>HTTP</strong> est vérifié pour s'assurer qu'il est égal à <strong>200</strong>, indiquant que l'application répond correctement et est prête pour le déploiement. Si le code est différent, une erreur est signalée indiquant un échec de connexion.</p>
</li>
</ul>
<h3 id="heading-425-stop-test-nettoyage-post-tests">4.2.5 Stop Test: Nettoyage post-tests</h3>
<pre><code class="lang-yaml">        <span class="hljs-string">stage('Clean</span> <span class="hljs-string">Test')</span> {
            <span class="hljs-string">agent</span> <span class="hljs-string">any</span>
            <span class="hljs-string">steps</span> {
                <span class="hljs-string">script</span> {
                    <span class="hljs-string">sh</span> <span class="hljs-string">''</span><span class="hljs-string">'
                        docker stop ${IMAGE_NAME}-test &amp;&amp; docker rm ${IMAGE_NAME}-test
                    '</span><span class="hljs-string">''</span>
                }
            }
        }
</code></pre>
<p>Le stage <strong>"Clean Test"</strong> dans notre pipeline Jenkins permet de maintenir un environnement de build propre et gérer efficacement les ressources. Ce stage est spécifiquement mis en place pour nettoyer les conteneurs Docker qui ont été utilisés pour les tests, assurant qu'aucun artefact ou état résiduel ne compromet les exécutions futures du pipeline.</p>
<h3 id="heading-426-release-tag-des-images-et-gestion-des-versions">4.2.6. Release: tag des images et gestion des versions</h3>
<p>Le stage <strong>"Release Docker image"</strong> joue un rôle central dans notre pipeline de CI/CD en s'assurant que l'image Docker construite et testée est publiée sur DockerHub. Ce processus permet de rendre les images disponibles pour un déploiement ultérieur sur différents environnements ou pour être utilisées par d'autres parties prenantes du projet.</p>
<pre><code class="lang-yaml">        <span class="hljs-string">stage('Release</span> <span class="hljs-string">Docker</span> <span class="hljs-string">image')</span> {
            <span class="hljs-string">environment</span> {
                <span class="hljs-string">DOCKERHUB_USER</span> <span class="hljs-string">=</span> <span class="hljs-string">credentials('DHUB_USER')</span>
                <span class="hljs-string">DOCKERHUB_TOKEN</span> <span class="hljs-string">=</span> <span class="hljs-string">credentials('DHUB_TOKEN')</span>        
            }
            <span class="hljs-string">agent</span> <span class="hljs-string">any</span>
            <span class="hljs-string">steps</span> {
                <span class="hljs-string">script</span> {                    
                    <span class="hljs-string">sh</span> <span class="hljs-string">'docker tag $IMAGE_NAME:$LOCAL_TAG $DOCKERHUB_USER/$IMAGE_NAME:$IMAGE_TAG'</span>
                    <span class="hljs-string">sh</span> <span class="hljs-string">'docker tag $IMAGE_NAME:$LOCAL_TAG $DOCKERHUB_USER/$IMAGE_NAME:$GIT_COMMIT'</span>
                    <span class="hljs-string">sh</span> <span class="hljs-string">'echo $DOCKERHUB_TOKEN | docker login -u $DOCKERHUB_USER --password-stdin'</span>
                    <span class="hljs-string">sh</span> <span class="hljs-string">'docker push $DOCKERHUB_USER/$IMAGE_NAME:$IMAGE_TAG'</span>
                    <span class="hljs-string">sh</span> <span class="hljs-string">'docker push $DOCKERHUB_USER/$IMAGE_NAME:$GIT_COMMIT'</span>  
                    <span class="hljs-string">sh</span> <span class="hljs-string">'echo "Publication de l image sur DockerHub..." '</span>
                }
            }
        }
</code></pre>
<h1 id="heading-5-utilisation-dansible-pour-le-deploiement-cd">5. Utilisation d'Ansible pour le déploiement (CD)</h1>
<h2 id="heading-51-creation-des-roles-ansible-pour-odoo-postgres-pgadmin-et-ic-webapp">5.1. Création des rôles Ansible pour Odoo, postgres, pgAdmin et ic-webapp</h2>
<h3 id="heading-511-utilisation-des-docker-compose-dans-ansible-pour-la-creation-dun-role-playbook-odoo-et-postgres">5.1.1. Utilisation des docker-compose dans Ansible pour la création d'un role, playbook odoo et postgres</h3>
<h4 id="heading-description-du-role-odoo"><strong>Description du role odoo</strong></h4>
<blockquote>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1715109049747/313889d7-9ae3-46f6-8164-54dd558a57d7.png" alt class="image--center mx-auto" /></p>
<p><em>Organisation des répertoires du rôle</em></p>
</blockquote>
<h3 id="heading-512-structure-du-role-ansible-pour-odoo">5.1.2 Structure du role Ansible pour Odoo</h3>
<p><strong>1. Variables (vars/main.yml et defaults/main.yml):</strong></p>
<p><strong>vars/main.yml:</strong> Contient les configurations spécifiques nécessaires pour le déploiement, comme les images Docker pour Odoo et PostgreSQL, les ports, et les volumes.</p>
<p><strong>defaults/main.yml:</strong> Définit les valeurs par défaut qui peuvent être utilisées globalement ou surchargées spécifiquement lors de l'exécution du playbook.</p>
<p><strong>2. Template Docker Compose (templates/odoo-template.yml.j2):</strong></p>
<p>Ce fichier est un modèle Jinja2 pour Docker Compose qui configure les services Odoo et PostgreSQL. Il inclut des directives pour les volumes, les réseaux, et les secrets nécessaires pour sécuriser la communication entre les services.</p>
<pre><code class="lang-yaml"><span class="hljs-attr">version:</span> <span class="hljs-string">'3.7'</span>

<span class="hljs-attr">services:</span>
  <span class="hljs-attr">odoo_web_service:</span>
    <span class="hljs-attr">image:</span> {{ <span class="hljs-string">ODOO_IMAGE</span> }}
    <span class="hljs-attr">depends_on:</span>
      <span class="hljs-bullet">-</span> <span class="hljs-string">db</span>
    <span class="hljs-attr">ports:</span>
      <span class="hljs-bullet">-</span> <span class="hljs-string">"<span class="hljs-template-variable">{{ ODOO_PORT }}</span>:8069"</span>
    <span class="hljs-attr">volumes:</span>
      <span class="hljs-bullet">-</span> <span class="hljs-string">"<span class="hljs-template-variable">{{ ODOO_DATA_VOLUME }}</span>:/var/lib/odoo"</span>
      <span class="hljs-bullet">-</span> <span class="hljs-string">"<span class="hljs-template-variable">{{ ODOO_CONFIG_VOLUME }}</span>:/etc/odoo"</span>
      <span class="hljs-bullet">-</span> <span class="hljs-string">"<span class="hljs-template-variable">{{ ODOO_ADDONS_VOLUME }}</span>:/mnt/extra-addons"</span>
    <span class="hljs-attr">networks:</span>
      <span class="hljs-bullet">-</span> <span class="hljs-string">odoo_network</span>
    <span class="hljs-attr">environment:</span>
      <span class="hljs-bullet">-</span> <span class="hljs-string">PASSWORD_FILE=/run/secrets/postgresql_password</span>
    <span class="hljs-attr">secrets:</span>
      <span class="hljs-bullet">-</span> <span class="hljs-string">postgresql_password</span>
    <span class="hljs-attr">restart:</span> <span class="hljs-string">always</span>

  <span class="hljs-attr">db:</span>
    <span class="hljs-attr">image:</span> {{ <span class="hljs-string">POSTGRES_IMAGE</span> }}
    <span class="hljs-attr">environment:</span>
      <span class="hljs-bullet">-</span> <span class="hljs-string">POSTGRES_DB={{</span> <span class="hljs-string">POSTGRES_DB</span> <span class="hljs-string">}}</span>
      <span class="hljs-bullet">-</span> <span class="hljs-string">POSTGRES_PASSWORD_FILE=/run/secrets/postgresql_password</span>
      <span class="hljs-bullet">-</span> <span class="hljs-string">POSTGRES_USER={{</span> <span class="hljs-string">POSTGRES_USER</span> <span class="hljs-string">}}</span>
      <span class="hljs-bullet">-</span> <span class="hljs-string">PGDATA=/var/lib/postgresql/data/pgdata</span>
    <span class="hljs-attr">volumes:</span>
      <span class="hljs-bullet">-</span> <span class="hljs-string">"<span class="hljs-template-variable">{{ POSTGRES_DATA_VOLUME }}</span>:/var/lib/postgresql/data/pgdata"</span>
    <span class="hljs-attr">secrets:</span>
      <span class="hljs-bullet">-</span> <span class="hljs-string">postgresql_password</span>
    <span class="hljs-attr">networks:</span>
      <span class="hljs-bullet">-</span> <span class="hljs-string">odoo_network</span>
    <span class="hljs-attr">restart:</span> <span class="hljs-string">always</span>

<span class="hljs-attr">networks:</span>
  <span class="hljs-attr">odoo_network:</span>
    <span class="hljs-attr">driver:</span> <span class="hljs-string">bridge</span>

<span class="hljs-attr">volumes:</span>
  {{ <span class="hljs-string">ODOO_DATA_VOLUME</span> }}<span class="hljs-string">:</span>
  {{ <span class="hljs-string">POSTGRES_DATA_VOLUME</span> }}<span class="hljs-string">:</span>

<span class="hljs-attr">secrets:</span>
  <span class="hljs-attr">postgresql_password:</span>
    <span class="hljs-attr">file:</span> {{ <span class="hljs-string">POSTGRES_PASSWORD_FILE</span> }}
</code></pre>
<p>ce template reprend intégralement la structure d'un <strong>docker compose conventionnel</strong> et intègre des variable ansible, ce qui le rend flexible et réutilisable selon le contexte</p>
<ol start="2">
<li><strong>Tâches Ansible (tasks/main.yml):</strong></li>
</ol>
<p><strong>Création du répertoire Docker Compose:</strong></p>
<pre><code class="lang-yaml"><span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Ensure</span> <span class="hljs-string">the</span> <span class="hljs-string">Docker</span> <span class="hljs-string">Compose</span> <span class="hljs-string">directory</span> <span class="hljs-string">exists</span>
  <span class="hljs-attr">ansible.builtin.file:</span>
    <span class="hljs-attr">path:</span> <span class="hljs-string">"<span class="hljs-template-variable">{{ odoo_compose_directory }}</span>"</span>
    <span class="hljs-attr">state:</span> <span class="hljs-string">directory</span>
</code></pre>
<p>Cette tâche crée le répertoire où le fichier Docker Compose sera stocké et ensuite exécuté, cela permet de s'assurer de l'emplacement du fichier avant toutes actions futures</p>
<p><strong>Gestion des secrets</strong></p>
<pre><code class="lang-yaml"><span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Ensure</span> <span class="hljs-string">odoo_pg_pass</span> <span class="hljs-string">exists</span>
  <span class="hljs-attr">ansible.builtin.file:</span>
    <span class="hljs-attr">path:</span> <span class="hljs-string">"<span class="hljs-template-variable">{{ POSTGRES_PASSWORD_FILE }}</span>"</span>
    <span class="hljs-attr">state:</span> <span class="hljs-string">touch</span>
    <span class="hljs-attr">mode:</span> <span class="hljs-string">'644'</span>
  <span class="hljs-attr">become:</span> <span class="hljs-literal">true</span>
</code></pre>
<p>Cette tache permet de s'assure que le fichier contenant le mot de passe PostgreSQL existe et est accessible.</p>
<p><strong>Déploiement de la configuration Docker Compose:</strong></p>
<pre><code class="lang-yaml"><span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Deploy</span> <span class="hljs-string">Odoo</span> <span class="hljs-string">Compose</span> <span class="hljs-string">configuration</span>
  <span class="hljs-attr">ansible.builtin.template:</span>
    <span class="hljs-attr">src:</span> <span class="hljs-string">"<span class="hljs-template-variable">{{ odoo_compose_file }}</span>"</span>
    <span class="hljs-attr">dest:</span> <span class="hljs-string">"<span class="hljs-template-variable">{{ odoo_compose_directory }}</span>/odoo-compose.yml"</span>
  <span class="hljs-attr">become:</span> <span class="hljs-literal">true</span>
</code></pre>
<p>Cette tache permet de déployer le fichier Docker Compose dans le répertoire spécifié en utilisant le template Jinja2 précédent.</p>
<p><strong>Exécution de Docker Compose</strong></p>
<pre><code class="lang-bash">- name: Run Docker Compose
  ansible.builtin.shell:
    <span class="hljs-built_in">chdir</span>: <span class="hljs-string">"{{ odoo_compose_directory }}"</span>
    cmd: <span class="hljs-string">"docker-compose -f odoo-compose.yml up -d"</span>
  become: <span class="hljs-literal">true</span>
</code></pre>
<p>Lance les services spécifiés dans le fichier Docker Compose, démarrant ainsi les conteneurs pour Odoo et PostgreSQL.</p>
<p>Pour en savoir plus : <a target="_blank" href="https://gitlab.com/CarlinFongang-Labs/Ansible/Roleshub/odoo_deploy.git">Le role odoo et postgres est disponible sur le dépôt via ce lien</a></p>
<p>Vous pourrez y consulter les variables utilisées ainsi que leurs roles et comment les ajuster</p>
<h4 id="heading-deploiement-de-la-stack-odoo"><strong>Déploiement de la stack Odoo</strong></h4>
<p>Pour mettre en œuvre le stage correspondant au déploiement de la stack Odoo, ayant le role déjà disponible, nous avons commencé par rédigé un playbook, qui à été intégré par la suite dans le stage</p>
<h4 id="heading-description-du-playbook-odoo-deployyml"><strong>Description du playbook odoo-deploy.yml</strong></h4>
<blockquote>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1715109077409/1cb11ff4-ba84-48e3-b375-32ec4e3feb33.png" alt class="image--center mx-auto" /></p>
<p><em>Organisation du playbook Odoo</em></p>
</blockquote>
<p>Le playbook Ansible décrit ci-dessous est conçu pour orchestrer le déploiement de l'application Odoo en utilisant le <a target="_blank" href="https://gitlab.com/CarlinFongang-Labs/Ansible/Roleshub/odoo_deploy.git">roles</a> qui à été mis en place à cet effet et qui facilitent la configuration et la mise en service des instances nécessaires. Ce playbook est structuré en deux phases principales :</p>
<p>vérification de la connectivité SSH via le role <strong>check_ssh"</strong>, l'installation de docker et docker-compose via le role <strong>"prepare_docker"</strong> et la configuration du déploiement d'Odoo via le role <strong>"odoo_deploy"</strong>.</p>
<pre><code class="lang-yaml"><span class="hljs-meta">---</span>
<span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Verify</span> <span class="hljs-string">SSH</span> <span class="hljs-string">Connectivity</span> <span class="hljs-string">on</span> <span class="hljs-string">Dynamic</span> <span class="hljs-string">Hosts</span>
  <span class="hljs-attr">hosts:</span> <span class="hljs-string">dynamic_hosts</span>
  <span class="hljs-attr">gather_facts:</span> <span class="hljs-literal">no</span>
  <span class="hljs-attr">roles:</span>
    <span class="hljs-bullet">-</span> <span class="hljs-string">check_ssh</span>

<span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Setup</span> <span class="hljs-string">Odoo</span>
  <span class="hljs-attr">hosts:</span> <span class="hljs-string">dynamic_hosts</span>
  <span class="hljs-attr">vars_files:</span>
    <span class="hljs-bullet">-</span> <span class="hljs-string">group_vars/all.yml</span>
  <span class="hljs-attr">roles:</span>
    <span class="hljs-bullet">-</span> <span class="hljs-string">prepare_docker</span>
    <span class="hljs-bullet">-</span> <span class="hljs-string">odoo_deploy</span>
</code></pre>
<p><em>fichier odoo-deploy.yml</em></p>
<p>Notez que ce playbook à la particularité d'embarquer une variable ansible dans le fichier hosts.yml, cette variable permet de récupérer l'adresse IP de l'instance sur laquelle sera déployé le stack au moment de l'exécution de celle-ci.</p>
<pre><code class="lang-yaml"><span class="hljs-attr">all:</span>
  <span class="hljs-attr">children:</span>
    <span class="hljs-attr">dynamic_hosts:</span>
      <span class="hljs-attr">vars:</span>
        <span class="hljs-attr">ansible_user:</span> <span class="hljs-string">"<span class="hljs-template-variable">{{ USER_SERVER }}</span>"</span>
      <span class="hljs-attr">hosts:</span>
        <span class="hljs-attr">prod:</span>
          <span class="hljs-attr">ansible_host:</span> <span class="hljs-string">"<span class="hljs-template-variable">{{ lookup('env', 'IP_ODOO') }}</span>"</span>
</code></pre>
<p><em>fichier hosts.yml</em></p>
<p>Pour en savoir plus sur le playbook ainsi que son utilisation : <a target="_blank" href="https://gitlab.com/CarlinFongang-Labs/projet-odoo/deploy-odoo-postgresql-pgadmin/odoo-postgresql-ansible.git">Dépôt du playbook permettant de déployer la stack Odoo+Postgres</a></p>
<h3 id="heading-513-utilisation-des-docker-compose-dans-ansible-pour-la-creation-dun-role-playbook-pgadmin-et-ic-webapp">5.1.3 Utilisation des docker-compose dans Ansible pour la création d'un role, playbook pgAdmin et ic-webapp</h3>
<p>De la même façon que que le role <strong>odoo_deploy</strong> ainsi que le playbook <strong>odoo-deploy</strong> ont été mis en œuvre, nous avons repris intégralement le même process pour l'élaboration des role et playbook ansible de la stack <strong>pgAdmin</strong> et <strong>ic-webapp</strong></p>
<p><a target="_blank" href="https://gitlab.com/CarlinFongang-Labs/Ansible/Roleshub/pgadmin_deploy.git">Pour en savoir plus sur le role pgadmin_deploy ainsi que son utilisation</a></p>
<p><a target="_blank" href="https://gitlab.com/CarlinFongang-Labs/projet-odoo/deploy-odoo-postgresql-pgadmin/pgadmin-webapp-with-ansible.git">Pour en savoir plus sur le playbook pgadmin-deploy ainsi que son utilisation</a></p>
<h1 id="heading-6-automatisation-des-deploiements">6 Automatisation des déploiements</h1>
<h2 id="heading-61-jobs-jenkins-pour-le-deploiement-dodoo-et-pgadmin">6.1. Jobs Jenkins pour le déploiement d'Odoo et PGAdmin</h2>
<h3 id="heading-611-description-du-stage-pour-le-deploiement-de-la-stack-odoo">6.1.1. Description du stage pour le déploiement de la stack Odoo</h3>
<p>Ce stage à pour objectif d'automatiser le déploiement de la pile comprenant l'application Odoo et la base de données PostgreSQL sur une instance ec2 spécifié par la variable <strong>IP_ODOO</strong> dans le fichier hosts.yml.</p>
<pre><code class="lang-yaml">        <span class="hljs-string">stage('Deploy</span> <span class="hljs-string">stack</span> <span class="hljs-string">Odoo_Postgres')</span> {
            <span class="hljs-string">environment</span> {
                <span class="hljs-string">SSH_EC2</span> <span class="hljs-string">=</span> <span class="hljs-string">credentials('SSH_EC2')</span>
            }
            <span class="hljs-string">steps</span> {
                <span class="hljs-string">script</span> { 
                    <span class="hljs-string">sh'''</span>
                        <span class="hljs-string">export</span> <span class="hljs-string">PATH=$PATH:/home/ubuntu/.local/bin</span>
                        <span class="hljs-string">rm</span> <span class="hljs-string">-rf</span> <span class="hljs-string">odoo-stack-deploy</span>
                        <span class="hljs-string">git</span> <span class="hljs-string">clone</span> <span class="hljs-string">$REPO_ODOO</span> <span class="hljs-string">./odoo-stack-deploy</span>
                        <span class="hljs-string">cd</span> <span class="hljs-string">odoo-stack-deploy</span>

                        <span class="hljs-string">ansible-galaxy</span> <span class="hljs-string">install</span> <span class="hljs-string">-r</span> <span class="hljs-string">roles/requirements.yml</span> <span class="hljs-string">-f</span>
                        <span class="hljs-string">chmod</span> <span class="hljs-number">600</span> <span class="hljs-string">$SSH_EC2</span>

                        <span class="hljs-string">ssh</span> <span class="hljs-string">-o</span> <span class="hljs-string">StrictHostKeyChecking=no</span> <span class="hljs-string">-i</span> <span class="hljs-string">$SSH_EC2</span> <span class="hljs-string">$</span>{<span class="hljs-string">USER_SERVER</span>}<span class="hljs-string">@$</span>{<span class="hljs-string">IP_ODOO</span>} <span class="hljs-string">"
                        rm -rf .secrets
                        mkdir .secrets
                        echo "</span><span class="hljs-string">odoo"</span> <span class="hljs-string">&gt;</span> <span class="hljs-string">.secrets/odoo_pg_pass</span>
                        <span class="hljs-string">"

                        ansible-playbook -i hosts.yml odoo-deploy.yml --private-key $SSH_EC2 -vvv  
                    '''
                }
            }
        }</span>
</code></pre>
<h3 id="heading-612-description-du-stage-pour-le-deploiement-de-la-stack-pgadmin">6.1.2. Description du stage pour le déploiement de la stack pgAdmin</h3>
<p>Ce stage à pour objectif d'automatiser le déploiement de la pile comprenant l'application pgAdmin et le site vitrine ic-webapp dont l'image à été buildé à l'entrée du pipeline, ceci sur une instance ec2 spécifié par la variable <strong>IP_PGADMIN</strong> dans le fichier hosts.yml.</p>
<pre><code class="lang-yaml">        <span class="hljs-string">stage('Deploy</span> <span class="hljs-string">stack</span> <span class="hljs-string">PGAdmin_IC_WebApp')</span> {
            <span class="hljs-string">environment</span> {
                <span class="hljs-string">SSH_EC2</span> <span class="hljs-string">=</span> <span class="hljs-string">credentials('SSH_EC2')</span>
            }
            <span class="hljs-string">steps</span> {
                <span class="hljs-string">script</span> { 
                    <span class="hljs-string">sh'''</span>
                        <span class="hljs-string">export</span> <span class="hljs-string">PATH=$PATH:/home/ubuntu/.local/bin</span>
                        <span class="hljs-string">rm</span> <span class="hljs-string">-rf</span> <span class="hljs-string">pgadmin-stack-deploy</span>
                        <span class="hljs-string">git</span> <span class="hljs-string">clone</span> <span class="hljs-string">$REPO_PGADMIN</span>  <span class="hljs-string">./pgadmin-stack-deploy</span>
                        <span class="hljs-string">cd</span> <span class="hljs-string">pgadmin-stack-deploy</span>
                        <span class="hljs-string">ansible-galaxy</span> <span class="hljs-string">install</span> <span class="hljs-string">-r</span> <span class="hljs-string">roles/requirements.yml</span> <span class="hljs-string">-f</span>
                        <span class="hljs-string">chmod</span> <span class="hljs-number">600</span> <span class="hljs-string">$SSH_EC2</span>

                        <span class="hljs-string">ssh</span> <span class="hljs-string">-o</span> <span class="hljs-string">StrictHostKeyChecking=no</span> <span class="hljs-string">-i</span> <span class="hljs-string">$SSH_EC2</span> <span class="hljs-string">$</span>{<span class="hljs-string">USER_SERVER</span>}<span class="hljs-string">@$</span>{<span class="hljs-string">IP_PGADMIN</span>} <span class="hljs-string">"
                        ls
                        "</span>

                        <span class="hljs-string">ansible-playbook</span> <span class="hljs-string">-i</span> <span class="hljs-string">hosts.yml</span> <span class="hljs-string">pgadmin-deploy.yml</span> <span class="hljs-string">--private-key</span> <span class="hljs-string">$SSH_EC2</span> <span class="hljs-string">-vvv</span>
                    <span class="hljs-string">''</span><span class="hljs-string">'
                }
            }
        }</span>
</code></pre>
<h2 id="heading-62-configuration-des-webhook-jenkins-et-gitlab">6.2. Configuration des webhook Jenkins et Gitlab</h2>
<h3 id="heading-etape-1-generer-un-token-gitlab-personnel">Étape 1 : Générer un Token Gitlab personnel</h3>
<p>Générer un Token personnel, pour cela, vous pouvez vous rendre dans Profile Settings &gt; Access Tokens.</p>
<blockquote>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1715109109893/73269d6d-2e77-47e3-b76b-9b23db60417f.png" alt class="image--center mx-auto" /></p>
</blockquote>
<h3 id="heading-etape-2-configurer-jenkins-pour-accepter-les-webhooks-de-gitlab">Étape 2 : Configurer Jenkins pour accepter les webhooks de GitLab</h3>
<p><strong>Installer le Plugin GitLab :</strong> Allez à Manage Jenkins &gt; Manage Plugins &gt; Available, recherchez "GitLab Plugin" et installez-le.</p>
<blockquote>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1715109134185/b80a5edb-e7ea-4702-b5fc-837a76ec2920.png" alt class="image--center mx-auto" /></p>
</blockquote>
<p><strong>Configurer le Plugin GitLab :</strong></p>
<ol>
<li><p>Dans Manage Jenkins &gt; Configure System, descendez jusqu'à la section GitLab.</p>
</li>
<li><p>Renseignez l'URL de GitLab et un token d’accès personnel (Personal Access Token)</p>
</li>
</ol>
<blockquote>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1715109139519/149db1c8-9fd8-448a-b6e9-4cee1c2fc018.png" alt class="image--center mx-auto" /></p>
</blockquote>
<h3 id="heading-etape-3-configurer-le-projet-jenkins-pour-utiliser-gitlab">Étape 3 : Configurer le Projet Jenkins pour utiliser GitLab</h3>
<p><strong>Configurer le Projet (pipeline) Jenkins :</strong></p>
<ol>
<li><p>Ouvrez la configuration dU projet Jenkins. Projet &gt; Configurer</p>
</li>
<li><p>Sous la section Source Code Management, choisissez "Git" et renseignez l’URL de votre dépôt GitLab.</p>
</li>
<li><p>Dans la section Build Triggers, cochez Build when a change is pushed to GitLab. GitLab webhook push doit être sélectionné.</p>
</li>
<li><p>Configurez les autres options selon vos besoins spécifiques (par exemple, les branches à construire).</p>
</li>
</ol>
<blockquote>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1715109148462/fd5bc40f-bd70-4592-a939-e9e25859c4ce.png" alt class="image--center mx-auto" /></p>
</blockquote>
<h3 id="heading-etape-4-creer-un-webhook-dans-gitlab">Étape 4 : Créer un Webhook dans GitLab</h3>
<ol>
<li><p>Accédez au projet dans GitLab</p>
</li>
<li><p>Allez dans Settings &gt; Webhooks.</p>
</li>
<li><p>Entrez l'URL du webhook Jenkins, qui est généralement sous la forme <a target="_blank" href="http://JENKINS_URL/project/NOM_DU_JOB">http://JENKINS_URL/project/NOM_DU_JOB</a>. L'URL exacte dans Jenkins sous la configuration du projet, dans la section Build Triggers.</p>
</li>
<li><p>Choisissez les événements pour lesquels vous souhaitez déclencher des builds. Généralement, vous sélectionnerez "Push events" pour les projets de développement standard. Cliquez sur Add Webhook.</p>
</li>
</ol>
<blockquote>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1715109167734/1cbe17fe-4b75-489a-87a5-1467532e8b5e.png" alt class="image--center mx-auto" /></p>
</blockquote>
<h3 id="heading-etape-5-tester-le-webhook">Étape 5 : Tester le Webhook</h3>
<p>Après avoir configuré le webhook, nous pouvons utiliser le bouton Test à côté du webhook dans GitLab pour envoyer une requête de test à Jenkins et vérifier que la connexion est établie correctement.</p>
<p>Si tout est configuré correctement, Jenkins devrait déclencher un build lorsque le webhook est activé par un push dans le dépôt GitLab.</p>
<blockquote>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1715109176453/7be06a84-5974-437a-adb9-3f13081dfc8e.png" alt class="image--center mx-auto" /></p>
</blockquote>
<h2 id="heading-63-run-et-test-du-pipile">6.3. Run et test du pipile</h2>
<h3 id="heading-631-execution-manuelle-du-pipeline">6.3.1. Exécution manuelle du pipeline</h3>
<p>Apres provisionnement des instances destinées à accueillir Odoo et pgAdmin, nous allons récupérer les IP publics de celle-ci que nous allons renseigner dans le fichier <strong>"releases.txt"</strong>, pour ensuite lancer manuellement notre pipeline et observer le résultat</p>
<blockquote>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1715109281888/0428b1b6-18f9-45c7-9dfe-bad0cc70597b.png" alt class="image--center mx-auto" /></p>
<p><em>Site vitrine ic-webapp</em></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1715109255910/7f2b6070-42c8-4918-832f-9777f1ab3c74.png" alt class="image--center mx-auto" /></p>
<p><em>Acces à l'interface d'Odoo</em></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1715109259441/10639386-0379-4286-a60e-627c66452572.png" alt class="image--center mx-auto" /></p>
<p><em>Acces à l'interface de pgAdmin</em></p>
</blockquote>
<h3 id="heading-632-execution-automatique-du-pipeline-declenchement-via-webhook">6.3.2. Exécution automatique du pipeline (déclenchement via webhook)</h3>
<blockquote>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1715109346953/2bad31de-ea21-4a6b-9d03-a913bd9873cb.png" alt class="image--center mx-auto" /></p>
<p><em>Pipeline update via le webhook</em></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1715109350750/449d8ac1-d92d-4b3b-8dd6-3b6022794b76.png" alt class="image--center mx-auto" /></p>
<p><em>L'application reste disponible après la mise jour du pipeline</em></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1715109355255/b50d053f-a004-4c9f-8b15-f5c302db07f4.png" alt class="image--center mx-auto" /></p>
<p><em>On peut confirmer le bon fonctionnement de webhook également via le détails de la requête push effectué par Gitlab réussie</em></p>
</blockquote>
<h2 id="heading-references">Références</h2>
<p><a target="_blank" href="https://docs.gitlab.com/ee/integration/jenkins.html#grant-jenkins-access-to-the-gitlab-project">Configurer des webhook jenkins et gitlab</a></p>
<p><a target="_blank" href="https://gitlab.com/CarlinFongang-Labs/Terraform/hub/terraform-provide-ec2-instance.git">Provisionner un instance ec2 avec terraform</a></p>
<p><a target="_blank" href="https://gitlab.com/CarlinFongang-Labs/Ansible/lab1-install-ansible.git">Installer Ansible</a></p>
<p><a target="_blank" href="https://gitlab.com/CarlinFongang-Labs/projet-odoo/deploy-odoo-postgresql-pgadmin/odoo-postgresql-ansible.git">Playbook Odoo et PostgreSQL</a></p>
<p><a target="_blank" href="https://gitlab.com/CarlinFongang-Labs/projet-odoo/deploy-odoo-postgresql-pgadmin/pgadmin-webapp-with-ansible.git">Playbook pgAdmin &amp; ic-webapp</a></p>
]]></content:encoded></item><item><title><![CDATA[Kubernetes | Déploiement d'une BD MySQL et Wordpress (PV, PVC, et deployment)]]></title><description><![CDATA[LinkedIn | GitLab | GitHub | Credly

Contexte
Ce laboratoire vise à effectuer un déploiement de Wordpress sur un cluster Kubernetes.
Objectifs

Création d'un déploiement MySQL : Nous mettrons en place un déploiement MySQL avec un seul réplica pour gé...]]></description><link>https://blog.acloud.digital/kubernetes-deploiement-dune-bd-mysql-et-wordpress-pv-pvc-et-deployment</link><guid isPermaLink="true">https://blog.acloud.digital/kubernetes-deploiement-dune-bd-mysql-et-wordpress-pv-pvc-et-deployment</guid><category><![CDATA[Kubernetes]]></category><category><![CDATA[kubeadm]]></category><category><![CDATA[WordPress]]></category><category><![CDATA[MySQL]]></category><category><![CDATA[deployment]]></category><dc:creator><![CDATA[Carlin FONGANG]]></dc:creator><pubDate>Tue, 16 Apr 2024 23:01:24 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/GSiEeoHcNTQ/upload/6757abfa8c6f45ee85c7a473d600cfd7.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<blockquote>
<p><a target="_blank" href="https://www.linkedin.com/in/carlinfongang/">LinkedIn</a> | <a target="_blank" href="https://gitlab.com/carlinfongang">GitLab</a> | <a target="_blank" href="https://github.com/carlinfongang">GitHub</a> | <a target="_blank" href="https://www.credly.com/users/carlin-fongang/badges">Credly</a></p>
</blockquote>
<h2 id="heading-contexte">Contexte</h2>
<p>Ce laboratoire vise à effectuer un déploiement de Wordpress sur un cluster Kubernetes.</p>
<h2 id="heading-objectifs">Objectifs</h2>
<ol>
<li><p><strong>Création d'un déploiement MySQL</strong> : Nous mettrons en place un déploiement MySQL avec un seul réplica pour gérer notre base de données.</p>
</li>
<li><p><strong>Exposition de MySQL</strong> : Un service de type ClusterIP sera créé pour exposer nos pods MySQL, permettant ainsi à d'autres services du cluster de communiquer avec la base de données.</p>
</li>
<li><p><strong>Déploiement de WordPress</strong> : Nous configurerons un déploiement WordPress avec les variables d'environnement nécessaires pour se connecter à la base de données MySQL.</p>
</li>
<li><p><strong>Stockage des données WordPress</strong> : Le déploiement WordPress sera configuré pour stocker les données dans un volume monté sur le répertoire <code>/data</code> d’un des nœuds du cluster, assurant la persistance des données.</p>
</li>
<li><p><strong>Exposition de WordPress</strong> : Nous créerons un service de type NodePort pour exposer l'interface de WordPress à l'extérieur, rendant le site accessible sur internet.</p>
</li>
</ol>
<h2 id="heading-1-prerequis-liste-des-exigences-materielles-et-logicielles">1. <strong>Prérequis</strong> : Liste des exigences matérielles et logicielles.</h2>
<p>Dans notre cas, nous allons provisionner une instances EC2 s'exécutant sous Ubuntu 20.04 Focal Fossa LTS, grace au provider AWS, à partir delaquelle nous effectuerons toutes nos opérations.</p>
<p><a target="_blank" href="https://gitlab.com/CarlinFongang-Labs/Terraform/lab2-terraform-aws">Provisionner une instance EC2 sur AWS à l'aide de Terraform</a> (recommandé)</p>
<p><a target="_blank" href="https://gitlab.com/CarlinFongang-Labs/Ansible/lab10-deploy-ec2">Provisionner une instance EC2 sur AWS à l'aide d'Ansible</a></p>
<h2 id="heading-2-creation-dun-cluster">2. Création d'un cluster</h2>
<p>Consultez le document <a target="_blank" href="https://gitlab.com/CarlinFongang-Labs/kubernetes/lab1.1-install-kubeadm.git">Installer kubeadm</a></p>
<p>Voici une structure détaillée pour la documentation technique sur l'installation de WordPress via Kubernetes :</p>
<h2 id="heading-3-creation-du-persistent-volume">3. Création du Persistent Volume</h2>
<pre><code class="lang-bash">nano mysql-pv.yml
</code></pre>
<p>Description du manfiest</p>
<pre><code class="lang-yaml"><span class="hljs-attr">apiVersion:</span> <span class="hljs-string">v1</span>
<span class="hljs-attr">kind:</span> <span class="hljs-string">PersistentVolume</span>
<span class="hljs-attr">metadata:</span>
  <span class="hljs-attr">name:</span> <span class="hljs-string">mysql-pv</span>
  <span class="hljs-attr">labels:</span>
    <span class="hljs-attr">type:</span> <span class="hljs-string">local</span>
<span class="hljs-attr">spec:</span>
  <span class="hljs-attr">capacity:</span>
    <span class="hljs-attr">storage:</span> <span class="hljs-string">3Gi</span>
  <span class="hljs-attr">volumeMode:</span> <span class="hljs-string">Filesystem</span>
  <span class="hljs-attr">accessModes:</span>
    <span class="hljs-bullet">-</span> <span class="hljs-string">ReadWriteOnce</span>
  <span class="hljs-attr">persistentVolumeReclaimPolicy:</span> <span class="hljs-string">Retain</span>
  <span class="hljs-attr">storageClassName:</span> <span class="hljs-string">standard</span>
  <span class="hljs-attr">hostPath:</span>
    <span class="hljs-attr">path:</span> <span class="hljs-string">/data/mysql-pv</span>
</code></pre>
<pre><code class="lang-bash">kubectl apply -f mysql-pv.yml
</code></pre>
<blockquote>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1713308226990/edb326ec-d802-41cb-a65a-192da860506a.png" alt class="image--center mx-auto" /></p>
<p><em>Le Persistent Volume (PV) a été crée</em></p>
</blockquote>
<h2 id="heading-3-creation-du-deploiement-mysql">3. <strong>Création du déploiement MySQL</strong></h2>
<h3 id="heading-31-manifeste-persistentvolumeclaim">3.1. Manifeste PersistentVolumeClaim</h3>
<pre><code class="lang-bash">nano mysql-pvc.yml
</code></pre>
<pre><code class="lang-yaml"><span class="hljs-attr">apiVersion:</span> <span class="hljs-string">v1</span>
<span class="hljs-attr">kind:</span> <span class="hljs-string">PersistentVolumeClaim</span>
<span class="hljs-attr">metadata:</span>
  <span class="hljs-attr">name:</span> <span class="hljs-string">mysql-pvc</span>
<span class="hljs-attr">spec:</span>
  <span class="hljs-attr">accessModes:</span>
    <span class="hljs-bullet">-</span> <span class="hljs-string">ReadWriteOnce</span>
  <span class="hljs-attr">volumeMode:</span> <span class="hljs-string">Filesystem</span>
  <span class="hljs-attr">resources:</span>
    <span class="hljs-attr">requests:</span>
      <span class="hljs-attr">storage:</span> <span class="hljs-string">2Gi</span>
  <span class="hljs-attr">storageClassName:</span> <span class="hljs-string">standard</span>
</code></pre>
<pre><code class="lang-bash">kubectl apply -f mysql-pvc.yml
</code></pre>
<blockquote>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1713308254388/6de4fc0c-f417-42e0-8eec-9daf5cdd5e32.png" alt class="image--center mx-auto" /></p>
</blockquote>
<h3 id="heading-32-details-du-manifeste-de-deploiement">3.2. Détails du manifeste de déploiement.</h3>
<pre><code class="lang-bash">nano mysql-deployment.yml
</code></pre>
<p>Contenu du manifest</p>
<pre><code class="lang-yaml"><span class="hljs-attr">apiVersion:</span> <span class="hljs-string">apps/v1</span>
<span class="hljs-attr">kind:</span> <span class="hljs-string">Deployment</span>
<span class="hljs-attr">metadata:</span>
  <span class="hljs-attr">name:</span> <span class="hljs-string">wordpress-mysql</span>
<span class="hljs-attr">spec:</span>
  <span class="hljs-attr">replicas:</span> <span class="hljs-number">1</span>
  <span class="hljs-attr">selector:</span>
    <span class="hljs-attr">matchLabels:</span>
      <span class="hljs-attr">app:</span> <span class="hljs-string">mysql</span>
  <span class="hljs-attr">template:</span>
    <span class="hljs-attr">metadata:</span>
      <span class="hljs-attr">labels:</span>
        <span class="hljs-attr">app:</span> <span class="hljs-string">mysql</span>
    <span class="hljs-attr">spec:</span>
      <span class="hljs-attr">containers:</span>
      <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">mysql</span>
        <span class="hljs-attr">image:</span> <span class="hljs-string">mysql:latest</span>
        <span class="hljs-attr">env:</span>
        <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">MYSQL_ROOT_PASSWORD</span>
          <span class="hljs-attr">value:</span> <span class="hljs-string">"password"</span>
        <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">MYSQL_DATABASE</span>
          <span class="hljs-attr">value:</span> <span class="hljs-string">"db-acd"</span>
        <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">MYSQL_USER</span>
          <span class="hljs-attr">value:</span> <span class="hljs-string">"acd"</span>
        <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">MYSQL_PASSWORD</span>
          <span class="hljs-attr">value:</span> <span class="hljs-string">"devops-acd"</span>
        <span class="hljs-attr">ports:</span>
        <span class="hljs-bullet">-</span> <span class="hljs-attr">containerPort:</span> <span class="hljs-number">3306</span>
        <span class="hljs-attr">volumeMounts:</span>
        <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">mysql-data</span>
          <span class="hljs-attr">mountPath:</span> <span class="hljs-string">/var/lib/mysql</span>
      <span class="hljs-attr">volumes:</span>
      <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">mysql-data</span>
        <span class="hljs-attr">persistentVolumeClaim:</span>
          <span class="hljs-attr">claimName:</span> <span class="hljs-string">mysql-pvc</span>
</code></pre>
<pre><code class="lang-bash">kubectl apply -f mysql-deployment.yml
</code></pre>
<p>Nous pouvons vérifier les pods en cours d'exécution :</p>
<pre><code class="lang-bash">kubectl get pod
</code></pre>
<blockquote>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1713308267920/e5db000e-0c45-40fa-b474-8e90b43031d8.png" alt class="image--center mx-auto" /></p>
<p><em>Pod mysql en cours d'exécution</em></p>
</blockquote>
<p>L'on peut vérifier également les détails du pod en cours d'exécution et constater et constater qu'il utiliser bien le PVC déclaré un précédement</p>
<pre><code class="lang-bash"> kubectl describe pods wordpress-mysql-75b599b99-9d756
</code></pre>
<blockquote>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1713308277344/16d4e1b2-a938-4245-836d-0b38bc9fd6de.png" alt class="image--center mx-auto" /></p>
</blockquote>
<h3 id="heading-33-creation-du-service-clusterip-pour-mysql">3.3. Création du service ClusterIP pour MySQL.</h3>
<p>Pour permettre à d'autres pods de communiquer avec MySQL, nous exposerons le déploiement via un service de type ClusterIP.</p>
<pre><code class="lang-bash">nano sv-mysql.yml
</code></pre>
<pre><code class="lang-yaml"><span class="hljs-attr">apiVersion:</span> <span class="hljs-string">v1</span>
<span class="hljs-attr">kind:</span> <span class="hljs-string">Service</span>
<span class="hljs-attr">metadata:</span>
  <span class="hljs-attr">name:</span> <span class="hljs-string">sv-mysql</span>
<span class="hljs-attr">spec:</span>
  <span class="hljs-attr">type:</span> <span class="hljs-string">ClusterIP</span>
  <span class="hljs-attr">ports:</span>
  <span class="hljs-bullet">-</span> <span class="hljs-attr">port:</span> <span class="hljs-number">3306</span>
  <span class="hljs-attr">selector:</span>
    <span class="hljs-attr">app:</span> <span class="hljs-string">mysql</span>
</code></pre>
<pre><code class="lang-bash">kubectl apply -f sv-mysql.yml
</code></pre>
<blockquote>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1713308286092/d6542c84-5810-40a6-a67d-5c59f412fd58.png" alt class="image--center mx-auto" /></p>
<p><em>ClusterIP en cours d'exécution</em></p>
</blockquote>
<p>En entrant la commande ci-dessous, on peut virifier que le ClusterIP est bien exécuté et associé aux pod dont le label est bien <strong>"app=mysql"</strong></p>
<pre><code class="lang-bash">kubectl describe svc sv-mysql
</code></pre>
<blockquote>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1713308293279/ba8d68b4-e5ad-44e3-b48d-f9706156c70b.png" alt class="image--center mx-auto" /></p>
</blockquote>
<h2 id="heading-4-installation-de-wordpress">4. <strong>Installation de WordPress</strong></h2>
<h3 id="heading-41-creation-du-persistent-volume">4.1. Création du Persistent Volume</h3>
<pre><code class="lang-bash">nano wordpress-pv.yml
</code></pre>
<pre><code class="lang-yaml"><span class="hljs-attr">apiVersion:</span> <span class="hljs-string">v1</span>
<span class="hljs-attr">kind:</span> <span class="hljs-string">PersistentVolume</span>
<span class="hljs-attr">metadata:</span>
  <span class="hljs-attr">name:</span> <span class="hljs-string">wordpress-pv</span>
  <span class="hljs-attr">labels:</span>
    <span class="hljs-attr">type:</span> <span class="hljs-string">local</span>
<span class="hljs-attr">spec:</span>
  <span class="hljs-attr">capacity:</span>
    <span class="hljs-attr">storage:</span> <span class="hljs-string">3Gi</span>
  <span class="hljs-attr">volumeMode:</span> <span class="hljs-string">Filesystem</span>
  <span class="hljs-attr">accessModes:</span>
    <span class="hljs-bullet">-</span> <span class="hljs-string">ReadWriteOnce</span>
  <span class="hljs-attr">persistentVolumeReclaimPolicy:</span> <span class="hljs-string">Retain</span>
  <span class="hljs-attr">storageClassName:</span> <span class="hljs-string">standard</span>
  <span class="hljs-attr">hostPath:</span>
    <span class="hljs-attr">path:</span> <span class="hljs-string">/data/wordpress-pv</span>
</code></pre>
<pre><code class="lang-bash">kubectl apply -f wordpress-pv.yml
</code></pre>
<blockquote>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1713308298919/f7587fc6-c441-4a72-8a8d-b14424cc17ca.png" alt class="image--center mx-auto" /></p>
</blockquote>
<h3 id="heading-42-manifeste-persistentvolumeclaim-pour-wordpress">4.2. Manifeste PersistentVolumeClaim pour WordPress</h3>
<pre><code class="lang-bash">nano wordpress-pvc.yml
</code></pre>
<pre><code class="lang-yaml"><span class="hljs-attr">apiVersion:</span> <span class="hljs-string">v1</span>
<span class="hljs-attr">kind:</span> <span class="hljs-string">PersistentVolumeClaim</span>
<span class="hljs-attr">metadata:</span>
  <span class="hljs-attr">name:</span> <span class="hljs-string">wordpress-pvc</span>
<span class="hljs-attr">spec:</span>
  <span class="hljs-attr">storageClassName:</span> <span class="hljs-string">standard</span>
  <span class="hljs-attr">accessModes:</span>
    <span class="hljs-bullet">-</span> <span class="hljs-string">ReadWriteOnce</span>
  <span class="hljs-attr">resources:</span>
    <span class="hljs-attr">requests:</span>
      <span class="hljs-attr">storage:</span> <span class="hljs-string">2Gi</span>
</code></pre>
<pre><code class="lang-bash">kubectl apply -f wordpress-pvc.yml
</code></pre>
<blockquote>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1713308306689/5037c675-727d-4307-a6dc-c3158630b92a.png" alt class="image--center mx-auto" /></p>
</blockquote>
<h3 id="heading-43-manifest-de-deploiement-de-wordpress">4.3. Manifest de déploiement de WordPress.</h3>
<pre><code class="lang-bash">nano wordpress-deployment.yml
</code></pre>
<pre><code class="lang-yaml"><span class="hljs-attr">apiVersion:</span> <span class="hljs-string">apps/v1</span>
<span class="hljs-attr">kind:</span> <span class="hljs-string">Deployment</span>
<span class="hljs-attr">metadata:</span>
  <span class="hljs-attr">name:</span> <span class="hljs-string">wordpress</span>
<span class="hljs-attr">spec:</span>
  <span class="hljs-attr">replicas:</span> <span class="hljs-number">1</span>
  <span class="hljs-attr">selector:</span>
    <span class="hljs-attr">matchLabels:</span>
      <span class="hljs-attr">app:</span> <span class="hljs-string">wordpress</span>
  <span class="hljs-attr">template:</span>
    <span class="hljs-attr">metadata:</span>
      <span class="hljs-attr">labels:</span>
        <span class="hljs-attr">app:</span> <span class="hljs-string">wordpress</span>
    <span class="hljs-attr">spec:</span>
      <span class="hljs-attr">containers:</span>
      <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">wordpress</span>
        <span class="hljs-attr">image:</span> <span class="hljs-string">wordpress:latest</span>
        <span class="hljs-attr">env:</span>
        <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">WORDPRESS_DB_HOST</span>
          <span class="hljs-attr">value:</span> <span class="hljs-string">"sv-mysql"</span>  <span class="hljs-comment"># Doit correspondre au nom du service qui expose MySQL</span>
        <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">WORDPRESS_DB_USER</span>
          <span class="hljs-attr">value:</span> <span class="hljs-string">"acd"</span>              <span class="hljs-comment"># Doit correspondre à MYSQL_USER</span>
        <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">WORDPRESS_DB_PASSWORD</span>
          <span class="hljs-attr">value:</span> <span class="hljs-string">"devops-acd"</span>       <span class="hljs-comment"># Doit correspondre à MYSQL_PASSWORD</span>
        <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">WORDPRESS_DB_NAME</span>
          <span class="hljs-attr">value:</span> <span class="hljs-string">"db-acd"</span>           <span class="hljs-comment"># Doit correspondre à MYSQL_DATABASE</span>
        <span class="hljs-attr">ports:</span>
        <span class="hljs-bullet">-</span> <span class="hljs-attr">containerPort:</span> <span class="hljs-number">80</span>
        <span class="hljs-attr">volumeMounts:</span>
        <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">wordpress-storage</span>
          <span class="hljs-attr">mountPath:</span> <span class="hljs-string">/var/www/html</span>
      <span class="hljs-attr">volumes:</span>
      <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">wordpress-storage</span>
        <span class="hljs-attr">persistentVolumeClaim:</span>
          <span class="hljs-attr">claimName:</span> <span class="hljs-string">wordpress-pvc</span>
</code></pre>
<pre><code class="lang-bash"> kubectl get deploy
</code></pre>
<blockquote>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1713308317829/b4fa5fc6-5301-42d2-b7f1-93c38f8913d4.png" alt class="image--center mx-auto" /></p>
</blockquote>
<p>On peut également vérifier à quel PVC le pod wordpress est rataché</p>
<pre><code class="lang-bash">kubectl get pod
</code></pre>
<p>ensuite</p>
<pre><code class="lang-bash">kubectl describe pods wordpress-6bcf6b499b-92b2z
</code></pre>
<blockquote>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1713308325563/4fbbcff2-7c6a-451b-af60-d2df68afbe07.png" alt class="image--center mx-auto" /></p>
</blockquote>
<h3 id="heading-43-exposition-de-wordpress">4.3. Exposition de wordpress</h3>
<pre><code class="lang-bash">nano sv-wordpress.yml
</code></pre>
<pre><code class="lang-yaml"><span class="hljs-attr">apiVersion:</span> <span class="hljs-string">v1</span>
<span class="hljs-attr">kind:</span> <span class="hljs-string">Service</span>
<span class="hljs-attr">metadata:</span>
  <span class="hljs-attr">name:</span> <span class="hljs-string">wordpress</span>
<span class="hljs-attr">spec:</span>
  <span class="hljs-attr">type:</span> <span class="hljs-string">NodePort</span>
  <span class="hljs-attr">ports:</span>
  <span class="hljs-bullet">-</span> <span class="hljs-attr">port:</span> <span class="hljs-number">80</span>
    <span class="hljs-attr">targetPort:</span> <span class="hljs-number">80</span>
    <span class="hljs-attr">nodePort:</span> <span class="hljs-number">30000</span>
  <span class="hljs-attr">selector:</span>
    <span class="hljs-attr">app:</span> <span class="hljs-string">wordpress</span>
</code></pre>
<pre><code class="lang-bash">kubectl apply -f sv-wordpress.yml
</code></pre>
<pre><code class="lang-bash">kubectl get services
</code></pre>
<blockquote>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1713308335191/f8ce8518-85f2-4557-993d-a231dcde6873.png" alt class="image--center mx-auto" /></p>
</blockquote>
<ol start="5">
<li><strong>Vérification et Tests</strong></li>
</ol>
<p>En entrant l'ip d'un des nodes suivi du port 30000 dans le navigateur, on accède à la page de configuration de wordpress</p>
<blockquote>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1713308341260/2defce6f-3383-48c2-980f-0030a34e86e1.png" alt class="image--center mx-auto" /></p>
</blockquote>
<h2 id="heading-documentation">Documentation</h2>
<h3 id="heading-volumes-persistantshttpskubernetesiofrdocsconceptsstoragepersistent-volumes"><a target="_blank" href="https://kubernetes.io/fr/docs/concepts/storage/persistent-volumes/">Volumes Persistants</a></h3>
<h3 id="heading-installer-kubeadm-sur-ubuntuhttpskubernetesiodocssetupproduction-environmenttoolskubeadminstall-kubeadm"><a target="_blank" href="https://kubernetes.io/docs/setup/production-environment/tools/kubeadm/install-kubeadm/">Installer kubeadm sur ubuntu</a></h3>
<h3 id="heading-creating-a-single-control-plane-cluster-with-kubeadmhttpskubernetesiodocssetupproduction-environmenttoolskubeadmcreate-cluster-kubeadm"><a target="_blank" href="https://kubernetes.io/docs/setup/production-environment/tools/kubeadm/create-cluster-kubeadm/">Creating a Single Control-Plane Cluster with kubeadm</a></h3>
]]></content:encoded></item><item><title><![CDATA[Kubernetes | Volume et stockage persistant]]></title><description><![CDATA[LinkedIn | GitLab | GitHub | Credly


Contexte
Ce lab vise à présenter les étapes de mise en place d'un volume persistant sur Kubernetes.
Objectifs
Dans ce laboratoire, nous allons mettre en place un environnement utilisant Kubernetes pour démontrer ...]]></description><link>https://blog.acloud.digital/kubernetes-volume-et-stockage-persistant</link><guid isPermaLink="true">https://blog.acloud.digital/kubernetes-volume-et-stockage-persistant</guid><category><![CDATA[Kubernetes]]></category><category><![CDATA[kubeadm]]></category><category><![CDATA[volume]]></category><dc:creator><![CDATA[Carlin FONGANG]]></dc:creator><pubDate>Sun, 14 Apr 2024 12:07:27 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/ZfVyuV8l7WU/upload/c1940aa2552daa326c0d0c9024108828.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<blockquote>
<p><a target="_blank" href="https://www.linkedin.com/in/carlinfongang/">LinkedIn</a> | <a target="_blank" href="https://gitlab.com/carlinfongang">GitLab</a> | <a target="_blank" href="https://github.com/carlinfongang">GitHub</a> | <a target="_blank" href="https://www.credly.com/users/carlin-fongang/badges">Credly</a></p>
</blockquote>
<hr />
<h2 id="heading-contexte">Contexte</h2>
<p>Ce lab vise à présenter les étapes de mise en place d'un volume persistant sur Kubernetes.</p>
<h2 id="heading-objectifs">Objectifs</h2>
<p>Dans ce laboratoire, nous allons mettre en place un environnement utilisant Kubernetes pour démontrer l'utilisation de volumes persistants avec MySQL :</p>
<ol>
<li><p><strong>Création du Pod MySQL</strong> :</p>
<ul>
<li><p>Rédigez un manifeste <code>mysql-volume.yml</code> pour déployer un pod MySQL nommé <code>mysql-volume</code>. Configurez les variables d'environnement pour le nom de la base de données, l'utilisateur, et les mots de passe.</p>
</li>
<li><p>Assurez-vous que le répertoire de données MySQL soit persistant en le montant sur <code>/data-volume</code>.</p>
</li>
</ul>
</li>
<li><p><strong>Gestion des Volumes</strong> :</p>
<ul>
<li><p>Écrivez un manifeste <code>pv.yml</code> pour créer un volume persistant (PV) de 5 Go, utilisant le dossier local <code>local/data-pv</code>.</p>
</li>
<li><p>Rédigez un manifeste <code>pvc.yml</code> pour un claim de volume persistant (PVC) de 1 Go qui utilise le PV créé précédemment.</p>
</li>
</ul>
</li>
<li><p><strong>Déploiement de MySQL avec PVC</strong> :</p>
<ul>
<li>Déployez MySQL avec le PVC à l'aide d'un nouveau manifeste <code>mysql-pv.yml</code>, assurant que MySQL utilise ce volume pour le stockage des données.</li>
</ul>
</li>
<li><p><strong>Vérifications</strong> :</p>
<ul>
<li><p>Lancez les ressources et vérifiez que le pod MySQL est bien démarré et utilise le dossier <code>/data-volume</code>.</p>
</li>
<li><p>Confirmez que les PV et PVC sont correctement créés et prêts à être utilisés.</p>
</li>
</ul>
</li>
</ol>
<h2 id="heading-1-definition-des-concepts">1. Définition des concepts</h2>
<h3 id="heading-11-cest-quoi-un-volume-persistant-pv">1.1. C'est quoi un Volume Persistant (PV) ?</h3>
<p>Un Volume Persistant (PV) dans Kubernetes est une ressource dans le cluster qui permet de stocker des données de manière persistante, indépendamment du cycle de vie des pods qui les utilisent. Les PV sont des volumes de stockage provisionnés par un administrateur ou dynamiquement par Kubernetes à l'aide de classes de stockage. Ils offrent une manière de gérer des volumes de stockage sur une infrastructure sous-jacente, permettant aux utilisateurs de consommer du stockage abstrait sans se préoccuper des détails spécifiques à un environnement ou un fournisseur.</p>
<h3 id="heading-12-cest-quoi-un-persistent-volume-claim-pvc">1.2. C'est quoi un Persistent Volume Claim (PVC) ?</h3>
<p>Un Persistent Volume Claim (PVC) dans Kubernetes est une requête de stockage. Il permet de demander des ressources de stockage spécifiques (taille et accessibilités), qui sont ensuite liées à des Persistent Volumes (PV) existants dans le cluster selon leur capacité et leurs accès. Un PVC consomme des ressources de PV, agissant comme une sorte de ticket pour l’utilisation de ressources de stockage définies dans un PV. Cela permet une abstraction entre la demande et la provision de stockage, offrant ainsi flexibilité et automatisation.</p>
<h2 id="heading-2-prerequis-liste-des-exigences-materielles-et-logicielles">2. <strong>Prérequis</strong> : Liste des exigences matérielles et logicielles.</h2>
<p>Dans notre cas, nous allons provisionner une instances EC2 s'exécutant sous Ubuntu 20.04 Focal Fossa LTS, grace au provider AWS, à partir delaquelle nous effectuerons toutes nos opérations.</p>
<p><a target="_blank" href="https://gitlab.com/CarlinFongang-Labs/Terraform/lab2-terraform-aws">Provisionner une instance EC2 sur AWS à l'aide de Terraform</a> (recommandé)</p>
<p><a target="_blank" href="https://gitlab.com/CarlinFongang-Labs/Ansible/lab10-deploy-ec2">Provisionner une instance EC2 sur AWS à l'aide d'Ansible</a></p>
<p>Nos nodes tournent sous ubuntu 20.04 LTS.</p>
<h2 id="heading-2-creation-dun-cluster">2. Création d'un cluster</h2>
<p>Consultez le document <a target="_blank" href="https://gitlab.com/CarlinFongang-Labs/kubernetes/lab1.1-install-kubeadm.git">Installer kubeadm</a></p>
<h2 id="heading-3-deploiement-du-pod-mysql">3. Déploiement du Pod MySQL</h2>
<h3 id="heading-31-redaction-du-manifeste-mysql-volumeyml">3.1. Rédaction du manifeste <code>mysql-volume.yml</code>.</h3>
<pre><code class="lang-bash">sudo nano mysql-volume.yml
</code></pre>
<pre><code class="lang-yaml"><span class="hljs-attr">apiVersion:</span> <span class="hljs-string">v1</span>
<span class="hljs-attr">kind:</span> <span class="hljs-string">Pod</span>
<span class="hljs-attr">metadata:</span>
<span class="hljs-attr">name:</span> <span class="hljs-string">mysql-volume</span>
<span class="hljs-attr">spec:</span>
<span class="hljs-attr">containers:</span>
<span class="hljs-bullet">-</span> <span class="hljs-attr">image:</span> <span class="hljs-string">mysql</span>
  <span class="hljs-attr">name:</span> <span class="hljs-string">mysql</span>
  <span class="hljs-attr">volumeMounts:</span>
  <span class="hljs-bullet">-</span> <span class="hljs-attr">montPath:</span> <span class="hljs-string">/var/lib/mysql</span>
    <span class="hljs-attr">name:</span> <span class="hljs-string">mysql-data</span>
  <span class="hljs-attr">env:</span>
    <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">MYSQL_ROOT_PASSWORD</span>
      <span class="hljs-attr">value:</span> <span class="hljs-string">password</span>
    <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">MYSQL_DATABASE</span>
      <span class="hljs-attr">value:</span> <span class="hljs-string">db-acd</span> 
    <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">MYSQL_USER</span>
      <span class="hljs-attr">value:</span> <span class="hljs-string">acd</span>
    <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">MYSQL_PASSWORD</span>
      <span class="hljs-attr">value:</span> <span class="hljs-string">devops-acd</span>
<span class="hljs-attr">volumes:</span>
<span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">mysql-data</span>
  <span class="hljs-attr">hostPath:</span>
    <span class="hljs-comment">#Path hote</span>
    <span class="hljs-attr">path:</span> <span class="hljs-string">/data-volume</span>
    <span class="hljs-attr">type:</span> <span class="hljs-string">Directory</span>
</code></pre>
<p>Dans ce manifeste nous définissons un <strong>Pod</strong> Kubernetes nommé <code>mysql-volume</code> qui utilise l'image officielle <code>mysql</code>. Le Pod est configuré avec un volume nommé <code>mysql-data</code> monté sur <code>/var/lib/mysql</code>, ce qui indique que les données de MySQL seront stockées dans un répertoire spécifique sur l'hôte. Les variables d'environnement définies dans le manifeste configurent les paramètres de base de données MySQL, y compris le mot de passe root, le nom de la base de données, l'utilisateur, et le mot de passe de l'utilisateur. Le volume <code>mysql-data</code> utilise <code>hostPath</code> pour lier le répertoire <code>/data-volume</code> sur l'hôte physique, assurant la persistance des données.</p>
<p>L'on va crée un repertoire <strong>"/data-volume"</strong> sur nos nodes <strong>worker1</strong> et <strong>worker2</strong></p>
<pre><code class="lang-bash">sudo mkdir /data-volume
</code></pre>
<pre><code class="lang-bash">kubectl apply -f mysql-volume.yml
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1713096208372/6c8bd57d-b602-4c0c-b3ca-58104295e88d.png" alt class="image--center mx-auto" /></p>
<h3 id="heading-32-verification-du-contenu-de-data-volume">3.2. Vérification du contenu de <code>/data-volume</code>.</h3>
<pre><code class="lang-bash">ls /data-volume/
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1713096224932/584efa3a-2b69-401e-bcc1-bccbac8c6c51.png" alt class="image--center mx-auto" /></p>
<p>Les données du pod <code>mysql-volume</code> sont bien stockées sur le volume persistant <strong>/data-volume</strong> situé sur le worker1</p>
<p>même en supprimant notre pod, les données continuerons d'être sauvegardées</p>
<h2 id="heading-4-gestion-des-volumes">4. Gestion des volumes</h2>
<h3 id="heading-41-creation-et-configuration-du-volume-persistant-pv-avec-pvyml">4.1. Création et configuration du volume persistant (PV) avec <code>pv.yml</code>.</h3>
<pre><code class="lang-bash">sudo nano pv.yml
</code></pre>
<pre><code class="lang-yaml"><span class="hljs-attr">apiVersion:</span> <span class="hljs-string">v1</span>
<span class="hljs-attr">kind:</span> <span class="hljs-string">PersistentVolume</span>
<span class="hljs-attr">metadata:</span>
<span class="hljs-attr">name:</span> <span class="hljs-string">pv</span>
<span class="hljs-attr">labels:</span>
  <span class="hljs-attr">type:</span> <span class="hljs-string">local</span>
<span class="hljs-attr">spec:</span>
<span class="hljs-attr">storageClassName:</span> <span class="hljs-string">manual</span>
<span class="hljs-attr">capacity:</span>
  <span class="hljs-attr">storage:</span> <span class="hljs-string">5Gi</span>
<span class="hljs-attr">accessModes:</span>
  <span class="hljs-bullet">-</span> <span class="hljs-string">ReadWriteOnce</span>
<span class="hljs-attr">hostPath:</span>
  <span class="hljs-attr">path:</span> <span class="hljs-string">"/data-pv"</span>
</code></pre>
<p>Ce <strong>Persistent Volume (PV)</strong> est étiqueté comme un stockage local avec une classe de stockage manuelle spécifiée sous <code>storageClassName: manual</code>. Le PV est configuré avec une capacité de stockage de 5 Go et un mode d'accès <code>ReadWriteOnce</code>, ce qui signifie qu'il peut être monté en lecture-écriture par un seul nœud. Il utilise <code>hostPath</code> pour lier le chemin <code>/data-pv</code> sur l'hôte, destiné à stocker les données persistantes utilisées par les pods dans le cluster.</p>
<pre><code class="lang-bash">kubectl apply -f pv.yml
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1713096235226/78954987-afa6-4a00-95ce-b3948c078b7b.png" alt class="image--center mx-auto" /></p>
<p><em>Le Persistent Volume est bien crée</em></p>
<h3 id="heading-42-creation-du-claim-de-volume-persistant-pvc-avec-pvcyml">4.2. Création du claim de volume persistant (PVC) avec <code>pvc.yml</code>.</h3>
<pre><code class="lang-bash">sudo nano pvc.yml
</code></pre>
<pre><code class="lang-yaml"><span class="hljs-attr">apiVersion:</span> <span class="hljs-string">v1</span>
<span class="hljs-attr">kind:</span> <span class="hljs-string">PersistentVolumeClaim</span>
<span class="hljs-attr">metadata:</span>
<span class="hljs-attr">name:</span> <span class="hljs-string">pvc</span>
<span class="hljs-attr">spec:</span>
<span class="hljs-attr">storageClassName:</span> <span class="hljs-string">manual</span>
<span class="hljs-attr">accessModes:</span>
  <span class="hljs-bullet">-</span> <span class="hljs-string">ReadWriteOnce</span>
<span class="hljs-attr">resources:</span>
  <span class="hljs-attr">requests:</span>
    <span class="hljs-attr">storage:</span> <span class="hljs-string">1Gi</span>
</code></pre>
<p>Nous définissons ici, une demande de volume persistant <strong>PersistentVolumeClaim (PVC)</strong> dans Kubernetes. Le manifest spécifi l'utilisation de la classe de stockage <strong>manual</strong>, nous respectons ici la configuration qui a été faites pour le <strong>PV</strong> plus haut. Le PVC demande un mode d'accès <strong>ReadWriteOnce</strong>, permettant le montage du volume en lecture et écriture sur un seul nœud. Il demande également une capacité de stockage de <strong>1 Gi</strong>. Il est utilisé pour réserver une partie de l'espace de stockage disponible dans un <strong>Persistent Volume</strong> correspondant qui remplit ces critères.</p>
<pre><code class="lang-bash">kubectl apply -f pvc.yml
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1713096246295/18cb2653-f16c-452e-b43f-d087a5ea6dfc.png" alt class="image--center mx-auto" /></p>
<p><em>PVC à été bien crée</em></p>
<h2 id="heading-5-deploiement-de-mysql-avec-stockage-persistant">5. Déploiement de MySQL avec stockage persistant</h2>
<h3 id="heading-51-redaction-du-manifeste-mysql-pvyml">5.1. Rédaction du manifeste <code>mysql-pv.yml</code>.</h3>
<pre><code class="lang-bash">sudo nano mysql-pv.yml
</code></pre>
<pre><code class="lang-yaml"><span class="hljs-attr">apiVersion:</span> <span class="hljs-string">v1</span>
<span class="hljs-attr">kind:</span> <span class="hljs-string">Pod</span>
<span class="hljs-attr">metadata:</span>
<span class="hljs-attr">name:</span> <span class="hljs-string">mysql-pv</span>
<span class="hljs-attr">spec:</span>
<span class="hljs-attr">containers:</span>
<span class="hljs-bullet">-</span> <span class="hljs-attr">image:</span> <span class="hljs-string">mysql</span>
  <span class="hljs-attr">name:</span> <span class="hljs-string">mysql</span>
  <span class="hljs-attr">volumeMounts:</span>
  <span class="hljs-bullet">-</span> <span class="hljs-attr">mountPath:</span> <span class="hljs-string">/var/lib/mysql</span>
    <span class="hljs-attr">name:</span> <span class="hljs-string">mysql-data</span>
  <span class="hljs-attr">env:</span>
    <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">MYSQL_ROOT_PASSWORD</span>
      <span class="hljs-attr">value:</span> <span class="hljs-string">password</span>
    <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">MYSQL_DATABASE</span>
      <span class="hljs-attr">value:</span> <span class="hljs-string">db-acd</span> 
    <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">MYSQL_USER</span>
      <span class="hljs-attr">value:</span> <span class="hljs-string">acd</span>
    <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">MYSQL_PASSWORD</span>
      <span class="hljs-attr">value:</span> <span class="hljs-string">devops-acd</span>
<span class="hljs-attr">volumes:</span>
<span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">mysql-data</span>
  <span class="hljs-attr">persistentVolumeClaim:</span>
    <span class="hljs-attr">claimName:</span> <span class="hljs-string">pvc</span>
</code></pre>
<p>Ce manifeste permet de ployer un Pod dans Kubernetes nommé <code>mysql-pv</code> qui exécute un conteneur basé sur l'image officielle <code>mysql</code>. Le Pod est configuré pour utiliser le <strong>PersistentVolumeClaim</strong><code>pvc</code> crée précédement, pour le stockage des données. Le volume est monté sur le chemin <code>/var/lib/mysql</code> dans le conteneur, ce qui est le répertoire standard où MySQL stocke ses données. Cette configuration assure que les données MySQL sont stockées de manière persistante et restent disponibles même si le Pod est redéployé sur un autre nœud du cluster.</p>
<h3 id="heading-52-deploiement-de-mysql-utilisant-le-pvc">5.2. Déploiement de MySQL utilisant le PVC.</h3>
<pre><code class="lang-bash">kubectl apply -f mysql-pv.yml
</code></pre>
<h3 id="heading-53-verification-et-tests">5.3. Vérification et tests</h3>
<pre><code class="lang-bash">kubectl describe pod mysql-pv
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1713096258100/b7e76277-5a0e-4947-a9a2-64edce97749d.png" alt class="image--center mx-auto" /></p>
<p>Comme on peut le voir sur la capture, le nouveau pod à été deployé sur le <strong>worker2</strong>, on peut donc se connecter sur ce worker afin de vérifier le repertoire <strong>/data-pv/</strong></p>
<pre><code class="lang-bash">ls /data-volume
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1713096266797/884506e1-3cbb-437a-ab0f-9c8b49e80433.png" alt class="image--center mx-auto" /></p>
<p>Sur le <strong>worker2</strong>, les données du pod <strong>mysql-pv</strong> sont bien stockées et sauvegardées dans le repertoire <strong>/data-volume</strong></p>
<h2 id="heading-documentation">Documentation</h2>
<h3 id="heading-installer-kubeadm-sur-ubuntuhttpskubernetesiodocssetupproduction-environmenttoolskubeadminstall-kubeadm"><a target="_blank" href="https://kubernetes.io/docs/setup/production-environment/tools/kubeadm/install-kubeadm/">Installer kubeadm sur ubuntu</a></h3>
<h3 id="heading-creating-a-single-control-plane-cluster-with-kubeadmhttpskubernetesiodocssetupproduction-environmenttoolskubeadmcreate-cluster-kubeadm"><a target="_blank" href="https://kubernetes.io/docs/setup/production-environment/tools/kubeadm/create-cluster-kubeadm/">Creating a Single Control-Plane Cluster with kubeadm</a></h3>
]]></content:encoded></item><item><title><![CDATA[Kubernetes | Services Nodeport & namespace : créer un environnement isolé et exposer des pods vers l'extérieur]]></title><description><![CDATA[LinkedIn | GitLab | GitHub | Credly

Contexte
Ce laboratoire vise à présenter les étapes de mise en place d'un service de type NodePort sur Kubernetes.
Objectifs
Dans ce lab, nous allons créer un environnement isolé sur Kubernetes et déployer une app...]]></description><link>https://blog.acloud.digital/kubernetes-services-nodeport-namespace-creer-un-environnement-isole-et-exposer-des-pods-vers-lexterieur</link><guid isPermaLink="true">https://blog.acloud.digital/kubernetes-services-nodeport-namespace-creer-un-environnement-isole-et-exposer-des-pods-vers-lexterieur</guid><category><![CDATA[Kubernetes]]></category><category><![CDATA[Kubernetes nodeport]]></category><category><![CDATA[networking]]></category><category><![CDATA[#namespaces]]></category><dc:creator><![CDATA[Carlin FONGANG]]></dc:creator><pubDate>Sat, 13 Apr 2024 12:54:33 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/pr5lUMgocTs/upload/a5ab7074791971079b8091db953f72c3.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<blockquote>
<p><a target="_blank" href="https://www.linkedin.com/in/carlinfongang/">LinkedIn</a> | <a target="_blank" href="https://gitlab.com/carlinfongang">GitLab</a> | <a target="_blank" href="https://github.com/carlinfongang">GitHub</a> | <a target="_blank" href="https://www.credly.com/users/carlin-fongang/badges">Credly</a></p>
</blockquote>
<h2 id="heading-contexte">Contexte</h2>
<p>Ce laboratoire vise à présenter les étapes de mise en place d'un service de type NodePort sur Kubernetes.</p>
<h2 id="heading-objectifs">Objectifs</h2>
<p>Dans ce lab, nous allons créer un environnement isolé sur Kubernetes et déployer une application accessible depuis l'extérieur du cluster. Voici les étapes à suivre pour ce processus :</p>
<ol>
<li><p><strong>Création d'un Namespace</strong> : Rédigez un manifeste <code>namespace.yml</code> pour créer un namespace appelé <code>production</code>.</p>
</li>
<li><p><strong>Déploiement d'un Pod</strong> : Créez un manifeste <code>pod-red.yml</code> pour déployer un pod utilisant l'image <code>mmumshad/simple-webapp-color</code>, avec la couleur rouge spécifiée et un label <code>app:web</code>.</p>
</li>
<li><p><strong>Exposition du Pod via NodePort</strong> : Élaborez un manifeste <code>service-nodeport-web.yml</code> qui expose le pod sur le réseau extérieur via un service de type NodePort. Configurez ce service pour utiliser le port 30008 comme NodePort et rediriger les requêtes vers le port 8080 des pods.</p>
</li>
<li><p><strong>Lancement et Vérification</strong> : Déployez le service et utilisez <code>kubectl describe</code> pour vérifier que le service a correctement identifié les deux pods sous le label <code>app:web</code>.</p>
</li>
<li><p><strong>Test d'Accessibilité</strong> : Testez l'accès à l'application en ouvrant le port 30008 du nœud pour s'assurer que l'application est accessible.</p>
</li>
</ol>
<h2 id="heading-1-definition-des-concepts">1. Définition des concepts</h2>
<h3 id="heading-11-cest-quoi-namespace">1.1. C'est quoi namespace ?</h3>
<p>Un namespace dans Kubernetes est une sorte de partition virtuelle au sein d'un cluster, qui permet d'isoler les groupes de ressources. Chaque namespace peut contenir des ressources (comme des pods, services, volumes, etc.) indépendamment des autres namespaces. Utiliser des namespaces permet de gérer efficacement les droits d'accès, de simplifier l'allocation des ressources, de segmenter le cluster pour différents utilisateurs ou projets, et d'organiser les ressources de manière plus structurée, facilitant ainsi la gestion et la maintenance du cluster.</p>
<h3 id="heading-12-concept-de-nodeport">1.2. Concept de Nodeport</h3>
<p>Le service de type NodePort dans Kubernetes permet d'exposer des services sur des ports fixes des nœuds du cluster. Chaque nœud redirige automatiquement ce port fixe (NodePort) vers le port du service. Ce mécanisme rend le service accessible de l'extérieur du cluster en utilisant &lt;IP du Nœud&gt;:. NodePort est généralement utilisé pour des applications de test ou des environnements de développement, car il offre un moyen simple et direct d'accéder aux services à travers les adresses IP des nœuds.</p>
<h2 id="heading-2-prerequis-liste-des-exigences-materielles-et-logicielles">2. <strong>Prérequis</strong> : Liste des exigences matérielles et logicielles.</h2>
<p>Dans notre cas, nous allons provisionner une instances EC2 s'exécutant sous Ubuntu 20.04 Focal Fossa LTS, grace au provider AWS, à partir delaquelle nous effectuerons toutes nos opérations.</p>
<p><a target="_blank" href="https://gitlab.com/CarlinFongang-Labs/Terraform/lab2-terraform-aws">Provisionner une instance EC2 sur AWS à l'aide de Terraform</a> (recommandé)</p>
<p><a target="_blank" href="https://gitlab.com/CarlinFongang-Labs/Ansible/lab10-deploy-ec2">Provisionner une instance EC2 sur AWS à l'aide d'Ansible</a></p>
<h2 id="heading-2-creation-dun-cluster">2. Création d'un cluster</h2>
<p>Consultez le document <a target="_blank" href="https://gitlab.com/CarlinFongang-Labs/kubernetes/lab1.1-install-kubeadm.git">Istaller kubeadm</a></p>
<h2 id="heading-3-configuration-initiale">3. Configuration initiale</h2>
<h3 id="heading-31-creation-du-fichier-namespaceyml-pour-le-namespace-production">3.1. Création du fichier namespace.yml pour le namespace production.</h3>
<pre><code class="lang-bash">nano namespace.yml
</code></pre>
<pre><code class="lang-yaml"><span class="hljs-attr">apiVersion:</span> <span class="hljs-string">v1</span>
<span class="hljs-attr">kind:</span> <span class="hljs-string">Namespace</span>
<span class="hljs-attr">metadata:</span>
  <span class="hljs-attr">name:</span> <span class="hljs-string">production</span>
</code></pre>
<h3 id="heading-32-creation-du-namespace">3.2. Création du namespace.</h3>
<pre><code class="lang-bash">kubectl apply -f namespace.yml
</code></pre>
<blockquote>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1713012297200/2c591986-37ee-47fd-afc7-454f4a065ce3.png" alt class="image--center mx-auto" /></p>
<p><em>Création du namespace effectuée</em></p>
</blockquote>
<pre><code class="lang-bash">kubectl get namespace
</code></pre>
<blockquote>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1713012313328/74b606a5-77c5-41ef-8754-2941f6e9d5dd.png" alt class="image--center mx-auto" /></p>
<p><em>Name space "production" crée</em></p>
</blockquote>
<h2 id="heading-4-deploiement-des-pods">4. Déploiement des Pods</h2>
<h3 id="heading-41-description-du-fichier-pod-redyml">4.1. Description du fichier pod-red.yml</h3>
<pre><code class="lang-bash">nano pod-red.yml
</code></pre>
<pre><code class="lang-yaml"><span class="hljs-attr">apiVersion:</span> <span class="hljs-string">v1</span>
<span class="hljs-attr">kind:</span> <span class="hljs-string">Pod</span>
<span class="hljs-attr">metadata:</span>
  <span class="hljs-attr">name:</span> <span class="hljs-string">simple-webapp-color-red</span>
  <span class="hljs-attr">labels:</span>
    <span class="hljs-attr">app:</span> <span class="hljs-string">web</span>
<span class="hljs-attr">spec:</span>
  <span class="hljs-attr">containers:</span>
    <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">web</span>
      <span class="hljs-attr">image:</span> <span class="hljs-string">mmumshad/simple-webapp-color</span>
      <span class="hljs-attr">ports:</span>
        <span class="hljs-bullet">-</span> <span class="hljs-attr">containerPort:</span> <span class="hljs-number">8080</span>
      <span class="hljs-attr">env:</span>
        <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">APP_COLOR</span>
          <span class="hljs-attr">value:</span> <span class="hljs-string">red</span> <span class="hljs-comment">#définition de la couleur</span>
</code></pre>
<h3 id="heading-42-procedure-pour-deployer-le-pod-dans-le-namespace-production">4.2. Procédure pour déployer le pod dans le namespace production.</h3>
<pre><code class="lang-bash">kubectl apply -f pod-red.yml -n production
</code></pre>
<p>Vérification de la création du pod dans le namespace définit</p>
<pre><code class="lang-bash">kubectl get pod --namespace production

ou 

kubectl get pod -n production
</code></pre>
<blockquote>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1713012532059/f8906b1c-ee90-4792-9ca7-e52bf95deeb5.png" alt class="image--center mx-auto" /></p>
</blockquote>
<h3 id="heading-43-description-du-fichier-pod-blueyml">4.3. Description du fichier pod-blue.yml</h3>
<pre><code class="lang-bash">nano pod-blue.yml
</code></pre>
<pre><code class="lang-yaml"><span class="hljs-attr">apiVersion:</span> <span class="hljs-string">v1</span>
<span class="hljs-attr">kind:</span> <span class="hljs-string">Pod</span>
<span class="hljs-attr">metadata:</span>
  <span class="hljs-attr">name:</span> <span class="hljs-string">simple-webapp-color-blue</span>
  <span class="hljs-attr">labels:</span>
    <span class="hljs-attr">app:</span> <span class="hljs-string">web</span>
<span class="hljs-attr">spec:</span>
  <span class="hljs-attr">containers:</span>
    <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">web</span>
      <span class="hljs-attr">image:</span> <span class="hljs-string">mmumshad/simple-webapp-color</span>
      <span class="hljs-attr">ports:</span>
        <span class="hljs-bullet">-</span> <span class="hljs-attr">containerPort:</span> <span class="hljs-number">8080</span>
      <span class="hljs-attr">env:</span>
        <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">APP_COLOR</span>
          <span class="hljs-attr">value:</span> <span class="hljs-string">blue</span> <span class="hljs-comment">#définition de la couleur</span>
</code></pre>
<h3 id="heading-44-creation-du-pod-blue">4.4. Création du pod blue</h3>
<pre><code class="lang-bash">kubectl apply -f pod-blue.yml -n production
</code></pre>
<blockquote>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1713012628188/43f5f036-334a-4b2c-83e6-ffe927bd007d.png" alt class="image--center mx-auto" /></p>
<p><em>Pod blue en cours d'exécution</em></p>
</blockquote>
<h2 id="heading-5-creation-du-service-nodeport">5. Création du Service NodePort</h2>
<h3 id="heading-51-description-du-fichier-service-nodeport-webyml">5.1. Description du fichier service-nodeport-web.yml</h3>
<pre><code class="lang-bash">nano service-nodeport-web.yml
</code></pre>
<pre><code class="lang-yaml"><span class="hljs-attr">apiVersion:</span> <span class="hljs-string">v1</span>
<span class="hljs-attr">kind:</span> <span class="hljs-string">Service</span>
<span class="hljs-attr">metadata:</span>
  <span class="hljs-attr">name:</span> <span class="hljs-string">service-nodeport-web</span>
<span class="hljs-attr">spec:</span>
  <span class="hljs-attr">type:</span> <span class="hljs-string">NodePort</span>
  <span class="hljs-attr">selector:</span>
    <span class="hljs-attr">app:</span> <span class="hljs-string">web</span>
  <span class="hljs-attr">ports:</span>
  <span class="hljs-bullet">-</span> <span class="hljs-attr">protocol:</span> <span class="hljs-string">TCP</span>
    <span class="hljs-attr">port:</span> <span class="hljs-number">8080</span>
    <span class="hljs-attr">targetPort:</span> <span class="hljs-number">8080</span>
    <span class="hljs-attr">nodePort:</span> <span class="hljs-number">30000</span>
</code></pre>
<p>Dans ce manifest, nous définissons un service de type NodePort ici désigné par <strong>service-nodeport-web</strong>. Il est configuré pour router le trafic TCP sur le port 8080 vers le targetPort 8080 des pods étiquetés avec app: web. De plus, ce service est exposé sur chaque nœud du cluster via le nodePort 30000. Cette configuration permet au trafic externe d'accéder aux pods spécifiés via l'adresse IP de n'importe quel nœud du cluster, suivi du port 30000.</p>
<h3 id="heading-52-creation-du-service-nodeport-et-exposition-des-pods">5.2. Création du service Nodeport et exposition des pods</h3>
<pre><code class="lang-bash">kubectl apply -f service-nodeport-web.yml -n production
</code></pre>
<blockquote>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1713012648694/24024170-7c48-412b-ac8a-92ec82d13e07.png" alt class="image--center mx-auto" /></p>
<p><em>Service nodePort est bien crée</em></p>
</blockquote>
<p>On peut vérifier les détails de notre service pour obtenir les IPs sur lesquelles il pointe</p>
<pre><code class="lang-bash">kubectl describe service -n production
</code></pre>
<blockquote>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1713012693219/be103e29-74ad-4499-9227-e3338ffdf44c.png" alt class="image--center mx-auto" /></p>
</blockquote>
<h2 id="heading-6-verification-et-tests">6. Vérification et Tests</h2>
<p>En entrant l'adresse IP de l'un des node du cluster, dans notre cas, celui du <strong>"node control"</strong> dans un navigateur suivi du port 3000, l'on obtiens une page du navigateur qui s'alterne.</p>
<blockquote>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1713012710684/e7a64362-6ce1-4282-914c-0adc62e158a3.png" alt class="image--center mx-auto" /></p>
<p><em>webapp bleu</em></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1713012723895/0ba071a9-11b6-4347-843a-68c0348c57bf.png" alt class="image--center mx-auto" /></p>
<p><em>webapp red</em></p>
</blockquote>
<p>on peut constater que l'exposition des deux applications/pods (red &amp; blue) vers l'extérieur et le loadbalancing marchent bien, car il permet d'alterner entre les deux pages.</p>
<h2 id="heading-documentation">Documentation</h2>
<h3 id="heading-installer-kubeadm-sur-ubuntuhttpskubernetesiodocssetupproduction-environmenttoolskubeadminstall-kubeadm"><a target="_blank" href="https://kubernetes.io/docs/setup/production-environment/tools/kubeadm/install-kubeadm/">Installer kubeadm sur ubuntu</a></h3>
<h3 id="heading-creating-a-single-control-plane-cluster-with-kubeadmhttpskubernetesiodocssetupproduction-environmenttoolskubeadmcreate-cluster-kubeadm"><a target="_blank" href="https://kubernetes.io/docs/setup/production-environment/tools/kubeadm/create-cluster-kubeadm/">Creating a Single Control-Plane Cluster with kubeadm</a></h3>
]]></content:encoded></item><item><title><![CDATA[Kubernetes | Créez des pods et des deployments à l'aide de kubernetes]]></title><description><![CDATA[LinkedIn | GitLab | GitHub | Credly


Contexte
Dans ce laboratoire, nous allons explorer les étapes clés pour déployer et gérer des applications en utilisant Kubernetes et nginx.
Objectifs
Dans ce lab, nous procèderons à :

Rédaction du manifeste pod...]]></description><link>https://blog.acloud.digital/creez-pods-et-deployments-avec-kubernetes</link><guid isPermaLink="true">https://blog.acloud.digital/creez-pods-et-deployments-avec-kubernetes</guid><category><![CDATA[Kubernetes]]></category><category><![CDATA[#DeploymentManagement #ReplicaSet #RollingUpdates #Rollback #Kubernetes #Scaling #DeploymentErrors #ApplicationConfiguration #ResourceManagement #ImagePullError #InsufficientPermission #LimitRanges #Quota]]></category><category><![CDATA[AWS]]></category><category><![CDATA[nginx]]></category><dc:creator><![CDATA[Carlin FONGANG]]></dc:creator><pubDate>Fri, 12 Apr 2024 16:46:30 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/ZfVyuV8l7WU/upload/9fbb604f31103feffe1ad82a246dae69.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<blockquote>
<p><a target="_blank" href="https://www.linkedin.com/in/carlinfongang/">LinkedIn</a> | <a target="_blank" href="https://gitlab.com/carlinfongang">GitLab</a> | <a target="_blank" href="https://github.com/carlinfongang">GitHub</a> | <a target="_blank" href="https://www.credly.com/users/carlin-fongang/badges">Credly</a></p>
</blockquote>
<hr />
<h2 id="heading-contexte">Contexte</h2>
<p>Dans ce laboratoire, nous allons explorer les étapes clés pour déployer et gérer des applications en utilisant Kubernetes et <strong>nginx</strong>.</p>
<h2 id="heading-objectifs">Objectifs</h2>
<p>Dans ce lab, nous procèderons à :</p>
<ol>
<li><p><strong>Rédaction du manifeste pod.yml</strong> : Créez un fichier <code>pod.yml</code> pour déployer un pod utilisant l'image <code>mmumshad/simple-webapp-color</code>, en spécifiant que la couleur de l'application sera rouge.</p>
</li>
<li><p><strong>Lancement et vérification du pod</strong> : Déployez le pod et assurez-vous qu'il est correctement en cours d'exécution dans votre cluster Kubernetes.</p>
</li>
<li><p><strong>Exposition du pod</strong> : Exposez le pod en utilisant la commande <code>kubectl port-forward nom_du_pod 8080:8080 --address 0.0.0.0</code> pour rendre l'application accessible via le port 8080.</p>
</li>
<li><p><strong>Accès à l'application</strong> : Confirmez que l'application est accessible en naviguant sur le port 8080 du nœud.</p>
</li>
<li><p><strong>Déploiement de Nginx</strong> : Écrivez un manifeste <code>nginx-deployment.yml</code> pour déployer deux réplicas d'un pod Nginx, utilisant la version <code>1.18.0</code> de l'image.</p>
</li>
<li><p><strong>Vérification du déploiement</strong> : Lancez le déploiement, vérifiez le nom des pods et confirmez que le déploiement, le ReplicaSet et la version de l'image ont été correctement créés.</p>
</li>
<li><p><strong>Mise à jour du déploiement</strong> : Modifiez <code>nginx-deployment.yml</code> pour utiliser la version <code>latest</code> de l'image Nginx, puis appliquez la modification avec <code>kubectl apply</code>.</p>
</li>
<li><p><strong>Observation des changements</strong> : Examinez les ReplicaSets actifs et l'image utilisée par le ReplicaSet en cours.</p>
</li>
<li><p><strong>Nettoyage</strong> : Supprimez toutes les ressources créées et recréez-les en utilisant des commandes impératives pour consolider la maîtrise de Kubernetes.</p>
</li>
</ol>
<p>En intégrant kubeadm dans notre flux de travail Kubernetes, vous simplifierons considérablement la gestion du cycle de vie de notre cluster, nous permettant ainsi de nous concentrer davantage sur le déploiement et la gestion de nos applications.</p>
<h2 id="heading-1-definition-des-conceptes">1. Définition des conceptes</h2>
<h3 id="heading-11-cest-quoi-kubeadm">1.1. C'est quoi kubeadm ?</h3>
<p>kubeadm est un outil conçu par la communauté Kubernetes pour simplifier la mise en place et la gestion des composants fondamentaux d'un cluster Kubernetes de manière sécurisée et automatisée. Il est destiné à fournir une méthode standardisée pour la formation rapide de clusters Kubernetes.</p>
<h3 id="heading-12-fonctionnalites-de-kubeadm">1.2. Fonctionnalités de kubeadm</h3>
<p><strong>Initialisation du Cluster :</strong> kubeadm initialise les composants nécessaires pour faire fonctionner un cluster Kubernetes, y compris le serveur API, le Controller Manager et l'ordonnanceur (Scheduler). Cette étape comprend la configuration de la sécurité du cluster, la génération de certificats, et la configuration des composants de gestion du cluster.</p>
<p><strong>Gestion des Tokens et de la Sécurité :</strong> kubeadm génère un token que les autres nœuds peuvent utiliser pour rejoindre le cluster de manière sécurisée. Il configure également les règles de base pour la communication sécurisée entre les nœuds du cluster.</p>
<p><strong>Configuration de Réseau :</strong> Après l'initialisation, kubeadm attend que l'administrateur installe un add-on réseau avant que les nœuds ne soient prêts à exécuter des applications. Cela garantit que la communication inter-pod sur le cluster est bien établie.</p>
<p><strong>Ajout de Nœuds :</strong> kubeadm fournit une commande simple pour ajouter des nœuds au cluster. Ceci est essentiel pour l'expansion du cluster.</p>
<p>Mise à niveau du Cluster : Avec kubeadm, la mise à niveau des composants du cluster vers de nouvelles versions est rationalisée et peut être exécutée avec des commandes simples, minimisant ainsi le risque d'erreurs humaines.</p>
<h3 id="heading-13-pourquoi-utiliser-kubeadm">1.3. Pourquoi utiliser kubeadm ?</h3>
<p><strong>Simplicité :</strong> kubeadm réduit la complexité de mise en place d'un cluster Kubernetes, ce qui le rend accessible même pour ceux qui sont relativement nouveaux dans la technologie Kubernetes.</p>
<p><strong>Standardisation :</strong> En utilisant kubeadm, vous suivez les meilleures pratiques et les configurations recommandées par la communauté Kubernetes, garantissant ainsi la fiabilité et la sécurité de votre cluster.</p>
<p><strong>Flexibilité :</strong> kubeadm est conçu pour fonctionner bien avec les systèmes d'exploitation et les environnements d'hébergement les plus courants, ce qui en fait une solution versatile pour divers cas d'utilisation.</p>
<h2 id="heading-2-prerequis-liste-des-exigences-materielles-et-logicielles">2. <strong>Prérequis</strong> : Liste des exigences matérielles et logicielles.</h2>
<p>Dans notre cas, nous allons provisionner une instances EC2 s'exécutant sous Ubuntu 20.04 Focal Fossa LTS, grace au provider AWS, à partir delaquelle nous effectuerons toutes nos opérations.</p>
<p><a target="_blank" href="https://gitlab.com/CarlinFongang-Labs/Terraform/lab2-terraform-aws">Provisionner une instance EC2 sur AWS à l'aide de Terraform</a> (recommandé)</p>
<p><a target="_blank" href="https://gitlab.com/CarlinFongang-Labs/Ansible/lab10-deploy-ec2">Provisionner une instance EC2 sur AWS à l'aide d'Ansible</a></p>
<h2 id="heading-1-configuration-initiale">1. Configuration initiale</h2>
<h3 id="heading-11-prerequis-techniques">1.1. Prérequis techniques</h3>
<p>Nous utiserons kubeadm pour ce lab, cet outil pour être déployé, nécessite : 2vCPU et 4Go de RAM minimum.</p>
<h3 id="heading-12-configuration-du-cluster">1.2. Configuration du cluster</h3>
<p>Pour la création de notre cluster, se reférer à la documentation sur <a target="_blank" href="https://gitlab.com/CarlinFongang-Labs/kubernetes/lab1.1-install-kubeadm.git">l'installation de kubeadm</a></p>
<h2 id="heading-2-deploiement-du-pod-simple">2. Déploiement du Pod Simple</h2>
<h3 id="heading-21-creation-du-fichier-podyml">2.1. Création du fichier pod.yml</h3>
<pre><code class="lang-bash">sudo nano pod.yml
</code></pre>
<p>contenu du manifest</p>
<pre><code class="lang-bash">apiVersion: v1
kind: Pod
metadata:
  name: simple-webapp-color
  labels:
    app: web
spec:
  containers:
    - name: web
      image: mmumshad/simple-webapp-color
      ports:
        - containerPort: 8080
      env:
        - name: APP_COLOR
          value: red
</code></pre>
<h3 id="heading-22-deploiement-du-pod-avec-limage-mmumshadsimple-webapp-color">2.2. Déploiement du pod avec l'image mmumshad/simple-webapp-color</h3>
<pre><code class="lang-bash">kubectl apply -f pod.yml
</code></pre>
<p>vérification des pods en cours</p>
<pre><code class="lang-bash">kubectl get pod
</code></pre>
<blockquote>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1712939839884/253743b9-4ba0-453b-ae75-56d29d89ff08.png" alt class="image--center mx-auto" /></p>
</blockquote>
<h2 id="heading-3-verification-et-exposition-du-pod">3. Vérification et exposition du Pod</h2>
<h3 id="heading-31-commandes-pour-lancer-et-verifier-letat-du-pod">3.1. Commandes pour lancer et vérifier l'état du pod</h3>
<pre><code class="lang-bash">kubectl describe pod simple-webapp-color
</code></pre>
<blockquote>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1712939858986/363314f6-b4e3-403b-82a0-b242e0755bac.png" alt class="image--center mx-auto" /></p>
</blockquote>
<p>Sur cette capture, on peut voir que le pod est assigné au node <strong>k8s-worker1/172.31.30.26</strong> et le label de celui ci est <strong>app=web</strong></p>
<h3 id="heading-32-exposition-du-pod-sur-le-reseau-via-port-forward">3.2. Exposition du pod sur le réseau via port-forward</h3>
<p>La commande ci-dessous permet de rediriger et d'écouter sur le port <strong>8080</strong> de toutes les interfaces réseau de la machine hôte, rendant ainsi accessible sur ce port le service fourni par le pod simple-webapp-color dans un cluster Kubernetes.</p>
<pre><code class="lang-bash">kubectl port-forward simple-webapp-color 8080:8080 --address 0.0.0.0
</code></pre>
<blockquote>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1712939876772/a25cdc3b-7570-4996-8691-1f1d9e30c69c.png" alt class="image--center mx-auto" /></p>
<p><em>Sortie console une fois la commande passée</em></p>
</blockquote>
<h3 id="heading-33-suppression-du-pod">3.3. Suppression du pod</h3>
<p>Pour supprimer le pod crée, de la même façon que nous l'avons lancé, nous allons utiliser la commande :</p>
<pre><code class="lang-bash">kubectl delete -f pod.yml --v=5
</code></pre>
<blockquote>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1712939895362/bd0f22be-c62c-4680-9a16-2dedaae12701.png" alt class="image--center mx-auto" /></p>
</blockquote>
<h2 id="heading-4-acces-et-test-de-lapplication">4. Accès et test de l'application</h2>
<p>Pour vérifier l'exposition du pod vers l'extérieur, l'on va entrée le nom de domaine/ip public du control node dans un navigateur suivi du port 8080 qui correspond au port d'exposition.</p>
<blockquote>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1712939908807/2d330731-a3d3-44c0-8a94-de7fec1bb595.png" alt class="image--center mx-auto" /></p>
<p><em>L'application web tournant sur le pod est bien accessible via internet</em></p>
</blockquote>
<p>Nous venons donc de déployer notre toute première application grace à kubernetes 🥳🙌</p>
<h2 id="heading-5-deploiement-de-nginx">5. Déploiement de Nginx</h2>
<h3 id="heading-51-redaction-du-manifeste-nginx-deploymentyml">5.1. Rédaction du manifeste nginx-deployment.yml</h3>
<pre><code class="lang-bash">sudo nano nginx-deployment.yml
</code></pre>
<pre><code class="lang-bash">apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment 
  labels:
    app: nginx
spec:
  replicas: 2
  strategy:
    <span class="hljs-built_in">type</span>: RollingUpdate
    rollingUpdate:
      maxSurge: 1
      maxUnavailable: 1
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.18.0
        ports:
        - containerPort: 80
</code></pre>
<h3 id="heading-52-deploiement-de-nginx">5.2. Déploiement de Nginx</h3>
<pre><code class="lang-bash">kubectl apply -f nginx-deployment.yml --v=5
</code></pre>
<h3 id="heading-53-verification-des-pods-et-des-replicasets">5.3. Vérification des pods et des ReplicaSets</h3>
<pre><code class="lang-bash">kubectl get pod
kubectl get replicaset
kubectl get deploy
</code></pre>
<blockquote>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1712939929209/ac80582d-1f0c-4292-8f8a-3ae9ddf1b2ce.png" alt class="image--center mx-auto" /></p>
</blockquote>
<p>on peut avoir des information sur le deployment également</p>
<pre><code class="lang-bash"> kubectl describe deploy
</code></pre>
<blockquote>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1712939949833/d43a9b09-ea5d-4f9f-bee2-3166c2ae0be6.png" alt class="image--center mx-auto" /></p>
</blockquote>
<p>Pour avoir plus de détail sur les pods</p>
<pre><code class="lang-bash">kubectl describe pod nginx-deployment-54bcfc567b-nf7dm
</code></pre>
<blockquote>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1712939966307/3dd6a762-0da8-457f-b1bc-b586dae223ba.png" alt class="image--center mx-auto" /></p>
<p><em>Informations sur le premier pod</em></p>
</blockquote>
<pre><code class="lang-bash">kubectl describe pod nginx-deployment-54bcfc567b-s9j8b
</code></pre>
<blockquote>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1712939984849/56aa99d2-2867-4aa5-8fd1-27701540e8ec.png" alt class="image--center mx-auto" /></p>
</blockquote>
<p>Comme on peut le constater, sur chacune des capture, chaque pod est hébergé sur un node distinct.</p>
<h2 id="heading-6-mise-a-jour-et-gestion-des-versions">6. Mise à jour et gestion des versions</h2>
<h3 id="heading-61-procedure-de-mise-a-jour-de-limage-nginx-vers-la-version-latest">6.1. Procédure de mise à jour de l'image Nginx vers la version latest</h3>
<p>Pour procéder à la mise à jour de Nginx vers la <strong>lastest</strong>, nous allons simplement mettre à jour notre ficher <strong>deployment</strong></p>
<pre><code class="lang-bash">sudo nano nginx-deployment.yml
</code></pre>
<pre><code class="lang-bash">apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment 
  labels:
    app: nginx
spec:
  replicas: 2
  strategy:
    <span class="hljs-built_in">type</span>: RollingUpdate
    rollingUpdate:
      maxSurge: 1
      maxUnavailable: 1
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:latest
        ports:
        - containerPort: 80
</code></pre>
<h3 id="heading-62-application-des-modifications-avec-kubectl-apply">6.2. Application des modifications avec kubectl apply</h3>
<pre><code class="lang-bash">kubectl apply -f nginx-deployment.yml
</code></pre>
<blockquote>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1712940007000/a0477aee-d884-4217-a39a-37c08b93a316.png" alt class="image--center mx-auto" /></p>
</blockquote>
<p>On observe une reconfiguration du deploiement et non pas un deploiement à part entier comme au tout début pour la version <strong>1.18.0</strong> de Nginx</p>
<h3 id="heading-63-observation-des-changements-dans-les-replicasets">6.3. Observation des changements dans les Replicasets</h3>
<pre><code class="lang-bash">kubectl get replicaset -o wide
</code></pre>
<blockquote>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1712940031469/1d50e3a6-04b9-48c5-b323-b85b4aabff2b.png" alt class="image--center mx-auto" /></p>
</blockquote>
<p>Apres application de la commande, on peut observer que les précédents pods tournant sous <strong>nginx:1.18.0</strong> sont à l'arrêt tandis qu'on à deux nouveaux pods en cours d'exécution et tournant sous la version <strong>latest</strong> Nginx</p>
<p>Il est important de noter que ce basculement est progressif, kubernetes va commencer pas créer un à un les nouveaux pods, tant dis qu'il va supprimer progressivement les anciens pods tout en gardant en cours d'exécution le nombre de replicas définit préalablement dans le deployment, soit <strong>"2"</strong></p>
<h2 id="heading-7-nettoyage-du-cluster">7. Nettoyage du cluster</h2>
<h3 id="heading-71-suppression-des-ressources-creees">7.1. Suppression des ressources créées</h3>
<p>A présent nous allons supprimer toutes les ressources créees, et reprendre tout celà de façon impérative.</p>
<pre><code class="lang-bash">kubectl delete -f nginx-deployment.yml
</code></pre>
<blockquote>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1712940049613/6fe530f5-da61-466c-9295-fccba4bcebfb.png" alt class="image--center mx-auto" /></p>
<p><em>suppression des ressources</em></p>
</blockquote>
<h3 id="heading-72-commandes-pour-recreer-les-ressources-de-maniere-imperative">7.2. Commandes pour recréer les ressources de manière impérative</h3>
<h4 id="heading-721-creation-du-pod-simple-webapp-color">7.2.1. Création du pod "simple-webapp-color"</h4>
<pre><code class="lang-bash">kubectl run --image=mmumshad/simple-webapp-color \
--env=<span class="hljs-string">"APP_COLOR=blue"</span> \
--restart=Never \
simple-webapp-color
</code></pre>
<blockquote>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1712940066766/e7c7f960-46d7-4a41-b455-b9c56a2664d1.png" alt class="image--center mx-auto" /></p>
<p><em>Le pod est bien crée</em></p>
</blockquote>
<p>Exposition du pod à internet</p>
<pre><code class="lang-bash">kubectl port-forward simple-webapp-color 8080:8080 --address 0.0.0.0
</code></pre>
<p>Une fois le pod exposé, on va de nouveau consulter l'application web grace à l'ip public/domaine de l'instance faisant office de node principal.</p>
<blockquote>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1712940081359/6dbf928d-b159-4fe7-ba0b-66b547e49f58.png" alt class="image--center mx-auto" /></p>
</blockquote>
<p>Pour supprimer notre pod, nous entrerons la commande suivante :</p>
<pre><code class="lang-bash">kubectl delete pod simple-webapp-color
</code></pre>
<blockquote>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1712940121793/3fb2e7de-31d8-4fa1-811b-123f5159d7f6.png" alt class="image--center mx-auto" /></p>
</blockquote>
<h4 id="heading-722-creation-imperatif-du-deployment">7.2.2. Création impératif du deployment</h4>
<p>Création du deploiement avec pour image nginx:1.18.0</p>
<pre><code class="lang-bash">kubectl create deployment --image=nginx:1.18.0 nginx-deployment
</code></pre>
<blockquote>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1712940158751/2b4e6290-43d9-484f-a349-2ecd4a4f90ae.png" alt class="image--center mx-auto" /></p>
</blockquote>
<p>Le pod à bien été lancé mais on a un seul pod au lieu de deux comme on le voudrais, pour régler ce problème, nous allons passer la commande suivante :</p>
<pre><code class="lang-bash"> kubectl scale --replicas=2 deployment/nginx-deployment
</code></pre>
<p>En controllant de nouveaux nos pods, on obtiens bien deux pods sous <strong>nginx:1.18.0</strong></p>
<pre><code class="lang-bash">kubectl get deploy
</code></pre>
<blockquote>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1712940179396/03d6dca0-3b7f-4cea-9e70-fccc3ed0562d.png" alt class="image--center mx-auto" /></p>
</blockquote>
<p>Pour faire upgrade nginx, nous allons passer la commande suivante :</p>
<pre><code class="lang-bash">kubectl <span class="hljs-built_in">set</span> image deployment/nginx-deployment nginx=nginx:latest
</code></pre>
<p>pour vérifier la mise à jour :</p>
<pre><code class="lang-bash">kubectl get replicasets -o wide
</code></pre>
<blockquote>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1712940192228/e2cfe325-8734-4449-8e55-9ae698d2dd00.png" alt class="image--center mx-auto" /></p>
</blockquote>
<p>Nous avons mis en place un objet de type deployment de manière impérative. Cependant, pour faciliter le travail collaboratif, il est recommandé d'utiliser des manifestes qui peuvent être versionnés.</p>
<h2 id="heading-documentation">Documentation</h2>
<h3 id="heading-installer-kubeadm-sur-ubuntuhttpskubernetesiodocssetupproduction-environmenttoolskubeadminstall-kubeadm"><a target="_blank" href="https://kubernetes.io/docs/setup/production-environment/tools/kubeadm/install-kubeadm/">Installer kubeadm sur ubuntu</a></h3>
<h3 id="heading-creating-a-single-control-plane-cluster-with-kubeadmhttpskubernetesiodocssetupproduction-environmenttoolskubeadmcreate-cluster-kubeadm"><a target="_blank" href="https://kubernetes.io/docs/setup/production-environment/tools/kubeadm/create-cluster-kubeadm/">Creating a Single Control-Plane Cluster with kubeadm</a></h3>
]]></content:encoded></item><item><title><![CDATA[Kubernetes | Installation de Kubeadm et création d'un cluster]]></title><description><![CDATA[LinkedIn | GitLab | GitHub | Credly

Contexte
Ce laboratoire vise à présenter les étapes d'installation de l'outil kubeadm sur des instances ec2.
Objectifs
Dans ce lab, nous allons :

Provisionner 3 instances ec2 sur les quelles nous allons effectuer...]]></description><link>https://blog.acloud.digital/kubernetes-installation-kubeadm-cluster</link><guid isPermaLink="true">https://blog.acloud.digital/kubernetes-installation-kubeadm-cluster</guid><category><![CDATA[Kubernetes]]></category><category><![CDATA[kubeadm]]></category><category><![CDATA[AWS]]></category><category><![CDATA[Linux]]></category><dc:creator><![CDATA[Carlin FONGANG]]></dc:creator><pubDate>Fri, 12 Apr 2024 10:11:23 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/9cXMJHaViTM/upload/c0a89f10cec025be2391961ebd1026d0.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<blockquote>
<p><a target="_blank" href="https://www.linkedin.com/in/carlinfongang/">LinkedIn</a> | <a target="_blank" href="https://gitlab.com/carlinfongang">GitLab</a> | <a target="_blank" href="https://github.com/carlinfongang">GitHub</a> | <a target="_blank" href="https://www.credly.com/users/carlin-fongang/badges">Credly</a></p>
</blockquote>
<h2 id="heading-contexte">Contexte</h2>
<p>Ce laboratoire vise à présenter les étapes d'installation de l'outil kubeadm sur des instances ec2.</p>
<h2 id="heading-objectifs">Objectifs</h2>
<p>Dans ce lab, nous allons :</p>
<ul>
<li><p>Provisionner 3 instances ec2 sur les quelles nous allons effectuer toutes nos opérations de configurations.</p>
</li>
<li><p>Effectuer les configurations nécessaires sur ces instances afin d'y installer <strong>docker et containerd</strong> sur l'ensemble des instances.</p>
</li>
<li><p>Configurer les réglages de réseau avec Calico</p>
</li>
<li><p>Gérer l'adhésion des nœuds workers au cluster principal.</p>
</li>
</ul>
<p>En intégrant <strong>kubeadm</strong> dans notre flux de travail <strong>Kubernetes</strong>, nous simplifierons considérablement la gestion du cycle de vie de notre cluster, nous permettant ainsi de nous concentrer davantage sur le déploiement et la gestion de nos applications.</p>
<h2 id="heading-1-definition-des-concepts">1. Définition des concepts</h2>
<h3 id="heading-11-cest-quoi-kubeadm">1.1. C'est quoi kubeadm ?</h3>
<p>kubeadm est un outil conçu par la communauté Kubernetes pour simplifier la mise en place et la gestion des composants fondamentaux d'un cluster Kubernetes de manière sécurisée et automatisée. Il est destiné à fournir une méthode standardisée pour la formation rapide de clusters Kubernetes.</p>
<h3 id="heading-12-fonctionnalites-de-kubeadm">1.2. Fonctionnalités de kubeadm</h3>
<p><strong>Initialisation du Cluster :</strong> kubeadm initialise les composants nécessaires pour faire fonctionner un cluster Kubernetes, y compris le serveur API, le Controller Manager et l'ordonnanceur (Scheduler). Cette étape comprend la configuration de la sécurité du cluster, la génération de certificats, et la configuration des composants de gestion du cluster.</p>
<p><strong>Gestion des Tokens et de la Sécurité :</strong> kubeadm génère un token que les autres nœuds peuvent utiliser pour rejoindre le cluster de manière sécurisée. Il configure également les règles de base pour la communication sécurisée entre les nœuds du cluster.</p>
<p><strong>Configuration de Réseau :</strong> Après l'initialisation, kubeadm attend que l'administrateur installe un add-on réseau avant que les nœuds ne soient prêts à exécuter des applications. Cela garantit que la communication inter-pod sur le cluster est bien établie.</p>
<p><strong>Ajout de Nœuds :</strong> kubeadm fournit une commande simple pour ajouter des nœuds au cluster. Ceci est essentiel pour l'expansion du cluster.</p>
<p>Mise à niveau du Cluster : Avec kubeadm, la mise à niveau des composants du cluster vers de nouvelles versions est rationalisée et peut être exécutée avec des commandes simples, minimisant ainsi le risque d'erreurs humaines.</p>
<h3 id="heading-13-pourquoi-utiliser-kubeadm">1.3. Pourquoi utiliser kubeadm ?</h3>
<p><strong>Simplicité :</strong> kubeadm réduit la complexité de mise en place d'un cluster Kubernetes, ce qui le rend accessible même pour ceux qui sont relativement nouveaux dans la technologie Kubernetes.</p>
<p><strong>Standardisation :</strong> En utilisant kubeadm, vous suivez les meilleures pratiques et les configurations recommandées par la communauté Kubernetes, garantissant ainsi la fiabilité et la sécurité de votre cluster.</p>
<p><strong>Flexibilité :</strong> kubeadm est conçu pour fonctionner bien avec les systèmes d'exploitation et les environnements d'hébergement les plus courants, ce qui en fait une solution versatile pour divers cas d'utilisation.</p>
<h2 id="heading-2-prerequis-liste-des-exigences-materielles-et-logicielles">2. <strong>Prérequis</strong> : Liste des exigences matérielles et logicielles.</h2>
<p>Dans notre cas, nous allons provisionner une instances EC2 s'exécutant sous Ubuntu 20.04 Focal Fossa LTS, grace au provider AWS, à partir delaquelle nous effectuerons toutes nos opérations.</p>
<p><a target="_blank" href="https://gitlab.com/CarlinFongang-Labs/Terraform/lab2-terraform-aws">Provisionner une instance EC2 sur AWS à l'aide de Terraform</a> (recommandé)</p>
<p><a target="_blank" href="https://gitlab.com/CarlinFongang-Labs/Ansible/lab10-deploy-ec2">Provisionner une instance EC2 sur AWS à l'aide d'Ansible</a></p>
<h2 id="heading-3-creation-dun-cluster">3. Création d'un cluster</h2>
<p>Nous allons provisionner 3 instances ec2 de type t3.medium ou avec des caractéristiques minimales (2 vCPU, 4Go de RAM)</p>
<h3 id="heading-31-definition-du-nom-dhote-du-control-plan">3.1. Définition du nom d'hôte du "Control plan"</h3>
<p>Nous allons commencer par renommer la première instance (principale)</p>
<pre><code class="lang-bash">sudo hostnamectl set-hostname k8s-control
</code></pre>
<p>une fois la commande entrée, on peut se déconnecter et se reconnecter de nouveau pour percevoir le changement.</p>
<blockquote>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1712915500860/7ad2df42-d675-4c42-8482-c077db641b81.png" alt /></p>
<p><em>k8s-Control</em></p>
</blockquote>
<h3 id="heading-32-definition-des-noms-dhotes">3.2. Définition des noms d'hôtes</h3>
<p>Nous allons ensuite renommé les 2 autres instaces respectivement en worker1 et worker2</p>
<pre><code class="lang-bash">sudo hostnamectl set-hostname k8s-worker1
</code></pre>
<pre><code class="lang-bash">sudo hostnamectl set-hostname k8s-worker2
</code></pre>
<blockquote>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1712915579862/58354669-189a-4a91-af64-199021256398.png" alt class="image--center mx-auto" /></p>
</blockquote>
<h2 id="heading-4-mappage-des-serveurs">4. Mappage des serveurs</h2>
<p>Depuis l'instance <strong>k8s-control</strong>, nous allons crée un mappage de l'ensemble des serveurs afin que la communication entre les différents serveurs puissent se faire via les noms d'hotes.</p>
<p>Nous allons éditer le fichier <strong>hosts</strong></p>
<pre><code class="lang-bash">sudo nano /etc/hosts
</code></pre>
<p>dans ce fichier, nous allons rajouter les <strong>ip privés</strong> ainsi que les noms <strong>utilisateurs</strong> de l'ensemble des instances. il est absolument nécessaire d'utiliser des adresses privée à ce niveau, car les ip publiques peuvent changer après redemarrage des instances</p>
<pre><code class="lang-bash">172.31.23.252 k8s-control
172.31.30.26 k8s-worker1
172.31.30.220 k8s-worker2
</code></pre>
<blockquote>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1712915665102/71496cde-7e13-48ba-905a-957ffbb24d09.png" alt class="image--center mx-auto" /></p>
</blockquote>
<p>Nous allons copier ces informations, sauvegarder le fichier <strong>hosts</strong> et répéter la même opération sur les deux autres serveur</p>
<blockquote>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1712915673382/69efedf6-f4bc-43e0-a974-85c83b3f3cf8.png" alt class="image--center mx-auto" /></p>
<p>Une fois ces opérations réalisées, on va se déconnecter et se reconnecter sur chacune des instances</p>
</blockquote>
<h2 id="heading-5-installation-et-configuration-de-docker-et-containerd">5. Installation et configuration de Docker et Containerd</h2>
<p>L'installation et la configuration de ces outils va se faire sur l'ensemble des instances</p>
<h3 id="heading-51-confiugration-de-docker-engine-et-containerd-valable-pour-toutes-les-instances">5.1. Confiugration de Docker Engine et containerd (valable pour toutes les instances)</h3>
<p>Activation des modules du noyau</p>
<pre><code class="lang-bash">cat &lt;&lt;EOF | sudo tee /etc/modules-load.d/k8s.conf
overlay
br_netfilter
EOF
</code></pre>
<blockquote>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1712915745857/3c3407d1-569f-4644-bda7-f055471da63d.png" alt class="image--center mx-auto" /></p>
</blockquote>
<pre><code class="lang-bash">sudo modprobe overlay
</code></pre>
<pre><code class="lang-bash">sudo modprobe br_netfilter
</code></pre>
<p>Les commandes <strong>sudo modprobe</strong> overlay et <strong>sudo modprobe br_netfilter</strong> jouent un rôle essentiel dans la configuration des environnements basés sur des conteneurs, notamment pour Docker et Kubernetes. Elles chargent respectivement les modules <strong>overlay</strong> et <strong>br_netfilter</strong> dans le noyau Linux.</p>
<p><strong>Module OverlayFS :</strong> OverlayFS est un système de fichiers de type union qui permet de superposer deux systèmes de fichiers différents. En contexte de conteneurisation, il est souvent utilisé pour fournir le système de fichiers de conteneurs. Cela permet à chaque conteneur d'avoir son propre système de fichiers, tout en partageant des images de base entre conteneurs, économisant ainsi de l'espace disque et augmentant l'efficacité.</p>
<p><strong>Module br_netfilter :</strong> Ce module permet le filtrage de trafic réseau au niveau des ponts Linux (bridges), essentiel pour la mise en place de réseaux de conteneurs.</p>
<h3 id="heading-52-parametres-sysctl-requis-par-la-configuration-et-parametres-persistent-apres-redemarrage-valable-pour-toutes-les-instances">5.2. Paramètres "sysctl" requis par la configuration et paramètres persistent après redémarrage. (valable pour toutes les instances)</h3>
<p>Nous allons ensuite apporter des modifications relatives au réseau</p>
<pre><code class="lang-bash">cat &lt;&lt;EOF | sudo tee /etc/sysctl.d/k8s.conf
net.bridge.bridge-nf-call-iptables  = 1
net.bridge.bridge-nf-call-ip6tables = 1
net.ipv4.ip_forward                 = 1
EOF
</code></pre>
<blockquote>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1712915769491/625296f9-a07b-4b6a-8a26-e76124a9bb54.png" alt class="image--center mx-auto" /></p>
</blockquote>
<p>Ces commandes sont utilisées pour configurer des paramètres du noyau Linux via <strong>"sysctl"</strong>, qui sont nécessaires pour le bon fonctionnement de certaines applications, dans notre cas il s'agit de Kubernetes, lorsqu'elles utilisent Docker et containerd comme runtime de conteneurs.</p>
<h3 id="heading-53-application-du-paramettre-sysctl-lors-du-redemarrage-systeme-valable-pour-toutes-les-instances">5.3. Application du paramettre "sysctl" lors du redemarrage système (valable pour toutes les instances)</h3>
<pre><code class="lang-bash">sudo sysctl --system
</code></pre>
<blockquote>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1712915777290/bcc474d7-f26d-49c0-b68e-f5fd389d8f8d.png" alt class="image--center mx-auto" /></p>
</blockquote>
<p>Les nouvelles configurations sont rechargées</p>
<p>Nous pouvons poursuivre avec la configuration de docker.</p>
<h3 id="heading-54-installation-de-docker">5.4. Installation de Docker</h3>
<h4 id="heading-configuration-du-repository-de-docker-valable-pour-toutes-les-instances">Configuration du repository de Docker (valable pour toutes les instances)</h4>
<pre><code class="lang-bash">sudo apt-get update &amp;&amp; sudo apt-get install -y ca-certificates curl gnupg lsb-release apt-transport-https
</code></pre>
<h4 id="heading-ajour-de-la-cle-gpg-officiel-docker-valable-pour-toutes-les-instances">Ajour de la clé GPG officiel Docker (valable pour toutes les instances)</h4>
<pre><code class="lang-bash">sudo mkdir -m 0755 -p /etc/apt/keyrings
</code></pre>
<pre><code class="lang-bash">curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
</code></pre>
<h4 id="heading-configuration-des-depots-docker-sur-la-distribution-linux-utilisee-valable-pour-toutes-les-instances">Configuration des dépots Docker sur la distribution linux utilisée (valable pour toutes les instances)</h4>
<p>Ajout d'un dépôt Docker au fichier de sources de paquets APT sur un système Ubuntu</p>
<pre><code class="lang-bash"><span class="hljs-built_in">echo</span> \
  <span class="hljs-string">"deb [arch=<span class="hljs-subst">$(dpkg --print-architecture)</span> signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \
  <span class="hljs-subst">$(lsb_release -cs)</span> stable"</span> | sudo tee /etc/apt/sources.list.d/docker.list &gt; /dev/null
</code></pre>
<p>Cette commande configure le dépôt APT pour Docker sur une machine Ubuntu. Elle crée une ligne de source de dépôt, spécifiant l'architecture de la machine (obtenue via dpkg <strong>--print-architecture</strong>), le chemin du fichier de <strong>clé GPG</strong> pour la vérification des signatures (<strong>signed-by=/etc/apt/keyrings/docker.gpg</strong>), l'URL du dépôt Docker, et la version de distribution Ubuntu correspondante (obtenue via <strong>lsb_release -cs</strong>).</p>
<h4 id="heading-mise-a-jour-des-index-de-packets-apt-valable-pour-toutes-les-instances">Mise à jour des index de packets apt (valable pour toutes les instances)</h4>
<pre><code class="lang-bash">sudo apt-get update
</code></pre>
<h4 id="heading-installation-de-docker-containerd-et-docker-compose-valable-pour-toutes-les-instances">Installation de Docker, containerd, et Docker Compose (valable pour toutes les instances)</h4>
<pre><code class="lang-bash">VERSION_STRING=5:23.0.1-1~ubuntu.20.04~focal
</code></pre>
<pre><code class="lang-bash">sudo apt-get install -y docker-ce=<span class="hljs-variable">$VERSION_STRING</span> docker-ce-cli=<span class="hljs-variable">$VERSION_STRING</span> containerd.io docker-buildx-plugin docker-compose-plugin
</code></pre>
<blockquote>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1712915854590/de52c184-e0b8-477a-94b3-2a2e324b2c7a.png" alt class="image--center mx-auto" /></p>
<p>Docker est bien install</p>
</blockquote>
<p>Ajout de l'utilisateur courant au au groupe docker (valable pour toutes les instances)</p>
<pre><code class="lang-bash">sudo usermod -aG docker <span class="hljs-variable">$USER</span>
</code></pre>
<p>Une fois cette commande entrée, se déconnecter et se reconnecter, il est alors possible d'exécuter les commandes docker passer le "sudo" au préalable</p>
<h4 id="heading-mise-en-commentaire-de-disabledplugins-dans-le-fichier-configtoml-valable-pour-toutes-les-instances">Mise en commentaire de 'disabled_plugins' dans le fichier <strong>config.toml</strong> (valable pour toutes les instances)</h4>
<pre><code class="lang-bash">sudo sed -i <span class="hljs-string">'s/disabled_plugins/#disabled_plugins/'</span> /etc/containerd/config.toml
</code></pre>
<p>Cette commande est utilisée pour commenter la ligne <strong>disabled_plugins</strong> dans le fichier de configuration de containerd. Cette opération permet d'activer les plugins qui étaient désactivés, car la suppression du préfixe "disabled_" modifie la configuration pour ne plus désactiver ces plugins. Cela est nécessaire pour assurer que certaines fonctionnalités ou dépendances de containerd soient disponibles et fonctionnelles, notamment lors de l'exécution de conteneurs Docker.</p>
<h4 id="heading-redemarrage-de-containerd-valable-pour-toutes-les-instances">Redemarrage de containerd (valable pour toutes les instances)</h4>
<pre><code class="lang-bash">sudo systemctl restart containerd
</code></pre>
<h4 id="heading-desactivation-de-swap-valable-pour-toutes-les-instances">Désactivation de <strong>swap</strong> (valable pour toutes les instances)</h4>
<pre><code class="lang-bash">sudo swapoff -a
</code></pre>
<h2 id="heading-6-installation-de-kubeadm-kubelet-and-kubectl-valable-pour-toutes-les-instances">6. Installation de kubeadm, kubelet, and kubectl (valable pour toutes les instances)</h2>
<h3 id="heading-61-installation">6.1. Installation</h3>
<pre><code class="lang-bash">curl -fsSL https://pkgs.k8s.io/core:/stable:/v1.27/deb/Release.key | sudo gpg --dearmor -o /etc/apt/keyrings/kubernetes-apt-keyring.gpg
</code></pre>
<p>Cette opération nous permet de télécharger la clé publique de signature de paquet depuis une URL spécifique, destinée aux packages Kubernetes. Cette clé est nécessaire pour authentifier et sécuriser les téléchargements de packages Kubernetes</p>
<pre><code class="lang-bash"><span class="hljs-built_in">echo</span> <span class="hljs-string">'deb [signed-by=/etc/apt/keyrings/kubernetes-apt-keyring.gpg] https://pkgs.k8s.io/core:/stable:/v1.27/deb/ /'</span> | sudo tee /etc/apt/sources.list.d/kubernetes.list
</code></pre>
<p>Ajout d'une source de dépôt pour Kubernetes dans les sources APT du système. Cette opération permet à APT de vérifier l'authenticité des paquets téléchargés de ce dépôt.</p>
<pre><code class="lang-bash">sudo apt-get update &amp;&amp; sudo apt-get install -y kubelet=1.27.0-* kubeadm=1.27.0-* kubectl=1.27.0-*
</code></pre>
<pre><code class="lang-bash">sudo apt-mark hold kubelet kubeadm kubectl
</code></pre>
<p>Cette commande empêche la mise à jour automatique des trois paquets, ce qui nous donne un control total sur la mise à jour de kubernetes</p>
<blockquote>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1712916013064/5d6ca072-f0f1-46dd-98f1-32265d4f3d7a.png" alt class="image--center mx-auto" /></p>
<p><em>Installation de kubelet, kubeadm et kubectl</em></p>
</blockquote>
<h3 id="heading-62-initialisation-du-cluster-et-configuration-des-lacces-kubectl">6.2. Initialisation du cluster et configuration des l'accès kubectl.</h3>
<pre><code class="lang-bash">sudo kubeadm init --pod-network-cidr 192.168.0.0/16 --kubernetes-version 1.27.0
</code></pre>
<p>Cette commande est utilisée pour initialiser un cluster Kubernetes. Cette initialisation est la première étape pour configurer un cluster Kubernetes.</p>
<blockquote>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1712916054370/7e5a63c8-4c82-4957-8b08-3031d6dd2a5b.png" alt class="image--center mx-auto" /></p>
</blockquote>
<p>Les commandes suivantes configurent l'accès à notre cluster Kubernetes pour notre utilisateur courant.</p>
<pre><code class="lang-bash">mkdir -p <span class="hljs-variable">$HOME</span>/.kube
</code></pre>
<pre><code class="lang-bash">sudo cp -i /etc/kubernetes/admin.conf <span class="hljs-variable">$HOME</span>/.kube/config
</code></pre>
<pre><code class="lang-bash">sudo chown $(id -u):$(id -g) <span class="hljs-variable">$HOME</span>/.kube/config
</code></pre>
<h2 id="heading-7-verification-du-bon-fonctionnement-du-cluster">7. Vérification du bon fonctionnement du cluster</h2>
<pre><code class="lang-bash">kubectl get nodes
</code></pre>
<blockquote>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1712916091516/d796418e-7d83-4767-9e63-cd35ae19fa7a.png" alt class="image--center mx-auto" /></p>
</blockquote>
<h2 id="heading-8-install-the-calico-network-add-on-control-plan">8. Install the Calico network add-on (Control plan)</h2>
<p><strong>Calico</strong> est un système de réseau et de sécurité pour conteneurs, sur un cluster Kubernetes.</p>
<p>Via la commande ci-dessous, Kubernetes télécharge et applique la configuration définie dans le fichier YAML qui sera téléchargé, installant ensuite <strong>Calico</strong> pour gérer le réseau, les politiques de sécurité, et d'autres fonctionnalités de réseau au sein de notre cluster.</p>
<pre><code class="lang-bash">kubectl apply -f https://raw.githubusercontent.com/projectcalico/calico/v3.25.0/manifests/calico.yaml
</code></pre>
<p>Ce manifest va crée un ensemble d'objet utile pour notre réseau grace à l'outil Calico.</p>
<blockquote>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1712916218655/909c709c-f856-4185-b21b-d0bb5df23230.png" alt class="image--center mx-auto" /></p>
</blockquote>
<p>A présent joignons les workers au control plan</p>
<h2 id="heading-8-generation-de-la-commande-de-communication-avec-le-control-plan-control-plan">8. Génération de la commande de communication avec le "Control plan" (Control plan)</h2>
<pre><code class="lang-bash">kubeadm token create --print-join-command
</code></pre>
<blockquote>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1712916265627/fe245e8a-11c3-41cf-b8ef-73ffc3e923da.png" alt class="image--center mx-auto" /></p>
</blockquote>
<p>Cette opération nous permet de générer un nouveau token d'authentification dans notre cluster Kubernetes tout en affichant la commande complète à utiliser sur les autres nœuds qui permettra de rejoindre le cluster.</p>
<pre><code class="lang-bash">sudo kubeadm join 172.31.23.252:6443 --token 6a91sy.5al82ueyuhtep9a4 --discovery-token-ca-cert-hash sha256:f46933aa3d09c2b58f649e2ff4bc8fab2ce0123bf912efe27ad803725a0cd50a
</code></pre>
<p>Nous allons exécuter cette commande en sudo sur les workers</p>
<blockquote>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1712916299286/1fbe6ae2-11bf-4eb6-8957-f4492550445e.png" alt class="image--center mx-auto" /></p>
<p>Les workers on bien rejoint le cluster</p>
<p>NB : vérifiez les groupes de sécurités au niveau des workers sur AWS afin de s'assurer que la communication est bien possible sur le port <strong>6443</strong></p>
</blockquote>
<h4 id="heading-verification-des-nodes">Vérification des nodes</h4>
<pre><code class="lang-bash">kubectl get nodes
</code></pre>
<blockquote>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1712916388197/26e48d0e-40c2-4323-9dd9-62b78d8c56a6.png" alt class="image--center mx-auto" /></p>
</blockquote>
<h2 id="heading-documentation">Documentation</h2>
<h3 id="heading-installer-docker-sur-ubuntuhttpsdocsdockercomengineinstallubuntu"><a target="_blank" href="https://docs.docker.com/engine/install/ubuntu/">Installer Docker sur ubuntu</a></h3>
<h3 id="heading-installer-kubeadm-sur-ubuntuhttpskubernetesiodocssetupproduction-environmenttoolskubeadminstall-kubeadm"><a target="_blank" href="https://kubernetes.io/docs/setup/production-environment/tools/kubeadm/install-kubeadm/">Installer kubeadm sur ubuntu</a></h3>
<h3 id="heading-creating-a-single-control-plane-cluster-with-kubeadmhttpskubernetesiodocssetupproduction-environmenttoolskubeadmcreate-cluster-kubeadm"><a target="_blank" href="https://kubernetes.io/docs/setup/production-environment/tools/kubeadm/create-cluster-kubeadm/">Creating a Single Control-Plane Cluster with kubeadm</a></h3>
]]></content:encoded></item><item><title><![CDATA[Ansible | Création de rôles Ansible et mise en place des rôles distant via Gitlab.]]></title><description><![CDATA[Carlin FONGANG | LinkedIn | GitLab | GitHub | Credly

Contexte
Notre plan d'action vise à améliorer la collaboration avec une autre équipe en transformant un playbook "monolithique" en un ensemble de rôles modulaires pour une adaptation aisée. Nous i...]]></description><link>https://blog.acloud.digital/creation-de-roles-ansible-et-gestion-des-roles-distant-via-gitlab</link><guid isPermaLink="true">https://blog.acloud.digital/creation-de-roles-ansible-et-gestion-des-roles-distant-via-gitlab</guid><category><![CDATA[ansible]]></category><category><![CDATA[ansible-playbook]]></category><category><![CDATA[ansible-role]]></category><category><![CDATA[AWS]]></category><dc:creator><![CDATA[Carlin FONGANG]]></dc:creator><pubDate>Sun, 07 Apr 2024 21:59:36 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/UHDx3BHlFvY/upload/8b821194d360a9b53cfa2dac2ae83eaf.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<blockquote>
<p><strong>Carlin FONGANG</strong> | <a target="_blank" href="https://www.linkedin.com/in/carlinfongang/">LinkedIn</a> | <a target="_blank" href="https://gitlab.com/carlinfongang">GitLab</a> | <a target="_blank" href="https://github.com/carlinfongang">GitHub</a> | <a target="_blank" href="https://www.credly.com/users/carlin-fongang/badges">Credly</a></p>
</blockquote>
<h2 id="heading-contexte">Contexte</h2>
<p>Notre plan d'action vise à améliorer la collaboration avec une autre équipe en transformant un playbook "monolithique" en un ensemble de rôles modulaires pour une adaptation aisée. Nous intégrerons également des playbooks de test pour faciliter l'évaluation de nos rôles, ainsi que l'intégration rapide dans d'autres processus de déploiement. De plus, nous créerons un dépôt privé pour nos rôles, permettant ainsi une gestion centralisée pour toute utilisation future. Ces mesures renforceront les workflows intégrant ces rôles comme tâches ou actions et augmenteront notre capacité à répondre aux besoins spécifiques de l'équipe.</p>
<h2 id="heading-objectifs">Objectifs</h2>
<p>Dans ce laboratoire, nous allons :</p>
<ol>
<li><p>Rédiger des rôles permettant de déployer des conteneurs Docker. Cette étape favorisera une modularité accrue, offrant ainsi la flexibilité nécessaire pour une adaptation contextuelle.</p>
</li>
<li><p>Intégrer deux playbooks de tests (httpd/Apache et Wordpress via docker-compose) à nos rôles pour une intégration souple dans les processus de déploiement existants.</p>
</li>
<li><p>Provisionner une instance cible EC2 à l'aide de Terraform et configurer cette instance avec Ansible afin d'y déployer nos nouveaux playbooks en guise de test.</p>
</li>
<li><p>Établir un hébergement distant pour nos rôles, destiné à la conservation et à la gestion centralisée de ceux-ci, ce qui renforcera l'efficacité et la réutilisation des ressources au sein de notre équipe.</p>
</li>
</ol>
<p>Ces actions permettront d'optimiser notre workflow et de répondre aux exigences spécifiques de l'équipe.</p>
<p><a target="_blank" href="https://gitlab.com/CarlinFongang-Labs/Ansible/lab8-role-wordpress.git">Lien vers le playbook à transformer en rôle</a></p>
<h2 id="heading-prerequis">Prérequis</h2>
<p>Disposer d'une machine avec ansible déjà installées.</p>
<p>Dans notre cas, nous allons provisionner une instances EC2 s'exécutant sous Ubuntu grace au provider AWS, à partir delaquelle nous effectuerons toutes nos opérations.</p>
<p>Documentation complémentaire :</p>
<p><a target="_blank" href="https://docs.ansible.com/ansible/latest/index.html">Documentation Ansible</a></p>
<p><a target="_blank" href="https://gitlab.com/CarlinFongang-Labs/Terraform/lab2-terraform-aws">Provisionner une instance EC2 sur AWS à l'aide de Terraform</a></p>
<p><a target="_blank" href="https://gitlab.com/CarlinFongang-Labs/Ansible/lab10-deploy-ec2">Provisionner une instance EC2 sur AWS à l'aide d'Ansible</a></p>
<h2 id="heading-1-refactorisation-de-notre-playbook-initial-en-role">1. Refactorisation de notre playbook initial en rôle</h2>
<p>Rappelons que nous avons mis en place un playbook permettant de lancer un conteneur <a target="_blank" href="https://gitlab.com/CarlinFongang-Labs/Ansible/lab5-playbook.git">Apache consultable ici</a>, et un autre permettant de déployer des conteneurs <a target="_blank" href="https://gitlab.com/CarlinFongang-Labs/Ansible/lab8-role-wordpress.git">Wordpress conultable ici</a>, ceci via docker-compose.</p>
<p>Dans la suite, nous allons transformer les différentes tâches du playbook nécessaires au déploiement d'un conteneur (par exemple Apache/httpd), en rôle. Ainsi, nous changerons le fichier de playbook de la description de ces tâches et nous ferons simplement appel aux rôles, dont nous pourrons modifier le comportement via des variables.</p>
<h2 id="heading-2-definition-des-taches">2. Définition des taches</h2>
<p>Pour déployer un conteneur, il faut suivre des étapes préparatoires essentielles :</p>
<ol>
<li><p>Préparer l'hôte Ansible en installant les paquets nécessaires.</p>
</li>
<li><p>Installer Terraform sur la machine Ansible pour gérer le provisionnement de l'infrastructure AWS.</p>
</li>
<li><p>Utiliser Terraform pour provisionner l'infrastructure et récupérer l'IP de l'instance créée.</p>
</li>
<li><p>Vérifier la connectivité SSH avec la nouvelle instance avant toute opération.</p>
</li>
<li><p>Installer les paquets requis, dont Docker, sur l'instance cible.</p>
</li>
<li><p>Copier le template Jinja depuis Ansible vers la machine distante.</p>
</li>
<li><p>Déployer le conteneur en utilisant le template Jinja et monter les volumes appropriés.</p>
</li>
</ol>
<h2 id="heading-3-creation-des-differents-roles">3. Création des différents roles</h2>
<p>Le playbook initial dont on va s'inspirer pour réaliser nos rôles se trouve dans le repository suivant : <a target="_blank" href="https://gitlab.com/CarlinFongang-Labs/Ansible/lab5-playbook.git">Déployez un conteneur Apache (httpd) à l'aide d'un palybook Ansible</a></p>
<p>Afin de respecter les normes de création des rôles sous Ansible, nous allons organiser notre projet (<strong>local-role</strong>) en sous répertoires avec une nomenclature spécifique comme décrit ci-dessous :</p>
<blockquote>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1712525858940/b3c16342-368a-4afb-8407-6b17a0243812.png" alt class="image--center mx-auto" /></p>
</blockquote>
<p>Pour donner un peu de contexte : Dans un rôle Ansible, chaque dossier et fichier a un but spécifique pour organiser et exécuter les tâches de configuration :</p>
<ul>
<li><p><strong>tasks/main.yml</strong> : Contient les principales tâches à exécuter par le rôle.</p>
</li>
<li><p><strong>handlers/main.yml</strong> : Définit les handlers, des tâches spéciales exécutées en réponse à d'autres tâches.</p>
</li>
<li><p><strong>defaults/main.yml</strong> : Spécifie les valeurs par défaut des variables utilisées dans le rôle.</p>
</li>
<li><p><strong>vars/main.yml</strong> : Stocke les variables du rôle qui ne devraient pas être modifiées par l'utilisateur.</p>
</li>
<li><p><strong>files/</strong> : Contient les fichiers statiques à copier sur les hôtes cibles.</p>
</li>
<li><p><strong>templates/</strong> : Stocke les templates Jinja2 qui seront traités et copiés sur les hôtes.</p>
</li>
<li><p><strong>meta/main.yml</strong> : Contient les métadonnées du rôle, comme les dépendances.</p>
</li>
<li><p><strong>tests/inventory</strong> et <strong>tests/test.yml</strong> : Utilisés pour tester le rôle.</p>
</li>
</ul>
<p>Cette structure aide à la modularité et à la réutilisation des manifest Ansible dans un contexte de travail collaboratif.</p>
<p>Dans notre cas nous mettrons en place et exploiterons une partie de ces repertoires.</p>
<h3 id="heading-1-role-setupenvironment">1. Role "setup_environment"</h3>
<h4 id="heading-11-definition-du-tasksmainyml">1.1. Définition du <strong>tasks/main.yml</strong></h4>
<p>Ce rôle Ansible est conçu pour mettre à jour le cache apt et installer une série de paquets essentiels sur les distributions Debian, y compris Ubuntu. Il inclut des outils et des bibliothèques couramment utilisés tels qu'unzip, Python, curl et git, en s'assurant que leur état soit présent sur la machine cible. La tâche devient effective uniquement si le système d'exploitation est identifié comme une distribution Debian, garantissant ainsi une exécution conditionnelle basée sur l'environnement du système.</p>
<p>Ce scipt sera décrit dans le fichier <strong>local-role/roles/setup_environment/tasks/main.yml</strong></p>
<pre><code class="lang-yaml"><span class="hljs-meta">---</span>
<span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Update</span> <span class="hljs-string">apt</span> <span class="hljs-string">cache</span> <span class="hljs-string">and</span> <span class="hljs-string">install</span> <span class="hljs-string">packages</span>
  <span class="hljs-attr">ansible.builtin.apt:</span>
    <span class="hljs-attr">name:</span>
      <span class="hljs-bullet">-</span> <span class="hljs-string">unzip</span>
      <span class="hljs-bullet">-</span> <span class="hljs-string">python3</span>
      <span class="hljs-bullet">-</span> <span class="hljs-string">python3-pip</span>
      <span class="hljs-bullet">-</span> <span class="hljs-string">apt-transport-https</span>
      <span class="hljs-bullet">-</span> <span class="hljs-string">ca-certificates</span>
      <span class="hljs-bullet">-</span> <span class="hljs-string">curl</span>
      <span class="hljs-bullet">-</span> <span class="hljs-string">gnupg-agent</span>
      <span class="hljs-bullet">-</span> <span class="hljs-string">software-properties-common</span>
      <span class="hljs-bullet">-</span> <span class="hljs-string">wget</span>
      <span class="hljs-bullet">-</span> <span class="hljs-string">git</span>
      <span class="hljs-bullet">-</span> <span class="hljs-string">gnupg-agent</span>
      <span class="hljs-bullet">-</span> <span class="hljs-string">software-properties-common</span>
      <span class="hljs-bullet">-</span> <span class="hljs-string">wget</span>
    <span class="hljs-attr">state:</span> <span class="hljs-string">present</span>
    <span class="hljs-attr">update_cache:</span> <span class="hljs-literal">true</span>
  <span class="hljs-attr">become:</span> <span class="hljs-literal">true</span>
  <span class="hljs-attr">when:</span> <span class="hljs-string">ansible_os_family</span> <span class="hljs-string">==</span> <span class="hljs-string">"Debian"</span>
</code></pre>
<h4 id="heading-12-definition-du-metamainyml">1.2. Définition du <strong>meta/main.yml</strong></h4>
<p>Le fichier <code>meta/main.yml</code> sous Ansible sert à définir les métadonnées d'un rôle. Ces métadonnées incluent des informations telles que les dépendances du rôle (autres rôles nécessaires pour son fonctionnement), les plateformes (systèmes d'exploitation) supportées, et d'autres détails qui aident Ansible Galaxy (le répertoire de rôles Ansible) à indexer et classer le rôle. Ce fichier permet également de spécifier les versions minimales d'Ansible requises pour le rôle, facilitant ainsi la gestion des dépendances de manière plus transparente et efficace.</p>
<p>Dans notre cas, nous allons héberger nos rôles sur GitLab afin de les utiliser comme une sorte de "Galaxy". Il est donc nécessaire de bien décrire les fichiers <code>meta</code> pour nos rôles.</p>
<p>Le scipt ci-dessous sera décrit dans le fichier <strong>local-role/roles/setup_environment/meta/main.yml</strong></p>
<pre><code class="lang-yaml"><span class="hljs-attr">galaxy_info:</span>
  <span class="hljs-attr">author:</span> <span class="hljs-string">Carlin_FONGANG</span>
  <span class="hljs-attr">description:</span> <span class="hljs-string">Update</span> <span class="hljs-string">apt</span> <span class="hljs-string">cache</span> <span class="hljs-string">and</span> <span class="hljs-string">install</span> <span class="hljs-string">packages</span> <span class="hljs-string">on</span> <span class="hljs-string">local</span> <span class="hljs-string">compute</span> 
  <span class="hljs-attr">company:</span> <span class="hljs-string">Carlin_FONGANG</span>

  <span class="hljs-attr">license:</span> <span class="hljs-string">MIT</span>
  <span class="hljs-attr">min_ansible_version:</span> <span class="hljs-number">2.16</span><span class="hljs-number">.5</span>

  <span class="hljs-attr">platforms:</span>
    <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Ubuntu</span>
      <span class="hljs-attr">versions:</span>
      <span class="hljs-bullet">-</span> <span class="hljs-string">focal</span>    <span class="hljs-comment"># Ubuntu 20.04</span>
      <span class="hljs-bullet">-</span> <span class="hljs-string">bionic</span>   <span class="hljs-comment"># Ubuntu 18.04</span>
      <span class="hljs-bullet">-</span> <span class="hljs-string">jammy</span>    <span class="hljs-comment"># Ubuntu 22.04</span>
    <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Debian</span>
      <span class="hljs-attr">versions:</span>
      <span class="hljs-bullet">-</span> <span class="hljs-string">bullseye</span> <span class="hljs-comment"># Debian 11</span>
      <span class="hljs-bullet">-</span> <span class="hljs-string">buster</span>   <span class="hljs-comment"># Debian 10</span>
  <span class="hljs-attr">galaxy_tags:</span>
    <span class="hljs-bullet">-</span> <span class="hljs-string">terraform</span>
    <span class="hljs-bullet">-</span> <span class="hljs-string">aws</span>
<span class="hljs-attr">dependencies:</span> []
</code></pre>
<h4 id="heading-13-definition-du-teststestyml">1.3. Définition du <strong>tests/test.yml</strong></h4>
<p>Nous pouvons mettre en palce un playbook de test pour vérfie la fiabilité de ce role</p>
<pre><code class="lang-bash">nano local-role/roles/setup_environment/tests/test.yml
</code></pre>
<pre><code class="lang-yaml"><span class="hljs-bullet">-</span> <span class="hljs-attr">hosts:</span> <span class="hljs-string">localhost</span>
  <span class="hljs-attr">become:</span> <span class="hljs-literal">true</span>
  <span class="hljs-attr">roles:</span>
    <span class="hljs-bullet">-</span> <span class="hljs-string">setup_environment</span>

  <span class="hljs-attr">tasks:</span>
    <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Vérifier</span> <span class="hljs-string">que</span> <span class="hljs-string">les</span> <span class="hljs-string">paquets</span> <span class="hljs-string">nécessaires</span> <span class="hljs-string">sont</span> <span class="hljs-string">installés</span>
      <span class="hljs-attr">ansible.builtin.package_facts:</span>
        <span class="hljs-attr">manager:</span> <span class="hljs-string">auto</span>

    <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Tester</span> <span class="hljs-string">la</span> <span class="hljs-string">présence</span> <span class="hljs-string">des</span> <span class="hljs-string">paquets</span>
      <span class="hljs-attr">assert:</span>
        <span class="hljs-attr">that:</span> 
          <span class="hljs-bullet">-</span> <span class="hljs-string">"'unzip' in ansible_facts.packages"</span>
          <span class="hljs-bullet">-</span> <span class="hljs-string">"'python3' in ansible_facts.packages"</span>
          <span class="hljs-bullet">-</span> <span class="hljs-string">"'python3-pip' in ansible_facts.packages"</span>
          <span class="hljs-bullet">-</span> <span class="hljs-string">"'apt-transport-https' in ansible_facts.packages"</span>
          <span class="hljs-bullet">-</span> <span class="hljs-string">"'ca-certificates' in ansible_facts.packages"</span>
          <span class="hljs-bullet">-</span> <span class="hljs-string">"'curl' in ansible_facts.packages"</span>
          <span class="hljs-bullet">-</span> <span class="hljs-string">"'gnupg-agent' in ansible_facts.packages"</span>
          <span class="hljs-bullet">-</span> <span class="hljs-string">"'software-properties-common' in ansible_facts.packages"</span>
          <span class="hljs-bullet">-</span> <span class="hljs-string">"'wget' in ansible_facts.packages"</span>
          <span class="hljs-bullet">-</span> <span class="hljs-string">"'git' in ansible_facts.packages"</span>
        <span class="hljs-attr">fail_msg:</span> <span class="hljs-string">"Un ou plusieurs paquets requis ne sont pas installés."</span>
        <span class="hljs-attr">success_msg:</span> <span class="hljs-string">"Tous les paquets requis sont installés."</span>
</code></pre>
<h4 id="heading-14-test-du-playbook-setupenvironment">1.4. Test du playbook <strong>setup_environment</strong></h4>
<pre><code class="lang-bash"><span class="hljs-built_in">cd</span> local-role
</code></pre>
<ol>
<li>Test du role <strong>setup_environment</strong></li>
</ol>
<pre><code class="lang-bash">ansible-playbook roles/setup_environment/tests/test.yml -K -vvv
</code></pre>
<p>Cette commande exécute le playbook Ansible <code>test.yml</code> situé dans le répertoire <code>roles/setup_environment/tests</code>.</p>
<p>L'option <code>-K</code> demande à Ansible d'afficher un prompt pour saisir le mot de passe de privilège (sudo), nécessaire pour exécuter certaines tâches demandant des droits élevés.</p>
<p>L'option <code>-vvv</code> active un mode de verbosité très détaillé, offrant un aperçu approfondi du déroulement du playbook, ce qui est utile pour le débogage ou pour comprendre précisément les opérations effectuées lors de l'exécution.</p>
<ol start="2">
<li>Résultat du <strong>test</strong></li>
</ol>
<blockquote>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1712526040524/6cf2a542-423c-4f79-b6a4-cfa80663210e.png" alt class="image--center mx-auto" /></p>
<p><em>Paquets requis installés</em></p>
</blockquote>
<p>L'on peut voir que le playbook de test à pu être déployé entièrement et que tous les paquets sont bien installés.</p>
<h3 id="heading-2-role-installterraform">2. Role "install_terraform"</h3>
<p>Ce rôle Ansible permet de télécharger, installer et vérifier la version prédéfinie de Terraform sur une machine ansible. Il commence par télécharger l'archive de Terraform depuis le site officiel de HashiCorp, en spécifiant la version et l'architecture désirées. Ensuite, il extrait l'archive dans <code>/usr/local/bin</code> pour installer Terraform. Enfin, il exécute Terraform pour vérifier l'installation et affiche la version installée, assurant ainsi que Terraform est prêt à être utilisé.</p>
<h4 id="heading-21-definition-du-tasksmainyml">2.1. Définition du <strong>tasks/main.yml</strong></h4>
<pre><code class="lang-bash">nano local-role/roles/install_terraform/tasks/main.yml
</code></pre>
<pre><code class="lang-yaml"><span class="hljs-meta">---</span>
<span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Download</span> <span class="hljs-string">Terraform</span>
  <span class="hljs-attr">ansible.builtin.get_url:</span>
    <span class="hljs-attr">url:</span> <span class="hljs-string">"https://releases.hashicorp.com/terraform/<span class="hljs-template-variable">{{ terraform_version }}</span>/terraform_<span class="hljs-template-variable">{{ terraform_version }}</span>_<span class="hljs-template-variable">{{ terraform_architecture }}</span>.zip"</span>
    <span class="hljs-attr">dest:</span> <span class="hljs-string">"/tmp/terraform_<span class="hljs-template-variable">{{ terraform_version }}</span>_<span class="hljs-template-variable">{{ terraform_architecture }}</span>"</span>
  <span class="hljs-attr">become:</span> <span class="hljs-literal">true</span>

<span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Unzip</span> <span class="hljs-string">Terraform</span>
  <span class="hljs-attr">ansible.builtin.unarchive:</span>
    <span class="hljs-attr">src:</span> <span class="hljs-string">"/tmp/terraform_<span class="hljs-template-variable">{{ terraform_version }}</span>_<span class="hljs-template-variable">{{ terraform_architecture }}</span>"</span>
    <span class="hljs-attr">dest:</span> <span class="hljs-string">"/usr/local/bin"</span>
    <span class="hljs-attr">remote_src:</span> <span class="hljs-literal">yes</span>
    <span class="hljs-attr">creates:</span> <span class="hljs-string">"/usr/local/bin/terraform"</span>
  <span class="hljs-attr">become:</span> <span class="hljs-literal">true</span>

<span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Verify</span> <span class="hljs-string">Terraform</span> <span class="hljs-string">installation</span>
  <span class="hljs-attr">ansible.builtin.command:</span> <span class="hljs-string">terraform</span> <span class="hljs-string">version</span>
  <span class="hljs-attr">register:</span> <span class="hljs-string">terraform_version</span>
  <span class="hljs-attr">changed_when:</span> <span class="hljs-literal">false</span>

<span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Show</span> <span class="hljs-string">Terraform</span> <span class="hljs-string">version</span>
  <span class="hljs-attr">debug:</span>
      <span class="hljs-attr">msg:</span> <span class="hljs-string">"Terraform version installed: <span class="hljs-template-variable">{{ terraform_version.stdout }}</span>"</span>
</code></pre>
<h4 id="heading-22-definition-du-defaultsmainyml">2.2. Définition du <strong>defaults/main.yml</strong></h4>
<pre><code class="lang-yaml"><span class="hljs-attr">terraform_version:</span> <span class="hljs-string">"1.7.5"</span>
<span class="hljs-attr">terraform_architecture:</span> <span class="hljs-string">"linux_amd64"</span>
</code></pre>
<p>Ces lignes définissent deux variables pour une utilisation avec Terraform dans le fichier de configuration <strong>tasks/main.yml</strong>.</p>
<p><code>terraform_version: "1.7.5"</code> spécifie la version de Terraform à utiliser, tandis que <code>terraform_architecture: "linux_amd64"</code> indique l'architecture cible pour laquelle Terraform est destiné, dans ce cas, Linux 64 bits. Ces variables sont ensuite utilisées pour télécharger la version correcte de Terraform correspondant à ces spécifications.</p>
<h4 id="heading-23-definition-du-metamainyml">2.3. Définition du <strong>meta/main.yml</strong></h4>
<p>Pour ce fichier, nous allons simplement reprendre le fichier décrit dans la section " <a target="_blank" href="https://gitlab.com/CarlinFongang-Labs/Ansible/ansible-project/local-role#12-d%C3%A9finition-du-metamainyml">1.2. Définition du <strong>meta/main.yml</strong></a>"</p>
<h4 id="heading-24-definition-du-teststesttfyml">2.4. Définition du <strong>tests/test_tf.yml</strong></h4>
<p>Ce playbook de test permet de valider l'installation de Terraform sur l'instance Ansible (l'instance sur laquelle nous travaillons).</p>
<pre><code class="lang-bash">nano roles/install_terraform/tests/test_tf.yml
</code></pre>
<pre><code class="lang-yaml"><span class="hljs-meta">---</span>
<span class="hljs-bullet">-</span> <span class="hljs-attr">hosts:</span> <span class="hljs-string">localhost</span>
  <span class="hljs-attr">gather_facts:</span> <span class="hljs-literal">false</span>
  <span class="hljs-attr">roles:</span>
    <span class="hljs-bullet">-</span> <span class="hljs-string">../../install_terraform/</span>
  <span class="hljs-attr">tasks:</span>
    <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Obtenir</span> <span class="hljs-string">la</span> <span class="hljs-string">version</span> <span class="hljs-string">de</span> <span class="hljs-string">Terraform</span>
      <span class="hljs-attr">command:</span> <span class="hljs-string">terraform</span> <span class="hljs-string">-v</span>
      <span class="hljs-attr">register:</span> <span class="hljs-string">terraform_version_output</span>

    <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Afficher</span> <span class="hljs-string">la</span> <span class="hljs-string">version</span> <span class="hljs-string">de</span> <span class="hljs-string">Terraform</span>
      <span class="hljs-attr">debug:</span>
        <span class="hljs-attr">msg:</span> <span class="hljs-string">"La version de Terraform installée est : <span class="hljs-template-variable">{{ terraform_version_output.stdout_lines[0] }}</span>"</span>
</code></pre>
<h4 id="heading-25-test-du-playbook-installterraform">2.5. Test du playbook <strong>install_terraform</strong></h4>
<pre><code class="lang-bash"><span class="hljs-built_in">cd</span> local-role
</code></pre>
<ol>
<li>Test du role <strong>install_terraform</strong></li>
</ol>
<pre><code class="lang-bash">ansible-playbook roles/install_terraform/tests/test_tf.yml -K -vvv
</code></pre>
<ol start="2">
<li><p>Résultat du <strong>test_tf</strong></p>
<blockquote>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1712526133520/385dfe61-a2a5-4c64-b831-3d3f041e8a87.png" alt class="image--center mx-auto" /></p>
<p><em>Vérification de la version de terraform</em></p>
</blockquote>
</li>
</ol>
<p>L'on peut voir que le playbook de test à pu être déployé entièrement et que la version de Terraform souhaitez à bien été installée.</p>
<h3 id="heading-3-role-providecompute">3. Role "provide_compute"</h3>
<h4 id="heading-31-definition-du-tasksmainyml">3.1. Définition du <strong>tasks/main.yml</strong></h4>
<p>Ce rôle Ansible effectue plusieurs tâches liées à la gestion d'une infrastructure, notamment le clonage d'un dépôt Git spécifié, l'initialisation et l'application de configurations Terraform dans un répertoire cible, et la gestion d'informations sur une instance EC2 qui sera provisionnée. Il commence par cloner un dépôt Git contenant les manifest terraform, puis utilise <code>terraform init -reconfigure</code> pour initialiser et <code>terraform apply -auto-approve</code> appliquer la configuration spécifiée. Enfin, il lit l'adresse IP de l'instance EC2 provisionnée à partir d'un fichier généré et ajoute cette information à un fichier 'hosts.yml', permettant ainsi une intégration facile aux autres opérations Ansible qui vont suivre.</p>
<pre><code class="lang-yaml"><span class="hljs-meta">---</span>
<span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Clone</span> <span class="hljs-string">repository</span>
  <span class="hljs-attr">ansible.builtin.git:</span>
    <span class="hljs-attr">repo:</span> <span class="hljs-string">"<span class="hljs-template-variable">{{ repo_url }}</span>"</span>
    <span class="hljs-attr">dest:</span> <span class="hljs-string">"<span class="hljs-template-variable">{{ repo_dest }}</span>"</span>
    <span class="hljs-attr">version:</span> <span class="hljs-string">"<span class="hljs-template-variable">{{ repo_tag }}</span>"</span>
    <span class="hljs-attr">update:</span> <span class="hljs-literal">yes</span>

<span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Initialize</span> <span class="hljs-string">Terraform</span>
  <span class="hljs-attr">ansible.builtin.command:</span>
    <span class="hljs-attr">cmd:</span> <span class="hljs-string">terraform</span> <span class="hljs-string">init</span> <span class="hljs-string">-reconfigure</span>
    <span class="hljs-attr">chdir:</span> <span class="hljs-string">"<span class="hljs-template-variable">{{ tf_init_apply_path }}</span>"</span>

<span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Apply</span> <span class="hljs-string">Terraform</span> <span class="hljs-string">configuration</span>
  <span class="hljs-attr">ansible.builtin.command:</span>
    <span class="hljs-attr">cmd:</span> <span class="hljs-string">terraform</span> <span class="hljs-string">apply</span> <span class="hljs-string">-auto-approve</span>
    <span class="hljs-attr">chdir:</span> <span class="hljs-string">"<span class="hljs-template-variable">{{ tf_init_apply_path }}</span>"</span>

<span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Read</span> <span class="hljs-string">EC2</span> <span class="hljs-string">instance</span> <span class="hljs-string">IP</span> <span class="hljs-string">from</span> <span class="hljs-string">generated</span> <span class="hljs-string">file</span>
  <span class="hljs-attr">ansible.builtin.include_vars:</span>
    <span class="hljs-attr">file:</span> <span class="hljs-string">"<span class="hljs-template-variable">{{ ec2_info_file_path }}</span>"</span>
    <span class="hljs-attr">name:</span> <span class="hljs-string">ec2_info</span>

<span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Add</span> <span class="hljs-string">EC2</span> <span class="hljs-string">instance</span> <span class="hljs-string">IP</span> <span class="hljs-string">to</span> <span class="hljs-string">'hosts.yml'</span>
  <span class="hljs-attr">ansible.builtin.lineinfile:</span>
    <span class="hljs-attr">path:</span> <span class="hljs-string">"<span class="hljs-template-variable">{{ hosts_file_path }}</span>"</span>
    <span class="hljs-attr">line:</span> <span class="hljs-string">"          ansible_host: <span class="hljs-template-variable">{{ ec2_info.ec2_info.server_public_ip }}</span>"</span>
    <span class="hljs-attr">create:</span> <span class="hljs-literal">yes</span>
  <span class="hljs-attr">delegate_to:</span> <span class="hljs-string">localhost</span>

<span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Debug</span> <span class="hljs-string">ec2_info</span>
  <span class="hljs-attr">ansible.builtin.debug:</span>
    <span class="hljs-attr">var:</span> <span class="hljs-string">ec2_info</span> <span class="hljs-comment">#</span>
</code></pre>
<h4 id="heading-32-definition-du-defaultsmainyml">3.2. Définition du <strong>defaults/main.yml</strong></h4>
<pre><code class="lang-yaml"><span class="hljs-attr">repo_url:</span> <span class="hljs-string">"https://gitlab.com/CarlinFongang-Labs/Ansible/tf-provide-target-instance.git"</span>
<span class="hljs-attr">repo_dest:</span> <span class="hljs-string">"/tmp/tf-provide-target-instance"</span>
<span class="hljs-attr">repo_tag:</span> <span class="hljs-string">"main"</span>
<span class="hljs-attr">tf_init_apply_path:</span> <span class="hljs-string">"/tmp/tf-provide-target-instance/ec2_target_host"</span>
<span class="hljs-attr">ec2_info_file_path:</span> <span class="hljs-string">"/tmp/tf-provide-target-instance/ec2_target_host/public_ip.yml"</span>
<span class="hljs-attr">hosts_file_path:</span> <span class="hljs-string">"~/local-role/hosts.yml"</span>
</code></pre>
<p>Ces variables sont configurées pour le rôle Ansible détaillé plus haut :</p>
<ul>
<li><p><code>repo_url</code> : URL du dépôt Git contenant la configuration Terraform.</p>
</li>
<li><p><code>repo_dest</code> : Emplacement local où le dépôt sera cloné.</p>
</li>
<li><p><code>repo_tag</code> : Branche ou tag du dépôt à cloner.</p>
</li>
<li><p><code>tf_init_apply_path</code> : Dossier contenant les fichiers de configuration Terraform à initialiser et appliquer.</p>
</li>
<li><p><code>ec2_info_file_path</code> : Chemin vers le fichier stockant l'adresse IP publique de l'instance EC2 générée.</p>
</li>
<li><p><code>hosts_file_path</code> : Emplacement du fichier <code>hosts.yml</code> à mettre qui sera mis à jour avec l'adresse IP de l'instance EC2 une fois celle ci provisionné à l'aide de Terraform.</p>
</li>
</ul>
<p>toutes ces variables sont ajustable dans le fichier <strong>group_vars/all.yml</strong>, selon le contexte d'utilisation</p>
<h4 id="heading-32-definition-du-metamainyml">3.2. Définition du <strong>meta/main.yml</strong></h4>
<p>Pour ce fichier, nous allons simplement reprendre le fichier décrit dans la section " <a target="_blank" href="https://gitlab.com/CarlinFongang-Labs/Ansible/ansible-project/local-role#12-d%C3%A9finition-du-metamainyml">1.2. Définition du <strong>meta/main.yml</strong></a>"</p>
<h4 id="heading-33-definition-du-teststestprovideyml">3.3. Définition du <strong>tests/test_provide.yml</strong></h4>
<p>Ce playbook de test permet de valider le bon fonctionneement du role <strong>provide_compute</strong> .</p>
<pre><code class="lang-bash">nano roles/provide_compute/tests/test_provide.yml
</code></pre>
<pre><code class="lang-yaml"><span class="hljs-meta">---</span>
<span class="hljs-bullet">-</span> <span class="hljs-attr">hosts:</span> <span class="hljs-string">localhost</span>
  <span class="hljs-attr">gather_facts:</span> <span class="hljs-literal">false</span>
  <span class="hljs-attr">roles:</span>
    <span class="hljs-bullet">-</span> <span class="hljs-string">../../provide_compute</span>

  <span class="hljs-attr">tasks:</span>
    <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Afficher</span> <span class="hljs-string">l'adresse</span> <span class="hljs-string">IP</span> <span class="hljs-string">de</span> <span class="hljs-string">l'instance</span> <span class="hljs-string">EC2</span>
      <span class="hljs-attr">debug:</span>
        <span class="hljs-attr">msg:</span> <span class="hljs-string">"L'adresse IP de l'instance EC2 est : <span class="hljs-template-variable">{{ ec2_info.ec2_info.server_public_ip }}</span>"</span>
</code></pre>
<h4 id="heading-34-test-du-playbook-providecompute">3.4. Test du playbook <strong>provide_compute</strong></h4>
<p>Afin de tester ce playbook, nous aurons besoin de mettre en place un <strong>bucket "s3"</strong> pour le stockage du <strong>Remote State</strong>, et récupérer également la paire de clé de sécurité de l'utilisateur AWS.</p>
<p>une fois ces informations récupérées :</p>
<ol>
<li>Exporter la paire de clés</li>
</ol>
<pre><code class="lang-bash"><span class="hljs-built_in">export</span> AWS_ACCESS_KEY_ID=<span class="hljs-string">"AKIAQ2LRBUZA7D32KAX3"</span>
<span class="hljs-built_in">export</span> AWS_SECRET_ACCESS_KEY=<span class="hljs-string">"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"</span>
</code></pre>
<p>Remplacer les valeurs par ceux du compte AWS à utiliser</p>
<ol start="2">
<li>Créer un <strong>Bucket s3</strong></li>
</ol>
<p>L'usage du manifest Terraform défini par défaut dans le rôle, est conditionné par l'existence d'un bucket où sera stocké le <strong>tfstate</strong>, le nom de ce bucket est consultable dans le code <a target="_blank" href="https://gitlab.com/CarlinFongang-Labs/Ansible/tf-provide-target-instance/-/blob/main/ec2_target_host/main.tf">Terraform - Provisionnement instance cible</a></p>
<blockquote>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1712526180575/900c0885-6b1a-43a1-84e3-04cd55dfafdd.png" alt class="image--center mx-auto" /></p>
</blockquote>
<p>Notez qu'il est également possible de <strong>forker</strong> le projet Terraform et de modifier le nom du bucket pour l'ajuster à un contexte spécifique, il faudra alors modifier la variable "<strong>repo_url"</strong> dans le fichier "<strong>group_vars/all.yml"</strong>, afin de définir le nouveau dépôt du code <strong>Terraform</strong>.</p>
<p>Une fois ces conditions préalables remplies, on peut tester le playbook</p>
<ol start="3">
<li>Test du role <strong>provide_compute</strong></li>
</ol>
<pre><code class="lang-bash">ansible-playbook roles/provide_compute/tests/test_provide.yml -K -vvv
</code></pre>
<ol start="4">
<li>Résultat du <strong>test_provide</strong></li>
</ol>
<blockquote>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1712526248484/8d97a487-5fd9-41b0-8cbc-e8ef687b7e9e.png" alt class="image--center mx-auto" /></p>
<p><em>Instance provisionnée et ip disponible</em></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1712526273206/695c185e-a4b1-4b7c-8068-7a828a8a20e6.png" alt class="image--center mx-auto" /></p>
<p><em>Instance provisionnée</em></p>
</blockquote>
<p>L'on peut voir que le playbook de test à pu être déployé entièrement et qu'une instance ec2 à été provisionnée ainsi qu'une adresse Elastic IP.</p>
<p>De plus ce role permet d'écrire directement l'EIP de la nouvelle instance dans le fichier hosts.yml, ce qui va être pratique par la suite pour effectuer les diverses opérations sur notre nouvelle machine distante.</p>
<h3 id="heading-4-role-checkssh">4. Role "check_ssh"</h3>
<h4 id="heading-41-definit-du-tasksmainyml">4.1. Définit du <strong>tasks/main.yml</strong></h4>
<p>Le rôle <code>check_ssh</code> est conçu pour vérifier la disponibilité du service SSH sur des serveurs. Il utilise la tâche <code>wait_for</code> pour attendre que le port 22 (SSH) sur les hôtes spécifiés soit accessible, assurant ainsi que les serveurs sont prêts pour des connexions SSH. Cette vérification est effectuée sur tous les hôtes listés dans le groupe <code>dynamic_hosts</code>.</p>
<pre><code class="lang-yaml"><span class="hljs-meta">---</span>
<span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Refresh</span> <span class="hljs-string">Inventory</span> <span class="hljs-string">to</span> <span class="hljs-string">Ensure</span> <span class="hljs-string">Latest</span> <span class="hljs-string">Hosts</span> <span class="hljs-string">are</span> <span class="hljs-string">Used</span>
  <span class="hljs-attr">meta:</span> <span class="hljs-string">refresh_inventory</span>

<span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Wait</span> <span class="hljs-string">for</span> <span class="hljs-string">SSH</span> <span class="hljs-string">to</span> <span class="hljs-string">come</span> <span class="hljs-string">up</span> <span class="hljs-string">on</span> <span class="hljs-string">the</span> <span class="hljs-string">servers</span>
  <span class="hljs-attr">ansible.builtin.wait_for:</span>
    <span class="hljs-attr">host:</span> <span class="hljs-string">"<span class="hljs-template-variable">{{ hostvars[item].ansible_host }}</span>"</span>
    <span class="hljs-attr">port:</span> <span class="hljs-number">22</span>
    <span class="hljs-attr">state:</span> <span class="hljs-string">started</span>
  <span class="hljs-attr">loop:</span> <span class="hljs-string">"<span class="hljs-template-variable">{{ groups['dynamic_hosts'] }}</span>"</span>
  <span class="hljs-attr">when:</span> <span class="hljs-string">"'dynamic_hosts' in groups"</span>
</code></pre>
<h4 id="heading-42-definition-du-metamainyml">4.2. Définition du <strong>meta/main.yml</strong></h4>
<p>Pour ce fichier, nous allons simplement reprendre le fichier décrit dans la section "<a target="_blank" href="https://gitlab.com/CarlinFongang-Labs/Ansible/ansible-project/local-role#12-d%C3%A9finition-du-metamainyml">1.2. Définition du <strong>meta/main.yml</strong></a>"</p>
<h4 id="heading-43-definition-du-teststestchecksshyml">4.3. Définition du <strong>tests/test_check_ssh.yml</strong></h4>
<p>Nous avons provisionné une instance ec2 dans l'étape précédente, nous allons à présent vérifier qu'il est possible de se connecter en ssh à cette instance</p>
<pre><code class="lang-bash">nano roles/check_ssh/tests/test_check_ssh.yml
</code></pre>
<pre><code class="lang-yaml"><span class="hljs-meta">---</span>
<span class="hljs-bullet">-</span> <span class="hljs-attr">hosts:</span> <span class="hljs-string">dynamic_hosts</span>
  <span class="hljs-attr">gather_facts:</span> <span class="hljs-literal">false</span>
  <span class="hljs-attr">roles:</span>
    <span class="hljs-bullet">-</span> <span class="hljs-string">../../check_ssh</span>
  <span class="hljs-attr">tasks:</span>
    <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Afficher</span> <span class="hljs-string">le</span> <span class="hljs-string">message</span> <span class="hljs-string">de</span> <span class="hljs-string">réussite</span>
      <span class="hljs-attr">debug:</span>
        <span class="hljs-attr">msg:</span> <span class="hljs-string">"Connexion ssh établie avec succes !"</span>
      <span class="hljs-attr">when:</span> <span class="hljs-string">ansible_failed_task</span> <span class="hljs-string">is</span> <span class="hljs-string">undefined</span>
</code></pre>
<h4 id="heading-44-test-du-playbook-testcheckssh">4.4. Test du playbook <strong>test_check_ssh</strong></h4>
<pre><code class="lang-bash">ansible-playbook roles/check_ssh/tests/test_check_ssh.yml -K -vvv
</code></pre>
<blockquote>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1712526304377/e48b2de8-b373-41b8-9cb4-859436757695.png" alt class="image--center mx-auto" /></p>
<p><em>Connexion ssh réussie</em></p>
</blockquote>
<h3 id="heading-5-role-preparedocker">5. Role "prepare_docker"</h3>
<h4 id="heading-51-definit-du-tasksmainyml">5.1. Définit du <strong>tasks/main.yml</strong></h4>
<p>Ce rôle Ansible est conçu pour installer Docker et ses dépendances sur un système. Il commence par mettre à jour le cache des paquets et installer des prérequis. Ensuite, il ajoute la clé GPG officielle de Docker et installe Docker en utilisant un script récupéré depuis le site officiel de Docker. Le playbook ajoute également l'utilisateur courant au groupe Docker pour permettre l'exécution de commandes Docker sans sudo. Enfin, il assure l'installation de pip et installe Docker Compose, en vérifiant la version installée.</p>
<pre><code class="lang-yaml"><span class="hljs-meta">---</span>
<span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Install</span> <span class="hljs-string">Docker</span> <span class="hljs-string">and</span> <span class="hljs-string">dependencies</span>
  <span class="hljs-attr">ansible.builtin.apt:</span>
    <span class="hljs-attr">name:</span>
      <span class="hljs-bullet">-</span> <span class="hljs-string">apt-transport-https</span>
      <span class="hljs-bullet">-</span> <span class="hljs-string">ca-certificates</span>
      <span class="hljs-bullet">-</span> <span class="hljs-string">curl</span>
      <span class="hljs-bullet">-</span> <span class="hljs-string">software-properties-common</span>
      <span class="hljs-bullet">-</span> <span class="hljs-string">gnupg-agent</span>
    <span class="hljs-attr">state:</span> <span class="hljs-string">present</span>
    <span class="hljs-attr">update_cache:</span> <span class="hljs-literal">yes</span>

<span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Add</span> <span class="hljs-string">Docker's</span> <span class="hljs-string">official</span> <span class="hljs-string">GPG</span> <span class="hljs-string">key</span>
  <span class="hljs-attr">ansible.builtin.apt_key:</span>
    <span class="hljs-attr">url:</span> <span class="hljs-string">https://download.docker.com/linux/ubuntu/gpg</span>
    <span class="hljs-attr">state:</span> <span class="hljs-string">present</span>
  <span class="hljs-attr">when:</span> <span class="hljs-string">ansible_os_family</span> <span class="hljs-string">==</span> <span class="hljs-string">"Debian"</span>

<span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Install</span> <span class="hljs-string">Docker</span>
  <span class="hljs-attr">ansible.builtin.shell:</span> <span class="hljs-string">curl</span> <span class="hljs-string">-fsSL</span> <span class="hljs-string">https://get.docker.com</span> <span class="hljs-string">-o</span> <span class="hljs-string">get-docker.sh</span> <span class="hljs-string">&amp;&amp;</span> <span class="hljs-string">sh</span> <span class="hljs-string">get-docker.sh</span>

<span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Add</span> <span class="hljs-string">current</span> <span class="hljs-string">user</span> <span class="hljs-string">to</span> <span class="hljs-string">Docker</span> <span class="hljs-string">group</span>
  <span class="hljs-attr">ansible.builtin.user:</span>
    <span class="hljs-attr">name:</span> <span class="hljs-string">"<span class="hljs-template-variable">{{ ansible_env.SUDO_USER | default(ansible_env.USER) }}</span>"</span>
    <span class="hljs-attr">groups:</span> <span class="hljs-string">docker</span>
    <span class="hljs-attr">append:</span> <span class="hljs-literal">true</span>

<span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Ensure</span> <span class="hljs-string">pip</span> <span class="hljs-string">is</span> <span class="hljs-string">installed</span>
  <span class="hljs-attr">ansible.builtin.package:</span>
    <span class="hljs-attr">name:</span> <span class="hljs-string">python3-pip</span>
    <span class="hljs-attr">state:</span> <span class="hljs-string">present</span>
  <span class="hljs-attr">become:</span> <span class="hljs-literal">true</span>

<span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Install</span> <span class="hljs-string">Docker</span> <span class="hljs-string">Compose</span>
  <span class="hljs-attr">block:</span>
    <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Download</span> <span class="hljs-string">Docker</span> <span class="hljs-string">Compose</span> <span class="hljs-string">binary</span>
      <span class="hljs-attr">ansible.builtin.get_url:</span>
        <span class="hljs-attr">url:</span> <span class="hljs-string">"https://github.com/docker/compose/releases/download/<span class="hljs-template-variable">{{ docker_compose_version }}</span>/docker-compose-<span class="hljs-template-variable">{{ ansible_system }}</span>-<span class="hljs-template-variable">{{ ansible_architecture }}</span>"</span>
        <span class="hljs-attr">dest:</span> <span class="hljs-string">"/usr/local/bin/docker-compose"</span>
        <span class="hljs-attr">mode:</span> <span class="hljs-string">'0755'</span>
      <span class="hljs-attr">become:</span> <span class="hljs-literal">true</span>

    <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Verify</span> <span class="hljs-string">Docker</span> <span class="hljs-string">Compose</span> <span class="hljs-string">installation</span>
      <span class="hljs-attr">command:</span> <span class="hljs-string">docker-compose</span> <span class="hljs-string">--version</span>
      <span class="hljs-attr">register:</span> <span class="hljs-string">docker_compose_version</span>
      <span class="hljs-attr">failed_when:</span> <span class="hljs-string">docker_compose_version.rc</span> <span class="hljs-type">!=</span> <span class="hljs-number">0</span>

    <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Output</span> <span class="hljs-string">Docker</span> <span class="hljs-string">Compose</span> <span class="hljs-string">version</span>
      <span class="hljs-attr">debug:</span>
        <span class="hljs-attr">msg:</span> <span class="hljs-string">"Docker Compose version installed: <span class="hljs-template-variable">{{ docker_compose_version.stdout }}</span>"</span>
  <span class="hljs-attr">when:</span> <span class="hljs-string">ansible_os_family</span> <span class="hljs-string">==</span> <span class="hljs-string">"Debian"</span> <span class="hljs-string">or</span> <span class="hljs-string">ansible_os_family</span> <span class="hljs-string">==</span> <span class="hljs-string">"RedHat"</span>
</code></pre>
<h4 id="heading-52-definition-du-defaultsmainyml">5.2. Définition du <strong>defaults/main.yml</strong></h4>
<p>Dans ce fichier, nous avons déclarer la version de docker-compose à installer, la variable <code>docker_compose_version</code> est ajustable dans le fichier <strong>group_vars/all.yml</strong></p>
<pre><code class="lang-bash">docker_compose_version: <span class="hljs-string">"1.29.2"</span>
</code></pre>
<h4 id="heading-52-definition-du-metamainyml">5.2. Définition du <strong>meta/main.yml</strong></h4>
<p>Pour ce fichier, nous allons simplement reprendre le fichier décrit dans la section " <a target="_blank" href="https://gitlab.com/CarlinFongang-Labs/Ansible/ansible-project/local-role#12-d%C3%A9finition-du-metamainyml">1.2. Définition du <strong>meta/main.yml</strong></a>"</p>
<h4 id="heading-53-definition-du-teststestdockerinstallyml">5.3. Définition du <strong>tests/test_docker_install.yml</strong></h4>
<pre><code class="lang-yaml"><span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Deploy</span> <span class="hljs-string">Apache</span> <span class="hljs-string">container</span>
  <span class="hljs-attr">hosts:</span> <span class="hljs-string">dynamic_hosts</span>
  <span class="hljs-attr">become:</span> <span class="hljs-literal">true</span>
  <span class="hljs-attr">vars_files:</span>
    <span class="hljs-bullet">-</span> <span class="hljs-string">group_vars/all.yml</span>
  <span class="hljs-attr">roles:</span>
    <span class="hljs-bullet">-</span> <span class="hljs-string">../../prepare_docker</span>
</code></pre>
<h4 id="heading-54-test-du-playbook-preparedocker">5.4. Test du playbook <strong>prepare_docker</strong></h4>
<pre><code class="lang-bash">ansible-playbook roles/prepare_docker/tests/test_docker_install.yml -K -vvv
</code></pre>
<blockquote>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1712526359507/c8f6fa54-3365-4198-864c-b0a7e3ce5796.png" alt class="image--center mx-auto" /></p>
<p><em>Bonne exécution du playbook</em></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1712526368281/614aa07b-bb5d-4ff0-babd-7f0da91402b0.png" alt class="image--center mx-auto" /></p>
<p><em>Vérification de docker sur l'instance cible</em></p>
</blockquote>
<h3 id="heading-6-role-copytemplate">6. Role "copy_template"</h3>
<h4 id="heading-61-definit-du-tasksmainyml">6.1. Définit du <strong>tasks/main.yml</strong></h4>
<p>Ce rôle utilise le module <code>ansible.builtin.template</code> pour copier un template de fichier web, spécifiquement <code>index.html.j2</code>, vers un chemin défini sur la machine distante. Il définit également les permissions du fichier cible à '0644', assurant ainsi que le fichier est lisible par tous mais modifiable uniquement par le propriétaire. Ce processus permet de personnaliser et de déployer facilement des fichiers de configuration ou des pages web sur des serveurs distants.</p>
<pre><code class="lang-yaml"><span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Copy</span> <span class="hljs-string">website</span> <span class="hljs-string">file</span> <span class="hljs-string">template</span>
  <span class="hljs-attr">ansible.builtin.template:</span>
    <span class="hljs-attr">src:</span> <span class="hljs-string">index.html.j2</span>
    <span class="hljs-attr">dest:</span> <span class="hljs-string">"<span class="hljs-template-variable">{{ remote_template_path }}</span>"</span>
    <span class="hljs-attr">mode:</span> <span class="hljs-string">'0644'</span>
</code></pre>
<h4 id="heading-62-definition-du-defaultsmainyml">6.2. Définition du <strong>defaults/main.yml</strong></h4>
<pre><code class="lang-bash">remote_template_path: <span class="hljs-string">"/home/{{ ansible_env.SUDO_USER | default(ansible_env.USER) }}/index.html"</span> <span class="hljs-comment">#1</span>
</code></pre>
<h4 id="heading-62-definition-du-metamainyml">6.2. Définition du <strong>meta/main.yml</strong></h4>
<p>Pour ce fichier, nous allons simplement reprendre le fichier décrit dans la section "<a target="_blank" href="https://gitlab.com/CarlinFongang-Labs/Ansible/ansible-project/local-role#12-d%C3%A9finition-du-metamainyml">1.2. Définition du <strong>meta/main.yml</strong></a>"</p>
<h4 id="heading-63-definition-du-teststestcopyyml">6.3. Définition du <strong>tests/test_copy.yml</strong></h4>
<pre><code class="lang-bash">nana roles/copy_template/tests/test_copy.yml
</code></pre>
<pre><code class="lang-yaml"><span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Copy</span> <span class="hljs-string">Template</span> <span class="hljs-string">jinja</span> <span class="hljs-string">on</span> <span class="hljs-string">target</span> <span class="hljs-string">instance</span>
  <span class="hljs-attr">hosts:</span> <span class="hljs-string">dynamic_hosts</span>
  <span class="hljs-attr">become:</span> <span class="hljs-literal">true</span>
  <span class="hljs-attr">roles:</span>
    <span class="hljs-bullet">-</span> <span class="hljs-string">../../copy_template</span>
  <span class="hljs-attr">tasks:</span>
    <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Afficher</span> <span class="hljs-string">le</span> <span class="hljs-string">message</span> <span class="hljs-string">de</span> <span class="hljs-string">réussite</span>
      <span class="hljs-attr">debug:</span>
        <span class="hljs-attr">msg:</span> <span class="hljs-string">"Opération réussie !"</span>
      <span class="hljs-attr">when:</span> <span class="hljs-string">ansible_failed_task</span> <span class="hljs-string">is</span> <span class="hljs-string">undefined</span>
</code></pre>
<h4 id="heading-64-test-du-playbook-testcopy">6.4. Test du playbook <strong>test_copy</strong></h4>
<pre><code class="lang-bash">ansible-playbook roles/copy_template/tests/test_copy.yml -K -vvv
</code></pre>
<blockquote>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1712526416479/92557024-efc4-4e84-870f-4218f0bb63cd.png" alt class="image--center mx-auto" /></p>
<p><em>Opération de copie réussie</em></p>
</blockquote>
<p>En se connectant sur l'instance cible, on peut constater que le fichier est bel et bien copié</p>
<blockquote>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1712526433785/331cb0fb-c338-4c1f-a72d-e0d6519389d3.png" alt class="image--center mx-auto" /></p>
<p><em>fichier index.html copié sur l'instance cible</em></p>
</blockquote>
<h3 id="heading-6-role-deploycontainer">6. Role "deploy_container"</h3>
<h4 id="heading-61-definit-du-tasksmainyml-1">6.1. Définit du <strong>tasks/main.yml</strong></h4>
<p>Ce rôle Ansible utilise le module <code>community.docker.docker_container</code> pour télécharger et exécuter un conteneur Docker spécifié. Il définit le nom du conteneur, l'image à utiliser, les ports à exposer, et monte un volume pour le contenu web. Le conteneur est configuré pour démarrer automatiquement et adhérer à une politique de redémarrage continue, garantissant sa disponibilité constante.</p>
<pre><code class="lang-yaml"><span class="hljs-meta">---</span>
<span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Pull</span> <span class="hljs-string">and</span> <span class="hljs-string">run</span> <span class="hljs-string">a</span> <span class="hljs-string">Docker</span> <span class="hljs-string">container</span>
  <span class="hljs-attr">community.docker.docker_container:</span>
    <span class="hljs-attr">name:</span> <span class="hljs-string">"<span class="hljs-template-variable">{{ container_name }}</span>"</span>
    <span class="hljs-attr">image:</span> <span class="hljs-string">"<span class="hljs-template-variable">{{ container_image }}</span>"</span>
    <span class="hljs-attr">ports:</span> <span class="hljs-string">"<span class="hljs-template-variable">{{ container_ports }}</span>"</span>
    <span class="hljs-attr">volumes:</span>
      <span class="hljs-bullet">-</span> <span class="hljs-string">"<span class="hljs-template-variable">{{ remote_template_path }}</span>:<span class="hljs-template-variable">{{ document_root }}</span>/index.html"</span>
    <span class="hljs-attr">state:</span> <span class="hljs-string">started</span>
    <span class="hljs-attr">restart_policy:</span> <span class="hljs-string">always</span>
</code></pre>
<h4 id="heading-62-definition-du-defaultsmainyml-1">6.2. Définition du <strong>defaults/main.yml</strong></h4>
<pre><code class="lang-yaml"><span class="hljs-attr">container_name:</span> <span class="hljs-string">webapp</span>
<span class="hljs-attr">container_image:</span> <span class="hljs-string">httpd</span>
<span class="hljs-attr">container_ports:</span>
  <span class="hljs-bullet">-</span> <span class="hljs-string">"80:80"</span>
<span class="hljs-attr">document_root:</span> <span class="hljs-string">"/usr/local/apache2/htdocs"</span> <span class="hljs-comment">#2</span>
<span class="hljs-attr">remote_template_path:</span> <span class="hljs-string">"/home/<span class="hljs-template-variable">{{ ansible_env.SUDO_USER | default(ansible_env.USER) }}</span>/index.html"</span>
</code></pre>
<p>Ces variables sont configurées pour le rôle visant à déployer un conteneur Docker :</p>
<ul>
<li><p><code>container_name</code>: Identifie le nom du conteneur, ici <code>webapp</code>.</p>
</li>
<li><p><code>container_image</code>: Spécifie l'image Docker à utiliser, dans ce cas <code>httpd</code> pour un serveur web Apache.</p>
</li>
<li><p><code>container_ports</code>: Définit les ports à exposer, mappant le port 80 du conteneur sur le port 80 de l'hôte.</p>
</li>
<li><p><code>document_root</code>: Le chemin où les fichiers du site web doivent être stockés dans le conteneur, <code>/usr/local/apache2/htdocs</code> étant le répertoire racine d'Apache.</p>
</li>
</ul>
<p>ces variables sont ajustable dans le fichier <strong>group_vars/all.yml</strong> selon le contexte.</p>
<h4 id="heading-62-definition-du-metamainyml-1">6.2. Définition du <strong>meta/main.yml</strong></h4>
<p>Pour ce fichier, nous allons simplement reprendre le fichier décrit dans la section " <a target="_blank" href="https://gitlab.com/CarlinFongang-Labs/Ansible/ansible-project/local-role#12-d%C3%A9finition-du-metamainyml">1.2. Définition du <strong>meta/main.yml</strong></a>"</p>
<h4 id="heading-63-definition-du-teststestdeploycontaineryml">6.3. Définition du <strong>tests/test_deploy_container.yml</strong></h4>
<pre><code class="lang-yaml"><span class="hljs-meta">---</span>
<span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Deploy</span> <span class="hljs-string">contenair</span>
  <span class="hljs-attr">hosts:</span> <span class="hljs-string">dynamic_hosts</span>
  <span class="hljs-attr">become:</span> <span class="hljs-literal">true</span>
  <span class="hljs-attr">roles:</span>
    <span class="hljs-bullet">-</span> <span class="hljs-string">../../deploy_container</span>
  <span class="hljs-attr">tasks:</span>
    <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Afficher</span> <span class="hljs-string">le</span> <span class="hljs-string">message</span> <span class="hljs-string">de</span> <span class="hljs-string">réussite</span>
      <span class="hljs-attr">debug:</span>
        <span class="hljs-attr">msg:</span> <span class="hljs-string">"Opération réussie !"</span>
      <span class="hljs-attr">when:</span> <span class="hljs-string">ansible_failed_task</span> <span class="hljs-string">is</span> <span class="hljs-string">undefined</span>
</code></pre>
<h4 id="heading-64-test-du-playbook-testdeploycontainer">6.4. Test du playbook <strong>test_deploy_container</strong></h4>
<pre><code class="lang-bash">ansible-playbook roles/deploy_container/tests/test.yml -K -vvv
</code></pre>
<blockquote>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1712526466177/a175a641-99a3-4c9a-959a-dc676f647dc1.png" alt class="image--center mx-auto" /></p>
<p><em>Déploiement du conteneur réussi</em></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1712526477489/c8c7e8d6-376b-47c4-893b-25b099abb2a5.png" alt class="image--center mx-auto" /></p>
<p>Conteneur en cours d'exécution</p>
</blockquote>
<p>En se connectant à l'instance cible, on peut voir que le conteneur est en cours</p>
<ol>
<li>Vérification via navigateur</li>
</ol>
<blockquote>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1712526513050/fbabb855-5333-40b8-9752-0ed2769a5c96.png" alt class="image--center mx-auto" /></p>
<p><em>L'application webApp ainsi que le Template Jinja son bien déployé</em></p>
</blockquote>
<h2 id="heading-3-definition-de-playbook-integrant-les-roles">3. Définition de playbook intégrant les roles</h2>
<h3 id="heading-31-playbook-de-deploiement-dun-conteneur-httpd-template-jinja-deployhttpdyml">3.1. Playbook de déploiement d'un conteneur httpd + template jinja : "deploy_httpd.yml"</h3>
<ol>
<li>Description du playbook :</li>
</ol>
<pre><code class="lang-yaml"><span class="hljs-meta">---</span>
<span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Setup</span> <span class="hljs-string">environment</span>
  <span class="hljs-attr">hosts:</span> <span class="hljs-string">localhost</span>
  <span class="hljs-attr">roles:</span>
    <span class="hljs-bullet">-</span> <span class="hljs-string">setup_environment</span>

<span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Install</span> <span class="hljs-string">Terraform</span> <span class="hljs-string">&amp;</span> <span class="hljs-string">provide</span> <span class="hljs-string">instance</span>
  <span class="hljs-attr">hosts:</span> <span class="hljs-string">localhost</span>
  <span class="hljs-attr">roles:</span>
    <span class="hljs-bullet">-</span> <span class="hljs-string">install_terraform</span>
    <span class="hljs-bullet">-</span> <span class="hljs-string">provide_compute</span>
  <span class="hljs-attr">tasks:</span>
    <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Refresh</span> <span class="hljs-string">Inventory</span> <span class="hljs-string">to</span> <span class="hljs-string">Ensure</span> <span class="hljs-string">Latest</span> <span class="hljs-string">Hosts</span> <span class="hljs-string">are</span> <span class="hljs-string">Used</span>
      <span class="hljs-attr">meta:</span> <span class="hljs-string">refresh_inventory</span>

<span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Verify</span> <span class="hljs-string">SSH</span> <span class="hljs-string">Connectivity</span> <span class="hljs-string">on</span> <span class="hljs-string">Dynamic</span> <span class="hljs-string">Hosts</span>
  <span class="hljs-attr">hosts:</span> <span class="hljs-string">dynamic_hosts</span>
  <span class="hljs-attr">gather_facts:</span> <span class="hljs-literal">no</span>
  <span class="hljs-attr">roles:</span>
    <span class="hljs-bullet">-</span> <span class="hljs-string">check_ssh</span>

<span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Deploy</span> <span class="hljs-string">Apache</span> <span class="hljs-string">container</span>
  <span class="hljs-attr">hosts:</span> <span class="hljs-string">dynamic_hosts</span>
  <span class="hljs-attr">become:</span> <span class="hljs-literal">true</span>
  <span class="hljs-attr">roles:</span>
    <span class="hljs-bullet">-</span> <span class="hljs-string">prepare_docker</span>
    <span class="hljs-bullet">-</span> <span class="hljs-string">copy_template</span>
    <span class="hljs-bullet">-</span> <span class="hljs-string">deploy_container</span>
</code></pre>
<p>Ce playbook Ansible est structuré en plusieurs phases pour configurer un environnement, installer Terraform, provisionner une instance, vérifier la connectivité SSH aux hôtes dynamiques, et déployer un conteneur Apache. Il utilise des rôles spécifiques pour chaque étape, définis et documentés précédement. Il assure aussi la mise à jour de l'inventaire pour inclure les hôtes récemment provisionnés.</p>
<ol start="2">
<li>Déploiement du playbook</li>
</ol>
<pre><code class="lang-bash">ansible-playbook deploy_httpd.yml -K -vvv
</code></pre>
<blockquote>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1712526554279/8b8cb093-b76f-449e-806f-8e328cb05207.png" alt class="image--center mx-auto" /></p>
<p><em>Le Mot de passe de l'utilisateur sudo est demandé pour l'opération</em></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1712526562178/5cd82c16-0337-418c-bbbf-8e4ac8edbba5.png" alt class="image--center mx-auto" /></p>
<p><em>L'installation est achevé et une nouvelle adresse est renseignée dans le fichier hosts</em></p>
</blockquote>
<ol start="3">
<li>Résultat du déploiement</li>
</ol>
<blockquote>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1712526575419/5445d8cf-ab36-4a67-b841-f9fe94c47d26.png" alt class="image--center mx-auto" /></p>
<p><em>Conteneur httpd et Template Jina déployé</em></p>
</blockquote>
<h3 id="heading-32-playbook-de-deploiement-de-conteneurs-wordpress">3.2. Playbook de déploiement de conteneurs Wordpress</h3>
<ol>
<li>Description du playbook :</li>
</ol>
<pre><code class="lang-yaml"><span class="hljs-meta">---</span>
<span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Setup</span> <span class="hljs-string">environment</span>
  <span class="hljs-attr">hosts:</span> <span class="hljs-string">localhost</span>
  <span class="hljs-attr">roles:</span>
    <span class="hljs-bullet">-</span> <span class="hljs-string">setup_environment</span>

<span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Install</span> <span class="hljs-string">Terraform</span> <span class="hljs-string">&amp;</span> <span class="hljs-string">provide</span> <span class="hljs-string">instance</span>
  <span class="hljs-attr">hosts:</span> <span class="hljs-string">localhost</span>
  <span class="hljs-attr">roles:</span>
    <span class="hljs-bullet">-</span> <span class="hljs-string">install_terraform</span>
    <span class="hljs-bullet">-</span> <span class="hljs-string">provide_compute</span>
  <span class="hljs-attr">tasks:</span>
    <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Refresh</span> <span class="hljs-string">Inventory</span> <span class="hljs-string">to</span> <span class="hljs-string">Ensure</span> <span class="hljs-string">Latest</span> <span class="hljs-string">Hosts</span> <span class="hljs-string">are</span> <span class="hljs-string">Used</span>
      <span class="hljs-attr">meta:</span> <span class="hljs-string">refresh_inventory</span>

<span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Verify</span> <span class="hljs-string">SSH</span> <span class="hljs-string">Connectivity</span> <span class="hljs-string">on</span> <span class="hljs-string">Dynamic</span> <span class="hljs-string">Hosts</span>
  <span class="hljs-attr">hosts:</span> <span class="hljs-string">dynamic_hosts</span>
  <span class="hljs-attr">gather_facts:</span> <span class="hljs-literal">no</span>
  <span class="hljs-attr">roles:</span>
    <span class="hljs-bullet">-</span> <span class="hljs-string">check_ssh</span>

<span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Deploy</span> <span class="hljs-string">Wordpress</span>
  <span class="hljs-attr">hosts:</span> <span class="hljs-string">dynamic_hosts</span>
  <span class="hljs-attr">become:</span> <span class="hljs-literal">true</span>
  <span class="hljs-attr">roles:</span>
    <span class="hljs-bullet">-</span> <span class="hljs-string">wordpress</span>
</code></pre>
<p>Ce playbook Ansible est structuré en plusieurs phases pour configurer un environnement, installer Terraform, provisionner une instance, vérifier la connectivité SSH aux hôtes dynamiques, et déployer un conteneur Wordpress. Il utilise des rôles spécifiques pour chaque étape, définis et documentés précédement. Il assure aussi la mise à jour de l'inventaire pour inclure les hôtes récemment provisionnés.</p>
<ol start="2">
<li>Déploiement du playbook</li>
</ol>
<pre><code class="lang-bash">ansible-galaxy install -r roles/requirements.yml -f
</code></pre>
<pre><code class="lang-bash">ansible-playbook deploy_wordpress.yml -K -vvv
</code></pre>
<blockquote>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1712526608114/45122578-c67b-4df2-812e-2ddee178fd1a.png" alt class="image--center mx-auto" /></p>
<p><em>Exécution du Playbook</em></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1712526634179/b42dd409-a61b-4570-b0af-afb7d1c5463d.png" alt class="image--center mx-auto" /></p>
<p><em>Ajout de l'EIP de la nouvelle instance au fichier hosts</em></p>
</blockquote>
<ol start="3">
<li>Résultat</li>
</ol>
<p>En se connectant à l'instance cible, l'on peux intéroger les conteneur en cours d'exécution</p>
<blockquote>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1712526716571/e03cc118-21fd-4b07-8cff-7cbef2d78c72.png" alt class="image--center mx-auto" /></p>
<p><em>Conteneurs Wordpress en cours d'exécution</em></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1712526721490/c80943bf-15cc-486c-bc95-be30fd5bef6f.png" alt class="image--center mx-auto" /></p>
<p><em>Interface Wordpress</em></p>
</blockquote>
<h2 id="heading-3-definition-de-playbook-integrant-les-roles-distant-heberges-sur-gitlab">3. Définition de playbook intégrant les roles distant (hébergés sur gitlab)</h2>
<p>Pour déployer de nouveaux playbooks utilisant des rôles définis précédemment, mais cette fois ci en remote, (usage semblable aux rôles sur "Ansible Galaxy"), ces rôles seront hébergés sur GitLab à l'adresse : <a target="_blank" href="https://gitlab.com/CarlinFongang-Labs/Ansible/Roleshub">RolesHub</a>.</p>
<p>Après avoir hébergé les rôles sur GitLab, le projet sera restructuré en actualisant le fichier <strong>roles/requirement.yml</strong> avec les sources des rôles et en supprimant les sous-répertoires inutiles du dossier <strong>roles</strong>. La nouvelle structure du projet sera ainsi simplifiée.</p>
<p>La nouvelle strucutre du projet sera alors la suivante :</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1712526772857/cf34df52-1ae8-43da-b167-fb7632c4a029.png" alt class="image--center mx-auto" /></p>
<ol>
<li>Définintion du fichier <strong>roles/requirement.yml</strong></li>
</ol>
<pre><code class="lang-yaml"><span class="hljs-attr">roles:</span>
  <span class="hljs-bullet">-</span> <span class="hljs-attr">src:</span> <span class="hljs-string">https://gitlab.com/CarlinFongang-Labs/Ansible/Roleshub/setup_environment.git</span>
    <span class="hljs-attr">scm:</span> <span class="hljs-string">git</span>
    <span class="hljs-attr">version:</span> <span class="hljs-string">"main"</span>
    <span class="hljs-attr">name:</span> <span class="hljs-string">setup_environment</span>

  <span class="hljs-bullet">-</span> <span class="hljs-attr">src:</span> <span class="hljs-string">https://gitlab.com/CarlinFongang-Labs/Ansible/Roleshub/install_terraform.git</span>
    <span class="hljs-attr">scm:</span> <span class="hljs-string">git</span>
    <span class="hljs-attr">version:</span> <span class="hljs-string">"main"</span>
    <span class="hljs-attr">name:</span> <span class="hljs-string">install_terraform</span>

  <span class="hljs-bullet">-</span> <span class="hljs-attr">src:</span> <span class="hljs-string">https://gitlab.com/CarlinFongang-Labs/Ansible/Roleshub/provide_compute.git</span>
    <span class="hljs-attr">scm:</span> <span class="hljs-string">git</span>
    <span class="hljs-attr">version:</span> <span class="hljs-string">"main"</span>
    <span class="hljs-attr">name:</span> <span class="hljs-string">provide_compute</span>

  <span class="hljs-bullet">-</span> <span class="hljs-attr">src:</span> <span class="hljs-string">https://gitlab.com/CarlinFongang-Labs/Ansible/Roleshub/check_ssh.git</span>
    <span class="hljs-attr">scm:</span> <span class="hljs-string">git</span>
    <span class="hljs-attr">version:</span> <span class="hljs-string">"main"</span>
    <span class="hljs-attr">name:</span> <span class="hljs-string">check_ssh</span>

  <span class="hljs-bullet">-</span> <span class="hljs-attr">src:</span> <span class="hljs-string">https://gitlab.com/CarlinFongang-Labs/Ansible/Roleshub/prepare_docker.git</span>
    <span class="hljs-attr">scm:</span> <span class="hljs-string">git</span>
    <span class="hljs-attr">version:</span> <span class="hljs-string">"main"</span>
    <span class="hljs-attr">name:</span> <span class="hljs-string">prepare_docker</span>

  <span class="hljs-bullet">-</span> <span class="hljs-attr">src:</span> <span class="hljs-string">https://gitlab.com/CarlinFongang-Labs/Ansible/Roleshub/copy_template.git</span>
    <span class="hljs-attr">scm:</span> <span class="hljs-string">git</span>
    <span class="hljs-attr">version:</span> <span class="hljs-string">"main"</span>
    <span class="hljs-attr">name:</span> <span class="hljs-string">copy_template</span>

  <span class="hljs-bullet">-</span> <span class="hljs-attr">src:</span> <span class="hljs-string">https://gitlab.com/CarlinFongang-Labs/Ansible/Roleshub/deploy_container.git</span>
    <span class="hljs-attr">scm:</span> <span class="hljs-string">git</span>
    <span class="hljs-attr">version:</span> <span class="hljs-string">"main"</span>
    <span class="hljs-attr">name:</span> <span class="hljs-string">deploy_container</span>
</code></pre>
<p>Ce fichier décrit plusieurs rôles Ansible, chacun provenant de dépôts GitLab, avec des informations sur le type de gestion de configuration (Git), la version (tous sur "main"), et leurs noms. Ces rôles couvrent diverses tâches comme la configuration de l'environnement, l'installation de Terraform, la vérification de la connectivité SSH, la préparation de Docker, la copie de modèles de site web, et le déploiement de conteneurs Docker, facilitant la gestion automatisée d'infrastructures et la réutilisabilité des roles.</p>
<ol start="2">
<li>Exécution du playbook</li>
</ol>
<pre><code class="lang-bash">ansible-galaxy install -r roles/requirements.yml -f
</code></pre>
<blockquote>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1712526810973/5b0c6e17-ad96-4a9b-acc9-ff9ceb91c6d5.png" alt class="image--center mx-auto" /></p>
<pre><code class="lang-bash">ansible-playbook deploy_httpd.yml -k -vvv
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1712526835727/7b25a8f4-7220-40a9-9595-9364c38fe7a7.png" alt class="image--center mx-auto" /></p>
<p><em>Déploiement du conteneur httpd achevé</em></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1712526856797/ac09f07b-9b6e-44f4-9763-91bcfa784012.png" alt class="image--center mx-auto" /></p>
<p><em>Le conteneur est en cours d'exécution</em></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1712526875082/407fe3cf-3fbf-46aa-8105-a60efb309f32.png" alt class="image--center mx-auto" /></p>
<p><em>L'application est consultable depuis le navigateur</em></p>
</blockquote>
<p>Dépôt du projet utilisant les roles en remote (roles distant sur Gitlab) : <a target="_blank" href="https://gitlab.com/CarlinFongang-Labs/Ansible/ansible-project/remote-role.git">Remote Role</a></p>
]]></content:encoded></item></channel></rss>