Cloud Intelligence™Cloud Intelligence™

Cloud Intelligence™

Débusquez le gaspillage cloud caché dans votre code

By Joshua FoxMay 19, 20256 min read

Cette page est également disponible en English, Deutsch, Español, Italiano, 日本語 et Português.

Une approche systématique de l'optimisation des coûts cloud

L'optimisation des coûts cloud obéit au principe de Pareto (80/20) : un faible pourcentage de vos ressources concentre généralement l'essentiel de vos coûts. Commencez par utiliser des outils comme DoiT Cloud Intelligence™ pour identifier vos principaux postes de dépenses.

Étape 2 : décrocher les gains administratifs rapides

Avant de vous plonger dans l'optimisation du code, traitez d'abord les ajustements d'administration cloud les plus simples :

  • Right-sizing des instances sous-utilisées
  • Suppression des ressources orphelines
  • Mise en place de niveaux de stockage adaptés
  • Ajustement des paramètres d'autoscaling

Ces actions coûtent bien moins cher qu'une plongée directe dans le code.

Étape 3 : repérer les indicateurs d'inefficacité au niveau du code

Une fois les optimisations administratives terminées, examinez les ressources les plus coûteuses pour détecter d'éventuelles inefficacités liées au code.

En raison de l'illusion d'efficacité, ces indicateurs peuvent être subtils. Les cas réels présentés plus loin dans cet article illustrent les signes révélateurs courants à surveiller, le plus souvent décelables avec les outils de monitoring standard des consoles GCP, AWS et Azure.

Étape 4 : enquêter, profiler, analyser

Passez du niveau cloud au niveau code grâce à des outils de profilage d'exécution utilisables dans le cloud.

  • Pour les bases de données : analyseurs de requêtes et performance insights des consoles cloud
  • Pour les applications : profileurs spécifiques au langage et analyseurs mémoire
  • Pour les pipelines de données : graphes d'exécution et métriques de distribution

Flamegraph, from Google Cloud Profiler

Flame graph issu de Google Cloud Profiler

La mise en œuvre peut être simple, comme pour le SQL où les outils sont disponibles directement dans le cloud, ou plus complexe, comme pour le profilage mémoire de Python dans des applications distribuées exécutées en environnements managés.

Étape 5 : déployer, mesurer, valider

Corrigez les problèmes identifiés, redéployez et mesurez les améliorations techniques via les consoles cloud AWS, GCP et Azure ; consultez les rapports de coûts Cloud Intelligence™ pour valider les gains financiers.

Cas réels et solutions

Scénario 1 : microservice Java avec fuites mémoire

Ce qui semblait efficace : un microservice Java Lambda affichant une utilisation mémoire de 70 à 100 %, semblant tirer pleinement parti des ressources allouées.

La réalité : l'application souffrait de fuites mémoire, un objet global conservant des chaînes de références qui retenaient des objets d'une invocation à l'autre. Les plantages occasionnels et les remplacements d'instances étaient suffisamment rares pour passer sous le radar des SRE.

L'indice : le monitoring a révélé un motif d'utilisation mémoire en dents de scie au fil du temps. L'analyse des chutes a mené aux logs CloudWatch, qui montraient des plantages périodiques.

Investigation : CodeGuru Profiler, une fois activé, a confirmé une utilisation mémoire croissante au fil du temps. Des analyses hors ligne avec un profileur JVM ont identifié une rétention d'objets inattendue.

Solution : modification du code pour libérer les références d'objets à la fin de chaque requête web.

Résultat : utilisation mémoire stable, moins de remplacements d'instances et coûts de ressources réduits.

Scénario 2 : pipeline de traitement de données Java avec structures de données inefficaces

Ce qui semblait efficace : un pipeline Dataflow avec des conteneurs Java personnalisés traitant quotidiennement des millions d'enregistrements avec une utilisation CPU élevée et constante.

La réalité : le code reposait sur des structures de données inefficaces, notamment des maps avec des concaténations de chaînes superflues par objet dans des boucles serrées, générant une charge excessive de garbage collection.

L'indice : une utilisation élevée des ressources justifiait une investigation plus approfondie.

Investigation : GCP Cloud Profiler a été ajouté au conteneur. Il a mis en évidence une mise à l'échelle super-linéaire du temps et de la mémoire à mesure que les jeux de données grossissaient.

Solution :

  • Remplacement des maps par des objets personnalisés ne contenant que les informations utiles.
  • Mise en place d'une jointure de chaînes appropriée plutôt que des concaténations répétées.

Résultat : utilisation mémoire réduite de 50 % et temps de traitement diminué de 70 %, permettant d'utiliser des machines worker plus petites et moins d'instances.

Scénario 3 : structures de données en mémoire entraînant des VM surdimensionnées

Ce qui semblait efficace : les VM à grande mémoire paraissaient économiques face aux solutions à mise à l'échelle horizontale, et les structures de données Python en mémoire offraient un avantage algorithmique en vitesse par rapport aux requêtes en base de données.

