GITOPS ET CONTINUOUS DELIVERY SUR L’INFRASTRUCTURE AVEC TERRAFORM, GITLAB, AWS ELASTIC KUBERNETES SERVICE (EKS) ET ARGOCD

Contexte et objectifs

Utiliser le modèle déclaratif pour déployer son infrastructure ( IaC ) ainsi que ces applications permet d’unifier son flux de travail. Le gain de temps est donc considérable et la gestion du cycle de vie des applications simplifiée.

Voici les composants que vous utiliserez :

Terraform est devenu un incontournable dans le déploiement d’infrastructures sur le cloud et on-premise avec la prise en charge de la majorité des fournisseurs d’infrastructures auxquels vous pouvez penser. Terraform est un excellent moyen de bootsraper vos clusters Kubernetes et de configurer quelques ressources de base avant de les transmettre à un système davantage orienté vers le déploiement d’applications comme Argo CD.

Gitlab CI / CD est un outil de management de code. Il vous permet de configurer les pipelines CI / CD avec un fichier «.gitlab-ci.yml» situé dans le répertoire racine du référentiel en plus d’agir comme votre outil de contrôle de source.

Amazon Elastic Kubernetes Service (Amazon EKS) vous offre la possibilité de démarrer, d’exécuter et de mettre à l’échelle des applications Kubernetes dans le cloud AWS ou on-premise avec la version EKS Distro.

Amazon S3 Amazon Simple Storage Service (Amazon S3) est un service de stockage d’objet qui vous permet de stocker et récupérer n’importe quelle quantité de données à tout moment sur Internet. Par défaut, Terraform stocke l’état de votre infrastructure dans un fichier local nommé terraform.tfstate . Cet état est utilisé par Terraform pour mapper les ressources du monde réel à celui de votre configuration. Puisque vous travaillez en équipe et, en particulier, lors de l’automatisation de Terraform via des pipelines, l’emplacement du stockage devient beaucoup plus important.

ArgoCD est un outil GitOps qui vous permet de maintenir l’état de vos ressources Kubernetes dans Git. Argo CD synchronise automatiquement vos ressources Kubernetes avec ce qui se trouve dans votre référentiel Git, tout en garantissant l’annulation des modifications manuelles. Cela préserve votre modèle de déploiement déclaratif.

Cert Manager est un outil qui s’exécute dans votre cluster Kubernetes. Il est utilisé pour générer et renouveler automatiquement des certificats TLS, et permet d’émettre un certificat auto-signé. Lorsqu’un certificat est demandé, Cert-Manager gérera le certificat, y compris le renouvellement, ce qui est essentiel car les certificats Let’s Encrypt ont une validité de 3 mois.

GitOps est une approche où on décrit l’état de notre infrastructure dans Git. Le repository git doit contenir l’état souhaité de l’infrastructure, ainsi que toutes les modifications apportées au projet. L’opérateur surveille les modifications dans le repository et applique ces modifications pour s’assurer qu’il n’y ait pas d’écart entre l’état souhaité (le contenu du repository) et l’état actuel (l’état de l’environnement). Les changements sont revus, approuvés et mergés ensuite dans la branche master.

Workflow GitOps avec ArgoCD

Le projet

Présentation du projet

Dans la première partie de cet article, vous allez déployez un cluster Kubernetes.

Dans la seconde partie , vous déploierez l’opérateur ARGOCD puis l’utiliserez pour installer divers applications.

Configuration

1 – Mise en place de l’environnement

a – Information sur l’infrastructure

Votre infrastructure sera hébergée sur le provider cloud AWS et sera composée des éléments suivants :

b – Conditions préalables

Vous aurez besoin des CLI suivantes installées sur votre système :

Vous aurez également besoin d’un accès administrateur sur AWS, de l’AWS ACCESS KEY ID ainsi que de l’AWS ACCESS SECRET

c – Obtention des informations d’identification AWS et création des variables d’environnement

Dans la console AWS. Développez le menu avec votre nom :

Sélectionnez Mes identifiants de sécurité et différentes options vous seront proposées pour créer des informations d’identification.

Développez l’onglet Clés d’accès (ID de clé d’accès et clé d’accès secrète), puis cliquez sur le bouton Créer une clé d’accès.

Vous devriez voir apparaître le message suivant vous indiquant que votre clé d’accès a été créée avec succès. Ne fermez PAS cette fenêtre avant d’avoir récupéré vos identifiants, car vous ne pourrez plus les visualiser une seconde fois.

