Gérer des clusters "presque" identiques en mode GitOps avec ArgoCD

Rémi Verchère @ Gravitek

Qui suis-je ?

👋 Rémi Verchère

💻 Cloud Native Infrastructure Consultant

  • Ops qui aide les Devs à mettre en prod

  • 🫶 Open Source & CNCF landscape

  • Kubestronaut, Cloud Native Aix-Marseille Orga

  • Papa x 👦👦👧👧

  • 🌐 @rverchere

Souvenez-vous, il y a 2 ans...

Plateformes Applis

Comment on déploie ?

  1. Depuis le manager OVHcloud, puis Helm pour les applis
  2. Terraform pour TOUT ⚠️ Fausse bonne idée
  3. Terraform pour bootstrap, puis Helm pour les applis
  4. Terraform pour bootstrap, GitOps - sur les applis "infras" ⬅️⬅️⬅️

                         

Kezako GitOps ?

GitOps

$ git push

GitOops 🤡

$ git push
$ paf la prod ^^

GitOps - Définition

➡️ 📚 https://enix.io/fr/blog/gitops/

  • Source of truth : git

  • Automatisation

    • Push
    • Pull
  • Outil pour "GitOps Pull"

    • Flux
    • ArgoCD

➡️ 📚 https://une-tasse-de.cafe/blog/argocd/

ArgoCD - Généralités

center

ArgoCD - Généralités

Ressources gérées

  • Applications: Ressource Kubernetes représentant une instance d'application déployée dans un environnement
    • Manifests
    • Kustomize
    • Helm Charts
    • App of Apps
  • ApplicationSets: Création d'Applications à partir d'un générateur et template
  • Projects: Groupe logique d'applications
  • Repositories, Clusters, etc.

ArgoCD - Généralités

apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: forge-logicielle-dev-helm-maintenance
  namespace: argocd
spec:
  destination:
    namespace: maintenance
    server: https://forge-logicielle-dev
  source:
    helm:
      releaseName: maintenance
    path: resources/helm-charts/versions/1.33/maintenance/
    repoURL: https://github.com/gravitek-io/argocd-demo.git
    targetRevision: 1.1.0
  syncPolicy:
    - [...]

ArgoCD - Généralités

center

ArgoCD - Généralités

center

ArgoCD - Généralités

center

ArgoCD - En Prod

center

Reprenons au début
Comment j'en suis arrivé jusque là ?

GitOps 💖

Mes Contraintes / Besoins

  • Gestion des applis "infra" communes
  • Intégration des clusters existants 🥵
    • Charts Helm déployés avec configuration, nom de release & namespace différents
  • Environnements dev & prod
  • Versions différentes de clusters
    • 1 version d'appli pour 1 version k8s
  • Faible dépendance à l'outil ArgoCD
  • Automatisation des upgrades
fill

Mes Contraintes / Besoins -> Challenges

Ré-ordonnés pour la présentation

Problème Solution Status
1. Configuration différente, hiérarchique
- Version k8s, Environnement dev/prod, Cluster
❓
2. Faible dépendance à l'outil ArgoCD ❓
3. Intégration des clusters existants
- Nom de release helm, Namespaces différents
❓
4. Automatisation des upgrades ❓

💡 Environnement de démo

  • 4 clusters Talos, localement sur Docker 🐳
    • 1 "Management" ArgoCD - talos-argocd-manager
    • 1 Dev - talos-argocd-1
    • 1 Prod - talos-argocd-2
    • 1 Prod mais pas trop talos-argocd-3
  • 3 Applications déployées
    • Goldilocks ⭐
    • Cert Manager ⭐⭐
    • Nginx ⭐⭐⭐
  • Code dispo sur Github: https://github.com/gravitek-io/argocd-demo

Challenges

Problème Solution Status
1. Configuration différente, hiérarchique
- Version k8s, Environnement dev/prod, Cluster
❓
2. Faible dépendance à l'outil ArgoCD ❓
3. Intégration des clusters existants
- Nom de release helm, Namespaces différents
❓
4. Automatisation des upgrades ❓

