ITSkillsCenter
Self-hosting

Bootstrap GitOps avec Argo CD sur Kubernetes pas-à-pas

13 دقائق للقراءة

Article principal · Ce tutoriel fait partie de la série Kubernetes domestique sur Proxmox VE. Tutoriel précédent : Rook-Ceph stockage. Tutoriel suivant : kube-prometheus-stack observabilité.

Déployer manuellement avec kubectl apply fonctionne pour deux ou trois charges. Au-delà, l état du cluster diverge insidieusement de ce qu on pense avoir déclaré, les rollbacks deviennent risqués, et on perd l historique des changements. Le pattern GitOps résout ces trois problèmes en plaçant le dépôt Git comme source de vérité unique : le cluster ne fait que synchroniser ce qui est commité. Argo CD est l implémentation de référence de ce pattern. La version 3.4, livrée mai 2026, ajoute un Application Controller multi-thread plus rapide et une meilleure gestion des références ApplicationSet. Ce tutoriel installe Argo CD 3.4, structure un dépôt Git, crée la première Application qui déploie une charge depuis Git, puis met en place une ApplicationSet qui décline la même charge sur plusieurs namespaces.

Étape 1 — Préparer le dépôt Git source de vérité

Le dépôt Git est la pièce centrale. Il peut être hébergé sur GitHub, GitLab, Gitea, Forgejo ou tout serveur SSH. Pour un homelab souverain, l idéal est de l héberger soi-même, mais on peut commencer sur un GitHub privé en attendant que Gitea soit déployé.

mkdir homelab-gitops && cd homelab-gitops
git init
mkdir -p apps clusters/homelab/bootstrap clusters/homelab/infra clusters/homelab/apps

# Structure recommandée :
# apps/                  — manifestes Helm/Kustomize par application
# clusters/homelab/      — définition Argo CD du cluster
#   bootstrap/           — Application racine (app-of-apps)
#   infra/               — Cilium, Rook, cert-manager, MetalLB
#   apps/                — Vaultwarden, Nextcloud, Gitea...

echo "# Homelab GitOps" > README.md
git add . && git commit -m "Initial structure"

# Pousser vers le dépôt distant (créer le dépôt manuellement avant)
git remote add origin git@github.com:moncompte/homelab-gitops.git
git branch -M main
git push -u origin main

La structure crée trois niveaux : apps/ pour les manifestes réutilisables, clusters/homelab/ pour la configuration spécifique du cluster, et trois sous-dossiers bootstrap/, infra/, apps/ qui correspondent aux trois grandes catégories de charges. Cette organisation se révèle robuste à l échelle, parce qu elle permet d ajouter d autres clusters (clusters/edge1/, clusters/labo/) sans réorganiser le dépôt.

Étape 2 — Installer Argo CD 3.4 via Helm

L installation d Argo CD se fait par Helm pour permettre un upgrade simple. Le chart officiel est dans le dépôt argoproj.

helm repo add argo https://argoproj.github.io/argo-helm
helm repo update

kubectl create namespace argocd

helm install argocd argo/argo-cd \
  --version 9.5.12 \
  --namespace argocd \
  --set server.service.type=ClusterIP \
  --set server.extraArgs[0]=--insecure \
  --set configs.params.server.insecure=true \
  --set redis-ha.enabled=false \
  --set controller.replicas=1 \
  --set server.replicas=2 \
  --set repoServer.replicas=2 \
  --set applicationSet.enabled=true \
  --set notifications.enabled=true

Le chart 9.5.12 du dépôt argo-helm livre Argo CD 3.4.x. L option --insecure sur le serveur évite la double couche TLS quand on l expose ensuite derrière un Ingress qui termine le TLS. Compter trois minutes pour que tous les pods soient en Running.

Étape 3 — Récupérer le mot de passe admin et accéder à l UI

Argo CD génère automatiquement un compte admin avec un mot de passe initial stocké dans un Secret. Le récupérer puis se connecter via port-forward.

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

kubectl -n argocd port-forward svc/argocd-server 8080:80 &
# Ouvrir http://localhost:8080 dans le navigateur, login admin, mot de passe ci-dessus

L interface affiche un écran « Aucune Application ». C est normal : le cluster n a pas encore d Application synchronisée. Avant tout, changer le mot de passe admin via User Info → Update Password, ou mieux, désactiver l auth interne et utiliser le SSO (Keycloak ou Authentik) — pratique standard en production.