Développez la section Afficher la clé d’accès et vous verrez l’AWS ACCESS KEY ID ainsi que l’AWS ACCESS SECRET. Vous les stockerez dans des variables d’environnement. Mais avant de faire cela, je vous recommande fortement de télécharger le fichier et de le stocker dans un endroit sûr, car c’est la première et la dernière fois que vous verrez ces clés depuis la console AWS.

export AWS_ACCESS_KEY_ID=[...]

export AWS_SECRET_ACCESS_KEY=[...]

export AWS_DEFAULT_REGION=[...]

d – Création du bucket S3

Dans ce déploiement, vous devez créer manuellement le compartiment S3. Avant de commencer, assurez-vous de créer votre compartiment et de le spécifier dans la section des variables. Le compartiment S3 conservera le fichier terraform.tfstate

Ce fichier d’état est indispensable pour créer des plans et apporter ainsi des modifications à votre infrastructure. En effet, lorsque vous exécutez la commande terraform apply pour la première fois, Terraform créera le nouveau fichier terraform.tfstate en local. Et quand vous souhaitez effectuer des modifications dans votre code Terraform, et que vous exécutez à nouveau sur la commande terraform apply, alors Terraform apportera des modifications sur ce même fichier pour ainsi tracer les changements à apporter sur votre infrastructure. C’est ainsi que Terraform assure le suivi de votre infrastructure réelle.

Via la CLI tapez ces commandes :

export BUCKET_NAME=your_bucket_name

aws s3api create-bucket 
  --bucket $BUCKET_NAME
  -- region $AWS_DEFAULT_REGION 
  -- acl private

e – Récupération du code source

Le code source de l’application se trouve sur mon repository GitHub à l’adresse suivante :

→ Repos Gitlab : https://gitlab.com/vumay/terraform-eks-argocd.git

2 – Gestion du projet Gitlab

a – Configuration du pipeline

Le pipeline Gitlab CI / CD utilise un Gitlab CI runner pour automatiser le déploiement et la configuration de votre cluster EKS. C’est avec le fichier .gitlab-ci.yml que vous pouvez contrôler votre pipeline CI. Un runner Gitlab est donc une application conteneurisée qui exécutera des tâches dans un pipeline et vous utiliserez les variables d’environnement précédemment créées pour que Terraform exécute des opérations en votre nom.

Dans les paramètres CI/CD de votre projet, ajouter les variables correspondantes à l’ID de clé d’access de votre compte, à la clé d’access secret et enfin à la région.

b – Définition du pipeline CD ( Continuous Delivery )

Dans un contexte d’automatisation, on utilise les commandes Terraform différemment. Plutôt que de faire un apply “dynamique”, on génère un fichier de planification via la commande plan, puis on utilise ce fichier comme input pour la commande apply. On évite l’input dynamique des variables avec le paramètre -input=false.

Le pipeline de déploiement du cluster comporte 3 jobs (initialisation, planification et application).

Les étapes sont les suivantes :

  • init : Vous initialisez le projet afin que les plugins requis soient téléchargés et plus important encore, que l’état stocké dans le compartiment S3 soit récupéré.
  • plan : Cette étape vous permet de passer en revue tous les changements que Terraform va appliquer.
  • apply : Application des changements listés dans le plan.

c – Définition des fichiers Terraform

Vous allez donc créer un cluster EKS, ou chaque nœud de travail est déployé dans un sous-réseau différent en fonction des zones de disponibilité (AZ) de sa région.

Ci-dessous : data nous permet de récupérer les informations liées aux zones de disponibilité (AZ).

Ces données sont réutilisées dans le code pour créer d’autres ressources comme les subnets :

variables.tf :

En modifiant les variables de ce fichier, vous adaptez en fonction de vos besoins, le nom du cluster, sa version, la région dans laquelle le déployer, le type d’instance du nœud, et le nombre de workers souhaité.

main.tf :

Ce fichier définit le S3 en backend, ce qui signifie que Terraform conserve le fichier d’état dans le compartiment AWS S3, au lieu de le stocker localement. En conséquence, vous serez en mesure de gérer les ressources à partir de n’importe quel emplacement ayant accès à ce stockage et sans être limité à une seule machine.

Attention le nom du bucket doit être codé en dur car celui-ci doit être unique.

output.tf : Les outputs permettent de renvoyer certaines données relatives au cluster qui peuvent être réutilisées soit dans le code soit dans l’interface de l’utilisateur.

REMARQUE : les outputs ne sont rendus que lorsque Terraform applique votre plan. L’exécution de la commande terraform plan ne renverra pas les outputs.

