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

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 - 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

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

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 !