Déploiement de notre première application

Oct 30, 2024 min read

Cet article fait partie d’une série d’articles :

1. Notre application (Partie CI)

Il s’agit d’un bot discord créant un quiz. C’est une application écrite en golang.

Le code est disponible ici

Remarque : Cette application ne fait que se connecter à des APIS, et n’a donc pas besoin de recevoir des requètes de l’extérieur. Il n’y a donc pas besoin de créer un accès ingress depuis internet vers notre cluster, ce qui simplifie la gestion de la sécurité.


La compilation de l’application est assez simple :

go mod tidy 
go build .

Ce qui se traduit pour le job suivant dans notre fichier de configuration de la CI/CD, le .gitlab-ci.yml par :

#.gitlab-ci.yml
buildgo:
  stage: build
  image: golang
  script:
    - go mod tidy
    - go build .
  cache:
    policy: push
    paths:
      - quizzbot

Chaque job de CI s’exécute dans une conteneur docker différent, et donc le cache permet de sauvegarder des fichiers et de les partager entre les différents conteneurs, comme ici quizzbot, le binaire compilé de notre application.

Nous packageons notre application dans une image docker, qui sera notre livrable :

#.gitlab-ci.yml
builddocker:
  stage: publish
  services:
    - name: docker:dind
      command: ["dockerd", "--host=tcp://0.0.0.0:2375"]
      alias: 'docker'
  before_script:
    - docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD"
  script:
    - docker build -t $CI_REGISTRY/discordquizbot .
    - docker push $CI_REGISTRY/discordquizbot
  cache:
    policy: pull
    paths:
      - quizzbot

(Petit disclaimer : la méthode ici présentée est ancienne, mais je le sais, je n’ai pas eu trop le temps de peaufiner cette partie)

Note : Toute cette partie est exécutée sur les runner partagés de gitlab.com, car il n’y a aucun avantage à utiliser nos propres ressources pour celà.

2. Le déploiement terraform (Partie CD)


Chose à savoir : Je suis un grand adepte de terraform, donc je vais l’utiliser, et peut-être un peu plus que de raison.

Je vais par exemple utiliser directement le provider terraform pour kubernetes là où il aurait été plus “joli” d’utiliser des configurations helm puis de les exécuter avec le provider helm de terraform, laissant la possibilité à tout un chacun de choisir de déployer via terraform, ou non.

Ceci étant dit, retournons à notre déploiement :

Dans cette partie, nous déclarons les variables non déclarées dans nos projets gitlab, ou leurs groupe parent (voir le chapitre Préparation du déploiement des applications)

#.gitlab-ci.yml
variables:
  TF_VAR_MINIKUBE_HOST: ${MINIKUBE_HOST}
  TF_VAR_CI_PROJECT_ID: ${CI_PROJECT_ID}
  TF_VAR_CI_REGISTRY: ${CI_REGISTRY}

Ici le préfixe TF_VAR_ est une façon de passer à terraform des variables.

Par exemple, la variable TF_VAR_CI_REGISTRY apparaîtra en tant que var.CI_REGISTRY dans notre code terraform.

Sur notre groupe gitlab, nous avons ajouté la variable

TF_VAR_KUBECONFIG_MKS8

qui contient le chemin de notre fichier de configuration au format lisible par kubectl (voir le chapitre Préparation du déploiement des applications)

Commençons par jouer la commande terraform init pour initialiser le dossier d’exécution puis terraform plan qui va valider en se connectant à kubernetes que tout est en place pour notre déploiement, sans pour autant le déclencher.

#.gitlab-ci.yml
terraform-plan:
  stage: build
  image:
    name: hashicorp/terraform:latest
    entrypoint:
      - '/usr/bin/env'
      - 'PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin'
  tags:
    - minikube
  only:
    - main
  script:
    - cd terraform
    - apk update && apk add envsubst
    - cat backend.tf.tpl | envsubst > backend.tf
    - terraform init -input=false
    - terraform plan -input=false -out=plan.cache

le terraform plan va s’exécuter sur notre cluster kubernetes grâce à ceci :

tags:
  - minikube

minikube est le tag que j’ai donné à mon runner gitlab lors de sa création (voir le chapitre Préparation du déploiement des applications)

Tout va s’exécuter dans le dossier terraform de ce repo et terraform utilisera tous les fichier *.tf présents dans ce dossier

Je vous laisse étudier la documentation de terraform. Nous nous intéresserons surtout à la manière de déployer dans notre cluster.

Pour aller à l’essentiel, nous allons configurer le provider (driver) terraform pour kubernetes, dans le fichier provider.tf

# provider.tf
provider "kubernetes" {
  config_path    = var.KUBECONFIG_MKS8
}

(C’est ici que nous transmettons le chemin de notre fichier de configuration kubernetes à terraform)

Ensuite, nous instancions notre application via un appel de module dans le fichier main.tf:

module "french" {
  source          = "./app_instance"
  MINIKUBE_NAMESPACE        = data.kubernetes_namespace.botspace.id
  CI_REGISTRY               = var.CI_REGISTRY
  DISCORD_TOKEN             = var.DISCORD_TOKEN
}

Ce module exécute ce qui se trouve dans le dossier terraform/app_instance

et le fichier terraform/app_instance/application.tf contient le code de déploiement de notre application :

resource "kubernetes_deployment" "discordbot" {
  metadata {
    name = "discordbot"
    namespace = var.MINIKUBE_NAMESPACE
    labels = {

    }
  }

  spec {
    replicas = 1

    selector {
      match_labels = {
        app = "discordbot"
      }
    }

    template {
      metadata {
        labels = {
          app = "discordbot"
        }
      }

      spec {
        container {
          image = "${var.CI_REGISTRY}/discordquizbot"
          name  = "discordquizbot"

          env {
            name  = "DISCORD_TOKEN"
            value = "${var.DISCORD_TOKEN}"
          }


        }
      }
    }
  }
}

Pour comprendre, je vous renvoie vers la documentation de l’objet kubernetes_deployment sur le site officiel

Une fois le terraform plan validé, notre pipeline gitlab exécutera le terrafom apply appliquera les modifications.

Voici à quoi ressemble notre pipeline gitlab :

Et notre conteneur sera démarré sur notre cluster kubernetes :


Voilà ! J'espère que cette série d'articles vous aura plu, et que vous prendrez autant de plaisir que j'ai eu à le faire pour monter mon cluster kubernetes !

-|