provider.tf : Fait appel aux différents providers, AWS, HELM et Kubernetes.

networking.tf : Définit les ressources réseaux du cluster, comme le VPC, les subnets, la gateway et les tables de routage.

Le paramètre depends_on permet à terraform d’établir une chronologie lors du déploiement. Ici, la création des subnets dépendra de la présence des policy attachement.

nginx-controller.tf : Lors du déploiement de votre Ingress Nginx via Helm celui-ci va créer un nouveau service Kubernetes et en même temps déployer le Load Balancer de type (ELB) qui sera en charge de gérer les requêtes HTTP.

Tout est maintenant en place pour que vous puissiez déployer votre infrastructure.

A ce moment, Gitlab s’assurera que l’état réel est convergé vers l’état souhaité.

La seule chose qui vous reste à faire est de pousser les modifications vers Gitlab.

git add .
git commit -m "my first commit"
git push

REMARQUE: L’infrastructure met environ 15 minutes pour être provisionnée.

3 – Vérification du cluster Kubernetes

Avant de pouvoir interagir avec votre cluster, vous devez créer votre fichier KubeConfig localement. Vous pouvez le faire via la commande aws eks update-kubeconfig. Pour que cela fonctionne, vous devez récupérer le nom du cluster et la région dans laquelle il s’exécute.

La commandes terraform output va vous être utile pour récupérer les informations dont vous avez besoin. Elle est utilisée pour extraire la valeur d’une variable de sortie du fichier d’état.

export KUBECONFIG=$PWD/kubeconfig

aws eks update-kubeconfig 
    --name 
    $(terraform output -raw cluster_name) 
    --region 
    $(terraform output -raw region) 
    --alias $(terraform output -raw cluster_name)

Maintenant, vérifions si votre cluster est opérationnel.

kubectl get nodes

Le résultat doit être similaire à :

Vous avez maintenant un cluster prêt et fonctionnel !

4 – Gitops et ArgoCD pour deployer ces applications

Vous avez vu dans la 1ère partie comment récupérer le fichier kubeconfig pour vérifier l’état de votre cluster. Maintenant que vous avez un cluster fonctionnel, configurez un nom DNS et un certificat SSL pour plus tard accéder à votre serveur argocd via une connexion sécurisée en HTTPS.

a – Configuration DNS

Pour DNS, je possède le domaine vumay.ddns.net créé gratuitement via le site NoIp, mais vous pouvez utiliser le fournisseur DNS de votre choix. Vous devez créer une entrée CNAME générique pour acheminer toutes les demandes vers votre AWS ELB qui gère l’entrée d’application.

Tout d’abord, obtenez votre nom d’hôte Elastic Load Balancer en accédant à votre console AWS, en accédant à la section EC2 et en cliquant sur Load Balancers dans le menu de gauche. Une fois que vous y êtes, vous devriez voir un nouveau LoadBalancer créé avec des caractères aléatoires. Si vous vérifiez les balises, il doit référencer votre nouveau cluster Kubernetes :

Copiez le nom DNS de cette entrée. Puis créez votre nom domaine et un enregistrement de type CNAME pointant vers le nom DNS que vous avez copié à partir d’AWS.

Pour vérifier que cela fonctionne, vous pouvez installer ou utiliser nslookup pour interroger le DNS.

b – Mise en place d’argoCD et du certificat SSL

Les certificats TLS seront gérés pas Cert-Manager et son installation dans le cluster se fait via un module qui fait référence à un repo git.

Un module terraform est simplement un regroupement de fichiers terraform placé dans un répertoire local ou distant.

Vous allez par la suite modifier le fichier argocd-values.yaml qui contient les configurations de l’Ingress d’ArgoCD et va vous permettre d’écraser les valeurs par défaut.

Il faut redéfinir les paramètres hosts avec l’entrée DNS pointant vers l’équilibreur de charge externe et laisser le reste par défaut.

c – Installation et gestion d’Argo CD

Pour lancer l’installation d’ARGO CD rendez vous sur le pipeline pour activer manuellement le job :

Vérifiez si tout s’est bien déroulé.

kubectl --namespace argocd get pods

kubectl --namespace argocd get ingresses

Le résultat doit être similaire à :

d – Récuperation du mot de passe

Le mot de passe initial est généré automatiquement par le nom du pod du serveur API d’Argo CD. Cela peut être récupéré avec la commande :

export PASS=$(kubectl --namespace argocd 
    get pods 
    --selector app.kubernetes.io/name=argocd-server 
    --output name 
    | cut -d'/' -f 2)

