Les connecteurs Lilt permettent à nos clients de conserver leurs contenus sur les systèmes qu'ils utilisent le plus (leurs articles de blog sur WordPress ou leurs wikis de support sur Zendesk, par exemple) et d'utiliser Lilt pour les traduire. Une fois le contenu importé dans Lilt, il est traduit, puis renvoyé au système de contenu d'origine. L'importation et l'exportation se font en toute facilité. Cette performance joue un rôle essentiel dans la mission que Lilt s'est donnée, celle de favoriser l'accès aux informations du monde entier.
Lilt propose actuellement des connecteurs pour plus de 15 systèmes différents. Nos clients s'appuient fortement sur les connecteurs Lilt dans leurs flux de localisation. En 2021, près de 90 % du contenu traduit sur la plateforme Lilt a été traité à l'aide d'un connecteur !
Notre architecture de connecteurs n'a pas toujours été conçue pour prendre en charge le volume incroyable qu'elle est en capacité de gérer actuellement. Dans cet article, nous vous expliquerons de quelle manière nous utilisons Argo Workflows pour faire évoluer la structure de connecteurs Lilt, notre plus grande offre à destination des entreprises à ce jour.
Aux premiers jours de Lilt, les connecteurs étaient implémentés chacun dans leur propre référentiel Github. Développés par différents ingénieurs, ils interagissaient avec Lilt de manières légèrement différentes et utilisaient des bases de données et des schémas distincts. Toute modification apportée à notre API impliquait une mise à jour de la base de code à plusieurs endroits. En outre, chaque connecteur avait son propre lot de bugs, tous difficiles à détecter et à corriger. Mettez-vous à la place d'un ingénieur qui devait maintenir plusieurs connecteurs... Aïe !
💡 Anecdote : Zendesk est le tout premier connecteur que nous avons lancé, début 2019.
Il était évident que ce modèle ne pouvait s'adapter au rythme auquel Lilt développait son offre de connecteurs. Nous avons donc unifié notre structure de connecteurs. Tout d'abord, nous avons centralisé le code. Ensuite, nous avons configuré les connecteurs de sorte qu'ils s'exécutent de la même manière, indépendamment du système connecté. Une fois le code mis dans un référentiel unique, nous avons commencé à utiliser des tâches Kubernetes natives pour gérer et exécuter toutes les tâches des connecteurs.
Par rapport à notre précédente structure, cela a représenté une grande avancée et un gain d'efficacité considérable. Ensuite, nous avons vu apparaître un nouveau type de problème d'échelle. Bien que Kubernetes, en lui-même, était fiable, nous avons fini par rencontrer des contraintes en termes de ressources, générant des problèmes de fiabilité.
- Les documents sont importés et exportés de Lilt selon un calendrier donné. Nous avions défini une configuration pour que le serveur de gestion exécute ce calendrier. Cependant, il arrivait souvent que Kubernetes programme trop de tâches à la fois (50 dans la même milliseconde), ce qui épuisait la mémoire du cluster et provoquait l'abandon et la perte de tâches.
- Les nouvelles tâches se retrouvaient bloquées et ne pouvaient pas être soumises en raison d'un manque de mémoire.
- Nous exécutions Kubernetes sur Google Kubernetes Engine (GKE) et le configurions pour générer des journaux d'application dans Stackdriver. Cependant, les journaux étaient mal organisés et portaient à confusion.
- Le filtrage manuel des journaux dans Stackdriver était chronophage et fastidieux, mais nécessaire pour déterminer la cause de l'échec des tâches.
- Kubernetes n'était pas optimisé pour le nettoyage de la mémoire. Nous devions nous-mêmes supprimer les tâches terminées et les pods, et nous devions implémenter un code distinct pour le nettoyage.
Face à ces problèmes, nous nous sommes retrouvés dans la même situation qu'à nos débuts. Nous avions besoin d'une meilleure solution. Sinon, impossible d'évoluer !
Nous avons évalué les solutions disponibles pour redimensionner notre architecture de connecteurs, notamment Airflow et Prefect, mais ces solutions ne prenaient pas en charge Kubernetes nativement. En définitive, nous voulions utiliser quelque chose en complément de Kubernetes. Argo Workflows prend en charge la gestion de l'orchestration de tâches basée sur des conteneurs pour Kubernetes. De plus, cette solution répondait à notre problème d'évolutivité grâce aux fonctionnalités suivantes :
- Par rapport à Stackdriver, Argo collecte plus d'informations sur chaque exécution, ce qui nous permet un débogage plus rapide des tâches défaillantes.
- Argo prend directement en charge l'enregistrement de journaux. Il ne nous restait plus qu'à préciser l'endroit où les sauvegarder.
- Argo tient un registre de l'historique de nos flux de travail. Ainsi, nous pouvions avoir encore plus de journaux et de visibilité.
- Grâce à Argo, nous pouvons régler le parallélisme. Si nous avons 100 tâches, Argo en effectue 5 à la fois. En outre, il exécute une tâche uniquement une fois que la précédente est terminée. Ainsi, notre système est considérablement plus fiable et nous ne faisons plus face aux problèmes de planification générés par une utilisation des tâches de Kubernetes seules.
- Argo utilise des cron workflows
en conjonction avec Kubernetes pour planifier et exécuter les tâches en fonction des ressources nécessaires. L'exécution de notre planificateur se fait directement via Argo.
- La mise à l'échelle se fait sans effort. Lorsque le volume augmente, il nous suffit d'augmenter les ressources de Kubernetes dans Google Cloud Platform (GCP) pour qu'Argo puisse les utiliser.
- Argo intègre des options de nettoyage de la mémoire pour gérer les tâches terminées.
- Argo est le « moteur de flux de travail pour Kubernetes », ce qui signifie que nous n'avons pas à passer d'un outil d'orchestration de conteneurs à un autre.
- Nous n'avions pas à modifier le code pour intégrer Argo à notre architecture. Nous pouvions ainsi continuer à l'exécuter à partir de notre référentiel centralisé.
- Les exigences d'installation étaient minimes. Nous avions uniquement besoin de spécifier la configuration du flux de travail Argo dans un fichier YAML
.
Depuis notre adoption d'Argo, nos services de connecteurs se composent désormais de trois composantes principales :
Le panneau connectors-admin est l'interface du serveur de gestion, qui permet aux utilisateurs d'exécuter des tâches. Le serveur de gestion se connecte à notre base de données et prend en charge les opérations CRUD sur les configurations et les tâches, par exemple : création/mise à jour de la configuration de connecteurs, suivi de la progression et de la sortie des journaux des tâches d'exécution. Le panneau connectors-admin donne accès à tout cela.
Argo est le serveur d'exécution connecté à un cluster Kubernetes local. Grâce à notre architecture améliorée, les tâches sont directement soumises du serveur de gestion à Argo au lieu de Kubernetes. Toutes les interactions avec Argo provenant du serveur de gestion se font via l'API REST d'Argo.
Bien que chaque connecteur soit différent, ils s'exécutent tous de la même manière. Pour les clients qui ont des exigences uniques quant à leur flux de travail de localisation, nous pouvons utiliser notre panneau connectors-admin pour contrôler la manière dont leur contenu est traité au moment de l'exécution des tâches et du transfert vers ou à partir de la plateforme Lilt.
Nous avons implémenté Argo Workflows au début de 2021. Son adoption a optimisé notre logiciel, qui a ainsi pu prendre en charge notre croissance spectaculaire, jusqu'au volume que nous traitons aujourd'hui. Le nombre de documents importés dans Lilt via un connecteur a augmenté de plus de 870 %. Nous prévoyons de voir ce chiffre augmenter à mesure que nous continuerons d'intégrer Argo à notre structure de connecteurs.