Lab 5: Continuous Integration (CI) and Continuous Delivery (CD) with Kubernetes

Objectifs

Ce laboratoire avait pour objectif de mettre en place des pipelines CI/CD complets en utilisant GitHub Actions, d’intégrer l’authentification sécurisée avec AWS via OIDC (OpenID Connect), et d’automatiser les déploiements d’infrastructure avec OpenTofu. Les concepts clés abordés incluent :

  • Configuration de tests automatisés pour une application Node.js et du code d’infrastructure (OpenTofu)
  • Mise en place de l’authentification OIDC entre GitHub Actions et AWS
  • Création de pipelines de déploiement avec différentes stratégies (plan/apply)
  • Exploration des stratégies de déploiement (Blue/Green, Canary, etc.) et du concept GitOps

Prérequis et Configuration Initiale

Préparation de l’environnement et adaptation des chemins pour le dépôt de groupe :

mkdir -p lab/lab5/scripts/sample-app
mkdir -p lab/lab5/scripts/tofu/modules
mkdir -p lab/lab5/scripts/tofu/live

Partie 1: Continuous Integration (CI)

1.1. Tests Automatisés pour l’Application (Jest)

Configuration du workflow GitHub Actions pour exécuter les tests Node.js :

name: Sample App Tests
on: push
jobs:
  sample_app_tests:
    name: "Run Tests Using Jest"
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - name: Setup Node.js
        uses: actions/setup-node@v3
        with:
          node-version: '18'
          cache: 'npm'
          cache-dependency-path: lab/lab5/scripts/sample-app/package-lock.json
      - name: Install dependencies
        working-directory: lab/lab5/scripts/sample-app
        run: npm ci
      - name: Run tests
        working-directory: lab/lab5/scripts/sample-app
        run: npm test

1.2. Authentification OIDC avec AWS

Création d’un module OpenTofu pour le fournisseur OIDC et les rôles IAM :

provider "aws" {
  region = "us-east-2"
}
module "oidc_provider" {
  source = "../../modules/github-aws-oidc"
  provider_url = "https://token.actions.githubusercontent.com"
}
module "iam_roles" {
  source = "../../modules/gh-actions-iam-roles"
  name = "lambda-sample"
  oidc_provider_arn = module.oidc_provider.oidc_provider_arn
  enable_iam_role_for_testing = true
  enable_iam_role_for_plan = true
  enable_iam_role_for_apply = true
  github_repo = "non0bi/mini-letterboxd"
  lambda_base_name = "lambda-sample"
  tofu_state_bucket = "tofu-state-gregoire-2026"
  tofu_state_dynamodb_table = "tofu-locks-gregoire"
}

Après application, récupération des ARN des rôles IAM et configuration des secrets GitHub.

1.3. Tests d’Infrastructure Automatisés avec OpenTofu

Workflow infra-tests.yml pour valider le code d’infrastructure :

name: Infrastructure Tests
on:
  push:
    paths: ['lab/lab5/scripts/tofu/live/lambda-sample/**']
  pull_request:
    paths: ['lab/lab5/scripts/tofu/live/lambda-sample/**']
jobs:
  opentofu_test:
    name: "Run OpenTofu tests"
    runs-on: ubuntu-latest
    permissions:
      id-token: write
      contents: read
    steps:
      - uses: actions/checkout@v3
      - uses: aws-actions/configure-aws-credentials@v3
        with:
          role-to-assume: ${{ secrets.TEST_ROLE_ARN }}
          aws-region: us-east-2
          audience: sts.amazonaws.com
      - uses: opentofu/setup-opentofu@v1
      - name: Tofu Test
        env:
          TF_VAR_name: lambda-sample-${{ github.run_id }}
        working-directory: lab/lab5/scripts/tofu/live/lambda-sample
        run: |
          tofu init -backend=false -input=false
          tofu test -verbose

Problème Majeur : Erreur OIDC

Erreur : Not authorized to perform sts:AssumeRoleWithWebIdentity. Cause probable : politique de confiance IAM incorrecte.

Exemple de politique de confiance correcte :

{
  "Effect": "Allow",
  "Principal": {
    "Federated": "arn:aws:iam::898034998292:oidc-provider/token.actions.githubusercontent.com"
  },
  "Action": "sts:AssumeRoleWithWebIdentity",
  "Condition": {
    "StringEquals": {
      "token.actions.githubusercontent.com:aud": "sts.amazonaws.com"
    },
    "StringLike": {
      "token.actions.githubusercontent.com:sub": "repo:non0bi/mini-letterboxd:*"
    }
  }
}

Partie 2: Continuous Delivery (CD)

2.1. Backend distant pour OpenTofu

Configuration du backend S3 et DynamoDB pour l’état partagé :