Étape 4 — Connecter Argo CD au dépôt Git

Argo CD doit pouvoir cloner le dépôt source de vérité. Pour un dépôt public en lecture seule, rien à faire. Pour un dépôt privé via SSH, il faut fournir une clé déployée. Pour HTTPS avec token, créer le Secret approprié.

apiVersion: v1
kind: Secret
metadata:
  name: homelab-gitops-repo
  namespace: argocd
  labels:
    argocd.argoproj.io/secret-type: repository
stringData:
  type: git
  url: git@github.com:moncompte/homelab-gitops.git
  sshPrivateKey: |
    -----BEGIN OPENSSH PRIVATE KEY-----
    [contenu de la clé privée déployée en read-only sur GitHub]
    -----END OPENSSH PRIVATE KEY-----
kubectl apply -f homelab-gitops-repo.yaml

# Vérifier dans l UI Argo CD : Settings → Repositories
# Le dépôt doit apparaître avec l état CONNECTION SUCCESSFUL

L état Connection Successful confirme qu Argo CD peut cloner le dépôt. À ce stade, on peut créer la première Application qui pointera vers un sous-dossier du dépôt.

Étape 5 — Créer la première Application

Une Application Argo CD est un objet déclaratif qui dit : « surveille tel chemin de tel dépôt et applique le résultat dans tel namespace ». Le manifest ci-dessous déploie un démonstrateur podinfo depuis un sous-dossier du dépôt.

apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: podinfo-demo
  namespace: argocd
spec:
  project: default
  source:
    repoURL: git@github.com:moncompte/homelab-gitops.git
    targetRevision: main
    path: apps/podinfo-demo
  destination:
    server: https://kubernetes.default.svc
    namespace: demo
  syncPolicy:
    automated:
      prune: true
      selfHeal: true
    syncOptions:
    - CreateNamespace=true
kubectl apply -f podinfo-app.yaml

# Dans l UI Argo CD, l Application apparaît
# Statut Sync : Synced (vert), Health : Healthy
kubectl get pods -n demo
# Le pod podinfo doit être en Running

Le pod podinfo qui apparaît dans le namespace demo a été créé sans kubectl apply manuel : Argo CD l a synchronisé depuis Git. Si l on commit un changement sur la branche main (par exemple porter le nombre de réplicas de 1 à 3), Argo CD détecte la dérive en moins de trois minutes et applique le changement. Le rollback est tout aussi simple : git revert et c est synchronisé en sens inverse.

Étape 6 — Mettre en place l app-of-apps

Créer chaque Application à la main devient pénible quand on en a vingt. Le pattern app-of-apps consiste à créer une Application racine qui déploie elle-même toutes les autres Applications du cluster. C est récursif et auto-suffisant : un seul kubectl apply initial suffit, ensuite tout vit dans Git.

apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: bootstrap-homelab
  namespace: argocd
spec:
  project: default
  source:
    repoURL: git@github.com:moncompte/homelab-gitops.git
    targetRevision: main
    path: clusters/homelab/bootstrap
  destination:
    server: https://kubernetes.default.svc
    namespace: argocd
  syncPolicy:
    automated:
      prune: true
      selfHeal: true

Le dossier clusters/homelab/bootstrap/ contient ensuite les manifestes Application qui pointent vers infra/ et apps/. Argo CD les découvre récursivement et synchronise tout. C est cette structure qui permet de reconstruire un cluster complet en deux commandes : helm install argocd puis kubectl apply -f bootstrap-homelab.yaml.

Étape 7 — Décliner sur plusieurs environnements avec ApplicationSet

Quand on a deux clusters (homelab et un labo), copier-coller chaque Application devient absurde. ApplicationSet génère dynamiquement les Applications à partir d un générateur (liste, matrice, cluster, Git directory).

apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
  name: monitoring-everywhere
  namespace: argocd
spec:
  generators:
  - list:
      elements:
      - cluster: homelab
        url: https://kubernetes.default.svc
      - cluster: labo
        url: https://10.0.1.10:6443
  template:
    metadata:
      name: '{{cluster}}-kube-prometheus-stack'
    spec:
      project: default
      source:
        repoURL: git@github.com:moncompte/homelab-gitops.git
        targetRevision: main
        path: clusters/{{cluster}}/infra/kube-prometheus-stack
      destination:
        server: '{{url}}'
        namespace: monitoring
      syncPolicy:
        automated:
          prune: true

