Lorsque vous décidez de migrer sur le Cloud, l’une des premières choses à faire, quel que soit le Cloud Provider choisi, est de renseigner ses informations de paiement (les numéros de carte de crédit), et c’est bien normal.

En effet, ces Clouds Providers vous donnent accès à un réseau massif de serveurs coûtant plusieurs milliards de dollars.

Dans l’article d’aujourd’hui, nous allons décortiquer une histoire réelle sur la façon dont une startup a accumulé une facture de 72 000$ de Google Cloud en une nuit seulement. Nous allons découvrir ensemble comment cela est possible, mais surtout nous allons examiner les moyens d’éviter que cela nous arrive.

L’histoire

Si vous écrivez du code de mauvaise qualité sur votre propre machine en local, ce n’est en général pas un problème : votre processeur va chauffer un peu, votre ordinateur ralentir et les ventilateurs vont s'accélérer un peu. Seulement, dans le Cloud, c’est complètement différent !
Une fonction récursive par exemple, peut virtuellement s’étendre à l’infini et utiliser un grand nombre de ressources. Celles que vous louez, et pour lesquelles quelqu’un devra bien payer un jour.

Imaginez que vous avez passé des mois à préparer votre startup, que vous êtes à quelques jours du grand lancement et que votre produit est prêt à être lancé. Vous avez juste besoin de récupérer des données sur le Web pour enrichir l'expérience utilisateur, vous élaborez donc un code spécifique pour le Job, vous le dockerisez et le déployer sur une plateforme serverless: Google Cloud Run. 

Si vous n’êtes pas familier avec ce service, n’hésitez pas à consulter un petit tutoriel sur le sujet.

Normalement le job n'a besoin de fonctionner que quelques heures, vous le déployez avant d’aller vous coucher et vous vous réveillez avec quelques e-mails surprenant le lendemain matin : 

  • Votre projet Firebase est passé de la formule gratuite à la formule payante nous avons dû activer une API qui nécessite une facturation, ce qui a automatiquement mis à niveau la formule”. Pas d'inquiétude, nous avons déjà une alerte budgétaire en place.
  • Le mail suivant nous indique que notre budget de sept dollars a été dépassé.
  • Le troisième mail nous indique que notre carte de crédit a été refusée. Ça commence à devenir suspect, allons ouvrir le panneau de facturation dans Google Cloud.

desastre_financier

Une facture de plus de cinq mille dollars en quelques heures, il s’agit probablement d'une erreur, actualisons la page et prions.

Mauvaise stratégie : cinq minutes plus tard la facture est de 15,000 $ dollars, après vingt minutes de  25,000 $. La facture finale est réglée après environ deux heures : juste un peu moins de 72,000 $.

Cette entreprise avait plusieurs produits dans plusieurs projets Google Cloud pour mieux les gérer. Pris de panique, ils ont dû désactiver tous leurs projets parce que les choses sont devenues hors de contrôle.

Et voilà comment une petite fonction récursive aurait pu faire mettre en faillite une entreprise entière. Heureusement pour eux, tout s’est bien terminé, je vous invite à lire la fin de l'histoire si cela vous intéresse.

Que faire pour que ça ne m'arrive pas ?

Maintenant, examinons le pourquoi de cette facture salée, et surtout, les moyens d’éviter que cela vous arrive. 
Je vous livre ici mes 5 conseils : 

Conseil #1

Mettez en place une alerte budgétaire, et ce même si vous bénéficiez d'un plan gratuit ou d'un niveau gratuit. 

Une fois que vous déployez du code dans le Cloud, il y a différentes façons de dépasser le free-tier sans le savoir. Ce n'est pas courant, mais c'est toujours une bonne pratique d'avoir une alerte budgétaire définie sur votre compte globalement.

L'entreprise a bien fait les choses en fixant un budget de sept dollars, mais le problème dans ce cas est que le coût a augmenté si rapidement, qu'une alerte ne vous enverra qu'un e-mail et ne fermera rien du tout. Lorsque le budget a été dépassé, il est en fait assez fou qu'il n'y ait pas un moyen facile d'arrêter les services. 

