GitOps sur OVHcloud Managed Kubernetes : une installation Argo CD prête pour la production
← Retour au blogKubernetes & Conteneurs

GitOps sur OVHcloud Managed Kubernetes : une installation Argo CD prête pour la production

14 juillet 20268 min de lectureKubernetesOVHcloudArgoCD

Guide pratique du GitOps sur OVHcloud Managed Kubernetes avec Argo CD : bootstrap Terraform, app-of-apps, ingress et SSO, secrets, ApplicationSet multi-région et pièges opérationnels.

Faire du GitOps sur un hyperscaler est un terrain balisé. Le faire sur OVHcloud Managed Kubernetes Service (MKS) est un exercice légèrement différent : le control plane est gratuit et entièrement managé, mais vous disposez de moins de services annexes managés que sur EKS ou GKE. C'est en réalité une bonne nouvelle pour Argo CD : cela pousse vers une stack de plateforme qui vit intégralement dans Git, reste portable, et n'est pas soudée à l'IAM et au gestionnaire de secrets d'un fournisseur unique.

Cet article couvre le chemin concret : ce qu'il faut savoir de MKS avant d'installer quoi que ce soit, comment bootstrapper Argo CD de façon reproductible, comment l'exposer et le sécuriser, et les pièges opérationnels qui apparaissent trois mois plus tard.

Ce que MKS vous donne — et ce qu'il ne vous donne pas

OVHcloud opère le control plane sans surcoût ; vous payez les nœuds workers, les load balancers, le stockage bloc et la sortie réseau. Avant de concevoir votre couche GitOps, intégrez quelques points structurants :

  • Pas d'accès au control plane. Pas d'etcd, pas de flags sur l'API server, pas de configuration d'admission au niveau du kube-apiserver. Tout ce que vous voulez imposer doit tourner dans le cluster (Kyverno, Gatekeeper) ou avant le cluster (Argo CD, contrôles de politique en CI).
  • CNI managé. OVHcloud provisionne le plugin réseau. Ne prévoyez pas de le remplacer : concevez vos NetworkPolicies pour ce que le cluster embarque réellement.
  • Du stockage bloc, par défaut. La StorageClass par défaut s'appuie sur Cinder et est ReadWriteOnce. Il n'existe pas de ReadWriteMany trivial. Si un workload a besoin d'un système de fichiers partagé, prévoyez du stockage objet compatible S3 ou un NAS dédié plutôt que d'espérer du RWX.
  • Un Service LoadBalancer provisionne un vrai load balancer facturé. Chaque type: LoadBalancer est une ressource avec un délai de provisioning. Un seul ingress controller derrière un seul LB, pas quinze.
  • Le node pool est l'unité de capacité. Autoscaling, politique de mise à jour et anti-affinité se pilotent au niveau du pool, pas du cluster.

L'angle souveraineté compte également : pour des équipes soumises à des contraintes de résidence des données en Europe, pouvoir épingler chaque workload sur GRA, SBG, DE ou WAW tout en conservant la définition complète de la plateforme dans un dépôt Git auto-hébergé est souvent la finalité même du projet.

Bootstrap : Terraform pour le cluster, Argo CD pour le reste

Tracez une frontière nette. Terraform possède ce qui doit exister avant de pouvoir parler à Kubernetes : le cluster, les node pools, le réseau privé, les buckets objet, les zones DNS. Argo CD possède tout ce qui s'exprime en manifestes Kubernetes. Si vous brouillez cette frontière, deux contrôleurs se disputeront les mêmes objets.

resource "ovh_cloud_project_kube" "prod" {
  service_name       = var.project_id
  name               = "prod-gra"
  region             = "GRA11"
  version            = "1.31"
  private_network_id = data.ovh_cloud_project_network_private.vrack.id
  update_policy      = "MINIMAL_DOWNTIME"
}

resource "ovh_cloud_project_kube_nodepool" "workers" {
  service_name  = var.project_id
  kube_id       = ovh_cloud_project_kube.prod.id
  name          = "workers-general"
  flavor_name   = "b3-16"
  autoscale     = true
  min_nodes     = 3
  max_nodes     = 12
  desired_nodes = 3

  lifecycle {
    ignore_changes = [desired_nodes] # ce champ appartient à l'autoscaler
  }
}