Avec un seul ApplicationSet, deux Applications sont créées : homelab-kube-prometheus-stack et labo-kube-prometheus-stack, chacune pointant vers son propre dossier. Ajouter un troisième cluster prend trois lignes au lieu de dupliquer trente lignes de YAML.

Étape 8 — Vérifier la chaîne complète après un commit

Le test final consiste à modifier un manifest dans Git et vérifier que le cluster évolue. C est le critère de fonctionnement réel d une chaîne GitOps.

# Sur le poste, modifier le nombre de réplicas
cd homelab-gitops
yq -i '.spec.replicas = 3' apps/podinfo-demo/deployment.yaml
git add apps/podinfo-demo/deployment.yaml
git commit -m "Scale podinfo to 3 replicas"
git push origin main

# Argo CD détecte le changement en moins de 3 minutes (intervalle de polling par défaut)
kubectl get pods -n demo -l app=podinfo -w
# Doit passer de 1 pod Running à 3 pods Running

Voir les trois pods apparaître sans avoir lancé une seule commande kubectl scale confirme que la boucle GitOps est complète : Git → Argo CD → cluster. À partir de maintenant, toute modification d infrastructure ou d application passe par un commit, jamais par une commande directe sur le cluster.

Erreurs fréquentes et résolutions

Symptôme Cause Résolution
L Application reste en OutOfSync indéfiniment Drift entre Git et le cluster, mais sync auto désactivée Cliquer Sync manuellement ou activer syncPolicy.automated
Connection Failed sur le repository Mauvaise clé SSH, ou clé non déployée sur GitHub Régénérer la clé, l ajouter dans Settings → Deploy keys du dépôt
Le sync échoue avec « namespace not found » Namespace inexistant et CreateNamespace=true non activé Ajouter syncOptions: [CreateNamespace=true]
Argo CD bouge les ressources mais ne les supprime pas prune: false par défaut Activer prune: true dans automated
L UI Argo CD est lente sur un gros cluster Application Controller saturé Augmenter controller.replicas et activer le sharding

Pour la suite du parcours

Le déploiement est désormais piloté par Git. Toute charge ajoutée au dépôt est automatiquement appliquée au cluster, et toute modification est tracée dans l historique Git. La couche manquante pour opérer sereinement est l observabilité : sans Prometheus ni Grafana, on déploie à l aveugle. Le tutoriel Observabilité Kubernetes avec kube-prometheus-stack détaille l installation du chart 84.5.0 et la configuration des dashboards essentiels. Pour la vue d ensemble, retourner au guide principal Kubernetes domestique sur Proxmox VE.

Ressources et documentation officielle

Étape 9 — Sécuriser les secrets dans Git avec Sealed Secrets

Le pattern GitOps a un défaut évident : on ne peut pas committer les Secrets Kubernetes en clair. Les mots de passe, les tokens d API, les certificats privés ne doivent jamais arriver dans Git. Plusieurs solutions existent ; la plus simple à opérer en homelab est sealed-secrets de Bitnami. Le principe : un contrôleur dans le cluster détient une clé privée qui peut déchiffrer des SealedSecret committés en Git. On chiffre côté poste de travail, on commit, le contrôleur déchiffre dans le cluster.

# Installer sealed-secrets via Helm
helm repo add sealed-secrets https://bitnami-labs.github.io/sealed-secrets
helm install sealed-secrets sealed-secrets/sealed-secrets \
  --namespace kube-system

# Installer la CLI kubeseal sur le poste
KUBESEAL_VERSION=0.36.6
curl -OL https://github.com/bitnami-labs/sealed-secrets/releases/download/v\$\{KUBESEAL_VERSION\}/kubeseal-\$\{KUBESEAL_VERSION\}-linux-amd64.tar.gz
tar xfz kubeseal-\$\{KUBESEAL_VERSION\}-linux-amd64.tar.gz
sudo install kubeseal /usr/local/bin/

# Chiffrer un secret existant
kubectl create secret generic db-password \
  --from-literal=password=monsecret \
  --dry-run=client -o yaml | \
  kubeseal --format yaml > apps/myapp/db-password.sealed.yaml

# Le fichier sealed peut être commité en clair dans Git, il est inutilisable hors du cluster

