DEV Community

Cover image for GitOps avec ArgoCD : comment j'ai automatisé mes déploiements Kubernetes
BeardDemon
BeardDemon

Posted on

GitOps avec ArgoCD : comment j'ai automatisé mes déploiements Kubernetes

Pourquoi ArgoCD ?

Avant ArgoCD, mon workflow de déploiement c'était:

  1. Push le code sur GitHub
  2. GitHub Actions build l'image Docker
  3. L'image est push sur GHCR (GitHub Container Registry)
  4. SSH sur le master Kubernetes
  5. kubectl apply -f manifests/
  6. Croiser les doigts

Résultat ? Souvent des erreurs genre "oups j'ai oublié de mettre à jour le manifest" ou "attends c'est quelle version qui tourne là ?".

Avec ArgoCD, c'est devenu:

  1. Push le code
  2. C'est tout. Vraiment.

ArgoCD surveille mon repo GitHub et déploie automatiquement les nouvelles versions.

Installation d'ArgoCD sur le cluster

Voici mon rôle Ansible qui installe ArgoCD:

- name: Créer namespace argocd
  command: kubectl create namespace argocd
  environment:
    KUBECONFIG: /etc/kubernetes/admin.conf
  ignore_errors: yes

- name: Installer ArgoCD
  command: kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/install.yaml
  environment:
    KUBECONFIG: /etc/kubernetes/admin.conf
  retries: 3

- name: Attendre les deployments ArgoCD
  command: kubectl wait --for=condition=available --timeout=300s deployment --all -n argocd
  environment:
    KUBECONFIG: /etc/kubernetes/admin.conf

- name: Patcher service en NodePort
  command: kubectl patch svc argocd-server -n argocd -p '{"spec":{"type":"NodePort","ports":[{"port":443,"targetPort":8080,"nodePort":30808}]}}'
  environment:
    KUBECONFIG: /etc/kubernetes/admin.conf

- name: Récupérer mot de passe admin
  shell: kubectl -n argocd get secret argocd-initial-admin-secret -o jsonpath="{.data.password}" | base64 -d
  environment:
    KUBECONFIG: /etc/kubernetes/admin.conf
  register: argocd_password

- name: Afficher les infos ArgoCD
  debug:
    msg:
      - "ArgoCD installé avec succès"
      - "URL: https://192.168.56.10:30808"
      - "Login: admin"
      - "Password: {{ argocd_password.stdout }}"
Enter fullscreen mode Exit fullscreen mode

Après ça, je peux accéder à l'interface web d'ArgoCD sur https://192.168.56.10:30808.

ArgoCD Image Updater : le vrai game changer

Le truc cool avec ArgoCD Image Updater, c'est qu'il surveille mon GitHub Container Registry et met à jour automatiquement mes manifests quand une nouvelle image est dispo.

Installation:

- name: Télécharger manifeste ArgoCD Image Updater
  get_url:
    url: https://raw.githubusercontent.com/argoproj-labs/argocd-image-updater/stable/config/install.yaml
    dest: /tmp/argocd-image-updater.yaml

# IMPORTANT: Tout mettre dans le namespace argocd
- name: Modifier les namespaces vers argocd
  shell: |
    sed -i 's/namespace: argocd-image-updater-system/namespace: argocd/g' /tmp/argocd-image-updater.yaml
    sed -i 's/namespace: argocd-image-updater/namespace: argocd/g' /tmp/argocd-image-updater.yaml

- name: Installer ArgoCD Image Updater
  command: kubectl apply -f /tmp/argocd-image-updater.yaml
  environment:
    KUBECONFIG: /etc/kubernetes/admin.conf

- name: Configurer le log-level à debug
  shell: kubectl patch deployment argocd-image-updater -n argocd --type json -p '[{"op": "add", "path": "/spec/template/spec/containers/0/args/-", "value": "--loglevel=debug"}]'
  environment:
    KUBECONFIG: /etc/kubernetes/admin.conf
Enter fullscreen mode Exit fullscreen mode

Créer une Application ArgoCD

Voici comment je déclare mon API Catalogue dans ArgoCD:

apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: catalogue-manager-application
  namespace: argocd
  annotations:
    # Config pour Image Updater
    argocd-image-updater.argoproj.io/image-list: catalogue-manager=ghcr.io/uha-sae53/api-catalogue
    argocd-image-updater.argoproj.io/catalogue-manager.update-strategy: latest
    argocd-image-updater.argoproj.io/catalogue-manager.force-update: "true"
    argocd-image-updater.argoproj.io/write-back-method: argocd