Le bloc ignore_changes n'est pas optionnel. Sans lui, chaque terraform apply entrera en conflit avec le cluster autoscaler et redescendra votre cluster de production.

Installez ensuite Argo CD une seule fois, via Helm, depuis Terraform — puis n'y touchez plus jamais à la main :

resource "helm_release" "argocd" {
  name             = "argocd"
  namespace        = "argocd"
  create_namespace = true
  repository       = "https://argoproj.github.io/argo-helm"
  chart            = "argo-cd"
  version          = var.argocd_chart_version
  values           = [file("${path.module}/values/argocd.yaml")]
}

La dernière étape du bootstrap est une unique Application racine qui pointe vers votre dépôt Git : le motif app-of-apps. À partir de là, Argo CD gère le reste de la plateforme, y compris sa propre release Helm.

apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: root
  namespace: argocd
spec:
  project: platform
  source:
    repoURL: https://git.interne.acme.eu/platform/gitops.git
    targetRevision: main
    path: clusters/prod-gra
  destination:
    server: https://kubernetes.default.svc
    namespace: argocd
  syncPolicy:
    automated:
      prune: true
      selfHeal: true
    syncOptions:
      - CreateNamespace=true
      - ServerSideApply=true

ServerSideApply=true mérite d'être souligné. Les charts embarquant de gros CRD — cert-manager, kube-prometheus-stack, Gateway API — dépassent régulièrement la limite de taille des annotations utilisée par l'apply côté client. Activer le SSA au niveau de l'Application vous épargne une catégorie d'erreurs pénibles à diagnostiquer.

Exposer Argo CD sans ouvrir une brèche