La réalité : cette approche cumulait plusieurs inefficacités :

  • Les fournisseurs cloud imposent des ratios CPU/mémoire minimum, d'où une capacité CPU coûteuse et inutilisée.
  • Les allocations mémoire se font par paliers prédéfinis, obligeant à payer une capacité tampon non utilisée.
  • Les longs temps d'initialisation imposaient de maintenir plusieurs instances coûteuses en exécution simultanée pour garantir la robustesse.

L'indice : DoiT Cloud Intelligence™ révélait qu'une part importante de la dépense totale provenait de VM ultra-grandes — typiquement le signe d'une statefulness problématique dans les architectures cloud.

Investigation : une analyse approfondie des algorithmes a révélé des opportunités de refactorisation pour permettre le stockage des données hors de la mémoire applicative.

Solution :

  • Refactorisation des algorithmes pour fonctionner avec des sous-ensembles de données interrogés à la demande dans les bases de données
  • Mise en place d'une base NoSQL avec Redis comme cache en mémoire
  • Lorsqu'un préchargement complet des données de référence clés s'imposait, des structures de données optimisées dans Redis offraient une empreinte mémoire plus faible que les objets en mémoire applicative

Résultat : ce changement architectural a considérablement réduit la taille des VM, ouvert la voie à la mise à l'échelle horizontale et radicalement diminué les coûts, au prix toutefois d'un effort d'engineering substantiel.

Retour sur des cas précédents

Revenons sur deux autres exemples tirés de l'article que j'ai mentionné plus tôt, Stop Chasing Idle Servers, et voyons comment ils s'inscrivent dans ce cadre.

Scénario 4 : base de données poussée à 85 % d'IOPS

Ce qui semblait efficace : l'instance RDS paraissait pleinement utilisée, suggérant une allocation optimale des ressources.

La réalité : chaque requête déclenchait des full-table scans faute de deux index critiques, ce qui faisait exploser les besoins en ressources.

L'indice : la plupart des requêtes SQL ne devraient pas exiger une utilisation élevée des ressources (sauf dans des traitements batch très optimisés) ; un schéma de forte utilisation pointait donc vers des opportunités d'optimisation.

Investigation : identification des requêtes problématiques et des index manquants à l'aide d'AWS RDS Performance Optimizer, disponible d'office dans la console AWS. (GCP propose l'équivalent avec Cloud SQL Query Insights.)

Solution : ajout des index manquants.

Résultat : latence des requêtes divisée par 10 et possibilité de réduire la taille de la base de deux niveaux.

Scénario 5 : job Spark à 70 % de CPU pendant quatre heures chaque nuit

Ce qui semblait efficace : le cluster maintenait une utilisation CPU élevée, suggérant une allocation appropriée des ressources.

La réalité : 80 % des données étaient concentrées sur une seule clé déséquilibrée, créant des tâches traînardes (stragglers) qui allongeaient considérablement le temps de traitement.

L'indice : le problème a démarré à un moment précis sans autre cause apparente. (On a découvert plus tard qu'il coïncidait avec l'arrivée de nouvelles données contenant la hot key.)

Investigation : le code Spark s'exécute dans un environnement hautement distribué, ce qui complique l'utilisation d'un profileur classique tel qu'on l'emploierait pour des applications. C'est une bonne raison de maintenir la logique centrée sur des transformations simples plutôt que sur de la logique métier complexe. Cela dit, l'analyse de la distribution des tâches entre les étapes via la Spark UI a permis d'identifier les stragglers. Le monitoring BigTable a révélé des hot keys dans la base traitée.

Solution : repartitionnement et salage de la clé problématique pour répartir la charge plus uniformément.

Résultat : le temps d'exécution du job est passé de 4 heures à 45 minutes, et la taille du cluster nécessaire a été réduite des deux tiers.

Atteindre une véritable efficacité cloud impose parfois de dépasser les seules configurations cloud pour s'attaquer aussi aux inefficacités au niveau du code. Lorsque le code est à l'origine des coûts cloud excessifs, les ajustements d'infrastructure ne suffiront pas à résoudre le problème.

En associant votre équipe de développement aux équipes FinOps et SRE, vous pouvez identifier et résoudre ces inefficacités cachées grâce à une approche systématique :

  1. Partez des principaux postes de dépenses mis en évidence par l'analyse des coûts.
  2. Traitez d'abord les gains rapides au niveau de la configuration cloud.
  3. Dans les consoles cloud, repérez les indices révélateurs qui appellent une investigation plus poussée.
  4. Utilisez des outils de profilage adaptés, de préférence dans le cloud, sinon hors ligne, pour cibler les inefficacités.
  5. Corrigez le code, redéployez et validez les économies.

Cette approche collaborative ne se contente pas de réduire les coûts : elle améliore souvent aussi les performances et la fiabilité des applications — un double bénéfice pour votre budget comme pour vos utilisateurs.

Au sein de l'équipe DoiT Customer Reliability Engineering, j'accompagne les organisations tout au long de leur parcours d'optimisation. En nous appuyant sur DoiT Cloud Intelligence™ et des décennies d'expérience, nous aidons à repérer les gains potentiels, à décrire les correctifs au niveau cloud, à débusquer les illusions d'efficacité et à valider l'impact des améliorations apportées au code. Contactez-nous sur doit.com/services