#0 - Source Of Truth : Git

Git

Gros travail de réflexion pour répondre à l'ensemble mes problématiques.

Structure

  • 1 seul dépôt pour toutes les applications infra
  • Pas de branches (yet), tout sur main
  • Gestion des configuration par arborescence avec dossiers / héritage

ArgoCD

  • ArgoCD
    • App-Of-Apps : 1 appli ArgoCD qui déploie d'autres applis ArgoCD
    • ApplicationSets : template d'appli ArgoCD pour chaque cluster (générateur)
  • Ressources déployées : (helm charts, manifests)

Git - Apps ArgoCD

❯ tree
.
├── argocd
│   └── applications
│       ├── app-of-apps
│       │   └── infra-apps.yaml # App Of Apps
│       └── infra # ApplicationSets
│           ├── 00-mon-app-helm.yaml # Chart Helm
│           ├── 01-goldilocks-helm.yaml
│           ├── 02-cert-manager-helm.yaml
│           └── 03-ingress-nginx-helm.yaml
└── resources
    └ [...]

Git - Ressources

$ tree resources
└── helm-charts
    ├── versions
    │   ├── 1.33
    │   │   └── mon-app
    │   │       └── values.yaml # 1) Version Kubernetes
    │   └── 1.34
    │       └── mon-app
    │           └── values.yaml
    ├── environments
    │   └── development
    │       └── mon-app
    │           └── values.yaml # 2) Environnement
    └── clusters
        └── talos-argocd-1
            └── mon-app
                └── values.yaml # 3) Cluster

#1 - 🤘 Highway to (AppSets) Helm 🤘

Exemple avec Goldilocks ⭐

⚠️ WARNING - Beaucoup de YAML ⚠️

Y aura un "tout petit" peu de JSON quand même

ArgoCD - ApplicationSet (1/3)

apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
  name: goldilocks
spec:
  generators:
    - clusters:
        values:
          # Kubernetes version : 1.33, 1.34, ...
          clusterVersion: '{{ metadata.labels.argocd.argoproj.io/kubernetes-version }}'
          # Kubernetes environment: development, production
          clusterType: '{{ metadata.labels.argocd.argoproj.io/cluster-type }}'
        selector:
          matchLabels:
            argocd.argoproj.io/secret-type: 'cluster'
  template:
[...]

ArgoCD - Cluster Labels

apiVersion: v1
kind: Secret
data:
  config: [...]
  name: talos-argocd-1 | base64
  server: https://172.30.0.111:6443 | base64
metadata:
  labels:
    argocd.argoproj.io/kubernetes-version: "1.33"
    argocd.argoproj.io/cluster-name: talos-argocd-1
    argocd.argoproj.io/cluster-type: development
    argocd.argoproj.io/secret-type: cluster

ArgoCD - ApplicationSet (2/3)

[...]
template:
  metadata:
    name: '{{ name }}-helm-goldilocks'
    namespace: 'argocd'
  spec:
    project: 'default'
    destination:
      server: '{{ server }}'
      namespace: 'goldilocks'
    sources:
      - repoURL:  https://charts.fairwinds.com/stable
        chart: goldilocks
        targetRevision: 9.0.2
        helm:
          releaseName: goldilocks
          valueFiles:
            - [...]

ArgoCD - ApplicationSet (3/3)

    [...]
    valueFiles:
      - '$values/[...]/versions/{{ values.clusterVersion }}/goldilocks/values.yaml'
      - '$values/[...]/environments/{{ values.clusterType }}/goldilocks/values.yaml'
      - '$values/[...]/clusters/{{ name }}/goldilocks/values.yaml'
    ignoreMissingValueFiles: true
- repoURL: 'https://github.com/gravitek-io/argocd-demo.git'
  targetRevision: HEAD
  ref: values

ArgoCD - ApplicationSet

center

ArgoCD - Application Helm

apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: talos-argocd-1-helm-goldilocks
spec:
  destination:
    namespace: goldilocks # Namespace de destination
  sources:
  - repoURL: https://charts.fairwinds.com/stable # URL du chart
    chart: goldilocks # Nom du chart
    targetRevision: 9.0.2 # Version du chart
    helm:
      releaseName: goldilocks # Nom de la release du chart
      valueFiles:
        - $values/resources/helm-charts/versions/1.33/goldilocks/values.yaml # 1)
        - $values/resources/helm-charts/environments/development/goldilocks/values.yaml # 2)
        - $values/resources/helm-charts/clusters/talos-argocd-1/goldilocks/values.yaml # 3)
      ignoreMissingValueFiles: true
  - ref: values # Pour récupérer les values
    repoURL: https://github.com/gravitek-io/argocd-demo.git

Démo (enfin) !

 

center

Challenges

Problème Solution Status
1. Configuration différente, hiérarchique
- Version k8s, Environnement dev/prod, Cluster
ApplicationSets Helm ✅
2. Faible dépendance à l'outil ArgoCD ❓
3. Intégration des clusters existants
- Nom de release helm, Namespaces différents
❓
4. Automatisation des upgrades ❓

Challenges

Problème Solution Status
1. Configuration différente, hiérarchique
- Version k8s, Environnement dev/prod, Cluster
ApplicationSets Helm ✅
2. Faible dépendance à l'outil ArgoCD ❓
3. Intégration des clusters existants
- Nom de release helm, Namespaces différents
❓
4. Automatisation des upgrades ❓

#2 - Umbrella Charts

Exemple avec Cert-Manager ⭐⭐

ArgoCD - Umbrella Charts

Avant : information du chart helm dans l'application ArgoCD directement 👎

kind: Application
spec:
  destination: 
    namespace: cert-manager # Namespace de destination
  sources:
  - repoURL: https://charts.jetstack.io # URL du chart
    chart: cert-manager # Nom du chart
    targetRevision: 1.17.2 # Version du chart
    helm:
      releaseName: cert-manager # Nom de la release du chart
  [...]
$ helm repo add jetstack https://charts.jetstack.io
$ helm install cert-manager jetstack/cert-manager --version 1.17.2

ArgoCD - Umbrella Charts

Après : information du chart helm en dehors de l'application ArgoCD 👍

# Chart.yaml
apiVersion: v2
name: helm-cert-manager
type: application
version: "1.33.0"    # Indicatif - Version du cluster                      
appVersion: "1.0"    # Indicatif - Chart principal "vide"

dependencies:
- name: cert-manager
  version: v1.17.2
  repository: https://charts.jetstack.io
$ helm dependency build && helm install ./

➡️ https://akuity.io/blog/argo-cd-helm-values-files

ArgoCD - Umbrella Charts

⚠️ Fichier values.yaml

Avant

# values.yaml
installCRDs: true

Après

# values.yaml
cert-manager: # Dependencies
  installCRDs: true

ArgoCD - Application & Umbrella Charts

apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: talos-argocd-1-helm-cert-manager
spec:
  destination:
    namespace: cert-manager
    server: https://172.30.0.111:6443
  project: default
  source:
    repoURL: https://github.com/gravitek-io/argocd-demo.git
    path: resources/helm-charts/versions/1.33/cert-manager/ #1)
    helm:
      releaseName: cert-manager
      valueFiles:
      - ../../../environments/development/cert-manager/values.yaml # 2)
      - ../../../clusters/talos-argocd-1/cert-manager/values.yaml # 3)
      ignoreMissingValueFiles: true

ArgoCD - Application & Umbrella Charts

  • Tout est défini dans le dépôt Git/Resources:

    • Chart.yaml: chart helm, version, url
    • values.yaml valeurs par défaut, hiérarchie
  • Possibilité de deployer sans ArgoCD

  • Référence aux différentes values.yaml du même dépôt Git

# resources/helm-charts/versions/1.33/cert-manager
$ helm dependency-build
$ helm template cert-manager ./ \
  --namespace cert-manager \
  -f ../../../environments/development/cert-manager/values.yaml \
  -f ../../../clusters/talos-argocd-1/cert-manager/values.yaml \
  --no-hooks | kubectl diff -f -
