Comment nous optimisons la vitesse de CircleCI et réduisons nos délais de construction de …


Sam Rubin

Le réglage d’un serveur d’intégration continue présente un défi intéressant: les ingénieurs d’infrastructure doivent trouver un équilibre entre la vitesse de construction, le coût et les temps de file d’attente dans un système sur lequel de nombreux développeurs n’ont pas une expérience étendue de la gestion à grande échelle. Les résultats, lorsqu'ils sont correctement effectués, peuvent constituer un avantage considérable pour votre entreprise, comme en témoigne le récent voyage que nous avons effectué pour améliorer notre configuration de CI.

Au fur et à mesure de la croissance de Coinbase, la satisfaction de nos développeurs avec nos outils internes a été une priorité. Pendant la majeure partie de l'histoire de Coinbase, nous avons utilisé le serveur CircleCI, un outil performant nécessitant peu de maintenance. Cependant, à mesure que la société et notre code de base se développaient, les exigences de notre serveur CI augmentaient également. Avant les optimisations décrites ici, les compilations pour l’application de monorail exécutant Coinbase.com augmentaient considérablement (doublant ou triplant les temps de construction moyens antérieurs) et les développeurs se plaignaient généralement des compilations longues ou inachevées.

Nos compilations CI ne répondaient plus à nos attentes et, ayant à l’esprit les problèmes susmentionnés, nous avons décidé de nous lancer dans une campagne visant à remettre notre configuration en forme.

Il convient de souligner ici que Coinbase utilise spécifiquement la version du serveur CircleCI local au lieu de son offre cloud: héberger notre propre infrastructure est important pour des raisons de sécurité, et ces concepts s’appliquent spécifiquement aux clusters. des CI autogérés.

Nous avons constaté que la première clé pour optimiser tout système de QI est l'observabilité, car sans moyen de mesurer les effets de vos ajustements et de vos changements, il est impossible de savoir vraiment si vous avez réellement apporté une amélioration. Dans notre cas, CircleCI hébergé sur le serveur utilise un cluster nomade pour les compilations et, à ce moment-là, ne fournissait aucune méthode pour surveiller leur cluster ou les noeuds qui se trouvent à l'intérieur. Nous devions construire nos propres systèmes et nous avons décidé qu’une bonne approche consisterait à utiliser le cadre des quatre signes d’or, Latence, Trafic, Erreurs, et Saturation.

État latent

La latence est le temps total nécessaire pour répondre à une demande. Dans un système IC, cela peut être considéré comme le temps total nécessaire à une compilation pour s'exécuter du début à la fin. La latence est mieux mesurée par rapport ou même par compilation, car la longueur de la compilation peut varier considérablement en fonction du projet.

Pour mesurer cela, nous avons créé une petite application qui consultait régulièrement l'API CircleCI pour connaître la durée des compilations, puis nous avons envoyé ces informations à Datadog pour nous permettre de créer des graphiques et des visualisations des temps de compilation moyens. Cela nous a permis de tracer les résultats de nos expériences d'amélioration de manière empirique et automatique au lieu de nous baser sur des résultats anecdotiques ou traités manuellement, comme nous l'avions fait précédemment.

Résultats de l'API CircleCI

Trafic

Le trafic est la quantité de demande placée sur votre système à un moment donné. Dans un système IC, cela peut être représenté par le nombre total de constructions exécutées simultanément.

Nous avons pu mesurer cela en utilisant le même système que celui que nous avons construit pour mesurer les métriques de latence. Cela a été utile pour déterminer les limites supérieure et inférieure pour l'utilisation de nos ressources de compilation, car cela nous a permis de voir exactement le nombre de tâches en cours d'exécution en même temps.

Les erreurs

Les erreurs représentent le nombre total de demandes ou d'appels ayant échoué. Dans un système IC, cela peut être représenté par le nombre total de constructions qui échouent pour des raisons d'infrastructure. Ici, il est important de faire la distinction entre les compilations qui échouent correctement, dues aux tests, à l’alignement, aux erreurs de code, etc. au lieu de compilations qui échouent en raison de problèmes de plate-forme.

L'un des problèmes rencontrés est que, occasionnellement, AWS nous a attribué de "mauvaises" instances lors de la création de nouveaux constructeurs dont l'exécution était beaucoup plus lente que celle d'une "bonne" instance normale. L'ajout de la détection d'erreur dans les scripts de démarrage de notre constructeur nous a permis de les terminer et d'activer de nouveaux noeuds avant qu'ils ne puissent ralentir nos compilations en cours d'exécution.

Saturation

La saturation est le degré de «complétion» de votre service ou la quantité de ressources utilisées dans votre système. Dans un système IC, cela est assez simple: la quantité d’E / S, de CPU et de mémoire sont les constructeurs qui utilisent la charge.

Pour mesurer la saturation de notre configuration, nous avons pu tirer parti des métriques du cluster en installant un agent Datadog dans chacun de nos constructeurs, ce qui nous a permis d'obtenir une vue des statistiques système dans l'ensemble du cluster.

Statistiques de travail Datadog

