Partie 6 : GitOps avec ArgoCD - L'installation
Partie 6 : GitOps avec ArgoCD - L'installation
16 décembre 2025
Le grand Reset et la reconstruction
Après avoir cassé toute l'infrastructure en essayant de résoudre les problèmes de redirections vers mes services externes (Passbolt, NAS, stack Arr), j'ai pris une décision radicale : tout réinstaller from scratch.
Une semaine de recherche pour tenter de récupérer, une semaine de pause pour accepter la situation, et finalement : formatage des cartes SD et réinstallation complète de Raspberry Pi OS sur les 4 Raspberry Pi.
Mais cette fois-ci, j'avais un atout majeur : mes playbooks Ansible.
Le sauvetage par l'Infrastructure as Code
Grâce aux playbooks Ansible créés précédemment, la réinstallation du cluster K3s a été un jeu d'enfant :
ansible-playbook -i inventory.yml playbooks/site.yml
En moins d'une heure, j'avais :
- Les 4 Raspberry Pi configurés
- K3s installé et clusterisé
- nginx-ingress-controller déployé
- cert-manager configuré
- Les certificats Let's Encrypt générés
C'est là que j'ai vraiment compris la puissance de l'Infrastructure as Code. Sans Ansible, j'aurais passé des jours à tout reconfigurer manuellement.
Le problème suivant : La dérive de configuration
Même avec Ansible pour l'infrastructure de base, je faisais encore beaucoup de kubectl apply manuels pour déployer mes applications. Et là, nouveau problème :
Comment savoir ce qui tourne réellement sur le cluster ?
- J'avais des manifests YAML éparpillés
- Des commandes Helm
upgradelancées à la main - Aucune trace de qui a modifié quoi et quand
- Impossible de revenir en arrière facilement
Exemple typique :
# Moi, un lundi
helm upgrade home-fonta ./helm-charts/homefonta -n home-fonta
# Moi, le mercredi (j'ai oublié ce que j'ai changé)
kubectl get deployment home-fonta-web -n home-fonta -o yaml
# "Attendez, pourquoi il y a 2 replicas ? J'avais pas mis 3 ?"
La dérive de configuration (configuration drift) était inévitable.
GitOps : Git comme source de vérité unique
J'ai découvert le concept de GitOps :
Principe fondamental : L'état désiré de ton infrastructure est dans Git, et c'est la seule source de vérité.
Le flux GitOps :
- Je modifie un fichier YAML dans Git
- Je commit et push
- Un outil détecte le changement
- L'outil synchronise automatiquement Kubernetes avec Git
- Zéro commande
kubectlmanuelle
Avantages :
- Historique complet dans Git (qui a changé quoi, quand, pourquoi)
- Rollback facile (juste un
git revert) - Code review via Pull Requests
- Audit trail complet
- Pas de dérive de configuration possible (auto-correction)
L'outil leader pour GitOps sur Kubernetes : ArgoCD
ArgoCD : Le contrôleur GitOps
ArgoCD est un contrôleur Kubernetes qui :
- Surveille un repository Git
- Compare l'état dans Git avec l'état dans Kubernetes
- Synchronise automatiquement si différence détectée
- Affiche une belle interface web pour visualiser tout ça
Installation d'ArgoCD sur K3s
Prérequis
Avant d'installer ArgoCD, j'avais déjà :
- Cluster K3s opérationnel (4 nodes)
- cert-manager installé
- Certificat wildcard Let's Encrypt pour
*.home-fonta.fr - Repository Git :
git@github.com:Nikob2o/ansible-k3s.git
Étape 1 : Installation ArgoCD
La méthode officielle recommandée :
# Créer le namespace
kubectl create namespace argocd
# Installer ArgoCD (version stable)
kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/install.yaml
Cette commande installe :
- Les Custom Resource Definitions (CRDs) : Application, ApplicationSet, AppProject
- Les contrôleurs : application-controller, repo-server, server
- Les services : argocd-server, argocd-repo-server, argocd-dex-server
- Redis pour le cache
Vérification :
kubectl get pods -n argocd
Tous les pods doivent être en Running (prend 1-2 minutes).
Étape 2 : Exposition via Ingress
ArgoCD installé, mais pas encore accessible depuis l'extérieur. Je devais créer un Ingress.
Fichier : manifests/02-argocd/ingress.yaml
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: argocd-server-ingress
namespace: argocd
annotations:
nginx.ingress.kubernetes.io/force-ssl-redirect: "true"
nginx.ingress.kubernetes.io/backend-protocol: "HTTPS"
nginx.ingress.kubernetes.io/ssl-passthrough: "false"
spec:
ingressClassName: nginx
tls:
- hosts:
- argo.home-fonta.fr
secretName: wildcard-home-fonta-tls
rules:
- host: argo.home-fonta.fr
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: argocd-server
port:
name: https
Point important : backend-protocol: "HTTPS" car ArgoCD server écoute en HTTPS en interne, mais je fais du TLS termination sur l'Ingress.
Application de l'Ingress :
kubectl apply -f manifests/02-argocd/ingress.yaml
Étape 3 : Configuration DNS
Création de l'enregistrement DNS dans Cloudflare via API :
curl -s -X POST "https://api.cloudflare.com/client/v4/zones/ZONE_ID/dns_records" \
-H "Authorization: Bearer API_TOKEN" \
-H "Content-Type: application/json" \
--data '{"type":"A","name":"argo","content":"80.9.222.151","ttl":1,"proxied":false}'
Maintenant : https://argo.home-fonta.fr est accessible !
Problème 1 : Certificat SSL invalide
En accédant à https://argo.home-fonta.fr, Firefox me bloque : "Connexion bloquée : problème de sécurité potentiel".
Cause : Le certificat wildcard-home-fonta-tls existe dans le namespace home-fonta, mais pas dans le namespace argocd.
Les Secrets Kubernetes ne traversent PAS les namespaces (isolation de sécurité).
Solution temporaire : Port-forward pour accéder via localhost
kubectl port-forward svc/argocd-server -n argocd 8080:443
Puis accès via https://localhost:8080 (accepter le certificat auto-signé).
La vraie solution (réplication de certificat entre namespaces) viendra plus tard avec Reflector.
Étape 4 : Récupération du mot de passe admin
ArgoCD génère un mot de passe admin aléatoire au premier démarrage :
kubectl -n argocd get secret argocd-initial-admin-secret \
-o jsonpath="{.data.password}" | base64 -d && echo
Credentials :
- Username :
admin - Password : (celui récupéré par la commande)

