Dagger — une introduction
Ecrit par Arnaud Soulié, consultant DevOps.
Chirurgien sur votre CI pendant la journée, Arnaud écume le net et teste tout ce qui lui tombe sous la main à ses heures perdues.
Chez Les Filles et les Garçons de la Tech, on est évidemment des mordus de Tech. Dans notre petit univers, il y a quelques noms qui sont bien connus de la communauté. Lorsqu’on a eu vent que Solomon Hykes, Andrea Luzzardi et Sam Alba lançaient un nouveau projet, toute l’équipe a rushé le formulaire d’accès ! Voici une petite introduction sur Dagger, nouvel outil prometteur qui répond à un besoin croissant de simplification chez nos clients, et qui on l’espère vous excitera autant que nous !
Dagger se définit comme “la superglue devops”. Le but de l’outil est de fournir un moyen facile d’intégrer de l’outillage et de l’infrastructure à travers l’utilisation de composants.
Toute cette configuration se fait en arrière plan par des experts outils devops, permettant ensuite aux développeurs de bénéficier d’une couche d’abstraction facile d’utilisation en front.
Un déploiement se fait via une simple commande dagger up !
L’historique sur Github remonte à fin 2020, direction https://dagger.io/ pour rejoindre la communauté ! L’outil étant encore en bêta privée, le code et les terminologies expliquées ci-dessous sont susceptibles d’évoluer rapidement.
Intégration, DataFlow, Composition
Dagger intègre tous les outils, l’infrastructure, et les flux de données au sein d’un DAG,
Chaque nœud dans ce graphe représente une “intégration”. Une intégration peut représenter… pas mal de choses, et c’est là une des forces de Dagger : un CVS, des scripts, des APIs, des services d’infrastructure, de la CI/CD…
Imaginez tous les composants de votre workflow d’intégration et de déploiement découpés sous forme de nœuds dans ce graphe.
Chaque nœud peut produire ou consommer de la data. Dagger permet de gérer ces flux de données échangées de manière native sans forcément avoir besoin d’une infrastructure externe supplémentaire.
Pour configurer chaque partie de ce graphe, on utilise le langage CUE.
CUE (Configure Unify Execute), est un langage open source conçu pour l’automatisation. Il permet de définir, valider, ou générer toutes sortes de données.
C’est un superset de JSON, qui mériterait un futur article à lui tout seul… Vous pouvez vous faire une idée plus précise avec la documentation complète ici. L’excellent Cuetorials vous permettra de prendre Cue en main rapidement.
Composants
Dagger met en oeuvre les concepts suivants :
- L’Environnement, qui contient la configuration complète pour un déploiement donné. Une application peut contenir plusieurs environnements (staging, dev…).
- Le Plan contient le code source déclaratif du déploiement, en Cue.
- Les Entrées sont définies par le plan. Elles peuvent être des valeurs, des artefacts, ou même des secrets fournis par un utilisateur.
- Les Sorties, définies également dans le plan, fournissent des informations utiles en fin de déploiement.
Pour écrire notre plan, Dagger fournit tout un ensemble de librairies qui permettent de s’interfacer avec les outils du quotidien. La liste des packages disponibles est déjà conséquente et évolue constamment.
C’est grâce à ces packages que l’on va pouvoir interagir avec nos outils de build (go, maven, yarn…), nos containers et clusters (docker, compose, gcr, k8s, helm, kustomize…), nos outils d’iac (terraform), nos cloud providers (aws, gcp, azure…).
Chaque package fournit un ensemble d’APIs, avec une liste d’entrées et de sorties bien définies, qui permettent d’exécuter une action spécifique, par exemple :
Dagger va venir se positionner comme un couche d’abstraction de tous les composants de notre workflow habituel et va faire le lien entre eux.
Let’s GO !
Voici un DAG trivial qui va nous permettre de builder une simple application en Go, et mettre en évidence :
- le parallélisme des intégrations
- la gestion des dépendances
- la gestion du cache
Le code ci-dessous fait appel à plusieurs packages fournis par Dagger, entre autres :
- docker : pour puller l’environnement de lint Go
- go : pour récupérer un environnement de build tout prêt
Dagger permet de lister rapidement les entrées et sorties déjà prévues par notre plan :
Il nous suffit de fournir notre entrée pour localiser les sources à builder, et Dagger sera en mesure de dérouler notre plan :
Que voit-on d’intéressant ici dans la séquence des commandes exécutées?
- les étapes lint et run sont lancées en parallèle.
- l’étape test se lance une fois le run terminé : il y a bien un lien de dépendance entre les deux.
- une fois le plan terminé, Dagger affiche les outputs définis dans notre Cue.
Lors d’un second run consécutif au précédent, Dagger ne recalcule pas les steps qui n’en ont pas besoin. Seule une modification de nos sources ou de notre plan Cue vont par exemple trigger un rebuild et les tests.
Peu importe l’environnement dans lequel on lancera dagger up, le résultat sera le même, que ce soit à distance sur un environnement de CI dédié, ou sur un poste de développeur.
En arrière-plan, Dagger utilise buildkit. Ce dernier permet de builder et de packager du logiciel en utilisant des conteneurs. Grâce à buildkit, Dagger est très efficace sur sa gestion de cache et le parallélisme.
K8s
Mettons maintenant en œuvre la composition suivante : on veut simplement builder une image Docker à partir de nos sources, pusher celle-ci dans un registry, et déployer cette nouvelle image sur notre cluster K8s.
Il nous suffit ici de définir correctement nos quelques entrées :
- le chemin vers notre fichier kubeconfig
- le chemin vers notre dockerfile
- le registry docker dans lequel pusher notre image construite
- le chemin vers notre manifest K8s
Un simple dagger up permet encore une fois de dérouler notre composition et de déployer notre nouvelle image sur le cluster K8s cible :
Tout reste transparent du point de vue de l’utilisateur encore une fois. Dagger vient agir comme un wrapper qui permet de s’abstraire de la complexité des opérations sous-jacentes. L’utilisateur fournit simplement quelques valeurs d’entrée et l’outil fait le reste pour lui, sur la base du plan prédéfini.
Les avantages
- L’exécution d’un pipeline peut se faire n’importe où. Plus besoin de générer une pull-request ou autre sur un environnement spécifique, dagger up fonctionne partout, même en local.
- Dagger gère les dépendances automatiquement en fonction du contenu du plan, et parallélise ce qui peut l’être.
- Dagger est très rapide, notamment grâce à l’utilisation du backend buildkit et l’optimisation du cache.
- Dagger est basé sur l’utilisation de conteneurs : Docker est un des seuls prérequis pour faire tourner l’environnement.
Pour aller plus loin
Site officiel de Dagger : https://dagger.io/
Documentation officielle Cue : https://cuelang.org/docs/
Buildkit: https://blog.mobyproject.org/introducing-buildkit-17e056cc5317 , https://github.com/moby/buildkit