Fort de ma propre expérience, je sais quelles motivations et chemins de développement conduisent à l'émergence d'outils internes : je tenterai ci-dessous d'identifier les raisons fondamentales de leur création en prenant comme exemple nos solutions.
Bonjour! Je veux expliquer pourquoi les grandes entreprises technologiques sont obsédées par la création de solutions propriétaires pour leur infrastructure. La réponse semble évidente : il ne s’agit que du syndrome des NIH. Mais cette réponse est loin d’être complète, encore moins objective.
Je suis le CTO de l'équipe Yandex Platform Engineering et notre objectif est d'aider les ingénieurs à construire l'ensemble du cycle de développement, de l'écriture du code aux services d'exploitation, afin de le rendre plus efficace. Cela inclut la rationalisation des processus : nous développons non seulement des offres en tant que service, mais nous aidons également à les mettre en œuvre au sein de l'entreprise. Cela fonctionne à l'échelle de Yandex : nos services sont utilisés par des milliers de développeurs dans toute l'entreprise.
Exemples d'outils pour organiser le cycle de développement
Pour résoudre un problème, nous développons souvent des outils propriétaires plutôt que d’implémenter des outils prêts à l’emploi. Par exemple, alors que j'étais encore programmeur dans l'équipe, j'ai travaillé sur un système de surveillance quantitative en C++ et Python et j'ai contribué à l'adapter à des dizaines de milliards de métriques traitées. Ainsi, grâce à ma propre expérience, je sais quelles motivations et quels chemins de développement conduisent à l'émergence d'outils internes : je tenterai ci-dessous d'identifier les raisons fondamentales de leur création en prenant comme exemple nos solutions.
Histoire n°1 : Cloud interne de Yandex
Définir la tâche. L'objectif de notre Runtime Cloud interne, ou RTC, est de fournir aux utilisateurs internes des outils simples de déploiement et de gestion du trafic. Les utilisateurs de RTC sont les mêmes ingénieurs qui développent les services Yandex. Et ils doivent, entre autres, lancer des dizaines de milliers d'applications qu'ils ont créées quelque part, y envoyer les requêtes des utilisateurs, équilibrer la charge et gérer les incidents.
Le besoin d'un cloud interne est apparu au début des années 2010, alors que le nombre de services se chiffrait déjà par centaines et que le nombre total de cœurs alloués augmentait de plusieurs dizaines de pour cent par an. Avoir des serveurs dédiés pour chaque service est devenu prohibitif et nous avions besoin d'outils qui nous permettraient d'exécuter des applications de plusieurs services sur un seul serveur. Nous avions plusieurs exigences pour ces outils au départ :
Il est nécessaire d'automatiser les actions de routine afin d'économiser les ressources opérationnelles et de réduire le nombre d'incidents lors des releases.
Une autre tâche importante consistait à accroître l'utilisation du cloud, d'autant plus que la plupart des services avaient une charge quotidienne et que le cloud était inactif la nuit. La situation était encore compliquée par le fait que tous les services Yandex n'étaient pas hébergés dans le cloud au cours de ces années et que l'augmentation constante du nombre de serveurs a exacerbé le problème.
Il était essentiel de déployer rapidement des fonctionnalités ou des corrections de bugs auprès des utilisateurs, car cela affectait directement la vitesse de développement de Yandex.
La prise en charge d'IPv6 uniquement est requise : pour fournir une connectivité de bout en bout entre les pods, nos centres de données ont été construits uniquement en IPv6, car à notre échelle, la plage d'adresses IPv4 ne nous suffirait pas.
Essentiellement, nous avions besoin de Kubernetes (et, au fil du temps, RTC s’en est approché). Mais voici le hic : k8s n'a été annoncé qu'en 2014. Apache Mesos existait à l'époque, mais il en était à ses balbutiements.
Implémentation des fonctions de base. Nous avons commencé à résoudre le problème avec une sorte de MVP - un simple ensemble d'outils, qui ressemblait davantage à un ensemble de blocs de construction qui automatisent les actions de routine, par exemple :
allocation des ressources du cluster ;
livraison de la version requise de l'application et de divers artefacts au cluster ;
lancement de la version requise de l'application sur le cluster.
Au fil du temps, il est devenu possible de créer un graphique de disposition de service à part entière en utilisant ces éléments de base (similaire à la livraison continue). Après un certain nombre d'itérations, Nanny, un système de gestion de services fonctionnant au RTC, apparaît en 2013.
Un autre aspect fondamental de Nanny était la mise en œuvre d’une isolation des applications basée sur la consommation des ressources. Nous avons initialement lancé des applications à partir de divers services sans isolement des ressources, ce qui a entraîné un grand nombre de problèmes et d'incidents opérationnels.
À l'époque, les seules solutions prêtes à l'emploi étaient LXC, qui avait alors arrêté de se développer, et Docker, qui ne pouvait pas utiliser uniquement IPv6 et redémarrait tous les conteneurs lors de la mise à jour de Dockerd, rendant impossible la mise à jour de Dockerd sans affecter l'utilisateur. En conséquence, nous avons commencé à développer notre système de conteneurisation au-dessus du groupe de contrôle du noyau Linux vers la mi-2014. La plupart des applications et certains agents système sur les serveurs ont déjà été déplacés vers des conteneurs Porto en 2015.
Résoudre les problèmes d'utilisation. À l’époque, la gestion des ressources dans le cloud interne se faisait via des commits dans le référentiel. Cependant, cela a ralenti le développement de Yandex et est entré en conflit avec la tâche d'augmenter l'utilisation : pour résoudre ce problème, nous avons dû placer notre système de réduction de carte dans les nuages, à savoir - notre système interne propriétaire de stockage de big data et de calcul distribué, que nous développions à l'époque depuis environ 7 ans. Il devait être intégré au cloud interne, mais il devait également fonctionner parallèlement aux applications utilisateur.
Pour amener YTsaurus au RTC, la possibilité de gérer les pods de manière dynamique plutôt que via des validations de référentiel était requise. Ainsi, en 2018, nous avons créé , un système de gestion des ressources informatiques du cluster. Yandex Planner a été intégré au système de déploiement Nanny existant, débloquant la migration de YTsaurus et transformant RTC en un cloud à part entière. RTC disposait à l'époque de plusieurs dizaines de milliers de serveurs, et avec l'introduction de la réduction de carte, ce nombre a considérablement augmenté.
De nouvelles douleurs de croissance. Au cours de la même période, k8s a évolué vers une solution beaucoup plus mature, devenant l'un des services AWS en 2017. Mais il ne répondait toujours pas à toutes nos exigences :
Échelle de dizaines de milliers de serveurs - une installation K8s ne peut toujours pas gérer notre échelle.
La prise en charge de la double pile IPv6 et IPv4 n'est apparue dans les k8 qu'en 2020, et IPv6 a été essentiel pour nous dès le début.
Prise en charge des conteneurs imbriqués, dont nous avions besoin car nous avons décidé de créer des planificateurs de lots et de calcul distincts. Nous avons comparé l'efficacité de cette option à celle d'un planificateur général à un moment donné, et il était plus pratique et plus rentable de ne pas essayer de faire un planificateur général pour tout.
YTsaurus a activement utilisé la possibilité de créer des conteneurs Porto imbriqués plutôt que de créer un seul planificateur. Bien sûr, nous pourrions nous-mêmes ajouter la prise en charge de la même double pile dans les k8. Cependant, l'expérience de développement du noyau Linux a montré que tout ne peut pas être envoyé vers l'open source, et nous nous efforçons de maintenir au minimum le delta du noyau en amont afin de simplifier la mise à jour vers les nouvelles versions.
Notre solution aujourd'hui. L'architecture du RTC est très similaire à celle de Kubernetes. L'utilisateur décrit son service de manière déclarative sous la forme d'une spécification décrivant comment lancer l'application spécifiée et dans quels centres de données. Chaque centre de données possède sa propre installation de Yandex Planner, qui sert d'une part de base de données pour tous les objets du cluster et d'autre part de planificateur de pods. Chaque serveur du centre de données exécute un agent qui reçoit les spécifications des pods de Yandex Planner et les lance à l'aide de notre système de conteneurisation propriétaire Porto.
Actuellement, RTC a lancé des dizaines de milliers de services, allouant plus de 5 millions de cœurs à plus de 100 000 serveurs. Chaque jour, plus de 100 000 modifications sont apportées aux spécifications des services.
Des plans. Et si les K8 pouvaient gérer notre échelle ? D'autant plus que l'écosystème k8s a commencé à nous surpasser en termes de fonctionnalités à un moment donné. Ne vaudrait-il pas mieux passer aux k8 et espérer que des outils prêts à l'emploi finiront par fournir le volume dont nous avons besoin ? Dans la pratique, nous restons un consommateur de niche pour les k8, car seul un petit pourcentage d'entreprises opèrent à une telle échelle, chacune disposant de ses propres solutions cloud internes.
Un autre point critique à retenir est la question de la migration. D'après le rapport de juillet 2018 Selon un rapport, 90 % des applications modernes seront encore utilisées d'ici 2025, et la dette technique pour le développement de ces systèmes représentera plus de 40 % des budgets informatiques. Ceci est proche de la réalité, d'après notre expérience en matière de migration des services utilisateur vers Yandex Planner : en 2023, environ 100 000 cœurs attendaient encore leur tour pour migrer vers Yandex Planner.
En 2021, nous avons estimé combien coûterait le passage d’un système de déploiement à un autre lors du choix de notre stratégie de développement. La migration de Yandex vers les Vanilla K8 serait une tâche extrêmement coûteuse, coûtant des centaines d'années-homme.
De cette manière simple, nous nous sommes retrouvés avec notre nuage intérieur, que nous ne pourrons probablement pas abandonner dans les 5 prochaines années, même si nous nous fixons un tel objectif.
Que faut-il faire face au manque de fonctionnalités cloud internes par rapport aux k8 ? En pratique, nos clients peuvent utiliser Managed Kubernetes dans Yandex Cloud. Cette option est principalement utilisée pour les projets où des exigences de conformité strictes doivent être respectées - il s'agit d'une faible proportion d'équipes, inférieure à 1 %. Pour les raisons évoquées ci-dessus, le reste de la population ne voit pas beaucoup d’avantages à déménager.
Dans le même temps, nous étudions activement les k8 et réfléchissons à la manière de nous rapprocher des normes généralement acceptées. Nous expérimentons déjà activement les k8 dans certaines tâches, telles que le démarrage du cloud ou l'organisation de l'IaaC à l'échelle de l'ensemble de Yandex. Idéalement, nous aimerions réutiliser l'interface k8s tout en conservant notre propre implémentation aussi adaptée que possible à nos besoins. Il ne reste plus qu'à trouver comment procéder en pratique.
Et les autres ? Puisque nous discutons de la grande technologie en général dans cet article, il convient de noter que notre cas n’est pas unique. Vérifiez ou cas pour exemples.
Histoire n°2 : monodépôt
Problèmes et exigences en matière de solutions . Notre monodépôt, Arcadia, partage le même objectif principal que notre cloud interne : fournir des outils de développement pratiques. Cela inclut tout un écosystème de développement dans le cas du référentiel :
système de contrôle de version (Arc),
Interface (Arcane),
construire un système (tu fais),
CI/CD (NouveauCI).
Arcadia est apparu à peu près en même temps que le cloud interne de Yandex. L'une des raisons de la création du monodépôt était la nécessité de réutiliser le code au sein de Yandex. Cela était gêné à l’époque par la présence de plusieurs systèmes de build. Un système unifié prenant en charge des builds distribués efficaces était nécessaire pour fonctionner à l'échelle de l'ensemble de Yandex. Il doit également être stable et utilisable.
Mise en place d'un système de build unifié. Notre système de build propriétaire ya make a fait ses débuts en 2013, alors qu'il était uniquement destiné au code C++. Avant de créer, nous avons utilisé CMake, mais sa vitesse l'empêchait d'évoluer à l'échelle d'un monodépôt. Le ya make propriétaire fonctionnait beaucoup plus rapidement avec Arcadia. Il n'y avait aucune autre option open source qui pourrait résoudre notre problème : par exemple, Bazel est sorti beaucoup plus tard, en 2015.
Mise à l'échelle du système de contrôle de version. Yandex utilisait auparavant SVN comme système de contrôle de version. Même si SVN avait une grande capacité, elle restait limitée et difficile à maintenir. De plus, nous étions conscients que nous finirions par nous heurter aux limites des capacités et de la commodité de SVN. Par exemple, des heuristiques ont été utilisées pour mettre en œuvre la possibilité de télécharger uniquement la partie requise du référentiel ou d'effectuer une extraction sélective. En conséquence, en 2016, nous avons commencé à expérimenter d'autres systèmes de contrôle de version que SVN.
Mercurial était le premier choix. Mais le principal problème que nous avions était la vitesse. Nous avons essayé pendant un an et demi de mettre Mercurial en production, mais les résultats ont été décevants. Par exemple, nous avons finalement dû réécrire certaines parties de Mercurial pour prendre en charge FUSE, ou nous aurions dû transférer l'intégralité du référentiel sur l'ordinateur portable de chaque développeur.
Finalement, il s'est avéré qu'il était moins coûteux d'écrire une solution interne à partir de zéro, et en 2019, Arc est apparu - un nouveau système de contrôle de version pour les utilisateurs d'Arcadia avec une UX de type git. La fondation d'Arc est FUSE (système de fichiers dans l'espace utilisateur) plutôt que l'extraction sélective. De plus, YDB agit comme une base de données évolutive, ce qui simplifie grandement le fonctionnement d'Arc par rapport à Mercurial.
On nous demande souvent pourquoi nous n’avons pas utilisé git. Parce qu'il a également des limites d'échelle et de fonctionnalités : si nous importons uniquement le tronc Arcadia dans git, le statut de git prendra quelques minutes à cette échelle. Dans le même temps, il n'y avait pas d'implémentation stable de FUSE construite sur git : VFS pour Git n'est plus développé et EdenFS a finalement été transformé en Sapling, mais cela s'est produit beaucoup plus tard.
État actuel de la solution et plans pour l'avenir. Pour commencer le développement, un utilisateur interne doit simplement créer un dossier dans notre monoréférentiel, écrire du code et vous expliquer comment créer son application en ajoutant le manifeste de construction. En conséquence, l'utilisateur reçoit des demandes d'extraction, une configuration CI et la possibilité de réutiliser n'importe quel code dans l'entreprise.
En termes d'échelle, le tronc contient actuellement 10 millions de fichiers, le référentiel dans son ensemble dépasse 2 TiB et plus de 30 000 commits sont effectués chaque semaine.
En conséquence, dans l’écosystème que nous avons créé, nous devons créer de nombreux composants à partir de zéro. Cependant, elle s’oriente désormais vers le respect des normes mondiales. Arc, par exemple, prend en charge l'utilisation de Git pour un ensemble prédéfini de projets.
Et les autres ? Encore une fois, si vous regardez la grande technologie en général, alors, à titre d'exemple, vous devriez prêter attention à et .
Qu'ont en commun ces histoires
Alors pourquoi les grandes entreprises technologiques doivent-elles inventer leurs propres solutions, et pourquoi ne peuvent-elles pas être remplacées par des solutions qui adhèrent à une norme généralement acceptée ?
Innovation. Les grandes entreprises sont souvent amenées à développer des solutions à des problèmes qui ne deviendront monnaie courante qu’à l’avenir. C’est ainsi que peuvent émerger des solutions innovantes susceptibles de devenir des standards du marché.
Il n’est pas toujours vrai qu’un problème résolu par une entreprise soit confronté à quelqu’un d’autre que l’entreprise elle-même. Parfois, l’expérience des grandes technologies face à un problème spécifique aide l’ensemble du secteur à éviter ce problème en empruntant une voie de développement complètement différente. Il n’est pas toujours possible de prédire l’évolution du marché et, par conséquent, différents exemples de solutions propriétaires ont eu des résultats très différents.
ClickHouse est un exemple de projet innovant véritablement réussi qui a considérablement enrichi le domaine du traitement analytique en ligne (OLAP). Toutefois, ce n’est pas le cas de tous les projets. Le Porto, qui a commencé comme un projet open source, n'a pas réussi à gagner du terrain pour diverses raisons. Bien que certaines de ses fonctionnalités, comme la possibilité de créer des conteneurs imbriqués, restent uniques.
Échelle. Ce point est similaire au précédent à certains égards, car toutes les entreprises ne sont pas confrontées au problème d’évolutivité. Il fut un temps où 640 Ko étaient plus que suffisants pour tout le monde, n'est-ce pas ?
En fait, l’augmentation exponentielle de la charge du système a été l’une des raisons les plus importantes du développement d’Arcadia et du cloud interne. C'est pourquoi Arc et Yandex Planner ont été développés. Arc a été créé en réponse au besoin d'un VCS convivial pouvant permettre aux utilisateurs de travailler sans difficulté avec un monodépôt contenant des dizaines de millions de fichiers dans un tronc. Yandex Planner a été créé en réponse à la nécessité de travailler efficacement avec des clusters de dizaines de milliers de nœuds et des millions de pods.
Les outils publics continuent de rencontrer des problèmes de mise à l’échelle (après tout, il s’agit d’un scénario relativement rare, et investir dans ce domaine n’est souvent tout simplement pas rentable).
Inertie. Considérez un outil interne qui résout un problème au sein d’une entreprise. Une entreprise qui utilise activement cet outil consacrerait des ressources pour mieux l’adapter à ses besoins, pour finalement le transformer en un outil hautement spécialisé. Ce processus peut durer des années.
Considérons maintenant la possibilité qu’à un moment donné, une norme universellement acceptée pour résoudre ce problème particulier émerge. Dans ce cas, la spécialisation peut encore être un facteur important dans le choix d’une solution interne. Envisagez de créer des systèmes. Nous utilisons votre marque chez Arcadia, bien qu'il existe Bazel de Google. Ils sont conceptuellement similaires, mais lorsque vous entrez dans les détails, de nombreux scénarios importants sont implémentés différemment, car les modèles de charge pour chaque charge de travail peuvent être radicalement différents. En conséquence, les ressources déjà dépensées devront presque certainement être réinvesties afin de personnaliser une nouvelle norme généralement acceptée.
Migrations. Si la section précédente abordait la question de l'adaptation du projet aux utilisateurs, abordons maintenant la question de la migration des utilisateurs eux-mêmes. À mon avis, la migration devrait être considérée comme le deuxième problème technologique le plus important après la dénomination. Si nous supposons que nous disposons déjà d’un outil interne à l’entreprise et que nous souhaitons le remplacer par un outil standardisé, nous aurons inévitablement besoin de migrations.
Nous connaissons de nombreux exemples de migrations grâce à notre expérience de développement d’un cloud interne. Les migrations à grande échelle prennent du temps, les deux outils doivent donc être pris en charge simultanément pendant de longues périodes. Si ce processus implique un grand nombre d’utilisateurs, des problèmes de gestion sont inévitables. Il vaut certainement la peine d'essayer de migrer sans la participation des utilisateurs, mais cela n'est pas toujours possible.
Continuité de l'activité. Pour être franc, ce point a récemment acquis une importance suffisante. Auparavant, un nombre beaucoup plus restreint d’entreprises prenaient cette question au sérieux en raison de préoccupations liées à la dépendance vis-à-vis d’un fournisseur. Confier les processus critiques à un fournisseur qui peut mettre fin à la collaboration à tout moment est risqué. JetBrains en est un excellent exemple, ayant restreint l'utilisation de ses IDE à certaines entreprises. Un autre exemple est celui de Github Enterprise, qui a commencé à suspendre les comptes d'utilisateurs basés en Russie.
Les solutions internes sont généralement insensibles à ce problème. D’une part, il existe encore des solutions open source. D'un autre côté, rien ne garantit que le modèle open source vous accompagnera jusqu'au bout : par exemple, Corona, l'amélioration développée en interne par Facebook pour le logiciel de planification Hadoop MapReduce, est apparue en premier lieu en raison de l'incapacité de s'engager. les correctifs requis pour faire évoluer Hadoop en amont.
En parallèle, l’aspect juridique de la problématique touche l’open source : par exemple, les commits en golang ou en k8s nécessitent la signature d’un CLA. Est-ce que cela continuera à être un problème ?
NIH. Oui, outre les raisons objectives, il est possible que les décisions prises ne soient pas pragmatiques. C’est le syndrome des NIH à son meilleur.
Par exemple, pour tenter d'éliminer l'influence des lots sur le calcul, nous avons tenté de créer notre propre planificateur dans le noyau Linux. En pratique, cela n’a rien donné de bon ; on aurait pu se contenter des capacités existantes du noyau Linux. Cependant, plus les coûts de main-d'œuvre sont élevés, plus les efforts sont déployés pour élaborer et résoudre le problème, et plus faible est le risque de souffrir du syndrome NIH.
En résumé , comme vous pouvez le constater, les grandes entreprises ont souvent besoin de solutions internes. La majorité d’entre elles fusionneront à l’avenir avec des solutions standards mondiales unifiées qui n’ont pas encore atteint leur maturité, tandis que le reste appartiendra à l’histoire ancienne. Quoi qu’il en soit, choisir entre une solution propriétaire et une solution toute faite reste une question difficile à laquelle on ne peut répondre sans comprendre au préalable le contexte et estimer le coût d’un tel projet.