Pour vous connecter, utilisez le mot de passe par défaut : admin.

argocd login 
    --insecure 
    --username admin 
    --password $PASS 
    --grpc-web 
    your-DNS-Hostname

Modifiez le mot de passe à l’aide de la commande :

argocd account update-password

Vous pouvez désormais accéder à argocd via votre domaine.

Pour ma part : https://argocd-vumay.ddns.net

REMARQUE : pour éviter toute limitation de débit de LetsEncrypt, vous utilisez des certificats de transfert qui ne sont pas valides. Il y a de fortes chances que lorsque vous accédez à Argo, vous receviez ce message d’avertissement. Cliquez sur Avancé, puis Continuer vers votre site (non sécurisé) et cela vous permettra de le contourner.

Vous verrez par la suite comment patcher votre certificat en environnement de production.

e – Mise en place du certificat de production

Pour mettre en place votre certificat de production, il suffira de mettre à jour le fichier argocd-values.yaml.

annotations :

cert-manager.io/cluster:letsencrypt-prod

Relancez le pipeline de déploiement d’Argo.

Le résultat doit être similaire à cela :

Cette fois-ci votre connexion est bien sécurisée avec un certificat valide.

5 – Déploiement d’applications avec ArgoCD

a – Mise en place du modèle app of apps

Pour notre test, vous allez déployer vos applications en utilisant le modèle app of apps d’ArgoCD.
Ce modèle consiste à déployer une application parent dans lequel on référence toutes les applications enfant que l’on souhaite déployer.

Modèle app of apps d’argocd :

ArgoCd surveille le référentiel de production grâce à l’application parent.

L’état réel est convergé vers l’état désiré qui est défini dans le dépôt de production avec tous les référentiels associés.

b – Création d’un projet

Vous allez tout d’abord créer un projet Argo CD qui agira comme un espace réservé pour toutes les applications que vous déploierez dans votre environnement de production.

kubectl apply --filename project.yaml

c- Création de l’application parent

L’installation des applications suivent tous le même modèle que le fichier ci-dessous.

Les options SynPolicy=auto et Prune=true garantissent que les applications enfant soient automatiquement créées, synchronisées et supprimées lorsque le manifeste est modifié.

L’ajout de resources-finalizer.argocd.argoproj.io s’assure que toutes les ressources créées pour l’application seront supprimées lorsque l’application n’existe plus.

Avec l’option repoURL vous indiquez à ArgoCD quel répertoire surveiller.

Dans project : vous précisez le projet dans lequel l’application sera déployé.

d – Installation des applications enfant

ArgoCD installera toutes les applications contenues dans le repo source qui est déclaré dans le fichier apps.yml .

→ Repos source : https://github.com/vumay/eks-argocd-production

Pour cette démo vous déploierez Prometheus en utilisant les charts officiels stockés dans le repo prometheus-community / helm-charts. Il sera déployé dans son propre Namespace et sera synchronisé automatiquement.

Ensuite, vous déploierez l’application Hello-world contenue dans mon repo personnel.

→ Repos Github : https://github.com/vumay/hello-world-manifests.git

Exécutez la commande pour tout déployer :

Kubectl apply -f apps.yaml

Une fois que cela est créé, revenez à votre interface utilisateur Argo CD et vous devriez voir trois nouvelles applications, production, demo-app, et Prometheus.

Cliquez sur demo-app et attendez que toutes les ressources soient saines.

6 – Destruction de l’infrastructure

Pour détruire le cluster, cliquez sur destroy dans la console CI / CD.

Terraform détruira toute l’infrastructure précédemment créée par le pipeline. La seule chose qui restera est le compartiment S3 qui contient le terraform.tfstate. L’état Terraform est crucial si vous devez exécuter une étape de destruction.

Bilan

Pour conclure, vous avez pu voir que travailler avec les outils CI/CD comporte plusieurs avantages dont celui de vous débarrasser de la gestion manuelle de l’infrastructure. Aujourd’hui, l’infrastructure est définie par du code et appliquer cette méthode sur des processus de livraison continue est tout autant avantageux pour l’infrastructure que pour les applications.

Si vous souhaitez en savoir davantage sur l’approche GitOps, je vous conseille cet article : https://eazytraining.fr/informatique/cloud/pipeline-ci-cd-gitops-avec-kubernetes-flux-gitlab-ce-et-aws/

Environnement

Version des applications

