<img src="https://ad.doubleclick.net/ddm/activity/src=11631230;type=pagevw0;cat=pw_allpg;dc_lat=;dc_rdid=;tag_for_child_directed_treatment=;tfua=;npa=;gdpr=${GDPR};gdpr_consent=${GDPR_CONSENT_755};ord=1;num=1?" width="1" height="1" alt=""> Rationaliser GitOps : comment automatiser vos correctifs ArgoCD avec Renovate

Supprimez la corvée de maintenance de GitOps : comment automatiser vos correctifs ArgoCD avec Renovate

TABLE OF CONTENTS

    { content.featured_image.alt }}

    Alors que nous entreprenons tous ensemble le voyage vers l'alignement sur les principes de GitOps, je suis sûr que nous pouvons tous nous souvenir du moment où nous avons initialement utilisé ArgoCD pour déployer notre première application sur un cluster Kubernetes via GitOps. Chez Virtru, nous avons adoré la facilité avec laquelle GitOps a rendu la gestion des applications et la rapidité avec laquelle il nous a permis de bouger tout en gardant tous nos environnements continuellement synchronisés.

    Nous savons tous qu'après le premier déploiement, il y a cette hâte et ce besoin d'agir rapidement. Avant que vous ne le réalisiez, vous avez de nombreux composants déployés sur vos clusters, par exemple

    Il semble que chaque semaine, un nouvel outil vienne combler une lacune. Avoir toutes ces options est formidable, mais l'introduction de chacune d'entre elles ajoute à la liste croissante des composants à gérer.

    La sécurité est au cœur de Virtru, et lorsque vous travaillez dans une entreprise où c'est le cas, vous devez vous assurer que tous les composants que vous utilisez sont mis à jour en temps voulu. Cependant, nous ne voulons pas non plus introduire de problèmes dans l'environnement.

    Gérer un nombre toujours croissant de composants

    Prenons un peu de recul et réfléchissons à ce qu'il faut faire pour gérer chaque composant. Pour chaque composant, vous devez:

    • Surveiller en permanence les nouvelles versions
    • Examiner les notes de mise à jour pour détecter tout changement potentiel (en particulier pour les API dépréciées de Kubernetes).
    • Faire progresser lentement la nouvelle version à travers vos clusters de développement, de préparation et de production (généralement une semaine de rodage entre chaque environnement)

    Cela devient rapidement une responsabilité à plein temps pour un membre de l'équipe. Nous avions besoin de réduire une partie du labeur inutile de notre équipe chez Virtru.

    Typiquement, pour gérer les dépendances, vous pouvez vous tourner vers quelque chose comme Dependabot. Dans notre cas, nous avions besoin de quelque chose qui puisse gérer plus que les versions des paquets npm ou go typiques. Nous avions besoin de gérer les versions de nos cartes de barre définies dans une application ArgoCD ainsi que nos fournisseurs et modules Terraform.

    C'est pourquoi nous avons commencé à chercher dans la communauté pour voir s'il existait une technologie existante que nous pourrions exploiter ou décider si nous devions construire quelque chose par nous-mêmes.

    Et voilà, nous n'étions pas les seuls à penser à ce problème !

    Bienvenue dans le monde de Renovate

    Renovate est un outil permettant de gérer les mises à jour automatisées des dépendances. Il est open-source et s'intègre à divers systèmes de contrôle de version, dont GitHub et GitLab. Il y a deux façons d'installer Renovate : via l'application GitHub ou en auto-hébergement.

    Nous voulions avoir plus de contrôle sur la façon dont nous exécutons Renovate, et quelle version est déployée. Cela nous a limité à l'application auto-hébergée. Nous voulions l'exécuter dans Kubernetes. Renovate est disponible en tant que conteneur à partir de DockerHub ou vous pouvez aussi facilement construire votre propre image de conteneur en installant l'application à partir de NPM, qui est la route que nous avons choisie pour avoir le plus de contrôle sur la configuration de Renovate.

    Renovate est déployé dans les clusters Virtru comme un CronJob. Notre configuration est similaire aux exemples de la documentation officielle :

    apiVersion: v1
    kind: ConfigMap
    metadata:
    name: renovate-config
    namespace: renovate-test
    data:
    config.json: |-
     {
       "repositories": ["<your-org>/<your-repo-1>, <your-org>/<your-repo-2>"]
      }
    ---
    apiVersion: batch/v1beta1
    kind: CronJob
    metadata:
    name: renovate-bot
    namespace: renovate-test
    spec:
    schedule: "@hourly"
    concurrencyPolicy: Forbid
    jobTemplate:
      spec:
        template:
          spec:
            containers:
              - image: renovate/renovate:31.14.0
                name: renovate-bot
                env:
                  - name: RENOVATE_PLATFORM
                    value: "github"
                  - name: RENOVATE_AUTODISCOVER
                    value: "false"
                  - name: RENOVATE_BASE_DIR
                    value: "/tmp/renovate/"
                  - name: RENOVATE_CONFIG_FILE
                    value: "/opt/renovate/config.json"
                  - name: LOG_LEVEL
                    value: debug
                  - name: RENOVATE_TOKEN
                    valueFrom:
                      secretKeyRef:
                        key: github-token
                        name: renovate-secrets
                volumeMounts:
                  - name: config-volume
                    mountPath: /opt/renovate/
                  - name: work-volume
                    mountPath: /tmp/renovate/
            restartPolicy: Never
            volumes:
              - name: config-volume
                configMap:
                  name: renovate-config
              - name: work-volume
                emptyDir: {}

    Ce manifeste suppose que l'espace de noms Renovate contient un secret Kubernetes appelé renovate-secrets, avec la clé github-token et la valeur d'un jeton API GitHub valide. Les permissions du token doivent être repo read/write. Vous pouvez créer le secret comme suit :

    ❯ kubectl create -n renovate secret generic renovate-secrets
    --from-literal=github-token=<token>

    Aussi flexible qu'il soit, Renovate est facile à prendre en main. Il offre la découverte automatique des dépôts. Cependant, une plus grande organisation voudrait l'omettre, puisque cette fonctionnalité fait que Renovate s'exécute sur chaque dépôt auquel la clé API GitHub a accès. Une alternative à la découverte automatique est la directive repository list dans le fichier de configuration de Renovate. L'embarquement pour chaque dépôt est également automatisé. Renovate soumet des demandes de pull avec un fichier de configuration par défaut pour ce dépôt.

    La configuration la plus simple pour un dépôt GitHub privé ressemble à ceci :

    {
      "$schema": "https://docs.renovatebot.com/renovate-schema.json"
    }

    Ceci indique à Renovate d'utiliser la configuration par défaut, qui est un bon endroit pour commencer.

    Étiquettes de RP

    Vous pouvez également ajouter des étiquettes pour filtrer facilement les RP créés par Renovate :
    {
      "$schema": "https://docs.renovatebot.com/renovate-schema.json",
      "labels": ["renovate"]
    }

    Ainsi, tous les PR seront étiquetés comme "rénovés".

    Ignorer les chemins

    Ignorer certains chemins peut également être utile lorsqu'un projet comporte des parties qui ne sont pas prêtes à accepter des mises à jour. Par exemple, voici comment ignorer tout ce qui se trouve dans le dossier "/argocd/sandbox" :

    {
      "$schema": "https://docs.renovatebot.com/renovate-schema.json",
        "ignorePaths": [
          "argocd/sandbox/**"
        ]
    }

    Règles pour les paquets

    Spécifier des règles de paquetage personnalisées est crucial pour tout référentiel de taille décente. Ces règles indiquent à Renovate comment appliquer un élément de configuration à un certain nombre de fichiers/paquets sélectionnés. La cible peut être choisie en fonction d'un ensemble de sélecteurs, y compris le chemin et le gestionnaire.

    Parlons plus en détail des "managers", qui sont l'abréviation de "gestionnaires de paquets". Il s'agit notamment des gestionnaires de paquets traditionnels comme npm, Gradle et Bundle, ainsi que des formats de fichiers moins traditionnels, comme les Dockerfiles ou les manifestes ArgoCD. Les gestionnaires sont utilisés pour détecter et maintenir les fichiers dans un référentiel.

    En fait, la configuration minimale du projet ArgoCD nécessite l'utilisation des règles de paquetage personnalisées, car par défaut, le gestionnaire ArgoCD ne définit aucun modèle de correspondance de fichiers, et ne correspondra donc à aucun fichier tant que le modèle n'aura pas été configuré.

    {
      "$schema": "https://docs.renovatebot.com/renovate-schema.json",
      "packageRules": [
        {
          "matchManagers": [
            "argocd"
          ],
          "matchPaths": [
            "argocd/production/**",
            "argocd/development/**",
            "argocd/staging/**"
          ],
        }   
      ]
    }

    La configuration ci-dessus permettra de gérer les manifestes ArgoCD dans le projet avec la structure suivante :

    └── argocd
       ├── development
       ├── production
       └── staging

    Les règles personnalisées dans la liste des règles de paquetage ont une priorité plus élevée que les règles globales. De cette façon, vous pouvez redéfinir la configuration globale dans les règles personnalisées. Par exemple, vous pouvez écraser l'étiquette globale "green" pour tous les fichiers ArgoCD dans le chemin "argocd/production" :

    {
      "$schema": "https://docs.renovatebot.com/renovate-schema.json",
      "labels": ["green"],
      "packageRules": [
        {
          "matchManagers": [
            "argocd"
          ],
          "matchPaths": [
            "argocd/production/**"
          ],
         "labels": ["red"]
        },
        {
          "matchManagers": [
            "argocd"
          ],
          "matchPaths": [
            "argocd/staging/**",
            "argocd/development/**"
          ]
        }
      ]
    }

    L'exemple précédent illustre également la façon dont vous pouvez établir une correspondance sur la base de plusieurs facteurs. Dans ce cas, il s'agissait de managers et de chemins.

    Regroupement des mises à jour

    Il est parfois utile de regrouper certains des objets qui ont été mis en correspondance. Cela peut être réalisé à l'aide de la directive groupName. Toutes les mises à jour correspondantes partageant le nom du groupe seront placées dans la même branche et le même PR. Le regroupement de toutes les mises à jour de versions non majeures peut se faire comme suit :

    {
      "$schema": "https://docs.renovatebot.com/renovate-schema.json",
      "packageRules": [
        {
          "matchManagers": ["argocd"],
          "matchUpdateTypes": ["minor", "patch", "pin", "digest", "lockFileMaintenance", "rollback", "bump"],
          "groupName": "argocd non-major updates"
        },
        {
          "matchManagers": ["argocd"],
          "matchUpdateTypes": ["major"]    
        }
      ]
    }

    Planifications personnalisées

    Enfin, vous pouvez définir une planification personnalisée pour un référentiel. Ce paramètre était essentiel pour nous, et nous avons fini par l'activer pour chaque référentiel géré par renovate. Une planification basée sur le référentiel nous a permis de lancer renovate toutes les 15 minutes, sans nous soucier de faire tourner une quantité excessive de tâches CI/CD ou de créer d'autres activités indésirables déclenchées par des événements GitHub.

    Les syntaxes Cron et Later peuvent être utilisées pour configurer la planification. Certains préréglages sont également pris en charge. Quand une planification est utilisée, Renovate ne créera plus de nouveaux PRs. Cependant, vous devez désactiver la valeur updateNotScheduled afin d'activer les PRs existants.

    Voici un exemple de planning mensuel sans mise à jour des PRs existants :

    {
      "$schema": "https://docs.renovatebot.com/renovate-schema.json",
      "schedule": [
        "before 3am on the first day of the month"
      ],
      "updateNotScheduled": false
    }

    Conclusion

    Comme vous pouvez le voir, Renovate apporte une pléthore d'options de configuration et fournit la flexibilité dont toute équipe pourrait avoir besoin. 

    Renovate a aidé à résoudre cette première étape dans le processus de gestion du cycle de vie qui consiste à vérifier s'il y a une nouvelle version. En couplant étroitement les notes de version aux demandes de retrait, il est plus facile pour l'équipe de vérifier ce qui a changé. 

    Pour l'instant, tout ce qui suit Rénovation est encore manuel, mais nous prévoyons de franchir quelques étapes supplémentaires :

    • Possibilité de fusionner automatiquement les corrections d'errata.
    • Une suite de tests qui examinera les notes de version pour détecter les changements importants. 
    • Un calendrier de promotion automatisé vers différents environnements

    Gardez l'œil ouvert pour d'autres articles de la série Virtru Technical Series de l'équipe d'ingénierie de la plateforme Virtru, car nous continuons à explorer et à mettre en œuvre ces étapes supplémentaires.