Une fois que la configuration de surveillance est en place, il est plus facile de plonger dans la cause première du ralentissement de la construction. L'une des difficultés pour diagnostiquer les problèmes de QI sans surveiller l'ensemble du cluster est qu'il peut être difficile d'identifier les constructeurs confrontés à une charge à un moment donné ou en quoi cette charge affecte leurs compilations. La surveillance de latence peut vous permettre de déterminer les compilations qui prennent le plus de temps, et la surveillance de saturation peut vous permettre d'identifier les noeuds qui exécutent ces compilations pour une investigation plus détaillée.

Pour nous, la nouvelle mesure de latence que nous avons ajoutée nous a permis de confirmer rapidement ce que nous avions deviné auparavant: toutes les constructions n'étaient pas identiques. Certaines compilations ont été exécutées à la vitesse que nous avions connue auparavant, mais d’autres se prolongeraient beaucoup plus longtemps que prévu.

Dans notre cas, cette découverte a été décisive: une fois que nous avons pu identifier rapidement les compilations avec la latence la plus élevée et trouver les nœuds saturés, le problème a été rapidement révélé: Conflits de ressources entre les constructions initiales! En raison du grand nombre de tests effectués pour nos compilations plus volumineuses, nous avons utilisé la fonction de parallélisation CircleCI pour diviser nos tests et les exécuter dans toute la flotte dans des conteneurs distincts. Chaque conteneur de test nécessite également un autre ensemble de conteneurs de support (Redis, MongoDB, etc.) pour répliquer l'environnement de production. Le démarrage de tous les conteneurs nécessaires pour chaque compilation est une opération gourmande en ressources qui nécessite d'importantes quantités d'E / S et de CPU. Etant donné que Nomad utilise des emballages de conteneurs pour la distribution des tâches, nos constructeurs lancent parfois simultanément jusqu'à 5 jeux différents de ces conteneurs, ce qui provoque un ralentissement considérable avant que les tests ne puissent commencer à s'exécuter.

La configuration d'un environnement de développement est essentielle pour résoudre les problèmes de CI une fois qu'ils ont été détectés, car ils vous permettent de tirer le meilleur parti de votre système tout en vous assurant qu'aucun de vos tests n'affecte la productivité en production. Coinbase maintient un cluster de développement pour CircleCI que nous utilisons pour tester les nouvelles versions avant de les mettre en production, mais pour étudier nos options, nous convertissons le cluster en une réplique plus petite de notre instance de production, ce qui nous permet de charger efficacement les constructeurs. de CircleCI. . Garder votre groupe de développement aussi proche que possible de la production peut vous aider à vous assurer que les solutions que vous trouvez reflètent ce qui peut réellement aider dans un environnement réel.

Une fois que nous avions identifié les raisons pour lesquelles nos compilations rencontraient des problèmes et créé un environnement propice aux expériences, nous pouvions commencer à développer une solution. À plusieurs reprises, nous avons exécuté les mêmes compilations volumineuses qui posaient des problèmes dans notre cluster de production dans différentes tailles et types d'instances EC2 afin de déterminer l'option la plus économique et la plus économique.

Comparaison de type d'instance EC2

Alors que nous utilisions auparavant un plus petit nombre de grandes instances pour exécuter nos compilations, il s’avère que La configuration optimale pour notre cluster était en réalité un très grand nombre d'instances plus petites. (m5.larges dans notre cas): assez petit pour que Circle ne envoie qu'un conteneur de compilateur en parallèle à chaque instance, évitant ainsi les problèmes de piétinement de la compilation à l'origine des décélérations. L’identification des types d’instance appropriés a eu un effet secondaire intéressant: en effet, elle nous a permis de réduire considérablement l’empreinte financière de notre serveur, car nous avons pu dimensionner notre cluster plus précisément pour son utilisation.

L'application des modifications à un environnement de production est la dernière étape. Déterminer si les effets du réglage travaillé peuvent être réalisés de la même manière que les problèmes ont été identifiés, avec les quatre signaux en or.

Après avoir identifié ce qui fonctionnait le mieux dans notre cluster de développement, nous avons rapidement implémenté la nouvelle taille du constructeur en production. Les résultats? Une réduction de 75% du temps de compilation de nos plus grandes compilations, des économies de coûts considérables en raison de la taille correcte de notre cluster et, le plus important: des développeurs heureux!

Construire, avant et après.

Ce site Web peut contenir des liens vers des sites Web tiers ou d’autres contenus à des fins d’information uniquement («sites tiers»). Les sites tiers ne sont pas sous le contrôle de Coinbase, Inc. et de ses sociétés affiliées ("Coinbase"), et Coinbase n'est pas responsable du contenu des sites tiers, y compris, sans limitation, des liens contenus dans des tiers. Le site de la partie, ou toute modification ou mise à jour vers un site tiers. Coinbase n'est pas responsable des transmissions via Internet ni de toute autre forme de transmission reçue d'un site tiers. Coinbase vous fournit ces liens uniquement pour votre commodité, et l’inclusion de tout lien n’implique en aucun cas l’approbation, l’approbation ou la recommandation du site par Coinbase, ni aucune association avec ses opérateurs.

Sauf indication contraire, toutes les images fournies dans ce document proviennent de Coinbase.