Voir le fichier db-password.sealed.yaml contenant un blob chiffré confirme que la chaîne fonctionne. Quand Argo CD synchronisera, il créera un SealedSecret, que le contrôleur transformera en Secret Kubernetes utilisable. La clé privée du contrôleur doit absolument être sauvegardée hors du cluster (Velero le fera, mais une copie manuelle initiale est prudente).

Étape 10 — Activer les notifications de synchronisation

Sans notification, on découvre les échecs de synchronisation au pire moment, en cliquant dans l UI. Le composant argocd-notifications intégré au chart envoie des messages vers Slack, Discord, email, ou n importe quel webhook quand un événement se produit.

apiVersion: v1
kind: ConfigMap
metadata:
  name: argocd-notifications-cm
  namespace: argocd
data:
  service.webhook.discord: |
    url: https://discord.com/api/webhooks/...
    headers:
    - name: Content-Type
      value: application/json
  template.app-sync-failed: |
    webhook:
      discord:
        method: POST
        body: |
          {"content": "🔴 {{.app.metadata.name}} sync failed: {{.app.status.operationState.message}}"}
  trigger.on-sync-failed: |
    - description: Application sync failed
      send: [app-sync-failed]
      when: app.status.operationState.phase in ['Error', 'Failed']

Avec cette configuration, chaque échec de synchronisation déclenche un message Discord. C est suffisant pour réagir en quelques minutes plutôt qu en quelques jours. Pour les utilisateurs sans Discord, le webhook fonctionne avec n importe quel service compatible (Mattermost auto-hébergé, Matrix, Pushover).

Étape 11 — Comprendre les pièges du selfHeal

L option selfHeal: true est puissante mais a un effet de bord à connaître. Si un opérateur applique manuellement un patch d urgence sur une ressource gérée par Argo CD (par exemple kubectl scale pour résoudre un incident), Argo CD va annuler ce patch lors de la prochaine synchronisation, parce qu il ne correspond plus à Git. C est par dessein, mais cela peut surprendre.

Deux contournements existent. Le premier consiste à annoter la ressource avec argocd.argoproj.io/sync-options: IgnoreExtraneous=true ou désactiver temporairement selfHeal sur l Application concernée. Le second, plus propre, consiste à committer le patch d urgence dans Git, ce qui réconcilie l état désiré avec l état réel et restaure la cohérence.

En pratique, on apprend à ne plus jamais utiliser kubectl apply sur les ressources gérées par Argo CD. Toute modification passe par un commit, même les corrections rapides. Cette discipline transforme l opération du cluster : on retrouve l historique de chaque changement, on peut rejouer une configuration trois mois plus tard, on peut diffuser une correction sur dix clusters via un seul ApplicationSet.

Étape 12 — Vérifier que Argo CD se gère lui-même

L étape ultime du GitOps est de faire gérer Argo CD par Argo CD lui-même. Le chart Helm est ajouté au dépôt, une Application pointe dessus, et toute mise à jour d Argo CD passe par un commit sur Git. C est un peu vertigineux la première fois mais c est cohérent.

# Ajouter le chart Argo CD au dépôt
mkdir -p clusters/homelab/infra/argocd
cat > clusters/homelab/infra/argocd/application.yaml <<EOF
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: argocd-self
  namespace: argocd
spec:
  project: default
  source:
    repoURL: https://argoproj.github.io/argo-helm
    targetRevision: 9.5.12
    chart: argo-cd
    helm:
      valueFiles:
      - $values/clusters/homelab/infra/argocd/values.yaml
  sources:
  - repoURL: git@github.com:moncompte/homelab-gitops.git
    ref: values
  destination:
    server: https://kubernetes.default.svc
    namespace: argocd
  syncPolicy:
    automated:
      selfHeal: true
EOF

git add clusters/homelab/infra/argocd
git commit -m "Self-manage Argo CD via GitOps"
git push

Une fois cette Application synchronisée, mettre à jour Argo CD revient à modifier targetRevision: 9.5.12 en 8.5.0 et committer. Le contrôleur upgrade lui-même son propre déploiement de manière transactionnelle. C est l aboutissement de la chaîne GitOps : tout le cluster, y compris l outil qui le synchronise, vit dans Git.

Sponsoriser ce contenu

Cet emplacement est à vous

Position premium en fin d'article — c'est l'instant où les lecteurs sont le plus engagés. Réservez cet espace pour votre marque, votre formation ou votre offre.

Recevoir nos tarifs
Publicité