ApplicationVersion
Terraform0.14.0
Kubectl1.20.2
Cert Manager1.3
Kubernetes1.18.9
ArgoCD 1.7.12
AWS CLI2.1.26
Amazon EKS1.18.9-20210310
Helm 3.5.4

Références

Techniques

Personnelles

Vuthy MAY
DevOps Enthusiast   | Kubernetes Certified CKA, CKAD & CKS | AWS Certified


8 réflexions sur “GITOPS ET CONTINUOUS DELIVERY SUR L’INFRASTRUCTURE AVEC TERRAFORM, GITLAB, AWS ELASTIC KUBERNETES SERVICE (EKS) ET ARGOCD”

  1. Avatar
    Franck Junior TCHOUNZOU

    Bon article sur Terraform,
    Proposition : Certmanager ne délivre pas (il me semble) des certificats autosignés. Il crée des certificats et fait une demande de signatures auprès de Letsencrypt, qui lui validé en procédant à la vérification de domaine (via les challenges DNS01 et http01).
    Il y’a deux serveurs : Letsencrypt staging et Letsencrypt prod. Le staging permet juste de valider la possibilité de valider son certificat et est recommandé d’utilisation car il y’a une limitation dans les validations de certificats. Prod est ce tu as utilisé.

  2. Avatar

    Bonjour Franck et merci pour ton commentaire. Pour information Cert-Manager délivre des certificats auto-signés ( on a un issuer de type self-signed ) Cela peut d’ailleurs être très utile pour bootstrapper une PKI personnalisée et faire des tests.
    Concernant le mécanisme utilisé par cert-manager pour délivrer des certificats j’ai volontairement choisi de ne pas rentrer dans les détails afin de ne pas complexifier l’article, qui je pense traite déjà beaucoup de sujets sur le fond.

    Source : https://cert-manager.io/docs/configuration/selfsigned/

  3. Avatar

    Bonjour Vuthy,
    merci pour ce super article
    lorsque j’initialise terraform sur ton projet que j’ai cloné terraform intit j’ai cette erreur ci dessous peux tu m’aidé? merci
    Error: Duplicate output definition

    │ on output.tf line 13:
    │ 13: output “endpoint” {

    │ An output named “endpoint” was already defined at instances.tf:22,1-18. Output names must be unique within a module.


    │ Error: Duplicate output definition

    │ on output.tf line 17:
    │ 17: output “kubeconfig-certificate-authority-data” {

    │ An output named “kubeconfig-certificate-authority-data” was already defined at instances.tf:26,1-47. Output names must be unique within a module.

    1. Avatar

      Bonjour Laabid,

      Merci pour ton commentaire.
      Cette erreur apparait car ces outputs sont en doublons !
      Il faut que tu supprimes les doublons du fichier instance.tf , ou que tu récupères le code que je viens de maj et tout devrait rouler 🙂

      Vuthy MAY

  4. Avatar

    merci vuthy,
    j’ai cette erreur maintenant une idée?
    module.cert_manager.kubernetes_namespace.cert_manager_namespace: Refreshing state… [id=cert-manager]
    time_sleep.wait_2_minutes: Refreshing state… [id=2021-08-31T14:39:02Z]

    │ Error: Get “http://localhost/api/v1/namespaces/cert-manager”: dial tcp [::1]:80: connect: connection refused

    │ with module.cert_manager.kubernetes_namespace.cert_manager_namespace,
    │ on .terraform/modules/cert_manager/main.tf line 2, in resource “kubernetes_namespace” “cert_manager_namespace”:
    │ 2: resource “kubernetes_namespace” “cert_manager_namespace” {

  5. Avatar

    merci vuthy,
    j’ai cette erreur maintenant une idée?
    module.cert_manager.kubernetes_namespace.cert_manager_namespace: Refreshing state… [id=cert-manager]
    time_sleep.wait_2_minutes: Refreshing state… [id=2021-08-31T14:39:02Z]

    │ Error: Get “http://localhost/api/v1/namespaces/cert-manager”: dial tcp [::1]:80: connect: connection refused

    │ with module.cert_manager.kubernetes_namespace.cert_manager_namespace,
    │ on .terraform/modules/cert_manager/main.tf line 2, in resource “kubernetes_namespace” “cert_manager_namespace”:
    │ 2: resource “kubernetes_namespace” “cert_manager_namespace” {

      1. Avatar

        Hello non j’ai cloné ton code suite à tes changements
        terraform init
        terraform plan et ça plante déjà pas moyen d’apply 🙁
        suis deg j’en ai vraiment besoin problème de version? ou autre

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *