Déployer une application sur plusieurs environnements. IaC + GitOps

ACEGIK
8 min readSep 14, 2021

--

Cet article présente dans une première partie comment créer des projets GCP avec Terraform. Dans la deuxième partie, il précise la manière dont les ressources sont gérées dans ces projets, toujours avec Terraform. La dernière partie présente le déploiement d’une application sur trois environnements en suivant le workflow GitOps.

Pré-requis

Cet article suppose que vous avez :

  • Un compte GCP.
  • L’outil de ligne de commande gcloud.
  • Un compte Gitlab.
  • Terraform.

Projet racine

Nous allons commencer par créer un projet GCP transverse qui contiendra:

  • Les buckets utilisées pour sauvegarder les états entre les différents déploiements Terraform.
  • Un service account ayant le droit de créer des projets.
  • L’outil ArgoCD qui sera utilisé pour le déploiement de l’application.
  1. Cloner le projet Terraform.
git clone https://gitlab.com/AndolsiZied/tf-root-project.git

La figure suivante détaille la structure globale du projet en tenant compte des
fichiers requis dans le cadre de la structure modulaire standard.

  • root: C’est le point d’entrée pour exécuter les commandes Terraform. C’est là où se trouve la définition des variables requises.
  • iam: Module Terraform qui crée des ressources IAM (service account, key).
  • compute: Ce module fournit le cluster Kubernetes.
  • network: Ce module est responsable de l’approvisionnement des composants réseaux.
  • project: Ce module génère le projet GCP.
  • storage: Ce module permet de créer les buckets GCS et de gérer les habilitations relatifs à ces derniers.

2. A l’aide de l’outil gcloud lancer la commande suivante afin de s’authentifier sur GCP. Cela permettra à Terraform de s’authentifier auprès de Google Cloud

gcloud auth application-default login

3. Ajouter/Adapter les variables Terraform. Les valeurs associées à ces variables sont définies dans le fichier “terraform.tfvars”. Pour des raisons de sécurité, certaines variables seront passées en option lors de l’exécution des commandes.

  • project_name: Le nom du projet.
  • prefix: Préfixe utilisé pour générer l’ID et le nom du projet.
  • namespace: Utilisé pour regrouper les ressources.
  • owners: Liste des membres au format IAM à définir comme propriétaires de projet.
  • viewers: Liste des membres au format IAM habilités à réaliser des actions en lecture seule sur le projet.
  • activate_apis: Liste des APIs GCP à activer.
  • billing_account: L’identifiant du compte de facturation auquel sera associé le projet.
  • org_id: L’identifiant de l’organisation.

4. Déployer les scripts

terraform init
terraform apply -var billing_account=xxxxxx-xxxxxx-xxxxxx -var org_id=xxxxxxxxx

A la fin de l’exécution, les noms des ressources sélectionnées dans le fichier “outputs.tf” seront affichés sur la console.

Apply complete! Resources: 4 added, 3 changed, 0 destroyed.Outputs:bucket = "tf-states-bucket"cluster_name = "transverse-k8s-cluster"project_id = "tf-root-pj"

Préparation des environnements

Notre environnement cible est constitué principalement d’un cluster Kubernetes et d’une base de données PostgreSql. Nous allons créer un projet GCP par environnement. Nous déléguons l’exécution des scripts Terraform dans cette partie à Gitlab CI/CD.

  1. Forker le projet tf-app-project.

2. Ajouter les variables suivantes dans “Settings → CI/CD → Variables”:

  • GCLOUD_SERVICE_KEY: Récupérer la valeur de la variable “private_key” du compte de service créé dans le projet tf-root-project” via la commande suivante :
grep -w \"private_key\" terraform.tfstate |tail -1 | cut -d\" -f4 | base64 -d
  • TF_VAR_billing_account: L’identifiant du compte de facturation auquel sera associé le projet.
  • TF_VAR_org_id: L’identifiant de l’organisation.

3. Adapter les variables Terraform pour chaque environnement.

  • project_name: Le nom du projet.
  • prefix: Préfixe utilisé pour générer l’ID et le nom du projet.

4. Pousser ces modifications dans Gitlab. Ceci déclenchera le pipeline Gitlab CI/CD suivant:

  • init: Premier job consacré aux téléchargements des providers.
  • plan_<env>: Crée le plan d’exécution sur l’environnement cible (dev, qa, prod).
  • apply_<env>: Exécute les actions définies dans le plan. Ce job est à déclencher manuellement après vérification du plan d’exécution.

Les trois projets seront accessibles sur GCP.

Création des ressources

Une fois les projets GCP créés, nous pouvons ajouter les ressources qui seront utilisées par l’application.

  1. Forker le projet tf-app-infra.

2. Ajouter la variable GCLOUD_SERVICE_KEY dans les variables CI/CD de Gitlab CI/CD. Cette variable contient la clé du compte de service ayant les droits nécessaires à la création des ressources dans les projets GCP.

3. Adapter les variables Terraform pour chaque environnement.

  • project: Le nom du projet.
  • namespace: Utilisé pour regrouper les ressources.

4. Pousser ces modifications dans Gitlab. Ceci déclenchera le pipeline Gitlab CI/CD. Il s’agit des mêmes jobs du pipeline utilisé pour créer les projets GCP.

Déploiement de l’application

Les trois environnements (Dev, QA et Prod) sont prêts pour héberger notre application. Il s’agit d’une simple API REST en Python qui sera encapsulé dans un conteneur docker déployé à son tour dans cluster Kubernetes.

Nous allons suivre le workflow GitOps pour déployer notre application. Cette approche consiste à gérer l’infrastructure de façon déclarative. Dans notre example, les manifests Kubernetes, définis en YAML, décriront l’état souhaité de notre application.

Il existe deux modèles d’implémentation GitOps: Push et Pull. Vous trouverez un comparatif des deux modèles dans cet article. Dans notre cas, nous optons pour le modèle pull.

A la fin de la chaîne d’intégration continue, nous créons un merge request dans un autre projet qui contient les manifests Kubernetes. Une fois le merge request validé, un opérateur Kubernetes détectera le décalage entre ce qui est déployé sur le cluster et le code source. A ce moment, il appliquera les modifications.

L’application

  1. Créer 3 projets sur Gitlab contenant chacun un dossier “manifest” qui contient un fichier vide “app.yaml”.
  2. Forker le projet sample-python-api
  3. Adapter le fichier .gitlab-ci.yml en mettant à jour l’identifiant des projets créés dans la première étape.
  4. Ajouter les variables suivantes dans “Settings → CI/CD → Variables”:
  • DOCKER_LOGIN: Login du compte Docker. Il sera utilisé pour pousser l’image créé dans DockerHub.
  • DOCKER_PASSWORD: Le mot de passe du compte Docker.
  • GITLAB_TOKEN: Le token du compte Gitlab. Il sera utilisé pour créer les merge request dans les projets CD.

5. Pousser les modifications. Gitlab CI/CD déclenchera un pipeline avec les étapes suivantes :

  • prepare: Initialisation de certaines variables comme la version.
  • setup: Création de l’environnement virtuel Python.
  • test: Exécution des tests unitaires.
  • build: Construction de l’image Docker.
  • tag: Création d’un tag git.
  • deploy: Création d’un merge request dans les projets CD avec les modifications apportées (principalement la version de l’image Docker).

ArgoCD

Pour le moment, même en validant les merge request créés, aucun déploiement ne sera réalisé puisque nous n’avons pas encore mis en place l’opérateur Kubernetes. Nous avons choisi ArgoCD pour ce rôle.

Au moment de la rédaction du présent article, il n’existe pas un provider Terraform mature pour créer ArgoCD, nous utilisons le provider Kubernetes qui se charge d’installer les manifests dans le cluster.

  1. Forker le projet tf-argo-cd.
  • server: Module Terraform qui install ArgoCD.
  • cluster: Ce module permet de créer un cluster dans ArgoCD utilisé ultérieurement comme cible pour déployer l’application.
  • application: Ce module permet de créer une application dans ArgoCD.

2. Adapter les variables Terraform.

  • cluster: Le nom du cluster Kubernetes dans lequel sera déployé ArgoCD.
  • projet: Le nom du projet GCP qui héberge le cluster Kubernetes.
  • namespace: Le namespace à créer dans le cluster Kubernetes afin de regrouper toutes les ressources liées à ArgoCD.
  • params_by_env: Une map clé/valeur contenant les paramètres nécessaires pour créer les objets ArgoCD (Cluster, Application, Credentiels,…). Dans notre exemple, on aura besoin des éléments suivants:
    - application_name: Le nom de l’application.
    - application_url: L’url du repository git contenant les manifests à déployer.
    - application_server: L’adresse du serveur Kubernetes.
    - application_cluster: Le nom du cluster Kubernetes.
    - application_project: Le nom du projet GCP hébergeant GKE.

3. Ajouter la variable GCLOUD_SERVICE_KEY dans les variables CI/CD de Gitlab CI/CD.

4. Pousser les modifications. Gitlab CI/CD déclenchera un pipeline avec les étapes suivantes :

  • init: Premier job consacré aux téléchargements des providers.
  • plan: Crée le plan d’exécution.
  • apply: Exécute les actions définies dans le plan. Ce job est à déclencher manuellement après vérification du plan d’exécution.

A la fin de ce pipeline, ArgoCD sera créé dans le cluster Kubernetes du projet transverse et initialisé avec 3 clusters cibles de déploiement et 3 applications à déployer (chaque cluster et chaque application présente un environnement).

5. Utiliser la commande en ligne suivante pour récupérer la configuration pour se connecter au cluster Kubernetes hébergeant ArgoCD.

gcloud container clusters get-credentials transverse-k8s-cluster --zone us-central1-b --project tf-root-pj

6. Récupérer le mot de passe du compte administrateur d’ArgoCD.

kubectl -n argocd get secret argocd-initial-admin-secret -o jsonpath="{.data.password}" | base64 -d

7. Récupérer l’adresse IP du service ArgoCD.

kubectl -n argocd get svc argocd-server -o jsonpath="{.status.loadBalancer.ingress[0].ip}"

8. Une fois connecté sur l’interface web d’ArgoCD, on aura le tableau des applications.

9. Récupérer la configuration pour se connecter au cluster Kubernetes hébergeant l’application sur un des 3 environnements.

gcloud container clusters get-credentials qa-app-k8s-cluster --zone us-central1-b --project tf-qa-infra-stack

10. Trouver l’adresse IP du service qui expose l’API.

kubectl -n argocd get svc svc-sample-python-api -o jsonpath="{.status.loadBalancer.ingress[0].ip}"

11. Tester l’accès à cette adresse IP.

 # curl 34.122.77.241{"message": "This API is running in qa environment."}

Clean-up

Même si les instances choisies dans cet exemple sont éphémères, il est important de faire le nettoyage à la fin de l’exercice.
Pour les projets tf-app-project, tf-app-infra et tf-argocd il suffit de lancer un pipeline avec le paramètre DESTROY=true et si nécessaire le nom de l’environnement à supprimer.

Pour les projets tf-root-project, il faut exécuter en local la commande terraform destroy.

--

--

No responses yet