{"id":52389,"date":"2019-11-07T00:00:00","date_gmt":"2019-11-06T21:00:00","guid":{"rendered":"https:\/\/prohoster.info\/blog\/blog_prohoster\/kak-realizuetsya-otkazoustojchivaya-veb-arhitektura-v-platforme-mail-ru-cloud-solutions"},"modified":"2020-02-18T14:00:05","modified_gmt":"2020-02-18T11:00:05","slug":"kak-realizuetsya-otkazoustojchivaya-veb-arhitektura-v-platforme-mail-ru-cloud-solutions","status":"publish","type":"post","link":"https:\/\/prohoster.info\/fr\/blog\/administrirovanie\/kak-realizuetsya-otkazoustojchivaya-veb-arhitektura-v-platforme-mail-ru-cloud-solutions","title":{"rendered":"Comment une architecture web r\u00e9siliente est-elle mise en \u0153uvre sur la plateforme Mail.ru Cloud Solutions","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<p><img decoding=\"async\" alt=\"Comment une architecture web r\u00e9siliente est-elle mise en \u0153uvre sur la plateforme Mail.ru Cloud Solutions\" src=\"\/wp-content\/uploads\/2019\/11\/fe7af07f3ac5ca4e75009993b742293e.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nBonjour, Habr ! Je suis Artem Karamyshev, responsable de l'\u00e9quipe d'administration syst\u00e8me. <noindex><a rel=\"nofollow\" href=\"https:\/\/mcs.mail.ru\/\">Mail.Ru Cloud Solutions (MCS)<\/a><\/noindex>. Au cours de la derni\u00e8re ann\u00e9e, nous avons lanc\u00e9 de nombreux nouveaux produits. Nous voulions nous assurer que les services API soient facilement \u00e9volutifs, fiables et pr\u00eats \u00e0 r\u00e9pondre rapidement \u00e0 une charge d'utilisateur croissante. Notre plateforme est bas\u00e9e sur OpenStack, et je souhaite partager les probl\u00e8mes de r\u00e9silience des composants que nous avons d\u00fb r\u00e9soudre pour obtenir un syst\u00e8me r\u00e9silient. Je pense que cela int\u00e9ressera ceux qui d\u00e9veloppent \u00e9galement des produits sur OpenStack.<\/p>\n<p>La r\u00e9silience globale de la plateforme d\u00e9pend de la fiabilit\u00e9 de ses composants. Nous allons donc passer progressivement par tous les niveaux o\u00f9 nous avons identifi\u00e9 des risques et les avons att\u00e9nu\u00e9s.<\/p>\n<p>Vous pouvez visionner la version vid\u00e9o de cette histoire, qui est issue d'une pr\u00e9sentation lors de la conf\u00e9rence Uptime Day 4, organis\u00e9e par <noindex><a rel=\"nofollow\" href=\"http:\/\/www.itsumma.ru\">ITSumma<\/a><\/noindex>, sur la cha\u00eene YouTube de Uptime Community. <noindex><a rel=\"nofollow\" href=\"https:\/\/www.youtube.com\/watch?v=3b06MVou-vg&amp;list=PLmXjIrLllpkjwuIGkzBkLbI7oHtUadmvZ&amp;index=5\">R\u00e9silience de l'architecture physique<\/a><\/noindex>. <br \/>\n<noindex><a rel=\"nofollow\" name=\"habracut\"><\/a><\/noindex><\/p>\n<h2>La partie publique du cloud MCS est actuellement bas\u00e9e dans deux centres de donn\u00e9es de niveau Tier III, entre lesquels il existe une fibre sombre r\u00e9serv\u00e9e au niveau physique par diff\u00e9rentes liaisons, avec une capacit\u00e9 de 200 Gbit\/s. Le niveau Tier III garantit le niveau n\u00e9cessaire de r\u00e9silience pour l'infrastructure physique.<\/h2>\n<p>\nLa fibre sombre est r\u00e9serv\u00e9e \u00e0 la fois au niveau physique et logique. Le processus de r\u00e9servation des canaux a \u00e9t\u00e9 it\u00e9ratif, avec des probl\u00e8mes surgissant, et nous am\u00e9liorons constamment la connexion entre les centres de donn\u00e9es. <\/p>\n<p>Par exemple, r\u00e9cemment, lors de travaux dans un puits pr\u00e8s de l'un des centres de donn\u00e9es, un excavateur a perc\u00e9 un tuyau, \u00e0 l'int\u00e9rieur duquel se trouvaient \u00e0 la fois un c\u00e2ble optique principal et de secours. Notre canal de communication r\u00e9silient avec le centre de donn\u00e9es s'est av\u00e9r\u00e9 vuln\u00e9rable \u00e0 un point, dans le puits. Par cons\u00e9quent, nous avons perdu une partie de l'infrastructure. Nous avons tir\u00e9 des le\u00e7ons de cette exp\u00e9rience et avons entrepris certaines actions, notamment en installant de la fibre optique suppl\u00e9mentaire dans le puits voisin. <\/p>\n<blockquote><p>Par exemple, il n'y a pas si longtemps, lors des travaux dans un puits pr\u00e8s de l'un des centres de donn\u00e9es, une pelle a percut\u00e9 un tuyau. \u00c0 l'int\u00e9rieur de ce tuyau se trouvaient \u00e0 la fois le c\u00e2ble de fibre optique principal et le c\u00e2ble de secours. Notre canal de communication redondant avec le centre de donn\u00e9es s'est av\u00e9r\u00e9 vuln\u00e9rable \u00e0 un point, dans le puits. Par cons\u00e9quent, nous avons perdu une partie de notre infrastructure. Nous avons tir\u00e9 des le\u00e7ons de cet incident et avons pris plusieurs mesures, y compris l'installation d'une fibre optique suppl\u00e9mentaire dans le puits voisin.<\/p><\/blockquote>\n<p>\nDans les centres de donn\u00e9es, il y a des points de pr\u00e9sence des fournisseurs de services, auxquels nous transmettons nos pr\u00e9fixes via BGP. Pour chaque direction de r\u00e9seau, la meilleure m\u00e9trique est choisie, permettant d'assurer la meilleure qualit\u00e9 de connexion \u00e0 nos diff\u00e9rents clients. Si la connexion via un fournisseur est interrompue, nous r\u00e9ajustons notre routage \u00e0 travers les fournisseurs disponibles.<\/p>\n<p>En cas de d\u00e9faillance d'un fournisseur, nous basculons automatiquement vers le suivant. En cas de d\u00e9faillance d'un des centres de donn\u00e9es, nous disposons d'une copie miroir de nos services dans un second centre de donn\u00e9es, qui prend toute la charge.<\/p>\n<p><img decoding=\"async\" alt=\"Comment une architecture web r\u00e9siliente est-elle mise en \u0153uvre sur la plateforme Mail.ru Cloud Solutions\" src=\"\/wp-content\/uploads\/2019\/11\/295ca212f48dd074d834154666e5b0c3.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>R\u00e9silience de l'infrastructure physique<\/i><\/p>\n<h2>Ce que nous utilisons pour la r\u00e9silience au niveau des applications<\/h2>\n<p>\nNotre service est construit sur un certain nombre de composants opensource. <\/p>\n<p><b>ExaBGP<\/b> \u2014 un service qui impl\u00e9mente un certain nombre de fonctions en utilisant le protocole de routage dynamique bas\u00e9 sur BGP. Nous l'utilisons activement pour annoncer nos adresses IP publiques, gr\u00e2ce auxquelles les utilisateurs acc\u00e8dent \u00e0 l'API.<\/p>\n<p><b>HAProxy<\/b> \u2014 un \u00e9quilibrage de charge hautement charg\u00e9 permettant de configurer des r\u00e8gles d'\u00e9quilibrage du trafic tr\u00e8s flexibles \u00e0 diff\u00e9rents niveaux du mod\u00e8le OSI. Nous l'utilisons pour \u00e9quilibrer devant tous les services : bases de donn\u00e9es, courtiers de messages, services API, services web, nos projets internes \u2014 tout repose sur HAProxy.<\/p>\n<p><b>Application API<\/b> \u2014 une application web \u00e9crite en python, qui permet \u00e0 l'utilisateur de g\u00e9rer son infrastructure, son service.<\/p>\n<p><b>Application Worker <\/b>(ci-apr\u00e8s simplement worker) \u2014 dans les services OpenStack, c'est un d\u00e9mon d'infrastructure qui permet de traduire les commandes API en infrastructure. Par exemple, la cr\u00e9ation d'un disque se produit justement dans le worker, tandis que la demande de cr\u00e9ation se fait dans l'application API. <\/p>\n<h2>Architecture standard de l'application OpenStack<\/h2>\n<p>\nLa plupart des services d\u00e9velopp\u00e9s sous OpenStack tentent de suivre une seule et m\u00eame paradigm. Un service se compose g\u00e9n\u00e9ralement de 2 parties : l'API et les workers (ex\u00e9cutants du backend). En r\u00e8gle g\u00e9n\u00e9rale, l'API est une application WSGI en python qui s'ex\u00e9cute soit comme un processus autonome (daemon), soit \u00e0 l'aide d'un serveur web d\u00e9j\u00e0 pr\u00eat comme Nginx ou Apache. L'API traite les requ\u00eates des utilisateurs et transmet des instructions suppl\u00e9mentaires \u00e0 l'application worker. La transmission se fait par le biais d'un broker de messages, g\u00e9n\u00e9ralement RabbitMQ, les autres \u00e9tant peu soutenus. Lorsque les messages parviennent au broker, ils sont trait\u00e9s par les workers qui, si besoin, retournent une r\u00e9ponse. <\/p>\n<p>Ce paradigme implique des points de d\u00e9faillance isol\u00e9s : RabbitMQ et la base de donn\u00e9es. Cependant, RabbitMQ est isol\u00e9 dans le cadre d'un seul service et peut id\u00e9alement \u00eatre individuel pour chaque service. Ainsi, chez MCS, nous s\u00e9parons au maximum ces services, en cr\u00e9ant une base s\u00e9par\u00e9e et un RabbitMQ pour chaque projet distinct. Cette approche a l'avantage que, en cas d'incident dans certaines zones vuln\u00e9rables, seul une partie du service est affect\u00e9e, et non l'ensemble.<\/p>\n<p>Le nombre d'applications worker n'est limit\u00e9 par rien, donc l'API peut facilement se mettre \u00e0 l'\u00e9chelle horizontalement derri\u00e8re des \u00e9quilibres de charge pour am\u00e9liorer les performances et la tol\u00e9rance aux pannes.<\/p>\n<blockquote><p>Dans certains services, une coordination au sein du service est n\u00e9cessaire \u2014 lorsque des op\u00e9rations s\u00e9quentielles complexes se produisent entre les API et les workers. Dans ce cas, un centre de coordination unique est utilis\u00e9, un syst\u00e8me de cluster comme Redis, Memcache, etcd, qui permet \u00e0 un worker de dire \u00e0 un autre que cette t\u00e2che lui a \u00e9t\u00e9 attribu\u00e9e (\u00ab toi, ne la prends pas s'il te pla\u00eet \u00bb). Nous utilisons etcd. En g\u00e9n\u00e9ral, les workers communiquent activement avec la base de donn\u00e9es, y \u00e9crivant et lisant des informations. Nous utilisons mariadb comme base de donn\u00e9es, qui se trouve dans un cluster multimaster.\n<\/p><\/blockquote>\n<p>\nUn service classique et isol\u00e9 est organis\u00e9 de mani\u00e8re standard pour OpenStack. Il peut \u00eatre consid\u00e9r\u00e9 comme un syst\u00e8me autonome, pour lequel les m\u00e9thodes d'\u00e9volutivit\u00e9 et de tol\u00e9rance aux pannes sont suffisamment \u00e9videntes. Par exemple, pour garantir la tol\u00e9rance aux pannes, il suffit de mettre un \u00e9quilibreur de charge devant l'API. L'\u00e9volutivit\u00e9 des workers est atteinte en augmentant leur nombre. <\/p>\n<p>Le point faible de tout le syst\u00e8me r\u00e9side dans RabbitMQ et MariaDB. Leur architecture m\u00e9rite un article \u00e0 part. Dans cet article, je souhaite me concentrer sur la r\u00e9silience de l'API.<\/p>\n<p><img decoding=\"async\" alt=\"Comment une architecture web r\u00e9siliente est-elle mise en \u0153uvre sur la plateforme Mail.ru Cloud Solutions\" src=\"\/wp-content\/uploads\/2019\/11\/f39e5a8ae350864e311bf4db3b9c34b3.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>Architecture de l'application Openstack. \u00c9quilibrage de charge et r\u00e9silience de la plateforme cloud.<\/i><\/p>\n<h2>Rendre le r\u00e9partiteur HAProxy r\u00e9silient gr\u00e2ce \u00e0 ExaBGP.<\/h2>\n<p>\nPour que nos API soient \u00e9volutives, rapides et r\u00e9silientes, nous avons plac\u00e9 un r\u00e9partiteur devant elles. Nous avons choisi HAProxy. \u00c0 mon avis, il poss\u00e8de toutes les caract\u00e9ristiques n\u00e9cessaires pour notre t\u00e2che : \u00e9quilibrage \u00e0 plusieurs niveaux de l'OSI, interface de gestion, flexibilit\u00e9 et \u00e9volutivit\u00e9, de nombreuses m\u00e9thodes d'\u00e9quilibrage, prise en charge des tables de session.<\/p>\n<p>Le premier probl\u00e8me \u00e0 r\u00e9soudre \u00e9tait la r\u00e9silience du r\u00e9partiteur lui-m\u00eame. Installer simplement un r\u00e9partiteur cr\u00e9e aussi un point de d\u00e9faillance : si le r\u00e9partiteur tombe en panne, le service s'arr\u00eate. Pour \u00e9viter cela, nous avons utilis\u00e9 HAProxy avec ExaBGP.<\/p>\n<p>ExaBGP permet de mettre en \u0153uvre un m\u00e9canisme de v\u00e9rification de l'\u00e9tat du service. Nous avons utilis\u00e9 ce m\u00e9canisme pour v\u00e9rifier le bon fonctionnement de HAProxy et, en cas de probl\u00e8me, d\u00e9sactiver le service HAProxy depuis BGP. <\/p>\n<p><b>Sch\u00e9ma ExaBGP+HAProxy.<\/b><\/p>\n<ol>\n<li>Installer le logiciel n\u00e9cessaire, ExaBGP et HAProxy, sur trois serveurs. <\/li>\n<li>Cr\u00e9er une interface de boucle sur chacun des serveurs.<\/li>\n<li>Sur les trois serveurs, configurer cette interface avec la m\u00eame adresse IP publique.<\/li>\n<li>L'adresse IP publique est annonc\u00e9e sur Internet via ExaBGP. <\/li>\n<\/ol>\n<p>\nLa r\u00e9silience est obtenue en annon\u00e7ant la m\u00eame adresse IP depuis les trois serveurs. Du point de vue du r\u00e9seau, la m\u00eame adresse est accessible depuis trois diff\u00e9rents next hops. Le routeur voit trois routes identiques et choisit la plus prioritaire selon sa propre m\u00e9trique (g\u00e9n\u00e9ralement la m\u00eame option), et le trafic est dirig\u00e9 uniquement vers l'un des serveurs. <\/p>\n<p>En cas de probl\u00e8me avec le fonctionnement de HAProxy ou de d\u00e9faillance d'un serveur, ExaBGP cesse d'annoncer la route, et le trafic bascule en douceur vers un autre serveur. <\/p>\n<p>Ainsi, nous avons atteint la r\u00e9silience du r\u00e9partiteur.<\/p>\n<p><img decoding=\"async\" alt=\"Comment une architecture web r\u00e9siliente est-elle mise en \u0153uvre sur la plateforme Mail.ru Cloud Solutions\" src=\"\/wp-content\/uploads\/2019\/11\/9fba0718176dc1266f25a2c01ec87348.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>R\u00e9silience des r\u00e9partiteurs HAProxy.<\/i><\/p>\n<p>Le sch\u00e9ma n'est pas id\u00e9al : nous avons appris \u00e0 rendre HAProxy redondant, mais nous n'avons pas su r\u00e9partir la charge au sein des services. Nous avons donc \u00e9largi ce sch\u00e9ma : nous avons opt\u00e9 pour un \u00e9quilibrage entre plusieurs adresses IP publiques.<\/p>\n<h2>\u00c9quilibrage bas\u00e9 sur DNS et BGP<\/h2>\n<p>\nLa question de l'\u00e9quilibrage de charge devant nos HAProxy reste \u00e0 r\u00e9soudre. N\u00e9anmoins, il est assez simple de le faire, comme nous l'avons fait chez nous.<\/p>\n<p>Pour \u00e9quilibrer trois serveurs, il faudra trois adresses IP publiques et le bon vieux DNS. Chacune de ces adresses est d\u00e9finie sur l'interface loopback de chaque HAProxy et annonc\u00e9e sur Internet. <\/p>\n<p>Dans OpenStack, un r\u00e9pertoire de services est utilis\u00e9 pour g\u00e9rer les ressources, dans lequel est d\u00e9fini le point de terminaison API de chaque service. Dans ce r\u00e9pertoire, nous inscrivons le nom de domaine \u2014 public.infra.mail.ru, qui est r\u00e9solu via DNS avec trois adresses IP diff\u00e9rentes. En cons\u00e9quence, nous obtenons une r\u00e9partition de charge entre les trois adresses par le biais de DNS. <\/p>\n<p>Cependant, lorsque nous annon\u00e7ons des adresses IP publiques, nous ne g\u00e9rons pas les priorit\u00e9s de s\u00e9lection du serveur, ce qui n'est pas encore de l'\u00e9quilibrage. En g\u00e9n\u00e9ral, un seul serveur sera choisi selon la hi\u00e9rarchie de l'adresse IP, tandis que les deux autres resteront inactifs, car aucune m\u00e9trique n'est sp\u00e9cifi\u00e9e dans BGP.<\/p>\n<p>Nous avons commenc\u00e9 \u00e0 annoncer des routes via ExaBGP avec diff\u00e9rentes m\u00e9triques. Chaque \u00e9quilibrage annonce les trois adresses IP publiques, mais l'une d'entre elles, celle principale pour cet \u00e9quilibrage, est annonc\u00e9e avec la m\u00e9trique minimale. Donc, tant que les trois \u00e9quilibrages sont en fonctionnement, les demandes \u00e0 la premi\u00e8re adresse IP atteignent le premier \u00e9quilibrage, celles \u00e0 la seconde vont au second, et ainsi de suite.<\/p>\n<p>Que se passe-t-il lorsque l'un des \u00e9quilibrages \u00e9choue ? Lorsque n'importe quel \u00e9quilibrage \u00e9choue, son adresse principale est toujours annonc\u00e9e par les deux autres, et le trafic entre eux est redistribu\u00e9. Ainsi, nous fournissons \u00e0 l'utilisateur plusieurs adresses IP via DNS. Gr\u00e2ce \u00e0 un \u00e9quilibrage par DNS et \u00e0 une m\u00e9trique diff\u00e9rente, nous obtenons une r\u00e9partition uniforme de la charge sur les trois \u00e9quilibreurs. Et nous ne perdons pas en tol\u00e9rance aux pannes.<\/p>\n<p><img decoding=\"async\" alt=\"Comment une architecture web r\u00e9siliente est-elle mise en \u0153uvre sur la plateforme Mail.ru Cloud Solutions\" src=\"\/wp-content\/uploads\/2019\/11\/1485367a934aea06b68c6d05c184d263.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>\u00c9quilibrage HAProxy bas\u00e9 sur DNS + BGP<\/i><\/p>\n<h2>Interaction entre ExaBGP et HAProxy<\/h2>\n<p>\nNous avons donc mis en place une tol\u00e9rance aux pannes en cas de d\u00e9faillance d'un serveur, bas\u00e9e sur l'arr\u00eat de l'annonce des routes. Mais HAProxy peut aussi tomber pour d'autres raisons que la d\u00e9faillance d'un serveur : erreurs d'administration, pannes au sein du service. Nous souhaitons retirer un \u00e9quilibrage d\u00e9faillant de la charge et dans ces cas-l\u00e0, un autre m\u00e9canisme est n\u00e9cessaire. <\/p>\n<p>Ainsi, en \u00e9largissant le sch\u00e9ma pr\u00e9c\u00e9dent, nous avons mis en \u0153uvre un heartbeat entre ExaBGP et HAProxy. C'est une impl\u00e9mentation logicielle de l'interaction entre ExaBGP et HAProxy, lorsque ExaBGP utilise des scripts personnalis\u00e9s pour v\u00e9rifier l'\u00e9tat des applications.<\/p>\n<p>Pour cela, il est n\u00e9cessaire de configurer un v\u00e9rificateur d'\u00e9tat dans la configuration d'ExaBGP qui pourra contr\u00f4ler le statut de HAProxy. Dans notre cas, nous avons configur\u00e9 un backend de v\u00e9rification d'\u00e9tat dans HAProxy, et c\u00f4t\u00e9 ExaBGP, nous v\u00e9rifions avec une simple requ\u00eate GET. Si l'annonce cesse d'avoir lieu, cela signifie que HAProxy ne fonctionne probablement pas, et il ne faut pas l'annoncer. <\/p>\n<p><img decoding=\"async\" alt=\"Comment une architecture web r\u00e9siliente est-elle mise en \u0153uvre sur la plateforme Mail.ru Cloud Solutions\" src=\"\/wp-content\/uploads\/2019\/11\/d5cda30043fe02ab81355b28c0d83ac6.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>V\u00e9rification d'\u00e9tat de HAProxy<\/i><\/p>\n<h2>Paires HAProxy : synchronisation des sessions <\/h2>\n<p>\nLa prochaine \u00e9tape consistait \u00e0 synchroniser les sessions. Lorsqu'on utilise des r\u00e9partiteurs de charge distribu\u00e9s, il est difficile d'organiser la conservation des informations sur les sessions des clients. Mais HAProxy est l'un des rares r\u00e9partiteurs capable de le faire gr\u00e2ce \u00e0 la fonctionnalit\u00e9 Peers \u2014 la possibilit\u00e9 de transf\u00e9rer des tables de sessions entre diff\u00e9rents processus HAProxy. <\/p>\n<p>Il existe diff\u00e9rentes m\u00e9thodes de r\u00e9partition : des m\u00e9thodes simples, telles que <noindex><a rel=\"nofollow\" href=\"https:\/\/ru.wikipedia.org\/wiki\/Round-robin_(%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC)\">round-robin<\/a><\/noindex>, et des m\u00e9thodes avanc\u00e9es, o\u00f9 la session du client est m\u00e9moris\u00e9e, et il est dirig\u00e9 \u00e0 chaque fois vers le m\u00eame serveur qu'auparavant. Nous souhaitions mettre en \u0153uvre la seconde option.<\/p>\n<p>Dans HAProxy, pour la conservation des sessions clients, on utilise des stick-tables. Elles sauvegardent l'adresse IP d'origine du client, l'adresse cible choisie (backend) et certaines informations auxiliaires. En g\u00e9n\u00e9ral, les stick-tables sont utilis\u00e9es pour enregistrer les paires source-IP + destination-IP, ce qui est particuli\u00e8rement utile pour les applications qui ne peuvent pas transmettre le contexte de la session utilisateur lors du passage \u00e0 un autre r\u00e9partiteur, par exemple \u2014 en mode de r\u00e9partition RoundRobin.<\/p>\n<p>Si l'on apprend \u00e0 la stick-table \u00e0 se d\u00e9placer entre diff\u00e9rents processus HAProxy (entre lesquels la r\u00e9partition s'effectue), nos r\u00e9partiteurs pourront travailler avec un seul pool de stick-tables. Cela permettra un passage fluide du r\u00e9seau client en cas de d\u00e9faillance de l'un des r\u00e9partiteurs ; le travail sur les sessions des clients continuera sur les m\u00eames backends qui avaient \u00e9t\u00e9 choisis pr\u00e9c\u00e9demment.<\/p>\n<p>Pour un bon fonctionnement, il est n\u00e9cessaire de r\u00e9soudre le probl\u00e8me de l'adresse IP source du r\u00e9partiteur \u00e0 partir duquel la session a \u00e9t\u00e9 \u00e9tablie. Dans notre cas, il s'agit d'une adresse dynamique sur l'interface loopback. <\/p>\n<p>Le bon fonctionnement des pairs n'est possible que dans certaines conditions. En d'autres termes, les d\u00e9lais d'attente TCP doivent \u00eatre suffisamment longs ou le basculement doit \u00eatre assez rapide pour \u00e9viter que la session TCP ne se rompe. Cela permet n\u00e9anmoins un basculement transparent. <\/p>\n<p>Nous avons un service dans l'IaaS bas\u00e9 sur la m\u00eame technologie. Il s'agit de <noindex><a rel=\"nofollow\" href=\"https:\/\/mcs.mail.ru\/app\/services\/infra\/balancers-list\/\">Load Balancer en tant que service pour OpenStack<\/a><\/noindex>, qui s'appelle Octavia. Il est bas\u00e9 sur une infrastructure de deux processus HAProxy, avec une prise en charge initiale des pairs. Dans ce service, ils ont fait leurs preuves.<\/p>\n<p>L'image illustre sch\u00e9matiquement le d\u00e9placement des tables de pairs entre trois instances HAProxy, avec une configuration propos\u00e9e pour la mise en place :<\/p>\n<p><img decoding=\"async\" alt=\"Comment une architecture web r\u00e9siliente est-elle mise en \u0153uvre sur la plateforme Mail.ru Cloud Solutions\" src=\"\/wp-content\/uploads\/2019\/11\/d31fab761da627923345b7ace7f0b943.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>HAProxy Peers (synchronisation des sessions)<\/i><\/p>\n<p>Si vous impl\u00e9mentez un sch\u00e9ma similaire, il faut le tester attentivement. Il n'est pas garanti que cela fonctionne de la m\u00eame mani\u00e8re dans 100 % des cas. Cependant, vous ne perdrez pas les tables de stick lorsque vous devez vous souvenir de l'adresse IP source du client.<\/p>\n<h2>Limitation du nombre de requ\u00eates simultan\u00e9es d'un m\u00eame client<\/h2>\n<p>\nTous les services accessibles publiquement, y compris nos API, peuvent \u00eatre sujets \u00e0 des vagues de requ\u00eates. Les raisons peuvent \u00eatre vari\u00e9es, allant d'erreurs des utilisateurs \u00e0 des attaques cibl\u00e9es. Nous subissons p\u00e9riodiquement des attaques DDoS par adresses IP. Les clients se trompent souvent dans leurs scripts, ce qui nous cause de mini-DDoS.<\/p>\n<p>Quoi qu'il en soit, il est n\u00e9cessaire de pr\u00e9voir une protection suppl\u00e9mentaire. Une solution \u00e9vidente consiste \u00e0 limiter le nombre de requ\u00eates \u00e0 l'API et \u00e0 ne pas perdre de temps processeur \u00e0 traiter des requ\u00eates malveillantes.<\/p>\n<p>Pour mettre en place de telles limitations, nous appliquons des taux limites, organis\u00e9s sur la base d'HAProxy, en utilisant les m\u00eames tables de stick. Les limites sont configur\u00e9es assez simplement et permettent de restreindre l'utilisateur par le nombre de requ\u00eates \u00e0 l'API. L'algorithme m\u00e9morise l'adresse IP source d'o\u00f9 proviennent les requ\u00eates et limite le nombre de requ\u00eates simultan\u00e9es d'un m\u00eame utilisateur. Bien s\u00fbr, nous avons calcul\u00e9 le profil moyen de charge sur l'API pour chaque service et avons \u00e9tabli une limite d'environ 10 fois sup\u00e9rieure \u00e0 cette valeur. Nous continuons \u00e0 surveiller attentivement la situation, en gardant un \u0153il sur le pouls.<\/p>\n<p>Quel est le rendu en pratique ? Nous avons des clients qui utilisent constamment nos API pour l'autoscaling. Ils cr\u00e9ent environ deux \u00e0 trois cents machines virtuelles le matin et les suppriment le soir. Pour OpenStack, cr\u00e9er une machine virtuelle avec des services PaaS n\u00e9cessite au moins 1000 requ\u00eates API, car l'interaction entre les services se fait \u00e9galement via API. <\/p>\n<p>Ces transferts de t\u00e2ches g\u00e9n\u00e8rent une charge assez importante. Nous avons \u00e9valu\u00e9 cette charge, collect\u00e9 les pics quotidiens, les avons multipli\u00e9s par dix, et cela est devenu notre taux limite. Nous restons vigilants. Nous voyons souvent des bots, des scanners qui essaient de v\u00e9rifier s'il y a des scripts CGA \u00e0 lancer, et nous les bloquons activement.<\/p>\n<h2>Comment mettre \u00e0 jour la base de code sans que les utilisateurs le remarquent<\/h2>\n<p>\nNous mettons en \u0153uvre la r\u00e9silience \u00e9galement au niveau des processus de d\u00e9ploiement du code. Des pannes peuvent survenir lors des d\u00e9ploiements, mais leur impact sur la disponibilit\u00e9 des services peut \u00eatre minimis\u00e9.<\/p>\n<p>Nous mettons constamment \u00e0 jour nos services et devons garantir le processus de mise \u00e0 jour de la base de code sans impact pour les utilisateurs. Nous avons pu r\u00e9soudre cette t\u00e2che en utilisant les fonctionnalit\u00e9s de gestion de HAProxy et la mise en \u0153uvre du Graceful Shutdown dans nos services.<\/p>\n<p>Pour r\u00e9soudre cette t\u00e2che, il \u00e9tait n\u00e9cessaire d'assurer la gestion du r\u00e9partiteur de charge et l'arr\u00eat 'correct' des services :<\/p>\n<ul>\n<li>Dans le cas de HAProxy, la gestion se fait via un fichier stats, qui est essentiellement un socket d\u00e9fini dans la configuration de HAProxy. Les commandes peuvent y \u00eatre transmises via stdio. Mais notre principal outil de contr\u00f4le des configurations est Ansible, donc il contient un module int\u00e9gr\u00e9 pour g\u00e9rer HAProxy. Que nous utilisons activement. <\/li>\n<li>La majorit\u00e9 de nos services API et Engine prennent en charge les technologies de shutdown gracieux : lors de l'arr\u00eat, ils attendent l'ach\u00e8vement complet de la t\u00e2che en cours, qu'il s'agisse d'une requ\u00eate http ou d'une t\u00e2che de maintenance. Il en va de m\u00eame pour le worker. Il conna\u00eet toutes les t\u00e2ches qu'il effectue et s'arr\u00eate lorsqu'il a termin\u00e9 avec succ\u00e8s toutes les t\u00e2ches. <\/li>\n<\/ul>\n<p>\nGr\u00e2ce \u00e0 ces deux points, notre algorithme de d\u00e9ploiement s\u00e9curis\u00e9 est le suivant.<\/p>\n<ol>\n<li>Le d\u00e9veloppeur assemble un nouveau paquet de code (pour nous, c'est un RPM), le teste dans l'environnement de d\u00e9veloppement, le teste dans l'environnement de pr\u00e9-production, et le laisse dans le d\u00e9p\u00f4t de pr\u00e9-production.<\/li>\n<li>Le d\u00e9veloppeur \u00e9tablit la t\u00e2che de d\u00e9ploiement avec une description aussi d\u00e9taill\u00e9e que possible des \u00ab artefacts \u00bb : version du nouveau package, description des nouvelles fonctionnalit\u00e9s et d'autres d\u00e9tails sur le d\u00e9ploiement si n\u00e9cessaire.<\/li>\n<li>L'administrateur syst\u00e8me commence la mise \u00e0 jour. Il lance le playbook Ansible, qui, \u00e0 son tour, effectue les actions suivantes : \n<ul>\n<li>Il prend le package du d\u00e9p\u00f4t de staging et met \u00e0 jour la version du package dans le d\u00e9p\u00f4t de production.<\/li>\n<li>Il dresse la liste des backends du service en cours de mise \u00e0 jour.<\/li>\n<li>Il d\u00e9sactive le premier service \u00e0 mettre \u00e0 jour dans HAProxy et attend la fin de ses processus. Gr\u00e2ce \u00e0 un arr\u00eat en douceur, nous sommes assur\u00e9s que toutes les demandes en cours des clients seront trait\u00e9es avec succ\u00e8s.<\/li>\n<li>Apr\u00e8s l'arr\u00eat complet de l'API, des workers et de l'arr\u00eat de HAProxy, le code est mis \u00e0 jour.<\/li>\n<li>Ansible d\u00e9marre les services.<\/li>\n<li>Pour chaque service, il ex\u00e9cute des \u00ab hooks \u00bb sp\u00e9cifiques qui effectuent des tests unitaires sur un certain nombre de tests cl\u00e9s pr\u00e9d\u00e9finis. Une v\u00e9rification de base du nouveau code est r\u00e9alis\u00e9e.<\/li>\n<li>Si aucune erreur n'est d\u00e9tect\u00e9e \u00e0 l'\u00e9tape pr\u00e9c\u00e9dente, le backend est activ\u00e9.<\/li>\n<li>Nous passons au backend suivant.<\/li>\n<\/ul>\n<\/li>\n<li>Apr\u00e8s la mise \u00e0 jour de tous les backends, des tests fonctionnels sont lanc\u00e9s. S'il en manque, le d\u00e9veloppeur examine toute nouvelle fonctionnalit\u00e9 qu'il a d\u00e9velopp\u00e9e.<\/li>\n<\/ol>\n<p>\nLe d\u00e9ploiement est maintenant termin\u00e9.<\/p>\n<p><img decoding=\"async\" alt=\"Comment une architecture web r\u00e9siliente est-elle mise en \u0153uvre sur la plateforme Mail.ru Cloud Solutions\" src=\"\/wp-content\/uploads\/2019\/11\/2d889fe1af33653e4bfebabe1cce6552.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>Le cycle de mise \u00e0 jour du service<\/i><\/p>\n<p>Ce sch\u00e9ma ne fonctionnerait pas s'il n'y avait pas une r\u00e8gle. Nous faisons fonctionner simultan\u00e9ment l'ancienne et la nouvelle version. Au pr\u00e9alable, au stade de d\u00e9veloppement du logiciel, il est pr\u00e9vu que m\u00eame s'il y a des modifications dans la base de donn\u00e9es du service, elles ne casseront pas le code pr\u00e9c\u00e9dent. En cons\u00e9quence, il y a une mise \u00e0 jour progressive de la base de code.<\/p>\n<h2>Conclusion<\/h2>\n<p>\nEn partageant mes r\u00e9flexions sur l'architecture web tol\u00e9rante aux pannes, je souhaite souligner \u00e0 nouveau ses points cl\u00e9s :<\/p>\n<ul>\n<li>tol\u00e9rance aux pannes physiques ;<\/li>\n<li>tol\u00e9rance aux pannes r\u00e9seau (\u00e9quilibreurs, BGP) ;<\/li>\n<li>tol\u00e9rance aux pannes des logiciels utilis\u00e9s et d\u00e9velopp\u00e9s.<\/li>\n<\/ul>\n<p>\n\u00c0 tous, un uptime stable !<br \/>\n<br \/>Source : <a content=\"nofollow\" rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/mailru\/blog\/474180\/\">habr.com<\/a><\/p>","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"excerpt":{"rendered":"<p>\u041f\u0440\u0438\u0432\u0435\u0442, \u0425\u0430\u0431\u0440! \u042f \u0410\u0440\u0442\u0435\u043c \u041a\u0430\u0440\u0430\u043c\u044b\u0448\u0435\u0432, \u0440\u0443\u043a\u043e\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c \u043a\u043e\u043c\u0430\u043d\u0434\u044b \u0441\u0438\u0441\u0442\u0435\u043c\u043d\u043e\u0433\u043e \u0430\u0434\u043c\u0438\u043d\u0438\u0441\u0442\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f Mail.Ru Cloud Solutions (MCS). \u0417\u0430 \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0438\u0439 \u0433\u043e\u0434 \u0443 \u043d\u0430\u0441 \u0431\u044b\u043b\u043e \u043c\u043d\u043e\u0433\u043e \u0437\u0430\u043f\u0443\u0441\u043a\u043e\u0432 \u043d\u043e\u0432\u044b\u0445 \u043f\u0440\u043e\u0434\u0443\u043a\u0442\u043e\u0432. \u041c\u044b \u0445\u043e\u0442\u0435\u043b\u0438 \u0434\u043e\u0431\u0438\u0442\u044c\u0441\u044f, \u0447\u0442\u043e\u0431\u044b API-\u0441\u0435\u0440\u0432\u0438\u0441\u044b \u043b\u0435\u0433\u043a\u043e \u043c\u0430\u0441\u0448\u0442\u0430\u0431\u0438\u0440\u043e\u0432\u0430\u043b\u0438\u0441\u044c, \u0431\u044b\u043b\u0438 \u043e\u0442\u043a\u0430\u0437\u043e\u0443\u0441\u0442\u043e\u0439\u0447\u0438\u0432\u044b\u043c\u0438 \u0438 \u0433\u043e\u0442\u043e\u0432\u044b\u043c\u0438 \u043a \u0431\u044b\u0441\u0442\u0440\u043e\u043c\u0443 \u0440\u043e\u0441\u0442\u0443 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u0441\u043a\u043e\u0439 \u043d\u0430\u0433\u0440\u0443\u0437\u043a\u0438. \u041d\u0430\u0448\u0430 \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u0430 \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043d\u0430 \u043d\u0430 OpenStack, \u0438 \u044f \u0445\u043e\u0447\u0443 \u0440\u0430\u0441\u0441\u043a\u0430\u0437\u0430\u0442\u044c, \u043a\u0430\u043a\u0438\u0435 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u044b \u043e\u0442\u043a\u0430\u0437\u043e\u0443\u0441\u0442\u043e\u0439\u0447\u0438\u0432\u043e\u0441\u0442\u0438 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u043e\u0432 \u043d\u0430\u043c \u043f\u0440\u0438\u0448\u043b\u043e\u0441\u044c \u0437\u0430\u043a\u0440\u044b\u0442\u044c, [&hellip;]<\/p>\n","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[688],"tags":[],"class_list":["post-52389","post","type-post","status-publish","format-standard","hentry","category-administrirovanie"],"aioseo_notices":[],"aioseo_head":"\n\t\t<!-- All in One SEO 5.0.2.1 - aioseo.com -->\n\t<meta name=\"description\" content=\".\" \/>\n\t<meta name=\"robots\" content=\"max-image-preview:large\" \/>\n\t<meta name=\"author\" content=\"Yuri Gagarin\"\/>\n\t<link rel=\"canonical\" href=\"https:\/\/prohoster.info\/fr\/blog\/administrirovanie\/kak-realizuetsya-otkazoustojchivaya-veb-arhitektura-v-platforme-mail-ru-cloud-solutions\" \/>\n\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 5.0.2.1\" \/>\n\t\t<meta property=\"og:locale\" content=\"fr_FR\" \/>\n\t\t<meta property=\"og:site_name\" content=\"ProHoster | \u041a\u0443\u043f\u0438\u0442\u044c \u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0439 \u0445\u043e\u0441\u0442\u0438\u043d\u0433 \u0434\u043b\u044f \u0441\u0430\u0439\u0442\u043e\u0432 \u0441 \u0437\u0430\u0449\u0438\u0442\u043e\u0439 \u043e\u0442 DDoS, VPS VDS \u0441\u0435\u0440\u0432\u0435\u0440\u044b\" \/>\n\t\t<meta property=\"og:type\" content=\"article\" \/>\n\t\t<meta property=\"og:title\" content=\"\ud83e\udd47\u041a\u0430\u043a \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u0442\u0441\u044f \u043e\u0442\u043a\u0430\u0437\u043e\u0443\u0441\u0442\u043e\u0439\u0447\u0438\u0432\u0430\u044f \u0432\u0435\u0431-\u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u0430 \u0432 \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u0435 Mail.ru Cloud Solutions | ProHoster\" \/>\n\t\t<meta property=\"og:description\" content=\".\" \/>\n\t\t<meta property=\"og:url\" content=\"https:\/\/prohoster.info\/fr\/blog\/administrirovanie\/kak-realizuetsya-otkazoustojchivaya-veb-arhitektura-v-platforme-mail-ru-cloud-solutions\" \/>\n\t\t<meta property=\"og:image\" content=\"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg\" \/>\n\t\t<meta property=\"og:image:secure_url\" content=\"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg\" \/>\n\t\t<meta property=\"og:image:width\" content=\"350\" \/>\n\t\t<meta property=\"og:image:height\" content=\"350\" \/>\n\t\t<meta property=\"article:published_time\" content=\"2019-11-06T21:00:00+00:00\" \/>\n\t\t<meta property=\"article:modified_time\" content=\"2020-02-18T11:00:05+00:00\" \/>\n\t\t<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/prohoster\" \/>\n\t\t<meta property=\"article:author\" content=\"https:\/\/www.facebook.com\/prohoster\" \/>\n\t\t<!-- All in One SEO -->\n\n","aioseo_head_json":{"title":"\ud83e\udd47Comment mettre en \u0153uvre une architecture web tol\u00e9rante aux pannes sur la plateforme Mail.ru Cloud Solutions | ProHoster","description":".","canonical_url":"https:\/\/prohoster.info\/fr\/blog\/administrirovanie\/kak-realizuetsya-otkazoustojchivaya-veb-arhitektura-v-platforme-mail-ru-cloud-solutions","robots":"max-image-preview:large","keywords":"","webmasterTools":{"miscellaneous":""},"schema":null,"og:locale":"fr_FR","og:site_name":"ProHoster | \u041a\u0443\u043f\u0438\u0442\u044c \u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0439 \u0445\u043e\u0441\u0442\u0438\u043d\u0433 \u0434\u043b\u044f \u0441\u0430\u0439\u0442\u043e\u0432 \u0441 \u0437\u0430\u0449\u0438\u0442\u043e\u0439 \u043e\u0442 DDoS, VPS VDS \u0441\u0435\u0440\u0432\u0435\u0440\u044b","og:type":"article","og:title":"\ud83e\udd47\u041a\u0430\u043a \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u0442\u0441\u044f \u043e\u0442\u043a\u0430\u0437\u043e\u0443\u0441\u0442\u043e\u0439\u0447\u0438\u0432\u0430\u044f \u0432\u0435\u0431-\u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u0430 \u0432 \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u0435 Mail.ru Cloud Solutions | ProHoster","og:description":".","og:url":"https:\/\/prohoster.info\/fr\/blog\/administrirovanie\/kak-realizuetsya-otkazoustojchivaya-veb-arhitektura-v-platforme-mail-ru-cloud-solutions","og:image":"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg","og:image:secure_url":"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg","og:image:width":350,"og:image:height":350,"article:published_time":"2019-11-06T21:00:00+00:00","article:modified_time":"2020-02-18T11:00:05+00:00","article:publisher":"https:\/\/www.facebook.com\/prohoster","article:author":"https:\/\/www.facebook.com\/prohoster"},"aioseo_meta_data":{"post_id":"52389","title":null,"description":null,"keywords":null,"keyphrases":null,"primary_term":null,"canonical_url":null,"og_title":null,"og_description":null,"og_object_type":"default","og_image_type":"default","og_image_url":null,"og_image_width":null,"og_image_height":null,"og_image_custom_url":null,"og_image_custom_fields":null,"og_video":null,"og_custom_url":null,"og_article_section":null,"og_article_tags":null,"twitter_use_og":false,"twitter_card":"default","twitter_image_type":"default","twitter_image_url":null,"twitter_image_custom_url":null,"twitter_image_custom_fields":null,"twitter_title":null,"twitter_description":null,"schema":{"blockGraphs":[],"customGraphs":[],"default":{"data":{"Article":[],"Course":[],"Dataset":[],"FAQPage":[],"Movie":[],"Person":[],"Product":[],"ProductReview":[],"Car":[],"Recipe":[],"Service":[],"SoftwareApplication":[],"WebPage":[]},"graphName":"","isEnabled":true},"graphs":[]},"schema_type":null,"schema_type_options":null,"pillar_content":false,"robots_default":true,"robots_noindex":false,"robots_noarchive":false,"robots_nosnippet":false,"robots_nofollow":false,"robots_noimageindex":false,"robots_noodp":false,"robots_notranslate":false,"robots_max_snippet":null,"robots_max_videopreview":null,"robots_max_imagepreview":"large","priority":null,"frequency":null,"local_seo":null,"seo_analyzer_scan_date":"2026-01-24 03:27:21","breadcrumb_settings":null,"limit_modified_date":false,"reviewed_by":null,"ai":null,"created":"2021-02-28 20:44:43","updated":"2026-01-24 03:27:21","focus_keyword":null,"additional_keywords":null,"truseo_locale":null},"gt_translate_keys":[{"key":"link","format":"url"}],"_links":{"self":[{"href":"https:\/\/prohoster.info\/fr\/wp-json\/wp\/v2\/posts\/52389","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/prohoster.info\/fr\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/prohoster.info\/fr\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/prohoster.info\/fr\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/prohoster.info\/fr\/wp-json\/wp\/v2\/comments?post=52389"}],"version-history":[{"count":0,"href":"https:\/\/prohoster.info\/fr\/wp-json\/wp\/v2\/posts\/52389\/revisions"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/fr\/wp-json\/wp\/v2\/media?parent=52389"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/fr\/wp-json\/wp\/v2\/categories?post=52389"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/fr\/wp-json\/wp\/v2\/tags?post=52389"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}