$

Demo

 

center

Challenges

Problème Solution Status
1. Configuration différente, hiérarchique
- Version k8s, Environnement dev/prod, Cluster
ApplicationSets Helm ✅
2. Faible dépendance à l'outil ArgoCD Umbrella Charts ✅
3. Intégration des clusters existants
- Nom de release helm, Namespaces différents
❓
4. Automatisation des upgrades ❓

Challenges

Problème Solution Status
1. Configuration différente, hiérarchique
- Version k8s, Environnement dev/prod, Cluster
ApplicationSets Helm ✅
2. Faible dépendance à l'outil ArgoCD Umbrella Charts ✅
3. Intégration des clusters existants
- Nom de release helm, Namespaces différents
❓
4. Automatisation des upgrades ❓

#3 - Git Generator & MergeKeys

Exemple avec Ingress Nginx (ou Nginx Ingress je sais plus) ⭐⭐⭐

ArgoCD - Charts Helm & Labels

Nom de release différente, Namespaces différents: Labels ? 🚫
Trop spécifique au chart helm, doit être dans le dépôt Git.

kind: Secret
metadata:
  labels:
    argocd.argoproj.io/kubernetes-version: "1.33"
    argocd.argoproj.io/cluster-name: talos-argocd-1
    argocd.argoproj.io/cluster-type: development
    argocd.argoproj.io/secret-type: cluster
    argocd.argoproj.io/ns-helm-nginx: nginx-ingress
    argocd.argoproj.io/ns-release-nginx: nginx-ingress
    argocd.argoproj.io/ns-helm-goldilocks: goldilocks
    argocd.argoproj.io/ns-release-goldilocks: glock
    [...]
  • Namespace & Release Helm pas dans fichier Chart.yaml 🥲

ArgoCD - Git Generator & MergeKeys

➡️ https://argo-cd.readthedocs.io/en/latest/operator-manual/applicationset/Generators-Git/#git-generator-files

ArgoCD - Git Generator & MergeKeys

kind: ApplicationSet
spec:
  generators:
    - merge:
        mergeKeys:
          - name
        generators:
          - clusters:
              values:
                helmChartName: 'ingress-nginx'
                # Can be different from a cluster to another
                helmReleaseName: 'ingress-nginx'
                # Can be different from a cluster to another
                namespace: 'ingress-nginx'
                [...]
          - git:
              repoURL: 'https://github.com/gravitek-io/argocd-demo.git'
              files:
                - path: 'resources/helm-charts/clusters/*/ingress-nginx/params.json'

ArgoCD - Git Generator & MergeKeys

Enfin du JSON !!

// resources/helm-charts/clusters/talos-argocd-3/ingress-nginx/params.json
{
  "name": "talos-argocd-3",
  "values": {
    "namespace": "incorrect-nginx",
    "helmReleaseName": "incorrect-nginx"
  }
}

ArgoCD - Git Generator & MergeKeys

center

ArgoCD - Git Generator & MergeKeys

template:
    metadata:
      name: '{{ name }}-helm-{{ values.helmChartName }}'
      namespace: 'argocd'
    spec:
      destination:
        server: '{{ server }}'
        namespace: '{{ values.namespace }}' # <--- ICI
      source:
        repoURL: 'https://github.com/gravitek-io/argocd-demo.git'
        targetRevision: 'HEAD' #  <--- ON POURRAIT LA AUSSI
        path: 'resources/helm-charts/versions/{{ values.clusterVersion }}/{{ values.helmChartName }}/'
        helm:
          releaseName: '{{ values.helmReleaseName }}' #  <--- LA
          valueFiles:
            - '../../../environments/{{ values.clusterType }}/{{ values.helmChartName }}/values.yaml'
            - '../../../clusters/{{ name }}/{{ values.helmChartName }}/values.yaml'

Demo

 

center

Challenges