spec:
  destination:
    namespace: apps
    server: https://kubernetes.default.svc
  source:
    path: ansible-provisioning/manifests/apicatalogue
    repoURL: https://github.com/uha-sae53/Vagrant.git
    targetRevision: main
  project: default
  syncPolicy:
    automated:
      prune: true        # Supprime les ressources qui sont plus dans Git
      selfHeal: true     # Remet en place si on modifie à la main
    syncOptions:
      - CreateNamespace=true
Enter fullscreen mode Exit fullscreen mode

Les annotations argocd-image-updater c'est ce qui fait la magie:

  • Il surveille ghcr.io/uha-sae53/api-catalogue
  • Dès qu'un tag :latest est push, il met à jour le manifest
  • force-update: true = il force même si le tag existe déjà (utile pour :latest)

Le workflow complet

  1. Je push du code sur main
  2. GitHub Actions:
   - name: Build and push Docker image
     uses: docker/build-push-action@v4
     with:
       context: .
       push: true
       tags: |
         ghcr.io/uha-sae53/api-catalogue:latest
         ghcr.io/uha-sae53/api-catalogue:${{ github.sha }}
Enter fullscreen mode Exit fullscreen mode
  1. ArgoCD Image Updater détecte la nouvelle image
  2. Il update le manifest dans ArgoCD (pas dans Git, dans ArgoCD)
  3. ArgoCD sync automatiquement sur le cluster
  4. Mes pods redémarrent avec la nouvelle version

Temps total: ~3 minutes.

Config GitHub Actions (le CI)

Voici ma CI complète pour l'API Catalogue:

name: Django CI

on:
  push:
    branches: [ "main", "dev" ]

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v4
    - name: Set up Python
      uses: actions/setup-python@v3
      with:
        python-version: 3.13
    - name: Install Dependencies
      run: |
        pip install -r requirements.txt
    - name: Run Tests
      run: |
        python projet/manage.py test

  build-and-push-docker:
    needs: test
    runs-on: ubuntu-latest
    steps:
      - name: Checkout repository
        uses: actions/checkout@v4

      - name: Log in to GitHub Container Registry
        uses: docker/login-action@v2
        with:
          registry: ghcr.io
          username: ${{ github.actor }}
          password: ${{ secrets.GITHUB_TOKEN }}

      - name: Build and push Docker image
        uses: docker/build-push-action@v4
        with:
          context: .
          file: ./Dockerfile
          push: true
          tags: |
            ghcr.io/uha-sae53/api-catalogue:latest
            ghcr.io/uha-sae53/api-catalogue:${{ github.sha }}
Enter fullscreen mode Exit fullscreen mode

Les erreurs que j'ai faites

Erreur #1: Images privées sans secret

Au début mes images GHCR étaient privées. ArgoCD Image Updater pouvait pas les pull.

Solution: Passer les images en publiques. C'est un projet d'école, pas besoin de les cacher.

Erreur #2: Namespaces multiples pour Image Updater

J'avais laissé le namespace par défaut argocd-image-updater-system. Ça créait des conflicts de droits.

Solution: Tout mettre dans le namespace argocd avec le sed.

Erreur #3: Pas de force-update

Sans force-update: true, Image Updater mettait pas à jour si le tag :latest existait déjà.

Résultat ? Mes nouveaux builds étaient ignorés.

Vérifier que ça marche

# Voir les applications ArgoCD
kubectl get applications -n argocd

# Logs d'Image Updater
kubectl logs -n argocd deployment/argocd-image-updater -f

# Voir l'état de sync
kubectl get app catalogue-manager-application -n argocd -o yaml
Enter fullscreen mode Exit fullscreen mode

Dashboard ArgoCD

Dans l'interface web d'ArgoCD, je vois:

  • Tous mes services
  • Leur état de sync (vert = ok)
  • L'historique des déploiements
  • Les différences entre Git et le cluster

C'est pratique pour voir d'un coup d'œil ce qui tourne.

Conclusion

GitOps c'est pas juste un buzzword. Ça m'a vraiment simplifié la vie:

  • Plus de kubectl apply manuel
  • Traçabilité complète (tout est dans Git)
  • Rollback facile
  • Pas de drift entre environnements

Le seul défaut ? C'est un peu overkill pour un cluster de dev. Mais bon, c'est cool à mettre sur le CV.

Code complet: [lien GitHub]

Top comments (0)