Je me connecte via https://localhost:8080 et... je suis dans ArgoCD !
Étape 5 : Installation du CLI ArgoCD
Pour gérer ArgoCD depuis le terminal, j'installe le CLI :
# Télécharger le binaire
mkdir -p ~/.local/bin
curl -sSL -o ~/.local/bin/argocd \
https://github.com/argoproj/argo-cd/releases/latest/download/argocd-linux-amd64
# Rendre exécutable
chmod +x ~/.local/bin/argocd
# Vérifier la version
~/.local/bin/argocd version --client
Création d'un alias pour simplifier (dans ~/.zshrc) :
alias argocd="~/.local/bin/argocd --grpc-web"
Le flag --grpc-web évite les warnings gRPC.
Étape 6 : Connexion du CLI au serveur
argocd login argo.home-fonta.fr --username admin --password MOT_DE_PASSE --insecure
Note : --insecure car certificat auto-signé pour l'instant.
Vérification :
argocd cluster list
Résultat :
SERVER NAME VERSION STATUS MESSAGE
https://kubernetes.default.svc in-cluster Unknown Cluster has no applications...
Parfait ! ArgoCD est connecté au cluster K3s.
Configuration SSH pour Git (Sécurité)
ArgoCD a besoin d'accéder à mon repository GitHub pour lire les manifests. Deux options :
- HTTPS avec token
- SSH avec clé privée
J'ai choisi SSH pour plus de sécurité.
Principe : Clé SSH dédiée (Least Privilege)
Mauvaise pratique : Utiliser ma clé SSH personnelle
- Si le cluster est compromis, l'attaquant a accès à TOUS mes repos GitHub
Bonne pratique : Créer une clé SSH dédiée pour ArgoCD
- Accès en lecture seule
- Limitée à UN seul repository
- Révocation facile sans impacter mes autres accès
Création de la paire de clés
ssh-keygen -t ed25519 -C "argocd@home-fonta-k3s" -f ~/.ssh/argocd_k3s -N ""
Paramètres :
-t ed25519: Type de clé moderne, sécurisé, compact-C "argocd@home-fonta-k3s": Commentaire pour identifier la clé-f ~/.ssh/argocd_k3s: Nom du fichier-N "": Pas de passphrase (ArgoCD doit pouvoir l'utiliser automatiquement)
Résultat : 2 fichiers créés
~/.ssh/argocd_k3s(privée)~/.ssh/argocd_k3s.pub(publique)
Ajout de la Deploy Key sur GitHub
Affichage de la clé publique :
cat ~/.ssh/argocd_k3s.pub
Exemple de sortie :
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAINJOPsG8SCftgMbQYyooLxbpV8VWBlYpC4NRV01DsUpW argocd@home-fonta-k3s
Sur GitHub :
- Aller sur
https://github.com/Nikob2o/ansible-k3s/settings/keys - Cliquer sur "Add deploy key"
- Titre :
ArgoCD K3s Cluster - Read Only - Clé : Coller la clé publique complète
- IMPORTANT : NE PAS cocher "Allow write access" (lecture seule)
- Cliquer sur "Add key"
Deploy Key vs SSH Key personnelle :
- Deploy Key = Liée à UN repository spécifique
- SSH Key = Liée à votre compte (accès à tous vos repos)
Création du Secret Kubernetes
ArgoCD a besoin de la clé privée pour se connecter à GitHub :
kubectl create secret generic argocd-repo-ssh-key \
--from-file=sshPrivateKey=~/.ssh/argocd_k3s \
-n argocd
Vérification :
kubectl get secret argocd-repo-ssh-key -n argocd
Résultat :
NAME TYPE DATA AGE
argocd-repo-ssh-key Opaque 1 10s
Connexion du repository à ArgoCD
argocd repo add git@github.com:Nikob2o/ansible-k3s.git \
--ssh-private-key-path ~/.ssh/argocd_k3s
Résultat :
Repository 'git@github.com:Nikob2o/ansible-k3s.git' added
Vérification :
argocd repo list

Le repository est connecté ! ArgoCD peut maintenant lire mes manifests Kubernetes depuis Git.
Structure du repository
Pour ArgoCD, j'ai organisé mon repository ainsi :
ansible-k3s/
├── argocd-apps/ # Définitions des Applications ArgoCD
│ └── applications/ # Applications individuelles (utilisé par App of Apps)
│ ├── home-fonta.yaml
│ ├── ghost.yaml
│ ├── infrastructure.yaml
│ └── external-services.yaml
├── helm-charts/ # Helm charts
│ ├── homefonta/
│ ├── ghost/
│ ├── infrastructure/
│ └── external-services/
└── manifests/ # Manifests Kubernetes bruts
├── 01-external-services/
└── 02-argocd/
État après l'installation
À ce stade, j'avais :
- ArgoCD installé et accessible via
https://argo.home-fonta.fr(via port-forward) - CLI ArgoCD configuré
- Repository Git connecté en SSH (lecture seule)
- Structure de fichiers prête pour GitOps
Problèmes en suspens :
- Certificat SSL sur l'Ingress ArgoCD (secret pas dans le bon namespace)
- Aucune application encore déployée via ArgoCD
Dans la prochaine partie, on va :
- Résoudre le problème de certificat avec Reflector
- Créer notre première Application ArgoCD
- Tester le workflow GitOps complet
- Migrer toutes les applications vers ArgoCD
Concepts clés appris
Sécurité SSH et principe de moindre privilège
Une clé par service : Chaque service (ArgoCD, CI/CD, etc.) doit avoir sa propre clé SSH, avec les permissions minimales nécessaires.
Si une clé est compromise, seul ce service est impacté, pas tous vos accès.
Secrets Kubernetes et isolation par namespace
Les Secrets Kubernetes ne sont accessibles que dans leur namespace. C'est une feature de sécurité (compartimentage), pas un bug.
Solutions pour partager un Secret entre namespaces :
- Copie manuelle (fastidieux, pas automatique au renouvellement)
- Outils de réplication : Reflector, Kubed (automatique)
TLS Termination vs SSL Passthrough
TLS Termination (ce que j'utilise) :
Client --[HTTPS]--> Ingress --[HTTP]--> Service
^
Certificat Let's Encrypt
Avantages :
- Certificat centralisé (Let's Encrypt)
- Un seul point de gestion TLS
- Inspection et logging possibles au niveau Ingress
SSL Passthrough :
Client --[HTTPS chiffré]--> Ingress --[HTTPS chiffré]--> Service
^
Certificat du service
Avantages :
- End-to-end encryption
- Le service contrôle son propre certificat
GitOps : Le paradigme déclaratif
Impératif (avant) :
kubectl apply -f deployment.yaml
kubectl scale deployment my-app --replicas=3
helm upgrade my-app ./chart
Problèmes :
- Pas d'historique
- Pas de source de vérité
- Dérive de configuration inévitable
Déclaratif (GitOps) :
# Je modifie values.yaml dans Git
git commit -m "Scale to 3 replicas"
git push
# ArgoCD détecte et applique automatiquement
# Aucune commande kubectl nécessaire
Avantages :
- Git = source de vérité unique
- Historique complet (qui, quoi, quand, pourquoi)
- Rollback facile (git revert)
- Code review (Pull Requests)
- Pas de dérive (auto-correction)
Prochaine partie
Dans la Partie 7, on va :
- Installer Reflector pour répliquer le certificat wildcard
- Créer notre première Application ArgoCD (home-fonta)
- Tester la synchronisation automatique Git vers Kubernetes
- Migrer Ghost, Infrastructure et External Services
- Implémenter le pattern "App of Apps"
- Sécuriser les secrets avec SealedSecrets
Le voyage GitOps continue...
Suite : Partie 7 - ArgoCD en action : Déploiement et GitOps