{"id":1578,"date":"2021-09-02T15:12:09","date_gmt":"2021-09-02T14:12:09","guid":{"rendered":"https:\/\/wp.qongzi.dev\/?p=1578"},"modified":"2023-12-21T15:17:07","modified_gmt":"2023-12-21T14:17:07","slug":"affaire-declassee-une-fuite-memoire-dans-e-chauffeur","status":"publish","type":"post","link":"https:\/\/qongzi.com\/affaire-declassee-une-fuite-memoire-dans-e-chauffeur\/","title":{"rendered":"Affaire d\u00e9class\u00e9e : une fuite m\u00e9moire dans e-Chauffeur"},"content":{"rendered":"\n
(NB : Pr\u00e9cisons que les IP dans les screenshots ne sont plus actives… ou au moins plus chez nous, raison pour laquelle j’ai pr\u00e9f\u00e9r\u00e9 l’esth\u00e9tisme de screenshots non flout\u00e9s)<\/p>\n\n\n\n
<\/p>\n\n\n\n
Parlons rapidement du projet : e-Chauffeur est une application de r\u00e9servation de v\u00e9hicule avec chauffeur, sans brique de paiement, \u00e0 destination des personnels des Arm\u00e9es. (Plus d’informations sur sa fiche beta.gouv.fr<\/a>). Son code est libre et disponible sur gitlab.com<\/a>.<\/p>\n\n\n\n Pour rester tr\u00e8s g\u00e9n\u00e9rique, une fuite m\u00e9moire r\u00e9sulte d’une accumulation de donn\u00e9es dans la m\u00e9moire vive d’un ordinateur entrainant sa saturation. Je pense pouvoir affirmer que nous l’avons tous exp\u00e9riment\u00e9 au moins une fois sans savoir ce que c’\u00e9tait : Votre ordinateur se mets soudain \u00e0 ralentir alors que vous l’utilisez, et relancer un logiciel ou l’ordinateur suffit \u00e0 r\u00e9soudre le probl\u00e8me… jusqu’\u00e0 ce que cela recommence.<\/p>\n\n\n\n Dans le d\u00e9veloppement logiciel, un programme requ\u00eate un espace m\u00e9moire aupr\u00e8s du syst\u00e8me d’exploitation, afin d’y stocker une donn\u00e9e. Ensuite, le programme doit lib\u00e9rer l’espace m\u00e9moire quand il n’en a plus besoin. A partir de l\u00e0, plusieurs strat\u00e9gies existent suivant les langages de programmation, citons en trois :<\/p>\n\n\n\n Pour peu qu’on analyse son graph d’utilisation m\u00e9moire, on peut presque distinguer un programme avec un Garbage Collector<\/em> : les moments o\u00f9 il va lib\u00e9rer de la m\u00e9moire sont cycliques. Par exemple, on peut imaginer que chaque seconde, le Garbage Collector<\/em> va regarder les adresses m\u00e9moires r\u00e9put\u00e9es inaccessibles et les lib\u00e9rer. Cette fr\u00e9quence est g\u00e9n\u00e9ralement bien plus rapide que “chaque seconde”, et est bien souvent configurable.<\/p>\n\n\n\n Comment une fuite m\u00e9moire est possible avec un Garbage Collector<\/em> ? Ce dernier d\u00e9duit un graph d’utilisation des entr\u00e9es m\u00e9moire. Quand des points du graph sont coup\u00e9s de la racine, c’est qu’ils sont inaccessibles et sont \u00e0 nettoyer. Tant que les variables sont accessibles, et reli\u00e9es \u00e0 la racine de ce graph, alors le Garbage Collector <\/em>va garder les variables pour \u00e9viter une erreur du programme.<\/p>\n\n\n\n Dans notre cas, le probl\u00e8me \u00e9tait li\u00e9 \u00e0 la m\u00e9thode utilis\u00e9e pour ajouter des plugins dans le programme. Ces plugins sont pr\u00e9vus pour \u00eatre ajout\u00e9s une fois dans la partie rendu serveur, au lancement du serveur. Dans notre cas, ils \u00e9taient ajout\u00e9s \u00e0 chaque requ\u00eate re\u00e7ue.<\/p>\n\n\n\n Ainsi, les \u00e9l\u00e9ments \u00e9taient ajout\u00e9s dans un tableau de plugins, et ce tableau \u00e9tait utilis\u00e9 r\u00e9guli\u00e8rement, et donc maintenu dans les variables “utiles” au programme. Ce tableau devenait de plus en plus grand, jusqu’\u00e0 saturer la m\u00e9moire.<\/p>\n\n\n\n Point int\u00e9ressant, plus le tableau \u00e9tait grand, plus la puissance de calcul n\u00e9cessaire \u00e0 le parcourir \u00e9tait grande \u00e9galement, ainsi le monitoring montre une augmentation similaire du processeur.<\/p>\n\n\n\n Nous n’avons pas vu cette fuite m\u00e9moire avant un paquet de temps, faute en est \u00e0 notre infrastructure, qui fonctionnait comme pr\u00e9vu : plusieurs conteneurs (au moins 3) fonctionnent en m\u00eame temps, dans le cas o\u00f9 une erreur est d\u00e9tect\u00e9e, le conteneur est red\u00e9marr\u00e9 (et \u00e7a va vite), dans le cas o\u00f9 un conteneur est indisponible, les requ\u00eates ne lui parviennent plus (les autres prennent la charge).<\/p>\n\n\n\n Une erreur possible, c’est que la m\u00e9moire d\u00e9passe l’espace qui lui est allou\u00e9. \u00c0 ce moment l\u00e0, Kubernetes va relancer (d\u00e9truire et recr\u00e9er serait plus exacte) le conteneur.<\/p>\n\n\n\n Une fois le correctif d\u00e9ploy\u00e9, on constate rapidement que ce motif en dents de scie cesse, et que les conteneurs ne red\u00e9marrent plus.<\/p>\n\n\n\n Peut \u00eatre vous demandez vous pourquoi corriger s’il n’y a pas de probl\u00e8me pour l’utilisateur, \u00e9tant donn\u00e9 que c’est compens\u00e9 par l’infrastructure ? Et bien d\u00e9j\u00e0, permettez moi de le mettre en premier : pour le principe ! C’est une anomalie, elle doit \u00eatre corrig\u00e9e. Autrement, il y a de meilleures raisons : la pollution des logs<\/em>, ces derniers vont \u00eatre pollu\u00e9s par des lignes indiquant le red\u00e9marrage des services, inutilement. Si vous avez un syst\u00e8me automatique de d\u00e9tection d’erreurs dans les logs<\/em>, bas\u00e9 sur un apprentissage, et bien il va se mettre \u00e0 consid\u00e9rer que quand le conteneur red\u00e9marre, c’est normal. Ensuite, la pollution des \u00e9v\u00e8nements<\/em> est \u00e9galement une bonne raison : on pr\u00e9f\u00e8re avoir des \u00e9v\u00e8nements<\/em> utiles dans les informations de Kubernetes.<\/p>\n\n\n\n La le\u00e7on \u00e0 tirer de tout \u00e7a ? Et bien il faut regarder les graphiques de monitoring des environnements de reviews (qui sont d\u00e9ploy\u00e9s \u00e0 la vol\u00e9e) avant de mettre en production des modifications ! Quand \u00e7a fonctionne, c’est pas n\u00e9cessairement que tout fonctionne correctement<\/em>.<\/p>\n","protected":false},"excerpt":{"rendered":" D\u00e9but 2020, \u00e0 l’occasion de la migration d’un projet (e-Chauffeur) sur un cluster Kubernetes, et la mise en place de son monitoring, nous avons d\u00e9cel\u00e9s une fuite m\u00e9moire. \u00c9tant corrig\u00e9e depuis bien longtemps, aujourd’hui est l’occasion de revenir sur ce cas d’\u00e9cole. <\/p>\n","protected":false},"author":2,"featured_media":1579,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[19],"tags":[40],"meta_box":{"card_category":"Cybers\u00e9curit\u00e9"},"_links":{"self":[{"href":"https:\/\/qongzi.com\/wp-json\/wp\/v2\/posts\/1578"}],"collection":[{"href":"https:\/\/qongzi.com\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/qongzi.com\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/qongzi.com\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/qongzi.com\/wp-json\/wp\/v2\/comments?post=1578"}],"version-history":[{"count":0,"href":"https:\/\/qongzi.com\/wp-json\/wp\/v2\/posts\/1578\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/qongzi.com\/wp-json\/wp\/v2\/media\/1579"}],"wp:attachment":[{"href":"https:\/\/qongzi.com\/wp-json\/wp\/v2\/media?parent=1578"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/qongzi.com\/wp-json\/wp\/v2\/categories?post=1578"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/qongzi.com\/wp-json\/wp\/v2\/tags?post=1578"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}\n
Une fuite invisible<\/h2>\n\n\n\n
Conclusion<\/h2>\n\n\n\n