Tl;dr : Ce billet de blog décrit comment nous avons développé un écosystème Python efficace et fiable à l’aide de Pants, un système de construction open source, et comment nous avons résolu le défi de la gestion des applications Python à grande échelle chez Coinbase.
Par l’équipe de la plateforme de calcul Coinbase
Python est l’un des langages de programmation les plus fréquemment utilisés par les scientifiques des données, les praticiens de l’apprentissage automatique et les chercheurs en blockchain chez Coinbase. Au cours des dernières années, nous avons assisté à une croissance des applications Python qui visent à résoudre de nombreux problèmes difficiles dans le monde de la crypto-monnaie, tels que les pipelines de données Airflow, les outils d’analyse de la blockchain, les applications d’apprentissage automatique et bien d’autres. Sur la base de nos données internes, le nombre d’applications Python a presque doublé depuis le troisième trimestre 2022. Selon nos données internes, il existe aujourd’hui environ 1 500 pipelines et services de traitement de données développés avec Python. Le nombre total de constructions est d’environ 500 par semaine au moment de la rédaction. Nous prévoyons une application encore plus large à mesure que davantage de frameworks centrés sur Python (tels que Ray, Modin, DASK, etc.) sont adoptés dans notre écosystème de données.
Le succès de l’ingénierie vient en grande partie du choix des bons outils. La création d’un écosystème Python à grande échelle pour répondre à nos besoins d’ingénierie croissants pourrait soulever certains défis, notamment l’utilisation d’un système de construction fiable, une gestion flexible des dépendances, une publication rapide des logiciels et un contrôle de qualité du code cohérent. Cependant, ces défis peuvent être combattus en intégrant Pants, un système de construction développé par les laboratoires Toolchain, dans l’infrastructure de construction Coinbase. Nous l’avons choisi comme système de construction Python pour les raisons suivantes :
- Le pantalon est ergonomique et convivial,
- Pants comprend de nombreuses commandes liées à la construction, telles que « test », « lint », « fmt », « typecheck » et « package »
- Pants a été conçu avec Python dans le monde réel comme cas d’utilisation de première classe, y compris la gestion des dépendances tierces. En fait, certaines parties de Pants lui-même sont écrites en Python (le reste étant écrit en Rust).
- Pants nécessite moins de métadonnées et de fichier BUILD standard que d’autres outils, grâce à l’inférence de dépendance, aux valeurs par défaut sensibles et à la génération automatique de fichiers BUILD. Bazel nécessite une énorme quantité de passe-partout BUILD manuscrits.
- Pants est facile à étendre, avec une puissante API de plugin qui utilise le code asynchrone Python 3 idiomatique, afin que les utilisateurs puissent avoir un flux de contrôle naturel dans leurs plugins.
- Pants a une véritable gouvernance OSS, où n’importe quelle organisation peut jouer un rôle égal.
- Le pantalon a une courbe d’apprentissage douce. Il a beaucoup moins de friction que les autres outils. Le coût de maintenance est modéré grâce à l’expérience d’installation en un clic de l’outil et aux fichiers de configuration simples.
Python est l’un des langages de programmation les plus populaires pour les applications d’apprentissage automatique et de science des données. Cependant, avant d’adopter le premier système de construction Python, Pants, notre investissement interne dans l’écosystème Python était faible par rapport à celui de Golang et Ruby – le premier choix pour l’écriture de services et d’applications Web chez Coinbase.
Selon les statistiques d’utilisation du monorepo de Coinbase, Python ne représente aujourd’hui que 4 % de l’utilisation en raison du manque de prise en charge du système de construction. Avant 2021, la plupart des projets Python se trouvaient dans plusieurs référentiels sans infrastructure de construction unifiée, ce qui entraînait les problèmes suivants :
- Défis avec le partage de code : Le processus pour un ingénieur de mettre à jour une bibliothèque partagée était complexe. Les modifications apportées au code ont été publiées sur un serveur PyPI interne avant de se révéler plus stables. Une bibliothèque qui a été mise à niveau vers une nouvelle version, mais qui n’a pas subi suffisamment de tests, pourrait potentiellement casser la dépendance qui a consommé la bibliothèque sans version épinglée.
- Absence de processus de publication rationalisé : Le changement de code nécessitait souvent des mises à jour et des versions complexes entre référentiels. Il n’y avait pas de flux de travail automatique pour effectuer les tests d’intégration et de staging des changements pertinents. Le manque d’observabilité et de fiabilité cohérentes a imposé une énorme surcharge d’ingénierie.
- Expériences de développement incohérentes : L’expérience de développement variait beaucoup car chaque référentiel avait sa propre méthode de configuration de l’environnement virtuel, de contrôle de la qualité du code, de construction et de déploiement, etc.
Nous avons décidé de construire PyNest – un nouveau « monorepo » Python pour l’organisation des données chez Coinbase. Il n’est pas dans notre intention que PyNest soit utilisé comme un dépôt unique pour l’ensemble de l’entreprise, mais plutôt que le référentiel soit utilisé pour des projets au sein de l’organisation des données.
- Construire un monorepo à l’échelle de l’entreprise nécessite une équipe d’élites. Nous n’avons pas assez d’équipage pour reproduire les réussites des monorepos sur Facebook, Twitter et Google.
- Python est principalement utilisé au sein de l’organisation des données de l’entreprise. Il est important de définir la bonne portée afin que nous puissions nous concentrer sur les priorités des données sans être distraits par des exigences ad hoc. L’infrastructure de construction PyNest peut être réutilisée par d’autres équipes pour accélérer leurs référentiels Python.
- Il est souhaitable de consolider les projets mutuellement dépendants (voir le graphique de dépendance pour les projets de plate-forme ML) dans un référentiel unique pour éviter les dépendances cycliques par inadvertance.
Figure 1. Graphique de dépendance pour les projets de plateforme d’apprentissage automatique (MLP).
- Bien que le monorepo promette un nouveau monde de productivité, il s’est avéré qu’il ne s’agissait pas d’une solution à long terme pour Coinbase. Le monorepo Golang est une leçon, où des problèmes sont apparus après un an d’utilisation, tels qu’une base de code tentaculaire, des intégrations IDE échouées, des CI/CD lents, des dépendances obsolètes, etc.
- Les projets open source doivent être conservés dans des référentiels individuels.
Le graphique ci-dessous montre l’architecture du référentiel chez Coinbase, où les blocs verts indiquent le nouvel écosystème Python que nous avons construit. L’opérabilité inter-dépôts est obtenue en servant des couches, y compris les artefacts de code et le registre de schémas.
Figure 2. Architecture de référentiel chez Coinbase
# dépendances tierces
# third-party dependencies├── 3rdparty│ ├── dependency1│ │ ├── BUILD│ │ ├── requirements.txt│ │ └── resolve1.lock # lockfile│ ││ └── dependency2│ │ ├── BUILD│ │ ├── requirements.txt│ │ └── resolve2.lock...│# shared libraries├── lib│# top level project folders├── project1 # project name│ ├── src│ │ └── python│ │ ├── databricks│ │ │ ├── BUILD│ │ │ ├── OWNERS│ │ │ ├── gateway.py│ │ │ ...│ │ └── notebook│ │ ├── BUILD│ │ ├── OWNERS│ │ ├── etl_job.py│ │ ...│ └── test│ └── python│ ├── databricks│ │ ├── BUILD│ │ ├── gateway_test.py│ │ ...│ └── notebook│ ├── BUILD│ ├── etl_job_test.py│ ...├── project2...│# Docker files├── dockerfiles│# tools for lint, formatting, etc.├── tools│# Buildkite CI workflow├── .buildkite│ ├── pipeline.yml│ └── hooks│# Pants library├── pants├── pants.toml└── pants.ci.toml
Figure 3. Structure du référentiel Pynest
Voici une liste des principaux éléments du référentiel et leurs explications.
1. Tiers
Les dépendances tierces sont placées sous ce dossier. Pants analysera les fichiers requirements.txt et générera automatiquement la cible « python_requirement » pour chacune des dépendances. Plusieurs versions de la même dépendance sont prises en charge par la fonctionnalité de fichiers de verrouillage multiples de Pants. Cette fonctionnalité permet aux projets d’avoir des conflits dans des dépendances directes ou transitives. Pants génère des fichiers de verrouillage pour épingler chaque dépendance et assurer une construction reproductible. Plus d’explications sur le verrouillage multiple des pantalons se trouvent dans la section gestion des dépendances.
2. Lib
Bibliothèques partagées accessibles à tous les projets. Les projets au sein de PyNest peuvent directement importer le code source. Pour les projets en dehors de PyNest, les bibliothèques sont accessibles via pip en installant les fichiers de roue à partir d’un serveur PyPI interne.
3. Dossiers de projet
Les projets individuels vivent dans ce dossier. Le chemin du dossier est au format « {project_name}/{src or test}/python/{namespace} ». La racine source est configurée en tant que « src/python » ou « test/python », et l’espace de noms ci-dessous est utilisé pour isoler les modules.
4. Fichiers du propriétaire du code
Les fichiers de propriétaire de code (OWNERS) sont ajoutés aux dossiers pour définir les individus ou les équipes qui sont responsables du code dans l’arborescence des dossiers. Le workflow CI invoque un script pour compiler tous les fichiers OWNERS dans un fichier CODEOWNERS sous « .github/ ». La règle d’approbation du propriétaire du code exige que toutes les demandes d’extraction aient au moins une approbation du groupe de propriétaires du code avant de pouvoir être fusionnées.
5. Outils
Le dossier Tools contient les fichiers de configuration des outils de qualité du code, par exemple flake8, black, isort, mypy, etc. Ces fichiers sont référencés par Pants pour configurer les linters.
6. Flux de travail Buildkite
Coinbase utilise Buildkite comme plate-forme CI. Le flux de travail Buildkite et les définitions de hook sont définis dans ce dossier. Le workflow CI définit les étapes telles que
- Vérifiez si les fichiers de verrouillage des dépendances doivent être mis à jour.
- Exécutez des lints et des outils de qualité de code.
- Générez du code source et des images Docker.
- Exécute des tests unitaires et d’intégration.
- Génère des rapports sur les couvertures de code.
7. Fichiers Docker
Les Dockerfiles sont définis dans ce dossier. Les images docker sont créées par le flux de travail CI et déployées par Codeflow, une plate-forme de déploiement interne chez Coinbase.
8. Bibliothèques de pantalons
Ce dossier contient le script Pants et les fichiers de configuration (pants.toml, pants.ci.toml).
Cet article décrit comment nous construisons PyNest à l’aide du système de construction Pants. Dans notre prochain article de blog, nous expliquerons la gestion des dépendances et CI/CD.
Source https://blog.coinbase.com/building-a-python-ecosystem-for-efficient-and-reliable-development-d986c97a94a0?source=rss—-c114225aeaf7—4