En octobre 2020, AWS a publié une fonctionnalité appelée Budget Actions où vous pouvez définir une action basée sur un seuil de budget, comme fermer un serveur une fois que vous avez dépensé trop d'argent par exemple.

En outre, sur Google Cloud, vous pouvez écouter les événements budgétaires avec Pub/Sub, ce qui signifie que vous pouvez écrire un petit bout de code pour créer un trigger qui désactive la facturation si le budget alloué à votre projet cloud est dépassé.

Conseil #2

boucles_cloud

En ce qui concerne le serverless, tout est basé sur des événements : un événement se produit dans le cloud, comme un upload vers un bucket.
Cet upload déclenche une fonction lambda, déclenchant un job supplémentaire.
Il est très facile de perdre le contrôle si la fonction conduit au même événement que celui qui l'a déclenchée : ici par exemple un upload vers le bucket sur lequel la fonction “écoute”. Un nouvel upload déclencherait un nouvel appel de fonction et ainsi de suite jusqu'à la fin des temps (ou jusqu'à ce que votre compte bancaire soit vide). 

C'est ce que nous appelons une boucle infinie et c'est probablement la première cause d'emballement des coûts de manière inattendue.

Plus généralement, vous pouvez considérer la complexité de vos algorithmes et comment ceux-ci affectent l’utilisation de vos ressources.

Les services serverless sont en fait très peu coûteux et parce qu'ils sont très faciles à utiliser, vous pouvez ne pas vous rendre compte que vous faites un mauvais choix de modélisation d’architecture avant qu'il soit trop tard.

Conseil #3

Ne configurez pas votre infrastructure pour gérer d'énormes charges de travail si elles n’en ont pas besoin.

Notre startup a utilisé un service appelé CloudRun, qui est une fonction serverless manageant les conteneurs Docker. Par défaut, CloudRun s'adapte à un maximum de 1000 instances.

cloud_run

Le scraper commence par une requête manuelle vers le point de terminaison de CloudRun, chaque exécution scrape l'URL et enregistre les résultats dans Firestore, puis il prend tous les liens qu'il a trouvés dans une page web scrappée et déclenche une autre exécution dans le cloud pour les traiter.

Nous avons ici une fonction récursive sans point d'arrêt qui conduit à un stack-overflow.

Il en a résulté 116 milliards de lectures dans la base de données et 33 millions d'écritures, ainsi que 16 000 heures de calcul dans le cloud.

La morale de cette histoire est qu'il faut configurer les services pour qu'ils n'évoluent pas si vous n'en avez pas besoin. Dans le cas de CloudRun, si le nombre d'instances maximal avait été défini sur 1 au lieu de 1,000, la facture aurait été de 72 dollars au lieu de 72,000.

En production, il est probable que vous souhaitiez que les choses soit scalables et, parfois, vous ne connaîtrez la gravité d'un problème que lorsque votre application évoluera.

Conseil #4

Assurez-vous que votre application soit sécurisée.

Il faut premièrement s’assurer de ne pas exposer ses clés d’identification (sans blague). Ça peut paraître trivial, mais cela arrive plus souvent qu’on ne le pense. Dès qu’elles sont exposées, des hackers n'hésitent pas à se servir de votre compte pour faire fondre des processeurs, pour lesquels vous devrez payer. 

Il faut également toujours suivre les best-practices des providers en termes de sécurité, en définissant des règles d’accès, des autorisations, etc. Celles-ci vous évitent des risques inutiles de sécurité pour votre application et une éventuelle surfacturation si un hacker parvient à accéder à votre infrastructure.

Conseil #5

Même en appliquant tous les conseils précédents, il se peut que votre infrastructure puisse être optimisée et vous permettre de réaliser de belles économies. Je vous invite donc à vous renseigner sur ce qu’est le FinOps et à suivre mes futurs articles ✍️

J’espère que cet article vous aura permis de comprendre que le Cloud n’est pas seulement virtuel, ainsi que d’y voir plus clair dans votre stratégie de maitrise du Cloud et de limitation des risques financiers.
Connaissez-vous d’autres techniques pour éviter ce genre de désastre dans le cloud ? N'hésitez pas à me faire des retours dans les commentaires ou par mail, j’y répondrai avec plaisir !