terraform {
  backend "s3" {
    bucket         = "tofu-state-gregoire-2026"
    key            = "lab/lab5/scripts/tofu/live/lambda-sample/terraform.tfstate"
    region         = "us-east-2"
    encrypt        = true
    dynamodb_table = "tofu-locks-gregoire"
  }
}

Migration de l’état local vers S3 :

cd lab/lab5/scripts/tofu/live/lambda-sample
tofu init -reconfigure -migrate-state

2.2. Workflows de Déploiement : Plan et Apply

Workflow tofu-plan.yml pour calculer le plan d’exécution OpenTofu :

name: Tofu Plan
on:
  pull_request:
    branches: ["main"]
    paths: ["lab/lab5/scripts/tofu/live/lambda-sample/**"]
jobs:
  plan:
    name: "Tofu Plan"
    runs-on: ubuntu-latest
    permissions:
      pull-requests: write
      id-token: write
      contents: read
    steps:
      - uses: actions/checkout@v3
      - uses: aws-actions/configure-aws-credentials@v3
        with:
          role-to-assume: ${{ secrets.PLAN_ROLE_ARN }}
          aws-region: us-east-2
          audience: sts.amazonaws.com
      - uses: opentofu/setup-opentofu@v1
      - name: tofu plan
        id: plan
        working-directory: lab/lab5/scripts/tofu/live/lambda-sample
        run: |
          tofu init -no-color -input=false
          tofu plan -no-color -input=false -lock=false
      - uses: peter-evans/create-or-update-comment@v4
        if: always()
        with:
          issue-number: ${{ github.event.pull_request.number }}
          body: |
            ## tofu plan output
            ```
            ${{ steps.plan.outputs.stdout }}
            ```

Workflow tofu-apply.yml pour appliquer les changements :

name: Tofu Apply
on:
  push:
    branches: ["main"]
    paths: ["lab/lab5/scripts/tofu/live/lambda-sample/**"]
jobs:
  apply:
    name: "Tofu Apply"
    runs-on: ubuntu-latest
    permissions:
      pull-requests: write
      id-token: write
      contents: read
    steps:
      - uses: actions/checkout@v3
      - uses: aws-actions/configure-aws-credentials@v3
        with:
          role-to-assume: ${{ secrets.APPLY_ROLE_ARN }}
          aws-region: us-east-2
          audience: sts.amazonaws.com
      - uses: opentofu/setup-opentofu@v1
      - name: tofu apply
        id: apply
        working-directory: lab/lab5/scripts/tofu/live/lambda-sample
        run: |
          tofu init -no-color -input=false
          tofu apply -no-color -input=false -auto-approve
      - name: Find current PR
        uses: jwalton/gh-find-current-pr@master
        id: find_pr
      - uses: peter-evans/create-or-update-comment@v4
        if: steps.find_pr.outputs.number
        with:
          issue-number: ${{ steps.find_pr.outputs.number }}
          body: |
            ## tofu apply output
            ```
            ${{ steps.apply.outputs.stdout }}
            ```

2.3. Test du Pipeline de Déploiement (Scénario Théorique)

Exemple de modification et test du pipeline :

git checkout -b feature/update-lambda-message
# Modification du code Lambda
# Commit, push et création de PR

Stratégies de Déploiement

StratégieDescriptionExpérience UtilisateurIdéal pour…
RecreateL’ancienne version est arrêtée avant la nouvelleInterruption de serviceDev/test, apps non critiques
Rolling UpdateInstances mises à jour progressivementProgressive, sans interruptionApps stateless en prod
Blue/GreenDeux environnements, bascule instantanéeMigration instantanéeApps critiques, rollback immédiat
CanaryDéploiement sur un sous-ensemble, puis extensionTests réels à petite échelleDéploiements à haut risque
Feature TogglesFonctionnalité déployée mais désactivéeAucun impactDéploiement fréquent, tests A/B
PromotionDéploiement successif dev → staging → prodTests progressifsValidation avant prod

Pour notre application serverless, Blue/Green ou Canary serait idéal.

Problèmes Rencontrés (Synthèse)

  • Structure de dépôt (résolu)
  • Permission Jest dans CI (résolu)
  • Authentification OIDC (non résolu sur dépôt de groupe)
  • Synchronisation Git (résolu)

Conclusion

Ce laboratoire a permis de mettre en place un pipeline CI/CD complet et fonctionnel sur nos dépôts personnels, depuis les tests unitaires jusqu’au déploiement automatisé d’infrastructure.

L’échec sur le dépôt de groupe a mis en lumière l’importance de la collaboration et de la documentation précise. Les compétences acquises sont directement applicables en contexte professionnel : construction de pipelines CI/CD, tests d’infrastructure, sécurité (OIDC), gestion d’état, stratégies de déploiement.

La prochaine étape serait de résoudre le problème IAM pour finaliser le pipeline et d’explorer l’intégration de Kubernetes et GitOps avec Flux.