Embrasser le changement dans une startup qui avance vite
Au moins une fois par an, je pars naviguer en famille. Rien d'extravagant : un voilier que nous manœuvrons nous-mêmes pour profiter de la nature et de bons moments ensemble. Étonnamment, un élément clé de ces sorties reste le vent — sa direction, sa force — et sa particularité : il ne cesse de changer !
À l'image du vent, la vie change en permanence. C'est particulièrement vrai dans une startup qui avance vite. Ce qui fonctionne bien aujourd'hui peut ne plus être adapté demain. Savoir reconnaître le moment où il faut pivoter, optimiser, voire refondre totalement un système est essentiel. En tant qu'ingénieurs, nous avons tendance à nous attacher à nos décisions et aux systèmes que nous construisons. Mais s'accrocher aux choix passés peut devenir un handicap.
Chez Attribute™, nous nous attachons aux personnes, pas à ce que nous construisons. Il n'est donc pas surprenant que le moment soit venu de revoir notre stack de traitement de données. Au départ, nous avons fait les meilleurs choix d'infrastructure compte tenu de nos contraintes. Mais à mesure que nous avons grandi, ces mêmes choix sont devenus des limites, nous obligeant à repenser et à nous adapter.
La décision initiale : Serverless Dataproc pour Spark
Lorsque nous avons commencé à bâtir notre infrastructure de traitement de données, nous avons choisi Serverless Dataproc pour exécuter nos jobs Spark. À l'époque, ce choix avait tout son sens. Équipe réduite disposant d'une bande passante d'ingénierie limitée, nous n'avions pas le luxe de construire et de maintenir un cluster Spark auto-géré. Serverless Dataproc nous permettait de nous concentrer sur la création de valeur, sans nous soucier de la charge opérationnelle. Nous pouvions écrire nos jobs Spark, les déployer facilement et laisser Google Cloud s'occuper du reste.
Les douleurs de la croissance : coûts et manque de contrôle
À mesure que notre activité grandissait, nos besoins en traitement de données ont augmenté eux aussi. Plus de données signifiait plus de jobs, une fréquence d'exécution plus élevée et, à terme, des coûts qui s'envolaient.
Nous avons également commencé à rencontrer des goulots d'étranglement opérationnels. L'aspect boîte noire de Dataproc nous laissait peu de visibilité sur les détails d'exécution des jobs, ce qui compliquait l'optimisation des performances et le débogage efficace des échecs.
À ce stade, les inconvénients l'emportaient sur les avantages. Il devenait clair qu'il fallait reprendre la main.
Le pourquoi derrière la migration
J'applique une règle simple à tout projet d'ingénierie : il doit partir d'un pourquoi solide. S'il n'y a aucune raison convaincante de faire quelque chose, nous ne devrions pas y consacrer notre ressource la plus précieuse : le temps. (Petit indice : essayer une nouvelle technologie uniquement parce qu'elle est cool n'est jamais une raison suffisante.)
Pour notre migration Dataproc, le pourquoi était clair :
- Efficacité des coûts : Serverless Dataproc était devenu trop onéreux.
- Transparence opérationnelle : il nous fallait un meilleur contrôle et une meilleure visibilité sur nos jobs Spark.
- Scalabilité et flexibilité : nous voulions pouvoir affiner notre infrastructure au fil de nos besoins.
Portés par ces motivations, nous nous sommes lancés dans un projet ciblé : migrer nos workloads Spark de Dataproc vers une solution auto-gérée basée sur Kubernetes.
La migration : faire passer Spark sur Kubernetes
Nous avons choisi de déployer nos jobs Spark via Spark-on-Kubernetes, qui permet d'exécuter des applications Spark comme des workloads natifs Kubernetes. Voici une vue d'ensemble de notre approche :
Mise en place de l'infrastructure :
- Nous avons provisionné un cluster Kubernetes sur Google Kubernetes Engine (GKE) avec l'autoscaling activé pour absorber les variations de workloads.
- Nous avons configuré un namespace dédié à nos jobs Spark, garantissant une séparation nette avec les autres services.
- Des instances Spot sont utilisées pour réduire encore les coûts.
Exécution des jobs avec la CRD SparkApplication :
Nous avons tiré parti du Spark Operator pour gérer les workloads Spark comme des ressources natives Kubernetes.
Cela nous a permis de définir les jobs Spark de manière déclarative via des Custom Resources (CRs) Kubernetes, ce qui simplifie leur gestion et leur passage à l'échelle.
Observabilité et monitoring :
Nous avons intégré Victoria Metrics et Grafana pour un monitoring en temps réel de l'exécution des jobs.
Le résultat : plus de contrôle, des coûts réduits et un meilleur monitoring
La migration a apporté des améliorations significatives :
- Réduction des coûts : en supprimant la surcharge managée de Dataproc et en optimisant l'utilisation des ressources, nous avons réduit nos coûts de traitement Spark de plus de 70 %.
- Transparence accrue : nous avons gagné en visibilité sur l'exécution des jobs, ce qui a amélioré le débogage et l'optimisation. Cela a aussi renforcé l'appropriation par l'équipe Engineering : la disparition de la boîte noire nous pousse à produire un meilleur travail d'ingénierie.
- Scalabilité : Kubernetes nous permet de faire évoluer dynamiquement nos workloads sans les limites imposées par un fournisseur. L'amélioration des performances de Spark et la réduction des temps d'exécution nous ont également permis de gagner en efficacité sur le développement des fonctionnalités, générant davantage de valeur produit.
Pour conclure
L'ingénierie, c'est résoudre des problèmes de la manière la plus efficace possible. Notre choix de Serverless Dataproc était le bon au départ, tout comme celui de passer à Kubernetes à mesure que nous avons grandi.
La leçon clé ? Restez adaptable. Ne vous attachez pas à vos décisions, embrassez le changement — car il viendra, que vous le vouliez ou non.
Je me demande quand nous commencerons à ressentir les frictions avec notre infrastructure Spark actuelle…