Problème Solution Status
1. Configuration différente, hiérarchique
- Version k8s, Environnement dev/prod, Cluster
ApplicationSets Helm ✅
2. Faible dépendance à l'outil ArgoCD Umbrella Charts ✅
3. Intégration des clusters existants
- Nom de release helm, Namespaces différents
Git Generator & MergeKeys ✅
4. Automatisation des upgrades ❓

Challenges

Problème Solution Status
1. Configuration différente, hiérarchique
- Version k8s, Environnement dev/prod, Cluster
ApplicationSets Helm ✅
2. Faible dépendance à l'outil ArgoCD Umbrella Charts ✅
3. Intégration des clusters existants
- Nom de release helm, Namespaces différents
Git Generator & MergeKeys ✅
4. Automatisation des upgrades ❓

#4 - auto-label-cluster-info & Renovate

auto-label-cluster-info

  • Met à jour automatiquement le label de la version k8s du cluster
  • Bascule automatique sur les bonnes versions de charts helm 💪
[...]
metadata:
  labels:
    # Génère automatiquement kubernetes-version
    argocd.argoproj.io/auto-label-cluster-info: "true"
    argocd.argoproj.io/kubernetes-version: "1.33"
    argocd.argoproj.io/cluster-name: talos-argocd-1
    argocd.argoproj.io/cluster-type: development
    argocd.argoproj.io/secret-type: cluster

Renovate -> Mend

center

Renovate -> Mend

center

Demo

 

center

Challenges

Problème Solution Status
1. Configuration différente, hiérarchique
- Version k8s, Environnement dev/prod, Cluster
ApplicationSets Helm ✅
2. Faible dépendance à l'outil ArgoCD Umbrella Charts ✅
3. Intégration des clusters existants
- Nom de release helm, Namespaces différents
Git Generator & MergeKeys ✅
4. Automatisation des upgrades auto-label-cluster-info & Renovate ✅

Challenges

Problème Solution Status
1. Configuration différente, hiérarchique
- Version k8s, Environnement dev/prod, Cluster
ApplicationSets Helm ✅
2. Faible dépendance à l'outil ArgoCD Umbrella Charts ✅
3. Intégration des clusters existants
- Nom de release helm, Namespaces différents
Git Generator & MergeKeys ✅
4. Automatisation des upgrades auto-label-cluster-info & Renovate ✅

ArgoCD - Challenges relevés!

center

La suite ...

Axes d'amélioration

  • Git Generator / Labels : on peut faire mieux
  • Exclusion des apps
  • Multi sources (mauvaise gestion < v2.14, je crois)
  • Mettre le chart helm complet dans Git
    (si jamais il disparait upstream)

Ressources

💗 Remerciements

Volcamp & Sponsors 🚀

center

OpenFeedback

center

Merci !

Rémi Verchère @ Gravitek

Abstract: ArgoCD est un outil parmi d’autres permettant de déployer des applications en mode GitOps sur Kubernetes. Il est d’autant plus efficace lorsqu’on gère une flotte de clusters, pour avoir un parc cohérent. Sauf que parfois, lorsqu’on reprend une infra existante, tout n’a pas été déployé à l’identique 🤷‍♂️. Je vous propose alors un retour d’expérience sur la mise en place d’ArgoCD pour gérer des clusters “presque” identiques, ou le mot “presque” à son importance 😅. Après une brève introduction de l’outil, nous verrons ensemble comment il a été déployé, et surtout comment ont été structurés les dépôts Git pour résoudre les problématiques suivantes : Environnements dev & prod Versions différentes de clusters Charts Helm déployés avec configuration, nom de releases & namespaces différents Intégration avec Renovate Faible dépendance à l’outil ArgoCD Le tout sera accompagné de démo pour valider les solutions proposées. Il existe une multitude de possibilités de mise en place du GitOps. Cette présentation est un exemple d’implémentation répondant à mon besoin, qui pourra correspondre à tout ou partie au vôtre !

Gestion des modules, trop peu utilisé vs maintenance code, templating helm over tf