Le schéma qui fonctionne sur MKS : un seul ingress controller en Service LoadBalancer, tout le reste derrière. Le serveur Argo CD tourne en --insecure (TLS terminé à l'ingress), cert-manager émet les certificats, et le challenge DNS-01 est résolu via un webhook communautaire pilotant l'API OVHcloud. Ce dernier point est déterminant pour les clusters privés, où le HTTP-01 n'est pas joignable depuis Internet.

# values/argocd.yaml (extrait)
configs:
  params:
    server.insecure: true
server:
  ingress:
    enabled: true
    ingressClassName: nginx
    hostname: argocd.platform.acme.eu
    tls: true
    annotations:
      cert-manager.io/cluster-issuer: letsencrypt-ovh-dns01
redis-ha:
  enabled: true
controller:
  replicas: 2

Ne vous arrêtez pas à l'ingress. Branchez Argo CD sur votre fournisseur d'identité en OIDC (Keycloak, Authentik ou l'IdP d'entreprise), désactivez le compte local admin une fois le SSO opérationnel, et mappez les groupes vers le RBAC Argo CD. Un mot de passe admin partagé dans un gestionnaire de mots de passe n'est pas un modèle de contrôle d'accès.

policy.csv: |
  g, equipe-plateforme, role:admin
  g, dev-paiements,     role:paiements-deployer
  p, role:paiements-deployer, applications, sync, paiements/*, allow
  p, role:paiements-deployer, applications, get,  paiements/*, allow

Matérialisez ensuite la frontière avec des AppProjects : restriction des dépôts sources, des namespaces de destination et des types de ressources cluster-scoped autorisés par projet. Sans AppProject, toute équipe capable de créer une Application peut déployer un ClusterRoleBinding.

Les secrets : la partie que l'on repousse

MKS ne fournit pas le couplage KMS/IAM profond que propose EKS avec IRSA. Deux approches fonctionnent bien en pratique.

SOPS avec des clés age est la plus simple : les valeurs chiffrées vivent dans Git, la clé de déchiffrement dans le cluster, et un plugin kustomize ou l'intégration SOPS d'Argo CD déchiffre au moment du rendu. Peu de pièces mobiles, fonctionne hors ligne, auditable. Le point faible reste la rotation et la révocation de clés.

External Secrets Operator passe mieux à l'échelle : les secrets restent dans un coffre (HashiCorp Vault auto-hébergé sur OVHcloud, ou équivalent), et Git ne contient que des références. Aucune donnée sensible n'atteint le dépôt, et la rotation est découplée des déploiements.

Quel que soit le choix, la règle est identique : Git contient des références ou du chiffré, jamais du clair. Et les credentials de dépôt d'Argo CD lui-même doivent être provisionnés par Terraform ou ESO, pas saisis dans l'interface.

Multi-cluster et multi-région avec ApplicationSet

OVHcloud rend économiquement indolore le fait d'exploiter plusieurs clusters, les control planes étant gratuits. Beaucoup d'équipes finissent avec une prod à GRA, un PRA à SBG ou en DE, plus un cluster de staging éphémère. Gérer cela en dupliquant des Applications ne tient pas ; ApplicationSet, si.

apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
  name: platform-addons
  namespace: argocd
spec:
  generators:
    - matrix:
        generators:
          - clusters:
              selector:
                matchLabels: { tier: production }
          - git:
              repoURL: https://git.interne.acme.eu/platform/gitops.git
              revision: main
              directories:
                - path: addons/*
  template:
    metadata:
      name: '{{path.basename}}-{{name}}'
    spec:
      project: platform
      source:
        repoURL: https://git.interne.acme.eu/platform/gitops.git
        targetRevision: main
        path: '{{path}}'
        helm:
          valueFiles:
            - values.yaml
            - 'values-{{metadata.labels.region}}.yaml'
      destination:
        server: '{{server}}'
        namespace: '{{path.basename}}'
      syncPolicy:
        automated: { prune: true, selfHeal: true }

Les fichiers de valeurs par région rendent explicites les différences régionales (noms de StorageClass, annotations de LB, zones DNS) au lieu de les enfouir dans de la logique de templating.

Argo CD ou Flux sur MKS ?

Les deux fonctionnent. Le choix relève de l'ergonomie d'équipe, pas de la compatibilité avec le fournisseur.

CritèreArgo CDFlux
UI / visualisation des diffsNative, réel moteur d'adoptionCLI d'abord, dashboards tiers
RBAC multi-tenantAppProjects + SSO, matureIsolation par namespace, plus manuelle
Empreinte ressourcesPlus lourde (controller, repo-server, Redis)Plus légère, petits contrôleurs
Fan-out multi-clustersHub-and-spoke, dimensionnement du hub à surveillerNaturellement par cluster
Déploiement progressifArgo RolloutsFlagger

Sur MKS en particulier, l'UI d'Argo CD est souvent décisive : faute de console cloud exposant l'état des déploiements, le dashboard Argo CD devient la surface de contrôle de la plateforme pour les développeurs.

Pièges opérationnels à anticiper

Mises à jour de cluster et drains. Les politiques de mise à jour MKS déterminent l'agressivité du recyclage des nœuds. Sans PodDisruptionBudget, une montée de version peut évincer les deux réplicas du controller Argo CD simultanément. Posez les PDB sur la stack plateforme avant d'en avoir besoin.

Argo CD qui se gère lui-même. Élégant, et piégeux. Un mauvais changement de values peut laisser le controller incapable de réconcilier le correctif. Conservez la release Helm pilotée par Terraform comme issue de secours, et gardez toujours un kubeconfig break-glass.

Pruning et ressources cluster-scoped. prune: true combiné à une Application mal scopée a déjà supprimé plus d'un jeu de CRD. Utilisez l'annotation Prune=false sur les CRD et les ressources porteuses de finalizers, et des sync waves pour ordonner namespaces, CRD puis workloads.

Sauvegardes. Le control plane est managé, mais vos objets ne sont pas sauvegardés pour vous. Faites tourner Velero avec le stockage objet compatible S3 d'OVHcloud comme cible, et snapshotez les volumes Cinder. Le GitOps restaure des manifestes, pas des données.

Dérive de coûts. Autoscaling plus GitOps rend l'ajout de workloads trivial. Suivez l'utilisation des node pools et le nombre de load balancers : les deux surprises de facture les plus fréquentes sur MKS sont les pools surdimensionnés et un LB par équipe.

Ce que vous obtenez au final

La combinaison MKS + Argo CD produit une plateforme dont la définition complète réside dans un dépôt que vous contrôlez, exécutée dans une région européenne que vous avez choisie, sans dépendance à un service de déploiement propriétaire. Reconstruire le cluster ailleurs devient un terraform apply suivi d'une Application racine — précisément la propriété recherchée quand la discussion porte sur la réversibilité ou la conformité.

Posez correctement les frontières — Terraform pour l'infrastructure, Argo CD pour les manifestes, un coffre pour les secrets, les AppProjects pour la tenancy — et le reste devient incrémental.

← Retour au blog