{"id":84114,"date":"2020-06-05T07:42:55","date_gmt":"2020-06-05T05:42:55","guid":{"rendered":"https:\/\/prohoster.info\/blog\/administrirovanie\/one-cloud-os-urovnya-data-czentra-v-odnoklassnikah"},"modified":"2020-06-05T07:42:55","modified_gmt":"2020-06-05T05:42:55","slug":"one-cloud-os-urovnya-data-czentra-v-odnoklassnikah","status":"publish","type":"post","link":"https:\/\/prohoster.info\/fr\/blog\/administrirovanie\/one-cloud-os-urovnya-data-czentra-v-odnoklassnikah","title":{"rendered":"One-cloud \u2014 Syst\u00e8me de niveau centre de donn\u00e9es \u00e0 Odnoklassniki","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<p><img decoding=\"async\" alt=\"One-cloud \u2014 Syst\u00e8me de niveau centre de donn\u00e9es \u00e0 Odnoklassniki\" src=\"\/wp-content\/uploads\/2020\/06\/fa983acacec59ff2d4ed098f87223971.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Aloha, tout le monde ! Je m'appelle Oleg Anastasyev, je travaille chez Odnoklassniki dans l'\u00e9quipe de la Plateforme. En plus de moi, il y a une multitude de mat\u00e9riel chez Odnoklassniki. Nous avons quatre centres de donn\u00e9es, avec environ 500 racks contenant plus de 8 000 serveurs. \u00c0 un certain moment, nous avons r\u00e9alis\u00e9 que l'impl\u00e9mentation d'un nouveau syst\u00e8me de gestion nous permettrait de mieux exploiter la technologie, de faciliter la gestion des acc\u00e8s, d'automatiser la (re)r\u00e9partition des ressources calculatoires, d'acc\u00e9l\u00e9rer le lancement de nouveaux services et d'am\u00e9liorer les r\u00e9actions lors de pannes majeures. <\/p>\n<p><\/p>\n<p>Alors, qu'est-ce que cela a donn\u00e9 ? <\/p>\n<p><noindex><a rel=\"nofollow\" name=\"habracut\"><\/a><\/noindex><\/p>\n<p>En plus de moi et du mat\u00e9riel, il y a aussi des gens qui travaillent avec cet \u00e9quipement : des ing\u00e9nieurs qui se trouvent directement dans les centres de donn\u00e9es ; des r\u00e9seaux qui configurent l'infrastructure r\u00e9seau ; des admins, ou SRE, qui assurent la r\u00e9silience de l'infrastructure ; et des \u00e9quipes de d\u00e9veloppeurs, chacune responsable d'une partie des fonctionnalit\u00e9s du portail. Les logiciels qu'ils cr\u00e9ent fonctionnent comme ceci :<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"One-cloud \u2014 Syst\u00e8me de niveau centre de donn\u00e9es \u00e0 Odnoklassniki\" src=\"\/wp-content\/uploads\/2020\/06\/592fd0acfa7322eb80fbb85601a92918.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Les requ\u00eates des utilisateurs arrivent \u00e0 la fois sur les frontaux du portail principal <noindex><a rel=\"nofollow\" href=\"http:\/\/www.ok.ru\/\">www.ok.ru<\/a><\/noindex>, mais aussi sur d'autres, comme les frontaux de l'API musicale. Pour traiter la logique m\u00e9tier, ils appellent un serveur d'applications qui, en traitant la requ\u00eate, appelle les microservices sp\u00e9cialis\u00e9s n\u00e9cessaires : one-graph (graph des relations sociales), user-cache (cache des profils utilisateurs), etc.<\/p>\n<p><\/p>\n<p>Chacun de ces services est d\u00e9ploy\u00e9 sur de nombreuses machines, et chacun d'eux a des d\u00e9veloppeurs responsables qui s'occupent du fonctionnement des modules, de leur exploitation et de leur d\u00e9veloppement technologique. Tous ces services sont d\u00e9ploy\u00e9s sur des serveurs physiques, et jusqu'\u00e0 r\u00e9cemment, nous lancions exactement une t\u00e2che sur un serveur, c'est-\u00e0-dire qu'il \u00e9tait sp\u00e9cialis\u00e9 pour une t\u00e2che sp\u00e9cifique.<\/p>\n<p><\/p>\n<p>Pourquoi cette approche ? Elle avait plusieurs avantages :<\/p>\n<p><\/p>\n<ul>\n<li>Elle facilite <strong>la gestion de masse<\/strong>. Supposons qu'une t\u00e2che n\u00e9cessite certaines biblioth\u00e8ques, certaines configurations. Dans ce cas, le serveur est attribu\u00e9 \u00e0 un groupe sp\u00e9cifique, une politique cfengine est d\u00e9crite pour ce groupe (ou elle est d\u00e9j\u00e0 d\u00e9crite), et cette configuration est d\u00e9ploy\u00e9e de mani\u00e8re centralis\u00e9e et automatique sur tous les serveurs de ce groupe.<\/li>\n<li>Elle simplifie <strong>le diagnostic<\/strong>Supposons que vous observiez une charge accrue sur le CPU et que vous r\u00e9alisiez que cette charge ne pourrait avoir \u00e9t\u00e9 g\u00e9n\u00e9r\u00e9e que par la t\u00e2che fonctionnant sur ce processeur physique. La recherche des responsables se termine tr\u00e8s rapidement.<\/li>\n<li>Elle simplifie <strong>surveillance<\/strong>Si quelque chose ne va pas avec le serveur, le moniteur en informe et vous savez exactement qui est \u00e0 bl\u00e2mer.<\/li>\n<\/ul>\n<p><\/p>\n<p>Un service compos\u00e9 de plusieurs r\u00e9plicas se voit attribuer plusieurs serveurs \u2014 un pour chacun. Ainsi, la ressource de calcul pour le service est r\u00e9partie tr\u00e8s simplement : autant de serveurs que le service poss\u00e8de, autant il peut consommer de ressources au maximum. \u00ab Simple \u00bb ici ne signifie pas que c'est facile \u00e0 utiliser, mais que la r\u00e9partition des ressources se fait manuellement.<\/p>\n<p><\/p>\n<p>Cette m\u00e9thode nous a \u00e9galement permis de r\u00e9aliser <strong>des configurations mat\u00e9rielles sp\u00e9cialis\u00e9es<\/strong> pour la t\u00e2che ex\u00e9cut\u00e9e sur ce serveur. Si la t\u00e2che stocke de grands volumes de donn\u00e9es, nous utilisons un serveur 4U avec un ch\u00e2ssis de 38 disques. Si la t\u00e2che est purement computationnelle, nous pouvons acheter un serveur 1U moins cher. Cela est efficace en termes de ressources de calcul. De plus, cette m\u00e9thode nous permet d'utiliser quatre fois moins de machines pour une charge comparable \u00e0 celle d'un r\u00e9seau social qui nous est amical. <\/p>\n<p><\/p>\n<p>Une telle efficacit\u00e9 dans l'utilisation des ressources de calcul devrait \u00e9galement garantir une efficacit\u00e9 \u00e9conomique, partant du principe que ce qui co\u00fbte le plus cher, ce sont les serveurs. Pendant longtemps, le mat\u00e9riel a \u00e9t\u00e9 le plus co\u00fbteux, et nous avons investi beaucoup d'efforts pour r\u00e9duire le prix du mat\u00e9riel en concevant des algorithmes de tol\u00e9rance aux pannes afin de r\u00e9duire les exigences en mati\u00e8re de fiabilit\u00e9 du mat\u00e9riel. Aujourd'hui, nous sommes arriv\u00e9s \u00e0 un stade o\u00f9 le prix du serveur ne constitue plus un facteur d\u00e9terminant. Si l'on ne prend pas en compte les derni\u00e8res excentricit\u00e9s, la configuration sp\u00e9cifique des serveurs dans le rack n'a pas d'importance. Nous avons d\u00e9sormais un autre probl\u00e8me \u2014 le co\u00fbt de l'espace occup\u00e9 par le serveur dans le datacenter, c'est-\u00e0-dire l'espace dans le rack.<\/p>\n<p><\/p>\n<p>Ayant r\u00e9alis\u00e9 cela, nous avons d\u00e9cid\u00e9 de calculer \u00e0 quel point nous utilisons efficacement les racks.<br \/>\nNous avons pris le prix du serveur le plus puissant parmi ceux \u00e9conomiquement viables, calcul\u00e9 combien de ces serveurs nous pouvions placer dans les racks, combien de t\u00e2ches nous pourrions y ex\u00e9cuter selon l'ancien mod\u00e8le \u00ab un serveur = une t\u00e2che \u00bb et dans quelle mesure ces t\u00e2ches pourraient utiliser le mat\u00e9riel. Les calculs ont \u00e9t\u00e9 d\u00e9chirants. Il s'est av\u00e9r\u00e9 que l'efficacit\u00e9 de l'utilisation des racks chez nous est d'environ 11 %. Le constat est clair : il faut am\u00e9liorer l'efficacit\u00e9 d'utilisation des centres de donn\u00e9es. \u00c0 premi\u00e8re vue, la solution para\u00eet \u00e9vidente : il faut ex\u00e9cuter plusieurs t\u00e2ches sur un m\u00eame serveur. Mais c'est l\u00e0 que commencent les complications. <\/p>\n<p><\/p>\n<p>La configuration de masse devient soudainement beaucoup plus complexe \u2014 il devient impossible d'attribuer un groupe unique \u00e0 un serveur. En effet, plusieurs t\u00e2ches de diff\u00e9rentes \u00e9quipes peuvent maintenant \u00eatre ex\u00e9cut\u00e9es sur un m\u00eame serveur. De plus, la configuration peut \u00eatre conflictuelle pour diff\u00e9rentes applications. Le diagnostic devient \u00e9galement plus complexe : si vous constatez une utilisation accrue des processeurs ou des disques sur le serveur, vous ne savez pas quelle t\u00e2che pose probl\u00e8me.<\/p>\n<p><\/p>\n<p>Mais le plus important, c'est qu'il n'y a pas d'isolation entre les t\u00e2ches ex\u00e9cut\u00e9es sur une m\u00eame machine. Par exemple, voici le graphique du temps de r\u00e9ponse moyen d'une t\u00e2che serveur avant et apr\u00e8s le lancement d'une autre application de calcul non li\u00e9e sur le m\u00eame serveur \u2014 le temps de r\u00e9ponse de la t\u00e2che principale a consid\u00e9rablement augment\u00e9.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"One-cloud \u2014 Syst\u00e8me de niveau centre de donn\u00e9es \u00e0 Odnoklassniki\" src=\"\/wp-content\/uploads\/2020\/06\/c7c07359ae572ca8c84a4c63559e4083.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Il est \u00e9vident qu'il faut ex\u00e9cuter les t\u00e2ches soit dans des conteneurs, soit dans des machines virtuelles. Comme la plupart des t\u00e2ches que nous ex\u00e9cutons fonctionnent sous un seul syst\u00e8me d'exploitation (Linux) ou sont adapt\u00e9es \u00e0 celui-ci, il n'est pas n\u00e9cessaire de g\u00e9rer plusieurs syst\u00e8mes d'exploitation diff\u00e9rents. En cons\u00e9quence, la virtualisation n'est pas n\u00e9cessaire, car en raison des co\u00fbts suppl\u00e9mentaires, elle sera moins efficace que la conteneurisation.<\/p>\n<p><\/p>\n<p>En tant qu'impl\u00e9mentation de conteneurs pour ex\u00e9cuter des t\u00e2ches directement sur les serveurs, Docker est un excellent candidat : les images des syst\u00e8mes de fichiers r\u00e9solvent efficacement les probl\u00e8mes de configurations conflictuelles. Le fait que les images puissent \u00eatre constitu\u00e9es de plusieurs couches nous permet de r\u00e9duire consid\u00e9rablement le volume de donn\u00e9es n\u00e9cessaires \u00e0 leur d\u00e9ploiement sur l'infrastructure, en isolant les parties communes dans des couches de base distinctes. Ainsi, les couches de base (et les plus volumineuses) seront rapidement mises en cache sur l'ensemble de l'infrastructure, et pour la livraison de divers types d'applications et versions, seules de petites couches devront \u00eatre transmises. <\/p>\n<p><\/p>\n<p>De plus, le registre et le marquage des images dans Docker nous fournissent des primitives pr\u00eates \u00e0 l'emploi pour la version et la livraison de code en production.<\/p>\n<p><\/p>\n<p>Docker, comme toute autre technologie similaire, nous offre un certain niveau d'isolation des conteneurs par d\u00e9faut. Par exemple, l'isolation par m\u00e9moire : chaque conteneur se voit attribuer une limite d'utilisation de la m\u00e9moire de la machine, au-del\u00e0 de laquelle il ne pourra pas consommer. Il est \u00e9galement possible d'isoler les conteneurs en fonction de l'utilisation du CPU. Cependant, pour nous, l'isolation standard \u00e9tait insuffisante. Mais nous y reviendrons plus bas.<\/p>\n<p><\/p>\n<p>L'ex\u00e9cution directe des conteneurs sur les serveurs n'est qu'une partie des probl\u00e8mes. L'autre partie concerne le placement des conteneurs sur les serveurs. Il faut comprendre quel conteneur peut \u00eatre plac\u00e9 sur quel serveur. Ce n'est pas une t\u00e2che facile, car il faut disposer les conteneurs sur les serveurs aussi dens\u00e9ment que possible, sans compromettre leur performance. Ce placement peut \u00e9galement \u00eatre complexe en termes de r\u00e9silience. Souvent, nous souhaitons placer des r\u00e9pliques du m\u00eame service dans diff\u00e9rents racks ou m\u00eame dans diff\u00e9rentes salles de donn\u00e9es afin qu'en cas de d\u00e9faillance d'un rack ou d'une salle, nous ne perdions pas toutes les r\u00e9pliques du service. <\/p>\n<p><\/p>\n<p>Distribuer des conteneurs manuellement n'est pas une option quand on a 8000 serveurs et 8000 \u00e0 16000 conteneurs. <\/p>\n<p><\/p>\n<p>De plus, nous voulions donner plus d'autonomie aux d\u00e9veloppeurs dans la distribution des ressources, afin qu'ils puissent d\u00e9ployer eux-m\u00eames leurs services en production, sans l'aide d'un administrateur. Tout en maintenant un contr\u00f4le, afin qu'un service secondaire ne consomme pas toutes les ressources de nos centres de donn\u00e9es. <\/p>\n<p><\/p>\n<p>Il est \u00e9vident qu'un niveau de gestion est n\u00e9cessaire pour s'en occuper automatiquement.<\/p>\n<p><\/p>\n<p>Nous voil\u00e0 arriv\u00e9s \u00e0 une image simple et claire, que tous les architectes adorent : trois carr\u00e9s. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"One-cloud \u2014 Syst\u00e8me de niveau centre de donn\u00e9es \u00e0 Odnoklassniki\" src=\"\/wp-content\/uploads\/2020\/06\/079df6e79874ef55b0d967fde3d5feca.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>one-cloud masters \u2014 un cluster tol\u00e9rant aux pannes, charg\u00e9 de l'orchestration du cloud. Le d\u00e9veloppeur envoie au master un manifeste contenant toutes les informations n\u00e9cessaires au d\u00e9ploiement du service. Sur cette base, le master donne des ordres aux minions s\u00e9lectionn\u00e9s (machines destin\u00e9es \u00e0 ex\u00e9cuter des conteneurs). Sur les minions, il y a notre agent, qui re\u00e7oit l'ordre, d\u00e9livre ses propres commandes \u00e0 Docker, et Docker configure le noyau Linux pour ex\u00e9cuter le conteneur correspondant. En plus d'ex\u00e9cuter les commandes, l'agent informe en continu le master des modifications d'\u00e9tat tant de la machine minion que des conteneurs qui y sont ex\u00e9cut\u00e9s.<\/p>\n<p><\/p>\n<h2 id=\"raspredelenie-resursov\">Distribution des ressources<\/h2>\n<p><\/p>\n<p>Voyons maintenant une t\u00e2che plus complexe de distribution des ressources pour plusieurs minions.<\/p>\n<p><\/p>\n<p>Une ressource de calcul dans one-cloud est :<\/p>\n<p><\/p>\n<ul>\n<li>La puissance de calcul du processeur utilis\u00e9e par une t\u00e2che sp\u00e9cifique. <\/li>\n<li>La quantit\u00e9 de m\u00e9moire disponible pour la t\u00e2che. <\/li>\n<li>Le trafic r\u00e9seau. Chacun des minions poss\u00e8de une interface r\u00e9seau sp\u00e9cifique avec une bande passante limit\u00e9e, il est donc impossible de distribuer des t\u00e2ches sans tenir compte du volume de donn\u00e9es qu'ils transmettent par le r\u00e9seau. <\/li>\n<li>Disques. En plus, bien s\u00fbr, de l'espace pour les donn\u00e9es de la t\u00e2che, nous sp\u00e9cifions \u00e9galement le type de disque : HDD ou SSD. Les disques peuvent servir un nombre final de requ\u00eates par seconde \u2014 IOPS. Ainsi, pour les t\u00e2ches qui g\u00e9n\u00e8rent plus d'IOPS que ce qu'un seul disque peut g\u00e9rer, nous r\u00e9servons \u00e9galement des \u00ab spindles \u00bb \u2014 c'est-\u00e0-dire des dispositifs de stockage qui doivent \u00eatre exclusivement r\u00e9serv\u00e9s pour la t\u00e2che.<\/li>\n<\/ul>\n<p><\/p>\n<p>Ainsi, pour un service comme user-cache, nous pouvons enregistrer les ressources consomm\u00e9es de cette mani\u00e8re : 400 c\u0153urs de processeur, 2,5 To de m\u00e9moire, 50 Gb\/s de trafic aller-retour, 6 To d'espace sur HDD, r\u00e9parti sur 100 spindles. Ou de mani\u00e8re plus famili\u00e8re comme ceci :<\/p>\n<p><\/p>\n<pre><code>alloc:\n    cpu: 400\n    mem: 2500\n    lan_in: 50g\n    lan_out: 50g\n    hdd:100x6T<\/code><\/pre>\n<p><\/p>\n<p>Les ressources du service user-cache ne consomment qu'une partie de toutes les ressources disponibles dans l'infrastructure de production. Il est donc souhaitable de s'assurer que, soudainement, \u00e0 cause d'une erreur d'op\u00e9rateur ou non, user-cache ne consomme pas plus de ressources que celles qui lui sont allou\u00e9es. Nous devons donc limiter les ressources. Mais sur quoi pourrions-nous baser la quota ?<\/p>\n<p><\/p>\n<p>Retournons \u00e0 notre sch\u00e9ma tr\u00e8s simplifi\u00e9 d'interaction entre les composants et redessinons-le avec plus de d\u00e9tails \u2014 comme ceci : <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"One-cloud \u2014 Syst\u00e8me de niveau centre de donn\u00e9es \u00e0 Odnoklassniki\" src=\"\/wp-content\/uploads\/2020\/06\/27e5bfbffadd3d4b9fdc6bf138d135ed.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Ce qui frappe imm\u00e9diatement :<\/p>\n<p><\/p>\n<ul>\n<li>Le front-end web et la musique utilisent des clusters isol\u00e9s du m\u00eame serveur d'applications.<\/li>\n<li>On peut distinguer des couches logiques, auxquelles appartiennent ces clusters : les frontaux, les caches, la couche de stockage et de gestion des donn\u00e9es.<\/li>\n<li>Le front-end est h\u00e9t\u00e9rog\u00e8ne, ce sont diff\u00e9rents sous-syst\u00e8mes fonctionnels. <\/li>\n<li>Les caches peuvent \u00e9galement \u00eatre r\u00e9partis selon le sous-syst\u00e8me, dont ils mettent en cache les donn\u00e9es.<\/li>\n<\/ul>\n<p><\/p>\n<p>Redessinons une fois de plus l'image :<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"One-cloud \u2014 Syst\u00e8me de niveau centre de donn\u00e9es \u00e0 Odnoklassniki\" src=\"\/wp-content\/uploads\/2020\/06\/905dacc0aca859e65bd33ef751a557cf.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Oh ! Nous voyons une hi\u00e9rarchie ! Cela signifie que nous pouvons distribuer les ressources par blocs plus importants : d\u00e9signer un d\u00e9veloppeur responsable d\u2019un n\u0153ud de cette hi\u00e9rarchie, correspondant au sous-syst\u00e8me fonctionnel (comme \u00ab musique \u00bb sur l'image), et lier une quota \u00e0 ce m\u00eame niveau hi\u00e9rarchique. Une telle hi\u00e9rarchie nous permet \u00e9galement d'organiser les services de mani\u00e8re plus flexible pour une meilleure gestion. Par exemple, tout le web, puisque c'est un tr\u00e8s grand regroupement de serveurs, nous le divisons en plusieurs groupes plus petits, montr\u00e9s sur l'image comme group1, group2.<\/p>\n<p><\/p>\n<p>En supprimant les lignes superflues, nous pouvons \u00e9crire chaque n\u0153ud de notre image de mani\u00e8re plus plate : <strong>group1.web.front<\/strong>, <strong>api.music.front<\/strong>, <strong>user-cache.cache<\/strong>.<\/p>\n<p><\/p>\n<p>Ainsi, nous arrivons au concept de \u00ab file d'attente hi\u00e9rarchique \u00bb. Elle a un nom, comme \u00ab group1.web.front \u00bb. Une quota de ressources et des droits d'utilisateur y sont attribu\u00e9s. Une personne du DevOps recevra le droit de soumettre un service \u00e0 la file d'attente, et cette personne pourra lancer quelque chose dans la file d'attente, alors qu'une personne de l'OpsDev \u2014 avec des droits d'administration \u2014 pourra g\u00e9rer la file d'attente, y attribuer des personnes, donner des droits \u00e0 ces personnes, etc. Les services lanc\u00e9s dans cette file d'attente seront ex\u00e9cut\u00e9s dans le cadre de la quota de la file d'attente. Si la quota de calcul de la file d'attente est insuffisante pour ex\u00e9cuter simultan\u00e9ment tous les services, ils seront ex\u00e9cut\u00e9s successivement, formant ainsi la file d'attente proprement dite. <\/p>\n<p><\/p>\n<p>Examinons les services de plus pr\u00e8s. Un service a un nom complet, qui inclut toujours le nom de la file d'attente. Ainsi, le service du front web aura le nom <strong>ok-web.group1.web.front<\/strong>. Tandis que le service du serveur d'applications auquel il fait appel s'appellera <strong>ok-app.group1.web.front<\/strong>. Chaque service a un manifeste, qui contient toutes les informations n\u00e9cessaires pour le d\u00e9ploiement sur des machines sp\u00e9cifiques : combien de ressources cette t\u00e2che consomme, quelle configuration elle n\u00e9cessite, combien de r\u00e9pliques doivent exister, les propri\u00e9t\u00e9s pour la gestion des pannes de ce service. Apr\u00e8s le d\u00e9ploiement du service sur les machines, ses instances apparaissent \u00e9galement. Elles sont aussi nomm\u00e9es de mani\u00e8re unique - par le num\u00e9ro de l'instance et le nom du service : <strong>1.ok-web.group1.web.front, 2.ok-web.group1.web.front, \u2026<\/strong><\/p>\n<p><\/p>\n<p>C'est tr\u00e8s pratique : en regardant uniquement le nom du conteneur en cours d'ex\u00e9cution, nous pouvons imm\u00e9diatement en apprendre beaucoup.<\/p>\n<p><\/p>\n<p>Jetons maintenant un regard plus attentif \u00e0 ce que ces instances effectuent r\u00e9ellement : les t\u00e2ches.<\/p>\n<p><\/p>\n<h2 id=\"klassy-izolyacii-zadach\">Classes d'isolation des t\u00e2ches<\/h2>\n<p><\/p>\n<p>Toutes les t\u00e2ches dans OK (et probablement ailleurs) peuvent \u00eatre divis\u00e9es en groupes :<\/p>\n<p><\/p>\n<ul>\n<li><strong>T\u00e2ches \u00e0 faible latence - prod<\/strong>. Pour ces t\u00e2ches et services, la latence de r\u00e9ponse est tr\u00e8s importante, c'est-\u00e0-dire combien de temps chaque requ\u00eate sera trait\u00e9e par le syst\u00e8me. Exemples de t\u00e2ches : interfaces web, caches, serveurs d'applications, bases de donn\u00e9es OLTP, etc.<\/li>\n<li><strong>T\u00e2ches de calcul - batch<\/strong>. Ici, la vitesse de traitement de chaque requ\u00eate individuelle n'est pas importante. Ce qui compte, c'est combien de calculs au total cette t\u00e2che effectuera sur une p\u00e9riode donn\u00e9e (grande). Cela inclura toutes les t\u00e2ches MapReduce, Hadoop, apprentissage automatique, statistiques.<\/li>\n<li><strong>T\u00e2ches en arri\u00e8re-plan - idle<\/strong>. Pour ces t\u00e2ches, ni la latence ni le d\u00e9bit ne sont tr\u00e8s importants. Cela inclut divers tests, migrations, recalcule, conversions de donn\u00e9es d'un format \u00e0 un autre. D'une part, elles ressemblent aux t\u00e2ches de calcul, mais d'autre part, nous nous soucions moins de la rapidit\u00e9 avec laquelle elles se termineront. <\/li>\n<\/ul>\n<p><\/p>\n<p>Voyons comment ces t\u00e2ches consomment des ressources, par exemple, le processeur central.<\/p>\n<p><\/p>\n<p><strong>T\u00e2ches \u00e0 faible latence.<\/strong> Pour une telle t\u00e2che, le mod\u00e8le de consommation du CPU ressemblera \u00e0 ceci :<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"One-cloud \u2014 Syst\u00e8me de niveau centre de donn\u00e9es \u00e0 Odnoklassniki\" src=\"\/wp-content\/uploads\/2020\/06\/1ed82c0df76325eb30056ad9af86e86e.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Une requ\u00eate est re\u00e7ue de l'utilisateur, la t\u00e2che commence \u00e0 utiliser tous les c\u0153urs de CPU disponibles, traite la requ\u00eate, renvoie une r\u00e9ponse, attend la prochaine requ\u00eate et reste inactive. Une nouvelle requ\u00eate est re\u00e7ue - encore une fois, elle utilise tout ce qui est disponible, traite, attend la suivante.<\/p>\n<p><\/p>\n<p>Pour garantir une latence minimale pour une telle t\u00e2che, nous devons prendre le maximum de ressources qu'elle consomme et r\u00e9server le nombre n\u00e9cessaire de c\u0153urs sur un minion (machine qui ex\u00e9cutera la t\u00e2che). La formule de r\u00e9servation pour notre t\u00e2che sera donc :<\/p>\n<p><\/p>\n<pre><code>alloc: cpu = 4 (max)<\/code><\/pre>\n<p><\/p>\n<p>Et si nous avons une machine-minion avec 16 c\u0153urs, nous pouvons ex\u00e9cuter exactement quatre de ces t\u00e2ches dessus. Il est particuli\u00e8rement notable que la consommation moyenne du processeur pour ces t\u00e2ches est souvent tr\u00e8s faible \u2014 ce qui est \u00e9vident, car une grande partie du temps, la t\u00e2che est en attente d'une requ\u00eate et ne fait rien.<\/p>\n<p><\/p>\n<p><strong>T\u00e2ches de calcul.<\/strong> Elles auront un motif quelque peu diff\u00e9rent :<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"One-cloud \u2014 Syst\u00e8me de niveau centre de donn\u00e9es \u00e0 Odnoklassniki\" src=\"\/wp-content\/uploads\/2020\/06\/35b37fa1d70a137287cafdbfe3bcfc2e.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>La consommation moyenne des ressources processeur pour ces t\u00e2ches est assez \u00e9lev\u00e9e. Fr\u00e9quemment, nous souhaitons que la t\u00e2che de calcul soit r\u00e9alis\u00e9e dans un certain d\u00e9lai, il est donc n\u00e9cessaire de r\u00e9server un minimum de c\u0153urs de processeur n\u00e9cessaires pour que tout le calcul se termine dans un d\u00e9lai acceptable. Sa formule de r\u00e9servation ressemblera alors \u00e0 :<\/p>\n<p><\/p>\n<pre><code>alloc: cpu = [1,*)<\/code><\/pre>\n<p><\/p>\n<p><em>\u00abVeuillez allouer sur le minion o\u00f9 il y a au moins un c\u0153ur libre, et ensuite, tout ce qu'il y a \u2014 \u00e7a prendra tout\u00bb.<\/em><\/p>\n<p><\/p>\n<p>Ici, l'efficacit\u00e9 d'utilisation est d\u00e9j\u00e0 significativement meilleure que pour les t\u00e2ches \u00e0 court d\u00e9lai. Mais le gain sera bien plus important si nous combinons les deux types de t\u00e2ches sur une seule machine-minion et r\u00e9partissons ses ressources \u00e0 la vol\u00e9e. Quand une t\u00e2che \u00e0 court d\u00e9lai n\u00e9cessite un processeur \u2014 elle l'obtient imm\u00e9diatement, et lorsque les ressources ne sont plus n\u00e9cessaires \u2014 elles sont transf\u00e9r\u00e9es \u00e0 la t\u00e2che de calcul, c'est-\u00e0-dire un peu comme \u00e7a :<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"One-cloud \u2014 Syst\u00e8me de niveau centre de donn\u00e9es \u00e0 Odnoklassniki\" src=\"\/wp-content\/uploads\/2020\/06\/875ad8d3f6a01e4fd0a89d0931e986c1.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Mais comment faire cela ?<\/p>\n<p><\/p>\n<p>Pour commencer, examinons prod et son alloc: cpu = 4. Nous devons r\u00e9server quatre c\u0153urs. Dans Docker run, cela peut \u00eatre fait de deux mani\u00e8res : <\/p>\n<p><\/p>\n<ul>\n<li>Avec l'option <code>--cpuset=1-4<\/code>, c'est-\u00e0-dire allouer \u00e0 la t\u00e2che quatre c\u0153urs sp\u00e9cifiques sur la machine.<\/li>\n<li>Utiliser <code>--cpuquota=400_000 --cpuperiod=100_000<\/code>, assigner un quota de temps processeur, c'est-\u00e0-dire sp\u00e9cifier que pour chaque 100 ms de temps r\u00e9el, la t\u00e2che consomme pas plus de 400 ms de temps processeur. Cela revient aux m\u00eames quatre c\u0153urs. <\/li>\n<\/ul>\n<p><\/p>\n<p>Mais lequel de ces moyens conviendra ?<\/p>\n<p><\/p>\n<p>Le cpuset a une apparence plut\u00f4t attrayante. La t\u00e2che dispose de quatre c\u0153urs d\u00e9di\u00e9s, ce qui signifie que les caches du processeur fonctionneront de mani\u00e8re optimale. Cependant, cela a un revers : nous devrions nous charger de la r\u00e9partition des calculs sur les c\u0153urs de la machine qui ne sont pas sollicit\u00e9s au lieu de le faire par l'OS, ce qui est une t\u00e2che assez non triviale, surtout si nous essayons de placer des t\u00e2ches batch sur cette machine. Les tests ont montr\u00e9 que l'option avec quota est plus adapt\u00e9e ici : cela donne \u00e0 l'op\u00e9rateur du syst\u00e8me d'exploitation plus de libert\u00e9 pour choisir le c\u0153ur \u00e0 utiliser pour la t\u00e2che \u00e0 ce moment pr\u00e9cis, et le temps processeur est r\u00e9parti plus efficacement.<\/p>\n<p><\/p>\n<p>Voyons comment faire une r\u00e9servation de c\u0153ur minimum dans docker. Le quota pour les t\u00e2ches batch n'est plus applicable, car limiter un maximum n'est pas n\u00e9cessaire, il suffit de garantir un minimum. Et \u00e0 cet \u00e9gard, l'option convient bien <code>docker run --cpushares<\/code>.<\/p>\n<p><\/p>\n<p>Nous avons convenu que si un batch n\u00e9cessite une garantie minimum sur un c\u0153ur, nous sp\u00e9cifions <code>--cpushares=1024<\/code>, et si c'est un minimum sur deux c\u0153urs, nous indiquons <code>--cpushares=2048<\/code>. Les cpu shares n'interf\u00e8rent pas avec la r\u00e9partition du temps processeur tant qu'il est suffisant. Ainsi, si le prod n'utilise pas tous ses quatre c\u0153urs \u00e0 ce moment-l\u00e0, rien ne limite les t\u00e2ches batch, et elles peuvent utiliser du temps processeur suppl\u00e9mentaire. En revanche, en cas de p\u00e9nurie de processeur, si le prod a consomm\u00e9 tous ses quatre c\u0153urs et atteint le quota, le temps processeur restant sera r\u00e9parti proportionnellement aux cpu shares, c'est-\u00e0-dire que dans le cas de trois c\u0153urs libres, une t\u00e2che avec 1024 cpu shares obtiendra un c\u0153ur, tandis que les deux autres iront \u00e0 une t\u00e2che avec 2048 cpu shares.<\/p>\n<p><\/p>\n<p>Mais l'utilisation des quotas et des shares n'est pas suffisante. Nous devons veiller \u00e0 ce qu'une t\u00e2che \u00e0 latence courte soit prioris\u00e9e par rapport \u00e0 une t\u00e2che batch lors de la r\u00e9partition du temps processeur. Sans cette priorisation, la t\u00e2che batch prendra tout le temps processeur au moment o\u00f9 il est n\u00e9cessaire pour le prod. Dans Docker run, il n'y a aucune option de priorisation des conteneurs, mais les politiques de planification du processeur dans Linux viennent \u00e0 la rescousse. Vous pouvez lire en d\u00e9tail \u00e0 leur sujet <noindex><a rel=\"nofollow\" href=\"http:\/\/man7.org\/linux\/man-pages\/man2\/sched_setscheduler.2.html\">ici<\/a><\/noindex>, et dans cet article, nous les parcourrons bri\u00e8vement :<\/p>\n<p><\/p>\n<ul>\n<li><strong>SCHED_OTHER<\/strong><br \/>\nPar d\u00e9faut, tous les processus utilisateurs normaux sur la machine Linux re\u00e7oivent cela.<\/li>\n<li><strong>SCHED_BATCH<\/strong><br \/>\nDestin\u00e9e aux processus gourmands en ressources. Lorsqu'une t\u00e2che est plac\u00e9e dans le processeur, il y a ce qu'on appelle une p\u00e9nalit\u00e9 d'activation : une telle t\u00e2che a moins de chances d'obtenir les ressources du processeur si, \u00e0 ce moment, une t\u00e2che avec SCHED_OTHER utilise le processeur.<\/li>\n<li><strong>SCHED_IDLE<\/strong><br \/>\nUn processus en arri\u00e8re-plan avec une priorit\u00e9 tr\u00e8s basse, m\u00eame inf\u00e9rieure \u00e0 nice \u201319. Nous utilisons notre biblioth\u00e8que open source <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/odnoklassniki\/one-nio\">one-nio<\/a><\/noindex>, pour d\u00e9finir la politique n\u00e9cessaire lors du lancement d'un conteneur via l'appel<\/li>\n<\/ul>\n<p><\/p>\n<pre><code class=\"java\">one.nio.os.Proc.sched_setscheduler( pid, Proc.SCHED_IDLE )<\/code><\/pre>\n<p><\/p>\n<p>Mais m\u00eame si vous ne programmez pas en Java, vous pouvez faire la m\u00eame chose en utilisant la commande chrt :<\/p>\n<p><\/p>\n<pre><code class=\"bash\">chrt -i 0 $pid<\/code><\/pre>\n<p><\/p>\n<p>Rassemblons tous nos niveaux d'isolation dans un tableau pour plus de clart\u00e9 :<\/p>\n<p><\/p>\n<p>Classe d'isolation<br \/>\nExemple alloc<br \/>\nOptions Docker run<br \/>\nsched_setscheduler chrt*<\/p>\n<p>Prod<br \/>\ncpu = 4<br \/>\n<code>--cpuquota=400000<\/code> <code>--cpuperiod=100000<\/code><br \/>\nSCHED_OTHER<\/p>\n<p>Batch<br \/>\nCpu = [1, * )<br \/>\n<code>--cpushares=1024<\/code><br \/>\nSCHED_BATCH<\/p>\n<p>Idle<br \/>\nCpu= [2, *)<br \/>\n<code>--cpushares=2048<\/code><br \/>\nSCHED_IDLE<\/p>\n<p><\/p>\n<p>*Si vous faites chrt depuis l'int\u00e9rieur du conteneur, la capacit\u00e9 sys_nice peut \u00eatre n\u00e9cessaire, car par d\u00e9faut Docker retire cette capacit\u00e9 lors du lancement du conteneur.<\/p>\n<p><\/p>\n<p>Mais les t\u00e2ches consomment non seulement du processeur, mais aussi du trafic, ce qui impacte encore plus la latence des t\u00e2ches r\u00e9seau que la r\u00e9partition incorrecte des ressources CPU. Par cons\u00e9quent, nous voulons naturellement obtenir la m\u00eame visualisation pour le trafic. C'est-\u00e0-dire, lorsque la t\u00e2che prod envoie des paquets sur le r\u00e9seau, nous quotaillons la vitesse maximale (formule <em>alloc: lan=[*,500mbps)<\/em> ), avec laquelle prod peut le faire. Pour batch, nous garantissons uniquement une capacit\u00e9 minimale, sans limiter le maximum (formule <em>alloc: lan=[10Mbps,* )<\/em> ) En m\u00eame temps, le trafic prod doit avoir la priorit\u00e9 sur les t\u00e2ches batch.<br \/>\nIci, Docker n'a pas de primitives que nous pourrions utiliser. Mais nous avons l'aide de <noindex><a rel=\"nofollow\" href=\"http:\/\/lartc.org\/\">Linux Traffic Control<\/a><\/noindex>. Nous avons pu obtenir le r\u00e9sultat souhait\u00e9 gr\u00e2ce \u00e0 la discipline <noindex><a rel=\"nofollow\" href=\"http:\/\/linux-ip.net\/articles\/hfsc.en\/\">Hierarchical Fair Service Curve<\/a><\/noindex>. Gr\u00e2ce \u00e0 cela, nous mettons en avant deux classes de trafic : prod \u00e0 haute priorit\u00e9 et batch\/idle \u00e0 basse priorit\u00e9. Au final, la configuration pour le trafic sortant est la suivante :<\/p>\n<p><\/p>\n<p><noindex><a rel=\"nofollow\" href=\"https:\/\/habrastorage.org\/webt\/gh\/5k\/kf\/gh5kkfwkhwv0ilmbdmdbo83dp6k.png\"><img decoding=\"async\" alt=\"One-cloud \u2014 Syst\u00e8me de niveau centre de donn\u00e9es \u00e0 Odnoklassniki\" src=\"\/wp-content\/uploads\/2020\/06\/3f52a968118b6021bd0c920af17a00c0.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/a><\/noindex><\/p>\n<p><\/p>\n<p>ici 1:0 \u2014 \u00abqdisc racine\u00bb de la discipline hsfc ; 1:1 \u2014 classe enfant hsfc avec une limite de bande passante totale de 8 Gbit\/s, sous laquelle se trouvent les classes enfants de tous les conteneurs ; 1:2 \u2014 classe enfant hsfc commune pour toutes les t\u00e2ches batch et idle avec une limite \u00ab dynamique \u00bb, comme indiqu\u00e9 ci-dessous. Les autres classes enfants hsfc sont des classes r\u00e9serv\u00e9es pour les conteneurs prod en cours d'ex\u00e9cution, avec des limites correspondant \u00e0 leurs manifestes, \u2014 450 et 400 Mbit\/s. \u00c0 chaque classe hsfc est attribu\u00e9e une file d'attente qdisc fq ou fq_codel, selon la version du noyau linux, pour \u00e9viter la perte de paquets lors des pics de trafic. <\/p>\n<p><\/p>\n<p>En g\u00e9n\u00e9ral, les disciplines tc servent \u00e0 prioriser uniquement le trafic sortant. Mais nous voulons \u00e9galement prioriser le trafic entrant \u2014 car une t\u00e2che batch peut facilement utiliser toute la bande passante entrante, par exemple en recevant un gros paquet de donn\u00e9es d'entr\u00e9e pour map&amp;reduce. Pour cela, nous utilisons le module <noindex><a rel=\"nofollow\" href=\"https:\/\/serverfault.com\/questions\/350023\/tc-ingress-policing-and-ifb-mirroring\">ifb<\/a><\/noindex>, qui cr\u00e9e une interface virtuelle ifbX pour chaque interface r\u00e9seau et redirige le trafic entrant de l'interface vers le sortant sur ifbX. Ensuite, pour ifbX, toutes les m\u00eames disciplines de contr\u00f4le du trafic sortant s'appliquent, pour lesquelles la configuration hsfc sera tr\u00e8s similaire :<\/p>\n<p><\/p>\n<p><noindex><a rel=\"nofollow\" href=\"https:\/\/habrastorage.org\/webt\/iz\/ao\/-k\/izao-kgthgu_ptgyq9cjb1il0wm.png\"><img decoding=\"async\" alt=\"One-cloud \u2014 Syst\u00e8me de niveau centre de donn\u00e9es \u00e0 Odnoklassniki\" src=\"\/wp-content\/uploads\/2020\/06\/967da9c0637cc70ba195af781db18adf.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/a><\/noindex><\/p>\n<p><\/p>\n<p>Au cours des exp\u00e9riences, nous avons constat\u00e9 que les meilleurs r\u00e9sultats de hsfc sont obtenus lorsque la classe 1:2 pour le trafic batch\/idle non prioritaire est limit\u00e9e sur les machines-minions \u00e0 une certaine bande passante disponible. Sinon, le trafic non prioritaire influence trop la latence des t\u00e2ches prod. La valeur actuelle de la bande passante disponible est d\u00e9termin\u00e9e par miniond chaque seconde, en mesurant la consommation moyenne de trafic de toutes les t\u00e2ches prod de ce minion <img decoding=\"async\" alt=\"One-cloud \u2014 Syst\u00e8me de niveau centre de donn\u00e9es \u00e0 Odnoklassniki\" src=\"\/wp-content\/uploads\/2020\/06\/9d6f38110d3b1693afe222b01430b9bb.jpg\" style=\"display:block;margin: 0 auto;\" \/> et en la soustrayant de la bande passante de l'interface r\u00e9seau <img decoding=\"async\" alt=\"One-cloud \u2014 Syst\u00e8me de niveau centre de donn\u00e9es \u00e0 Odnoklassniki\" src=\"\/wp-content\/uploads\/2020\/06\/d5608ec4c58e44b8571ab0b1d0cc7701.jpg\" style=\"display:block;margin: 0 auto;\" \/> avec une l\u00e9g\u00e8re marge, c'est-\u00e0-dire.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"One-cloud \u2014 Syst\u00e8me de niveau centre de donn\u00e9es \u00e0 Odnoklassniki\" src=\"\/wp-content\/uploads\/2020\/06\/fb01347c2224bd5bbd82169861eeb7e4.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Les bandes sont d\u00e9finies de mani\u00e8re ind\u00e9pendante pour le trafic entrant et sortant. Et en fonction des nouvelles valeurs, miniond reconfigure la limite de la classe 1:2 non prioritaire.<\/p>\n<p><\/p>\n<p>Ainsi, nous avons mis en \u0153uvre les trois classes d'isolation : prod, batch et idle. Ces classes ont un impact important sur les performances des t\u00e2ches. Par cons\u00e9quent, nous avons d\u00e9cid\u00e9 de placer ce crit\u00e8re en haut de la hi\u00e9rarchie, afin qu'en regardant le nom de la queue hi\u00e9rarchique, on puisse imm\u00e9diatement comprendre de quoi il s'agit : <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"One-cloud \u2014 Syst\u00e8me de niveau centre de donn\u00e9es \u00e0 Odnoklassniki\" src=\"\/wp-content\/uploads\/2020\/06\/34dc89c461db711b19a0f4eccc50efce.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Tous nos fronts familiers <strong>web<\/strong> et <strong>music<\/strong> sont alors plac\u00e9s dans la hi\u00e9rarchie sous prod. Par exemple, pla\u00e7ons le service sous batch <strong>music catalog<\/strong>, qui \u00e9tablit p\u00e9riodiquement un catalogue de titres \u00e0 partir de la collection de fichiers mp3 t\u00e9l\u00e9charg\u00e9s sur \u00ab Odnoklassniki \u00bb. Un exemple de service idle pourrait \u00eatre <strong>transformateur de musique<\/strong>, normalisant le niveau de volume de la musique.<\/p>\n<p><\/p>\n<p>Encore une fois, en supprimant les lignes superflues, nous pouvons \u00e9crire les noms de nos services de mani\u00e8re plus plate, en ajoutant la classe d'isolation de la t\u00e2che \u00e0 la fin du nom complet du service : <strong>web.front.prod<\/strong>, <strong>catalog.music.batch<\/strong>, <strong>transformer.music.idle<\/strong>.<\/p>\n<p><\/p>\n<p>Et maintenant, en regardant le nom du service, nous comprenons non seulement la fonction qu'il remplit, mais aussi sa classe d'isolation, ce qui signifie sa criticit\u00e9, etc.<\/p>\n<p><\/p>\n<p>Tout est formidable, mais il y a une dure v\u00e9rit\u00e9. Il est impossible d'isoler compl\u00e8tement les t\u00e2ches fonctionnant sur une seule machine.<\/p>\n<p><\/p>\n<p>Ce que nous avons r\u00e9ussi \u00e0 accomplir : si le batch consomme intensivement <strong>uniquement<\/strong> des ressources processeur, le planificateur de CPU de Linux g\u00e8re tr\u00e8s bien sa t\u00e2che, et l'impact sur la t\u00e2che prod est presque nul. Mais si cette t\u00e2che batch commence \u00e0 travailler activement avec la m\u00e9moire, alors l'influence mutuelle se manifeste d\u00e9j\u00e0. Cela se produit parce que la t\u00e2che prod a ses caches processeur \u00ab vid\u00e9s \u00bb \u2014 en fin de compte, le nombre de d\u00e9fauts dans le cache augmente, et le processeur traite la t\u00e2che prod plus lentement. Une telle t\u00e2che batch peut augmenter les latences de notre conteneur prod typique de 10 %.<\/p>\n<p><\/p>\n<p>Isoler le trafic est encore plus difficile \u00e0 cause du fait que les cartes r\u00e9seau modernes poss\u00e8dent une file d'attente interne de paquets. Si un paquet d'une t\u00e2che batch est le premier \u00e0 y entrer, alors il sera le premier \u00e0 \u00eatre envoy\u00e9 par c\u00e2ble, et il n'y a rien \u00e0 faire.<\/p>\n<p><\/p>\n<p>De plus, nous avons pour l'instant uniquement r\u00e9ussi \u00e0 r\u00e9soudre le probl\u00e8me de priorisation du trafic TCP : pour UDP, l'approche avec hsfc ne fonctionne pas. Et m\u00eame dans le cas du trafic TCP, si la t\u00e2che batch g\u00e9n\u00e8re beaucoup de trafic, cela entra\u00eene \u00e9galement une augmentation d'environ 10 % de la latence de la t\u00e2che prod.<\/p>\n<p><\/p>\n<h2 id=\"otkazoustoychivost\">R\u00e9silience<\/h2>\n<p><\/p>\n<p>L'un des objectifs lors du d\u00e9veloppement de one-cloud \u00e9tait d'am\u00e9liorer la r\u00e9sistance aux pannes d'Odnoklassniki. Par cons\u00e9quent, j'aimerais examiner plus en d\u00e9tail les sc\u00e9narios possibles de pannes et d'incidents. Commen\u00e7ons par un sc\u00e9nario simple \u2014 la panne d'un conteneur. <\/p>\n<p><\/p>\n<p>Un conteneur peut \u00e9chouer de plusieurs mani\u00e8res. Cela peut \u00eatre d\u00fb \u00e0 une exp\u00e9rience, un bug ou une erreur dans le manifeste, ce qui fait que la t\u00e2che prod commence \u00e0 consommer plus de ressources que celles sp\u00e9cifi\u00e9es dans le manifeste. Nous avons eu un cas : un d\u00e9veloppeur a mis en \u0153uvre un algorithme complexe, l'a plusieurs fois modifi\u00e9, s'est perdu dans ses propres optimisations et, en fin de compte, la t\u00e2che s'est retrouv\u00e9e \u00e0 s'ex\u00e9cuter en boucle de mani\u00e8re assez non triviale. Et puisque la t\u00e2che prod est prioritaire par rapport \u00e0 toutes les autres sur les m\u00eames minions, elle a commenc\u00e9 \u00e0 consommer toutes les ressources processeur disponibles. Dans cette situation, l'isolation a sauv\u00e9 la mise, ou plut\u00f4t le quota de temps processeur. Si un quota est attribu\u00e9 \u00e0 la t\u00e2che, celle-ci ne consommera pas plus. Ainsi, les t\u00e2ches batch et autres t\u00e2ches prod qui fonctionnaient sur la m\u00eame machine n'ont rien remarqu\u00e9. <\/p>\n<p><\/p>\n<p>Le deuxi\u00e8me probl\u00e8me possible est l'arr\u00eat du conteneur. Et ici, nous sommes sauv\u00e9s par les politiques de red\u00e9marrage, que tout le monde conna\u00eet, Docker g\u00e8re cela tr\u00e8s bien. Pratiquement toutes les t\u00e2ches prod ont une politique de red\u00e9marrage toujours. Parfois, nous utilisons on_failure pour les t\u00e2ches batch ou pour le d\u00e9bogage des conteneurs prod.<\/p>\n<p><\/p>\n<p>Que peut-on faire en cas d'indisponibilit\u00e9 d'un minion entier ?<\/p>\n<p><\/p>\n<p>\u00c9videmment, lancer le conteneur sur une autre machine. L'aspect int\u00e9ressant ici est ce qui se passe avec l'adresse IP (les adresses) assign\u00e9es au conteneur. <\/p>\n<p><\/p>\n<p>Nous pouvons attribuer aux conteneurs les m\u00eames adresses IP que celles des machines-minions sur lesquelles ces conteneurs sont lanc\u00e9s. Donc, lors du lancement du conteneur sur une autre machine, son adresse IP change, et tous les clients doivent comprendre que le conteneur a d\u00e9m\u00e9nag\u00e9, il faut maintenant se rendre \u00e0 une autre adresse, ce qui n\u00e9cessite un service de d\u00e9couverte de services. <\/p>\n<p><\/p>\n<p>La d\u00e9couverte de services est pratique. Il existe sur le march\u00e9 de nombreuses solutions de diff\u00e9rents niveaux de tol\u00e9rance aux pannes pour l'organisation d'un registre de services. Souvent, ces solutions int\u00e8grent la logique d'un \u00e9quilibreur de charge, le stockage de configurations suppl\u00e9mentaires sous forme de KV-store, etc.<br \/>\nCependant, nous aimerions \u00e9viter la n\u00e9cessit\u00e9 d'impl\u00e9menter un registre s\u00e9par\u00e9, car cela impliquerait l'introduction d'un syst\u00e8me critique utilis\u00e9 par tous les services en production. Cela signifie donc un potentiel point de d\u00e9faillance, et nous devons choisir ou d\u00e9velopper une solution tr\u00e8s r\u00e9siliente, ce qui est \u00e9videmment tr\u00e8s difficile, long et co\u00fbteux. <\/p>\n<p><\/p>\n<p>Un autre inconv\u00e9nient majeur : pour que notre ancienne infrastructure fonctionne avec la nouvelle, il aurait fallu r\u00e9\u00e9crire toutes les t\u00e2ches pour utiliser un syst\u00e8me de d\u00e9couverte de services. Cela repr\u00e9sente un travail ENORME, et parfois quasiment impossible, surtout lorsqu'il s'agit de dispositifs bas-niveau fonctionnant au niveau du noyau OS ou directement avec le mat\u00e9riel. La mise en \u0153uvre de cette fonctionnalit\u00e9 \u00e0 l'aide de mod\u00e8les de solutions \u00e9tablis, tels que <noindex><a rel=\"nofollow\" href=\"https:\/\/linkerd.io\">side-car<\/a><\/noindex> signifierait parfois une charge suppl\u00e9mentaire, parfois une complexit\u00e9 accrue et des sc\u00e9narios d'\u00e9chec suppl\u00e9mentaires. Nous ne voulions pas complexifier les choses, donc nous avons d\u00e9cid\u00e9 de rendre l'utilisation de la d\u00e9couverte de services optionnelle. <\/p>\n<p><\/p>\n<p>Dans one-cloud, l'IP suit le conteneur, c'est-\u00e0-dire que chaque instance de t\u00e2che a sa propre adresse IP. Cette adresse est \"statique\" : elle est attribu\u00e9e \u00e0 chaque instance au moment de la premi\u00e8re mise en service dans le cloud. Si, au cours de sa vie, le service a eu un nombre variable d'instances, alors \u00e0 la fin, autant d'adresses IP seront attribu\u00e9es qu'il y a eu d'instances au maximum.<\/p>\n<p><\/p>\n<p>Par la suite, ces adresses ne changent pas : elles sont attribu\u00e9es une fois et restent valides pendant toute la dur\u00e9e de vie du service en production. Les adresses IP suivent les conteneurs sur le r\u00e9seau. Si un conteneur est d\u00e9plac\u00e9 vers un autre minion, l'adresse le suivra. <\/p>\n<p><\/p>\n<p>Ainsi, l'association entre le nom du service et la liste de ses adresses IP change tr\u00e8s rarement. Si l'on regarde \u00e0 nouveau les noms des instances de service que nous avons mentionn\u00e9s au d\u00e9but de l'article (<strong>1.ok-web.group1.web.front.prod, 2.ok-web.group1.web.front.prod, \u2026<\/strong>), nous pouvons remarquer qu'ils ressemblent \u00e0 des FQDN utilis\u00e9s dans le DNS. C'est en effet le cas, nous utilisons le protocole DNS pour afficher les noms des instances de services dans leurs adresses IP. De plus, ce DNS renvoie toutes les adresses IP r\u00e9serv\u00e9es de tous les conteneurs, qu\u2019ils soient en cours d\u2019ex\u00e9cution ou arr\u00eat\u00e9s (par exemple, si trois r\u00e9pliques sont utilis\u00e9es et que cinq adresses sont r\u00e9serv\u00e9es, toutes les cinq seront renvoy\u00e9es). Les clients, apr\u00e8s avoir re\u00e7u cette information, essaieront de se connecter \u00e0 toutes les cinq r\u00e9pliques, d\u00e9terminant ainsi celles qui sont op\u00e9rationnelles. Cette m\u00e9thode de d\u00e9termination de la disponibilit\u00e9 est beaucoup plus fiable, car elle n'implique ni DNS ni Service Discovery, ce qui \u00e9limine les probl\u00e8mes complexes d\u2019actualisation des informations et de r\u00e9silience de ces syst\u00e8mes. De plus, pour les services critiques dont d\u00e9pend le fonctionnement de l'ensemble du portail, nous pouvons ne pas utiliser le DNS du tout et simplement inscrire les adresses IP dans la configuration.<\/p>\n<p><\/p>\n<p>La mise en \u0153uvre d'un tel transfert d'IP derri\u00e8re des conteneurs peut \u00eatre non triviale \u2014 et nous nous baserons sur un exemple pour expliquer comment cela fonctionne\u00a0:<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"One-cloud \u2014 Syst\u00e8me de niveau centre de donn\u00e9es \u00e0 Odnoklassniki\" src=\"\/wp-content\/uploads\/2020\/06\/faf99c2609a57daa1bdc193cb0f4cb31.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Supposons que le ma\u00eetre one-cloud donne l'ordre au minion M1 de lancer <strong>1.ok-web.group1.web.front.prod<\/strong> avec l'adresse 1.1.1.1. Sur le minion, il fonctionne <noindex><a rel=\"nofollow\" href=\"https:\/\/en.wikipedia.org\/wiki\/Bird_Internet_routing_daemon\">BIRD<\/a><\/noindex>, qui annonce cette adresse sur des serveurs sp\u00e9ciaux <noindex><a rel=\"nofollow\" href=\"https:\/\/en.wikipedia.org\/wiki\/Route_reflector\">route reflector<\/a><\/noindex>. Ces derniers ont une session BGP avec le mat\u00e9riel r\u00e9seau, \u00e0 laquelle le chemin de l'adresse 1.1.1.1 sur M1 est diffus\u00e9. M1, quant \u00e0 lui, achemine les paquets vers l'int\u00e9rieur du conteneur en utilisant les outils Linux. Il y a trois serveurs route reflector, car cet \u00e9l\u00e9ment de l'infrastructure one-cloud est tr\u00e8s critique \u2014 sans eux, le r\u00e9seau dans one-cloud ne fonctionnera pas. Nous les pla\u00e7ons dans diff\u00e9rentes baies, id\u00e9alement situ\u00e9es dans des salles diff\u00e9rentes du centre de donn\u00e9es, afin de r\u00e9duire la probabilit\u00e9 d'une panne simultan\u00e9e des trois.<\/p>\n<p><\/p>\n<p>Supposons maintenant que la connexion entre le ma\u00eetre one-cloud et le minion M1 ait \u00e9t\u00e9 perdue. Le ma\u00eetre one-cloud agira d\u00e9sormais en supposant que M1 a compl\u00e8tement \u00e9chou\u00e9. En d'autres termes, il donnera l'ordre au minion M2 de lancer <strong>web.group1.web.front.prod<\/strong> avec la m\u00eame adresse 1.1.1.1. Nous avons maintenant deux routes conflictuelles dans le r\u00e9seau pour 1.1.1.1 : sur M1 et sur M2. Pour r\u00e9soudre de tels conflits, nous utilisons le Multi Exit Discriminator, qui est sp\u00e9cifi\u00e9 dans l'annonce BGP. C'est un nombre qui indique le poids de la route annonc\u00e9e. Parmi les routes conflictuelles, celle avec la valeur MED la plus basse sera choisie. Le ma\u00eetre one-cloud prend en charge le MED comme partie int\u00e9grante des adresses IP des conteneurs. La premi\u00e8re fois, l'adresse est annonc\u00e9e avec un MED suffisamment \u00e9lev\u00e9 = 1 000 000. Dans une situation de migration d'urgence du conteneur, le ma\u00eetre r\u00e9duit le MED, et M2 re\u00e7oit d\u00e9j\u00e0 l'ordre d'annoncer l'adresse 1.1.1.1 avec MED = 999 999. L'instance fonctionnant sur M1 restera sans connexion, et son sort ne nous int\u00e9resse gu\u00e8re jusqu'\u00e0 ce que la connexion avec le ma\u00eetre soit r\u00e9tablie, moment o\u00f9 elle sera arr\u00eat\u00e9e en tant qu'ancien doublon.<\/p>\n<p><\/p>\n<h2 id=\"avarii\">Pannes<\/h2>\n<p><\/p>\n<p>Tous les syst\u00e8mes de gestion des data centers g\u00e8rent toujours de mani\u00e8re acceptable les petites pannes. La d\u00e9faillance d'un conteneur est une norme presque partout.<\/p>\n<p><\/p>\n<p>Examinons comment nous g\u00e9rons une panne, par exemple, une coupure de courant dans une ou plusieurs salles de data center.<\/p>\n<p><\/p>\n<p>Que signifie une panne pour le syst\u00e8me de gestion des data centers ? Avant tout, cela repr\u00e9sente une d\u00e9faillance massive et simultan\u00e9e de nombreux ordinateurs, et le syst\u00e8me de gestion doit simultan\u00e9ment migrer un grand nombre de conteneurs. Cependant, si la panne est tr\u00e8s vaste, il se peut que toutes les t\u00e2ches ne puissent pas \u00eatre relocalis\u00e9es sur d'autres minions, car la capacit\u00e9 des ressources du data center tombe en dessous de 100 % de charge. <\/p>\n<p><\/p>\n<p>Souvent, les pannes s'accompagnent d'une d\u00e9faillance de la couche de gestion. Cela peut se produire en raison de la d\u00e9faillance de son mat\u00e9riel, mais plus souvent parce que les pannes ne sont pas test\u00e9es, et la couche de gestion s'effondre elle-m\u00eame sous la charge accrue. <\/p>\n<p><\/p>\n<p>Que peut-on faire avec tout cela ?<\/p>\n<p><\/p>\n<p>Les migrations massives signifient qu'un grand nombre d'actions, de migrations et de placements ont lieu dans l'infrastructure. Chacune des migrations peut n\u00e9cessiter du temps pour livrer et d\u00e9baller les images des conteneurs aux minions, d\u00e9marrer et initialiser les conteneurs, etc. Il est donc souhaitable que les t\u00e2ches les plus importantes soient lanc\u00e9es avant celles qui le sont moins.<\/p>\n<p><\/p>\n<p>Revenons \u00e0 notre hi\u00e9rarchie famili\u00e8re des services et essayons de d\u00e9cider quelles t\u00e2ches nous souhaitons lancer en premier.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"One-cloud \u2014 Syst\u00e8me de niveau centre de donn\u00e9es \u00e0 Odnoklassniki\" src=\"\/wp-content\/uploads\/2020\/06\/2e827271adb8d3ff3d385e53553aaacf.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Bien s\u00fbr, ce sont les processus qui participent directement au traitement des demandes des utilisateurs, c'est-\u00e0-dire le prod. Nous le signalons par <strong>priorit\u00e9 de placement<\/strong> \u2014 un nombre qui peut \u00eatre attribu\u00e9 \u00e0 la file d'attente. Si une file a une priorit\u00e9 plus \u00e9lev\u00e9e, ses services sont plac\u00e9s en premier.<\/p>\n<p><\/p>\n<p>Dans le prod, nous attribuons des priorit\u00e9s plus \u00e9lev\u00e9es, 0 ; dans le batch \u2014 un peu plus bas, 100 ; dans l\u2019idle \u2014 encore plus bas, 200. Les priorit\u00e9s s'appliquent de mani\u00e8re hi\u00e9rarchique. Toutes les t\u00e2ches inf\u00e9rieures dans la hi\u00e9rarchie auront la priorit\u00e9 correspondante. Si nous voulons que les caches se lancent avant les frontends dans le prod, nous attribuons des priorit\u00e9s sur le cache = 0 et sur le front en sous-file = 1. Si nous voulons que, par exemple, le portail principal se lance avant le frontend musical, nous pouvons attribuer une priorit\u00e9 plus basse \u00e0 ce dernier \u2014 10.<\/p>\n<p><\/p>\n<p>Le probl\u00e8me suivant est le manque de ressources. Ainsi, nous avons subi une panne d'un grand nombre de serveurs, des salles enti\u00e8res dans le data center, et nous avons lanc\u00e9 tant de services qu'il n'y a plus de ressources pour tous. Il faut d\u00e9cider quelles t\u00e2ches sacrifier pour faire fonctionner les principales services critiques. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"One-cloud \u2014 Syst\u00e8me de niveau centre de donn\u00e9es \u00e0 Odnoklassniki\" src=\"\/wp-content\/uploads\/2020\/06\/1b1ad3da16df6677dd0ba4b038cdd7d6.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Contrairement \u00e0 la priorit\u00e9 de placement, nous ne pouvons pas sacrifier toutes les t\u00e2ches batch sans distinction, certaines d'entre elles sont importantes pour le fonctionnement du portail. C'est pourquoi nous avons mis en place une priorit\u00e9 distincte <strong>d'\u00e9viction<\/strong> des t\u00e2ches. Lors de l'attribution, une t\u00e2che avec une priorit\u00e9 plus \u00e9lev\u00e9e peut \u00e9vincer, c'est-\u00e0-dire arr\u00eater une t\u00e2che avec une priorit\u00e9 plus basse, s'il n'y a plus de minions disponibles. Dans ce cas, la t\u00e2che avec une priorit\u00e9 inf\u00e9rieure restera probablement non allou\u00e9e, c'est-\u00e0-dire qu'il n'y aura plus de minion adapt\u00e9 avec suffisamment de ressources libres.<\/p>\n<p><\/p>\n<p>Dans notre hi\u00e9rarchie, il est tr\u00e8s simple d'indiquer une telle priorit\u00e9 d'\u00e9viction, pour que les t\u00e2ches prod et batch \u00e9vincient ou arr\u00eatent les t\u00e2ches idle, mais pas entre elles, en attribuant une priorit\u00e9 de 200 \u00e0 idle. Tout comme dans le cas de la priorit\u00e9 de placement, nous pouvons utiliser notre hi\u00e9rarchie pour d\u00e9crire des r\u00e8gles plus complexes. Par exemple, sp\u00e9cifions que nous sacrifierons la fonction de musique si nous manquons de ressources pour le portail web principal, en fixant une priorit\u00e9 plus basse pour les n\u0153uds correspondants : 10.<\/p>\n<p><\/p>\n<h2 id=\"avarii-dc-celikom\">Pannes de data center en entier<\/h2>\n<p><\/p>\n<p>Pourquoi un data center entier peut-il tomber en panne ? \u00c9v\u00e9nements naturels. Il y avait un bon post sur la fa\u00e7on dont <noindex><a rel=\"nofollow\" href=\"https:\/\/habrahabr.ru\/company\/dataline\/blog\/333578\/\">un ouragan a affect\u00e9 le fonctionnement du data center<\/a><\/noindex>. On peut consid\u00e9rer que la communaut\u00e9 des sans-abris a br\u00fbl\u00e9 un c\u00e2ble en fibre optique dans un collecteur, ce qui a entra\u00een\u00e9 une perte totale de connexion entre le centre de donn\u00e9es et les autres sites. Une d\u00e9faillance peut \u00e9galement \u00eatre caus\u00e9e par le facteur humain : un op\u00e9rateur peut donner une commande qui fera tomber tout le centre de donn\u00e9es. Cela peut se produire \u00e0 cause d'un bug majeur. En somme, les centres de donn\u00e9es tombent en panne \u2014 ce n'est pas rare. Cela se produit chez nous environ tous les quelques mois. <\/p>\n<p><\/p>\n<p>Et voici ce que nous faisons pour que personne #\u043e\u043a\u0436\u0438\u0432\u0438 ne publie sur Twitter.<\/p>\n<p><\/p>\n<p>La premi\u00e8re strat\u00e9gie est l'isolation. Chaque instance one-cloud est isol\u00e9e et ne peut g\u00e9rer que des machines d'un seul centre de donn\u00e9es. Par cons\u00e9quent, la perte d'un cloud \u00e0 cause de bugs ou d'une mauvaise commande de l'op\u00e9rateur ne concerne qu'un seul centre de donn\u00e9es. Nous sommes pr\u00eats pour cela : nous avons une politique de sauvegarde qui place les r\u00e9pliques d'applications et de donn\u00e9es dans tous les centres de donn\u00e9es. Nous utilisons des bases de donn\u00e9es tol\u00e9rantes aux pannes et testons p\u00e9riodiquement les d\u00e9faillances.<br \/>\nPuisque nous avons aujourd'hui quatre centres de donn\u00e9es, cela signifie \u00e9galement quatre instances one-cloud s\u00e9par\u00e9es et enti\u00e8rement isol\u00e9es.<\/p>\n<p><\/p>\n<p>Cette approche non seulement prot\u00e8ge contre les pannes physiques, mais peut \u00e9galement prot\u00e9ger contre les erreurs de l'op\u00e9rateur.<\/p>\n<p><\/p>\n<p>Que peut-on d'autre faire face au facteur humain ? Lorsque l'op\u00e9rateur donne au cloud une commande \u00e9trange ou potentiellement dangereuse, il peut soudainement \u00eatre invit\u00e9 \u00e0 r\u00e9soudre une petite t\u00e2che pour v\u00e9rifier \u00e0 quel point il a bien r\u00e9fl\u00e9chi. Par exemple, s'il s'agit d'un arr\u00eat massif de nombreuses r\u00e9pliques ou d'une simple commande \u00e9trange \u2014 r\u00e9duire le nombre de r\u00e9pliques ou changer le nom de l'image, et non simplement le num\u00e9ro de version dans le nouveau manifeste.<\/p>\n<p><\/p>\n<p><noindex><a rel=\"nofollow\" href=\"https:\/\/habrastorage.org\/webt\/vh\/vw\/0d\/vhvw0dzobo9sd4x7zih_cnfnlu8.png\"><img decoding=\"async\" alt=\"One-cloud \u2014 Syst\u00e8me de niveau centre de donn\u00e9es \u00e0 Odnoklassniki\" src=\"\/wp-content\/uploads\/2020\/06\/f7ee44a77e30612a3cd99a6f7aee3820.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/a><\/noindex><\/p>\n<p><\/p>\n<h2 id=\"itogi\">R\u00e9sultats<\/h2>\n<p><\/p>\n<p>Les caract\u00e9ristiques distinctives de one-cloud : <\/p>\n<p><\/p>\n<ul>\n<li><strong>Un sch\u00e9ma hi\u00e9rarchique et clair de nommage des services et des conteneurs<\/strong>, qui permet de savoir tr\u00e8s rapidement de quelle t\u00e2che il s'agit, \u00e0 quoi elle se rapporte, comment cela fonctionne et qui en est responsable. <\/li>\n<li>Nous appliquons notre <strong>technique de combinaison des t\u00e2ches prod- et batch-<\/strong>sur les minions pour am\u00e9liorer l'efficacit\u00e9 du partage des ressources. Au lieu de cpuset, nous utilisons des quotas CPU, des parts, des politiques de planification CPU et Linux QoS.<\/li>\n<li>Nous n'avons pas r\u00e9ussi \u00e0 isoler compl\u00e8tement les conteneurs fonctionnant sur une seule machine, mais leur influence mutuelle reste dans une limite de 20 %.<\/li>\n<li>L'organisation des services en hi\u00e9rarchie aide lors de l'\u00e9limination automatique des pannes gr\u00e2ce aux <strong>priorit\u00e9s de placement et d'\u00e9viction.<\/strong>.<\/li>\n<\/ul>\n<p><\/p>\n<h2 id=\"chavo\">FAQ<\/h2>\n<p><\/p>\n<p>Pourquoi nous n'avons pas choisi une solution pr\u00eate \u00e0 l'emploi.<\/p>\n<p><\/p>\n<ul>\n<li>Diff\u00e9rents classes d'isolation des t\u00e2ches n\u00e9cessitent une logique diff\u00e9rente lors de leur placement sur des machines virtuelles. Alors que les t\u00e2ches de production peuvent \u00eatre plac\u00e9es par simple r\u00e9servation des ressources, les t\u00e2ches batch et idle doivent \u00eatre plac\u00e9es en surveillant l'utilisation r\u00e9elle des ressources sur les machines. <\/li>\n<li>La n\u00e9cessit\u00e9 de prendre en compte les ressources consomm\u00e9es par ces t\u00e2ches, telles que : \n<ul>\n<li>la bande passante r\u00e9seau;<\/li>\n<li>les types et les \"spindles\" des disques.<\/li>\n<\/ul>\n<\/li>\n<li>La n\u00e9cessit\u00e9 d'indiquer les priorit\u00e9s des services lors de l'\u00e9limination des pannes, ainsi que les droits et quotas des \u00e9quipes sur les ressources, ce qui se r\u00e9sout gr\u00e2ce \u00e0 des files d'attente hi\u00e9rarchiques dans one-cloud.<\/li>\n<li>La n\u00e9cessit\u00e9 d'avoir une nomenclature humaine pour faciliter le temps de r\u00e9action aux pannes et incidents.<\/li>\n<li>L'impossibilit\u00e9 de d\u00e9ployer simultan\u00e9ment Service Discovery \u00e0 grande \u00e9chelle ; la n\u00e9cessit\u00e9 de coexister longtemps avec des t\u00e2ches ex\u00e9cut\u00e9es sur des serveurs physiques \u2014 cela se r\u00e9sout par des adresses IP \"statiques\" suivant les conteneurs, et par cons\u00e9quent, la n\u00e9cessit\u00e9 d'une int\u00e9gration unique avec une grande infrastructure r\u00e9seau.<\/li>\n<\/ul>\n<p><\/p>\n<p>Toutes ces fonctions n\u00e9cessiteraient d'importantes modifications des solutions existantes, et apr\u00e8s avoir \u00e9valu\u00e9 la charge de travail, nous avons r\u00e9alis\u00e9 que nous pourrions d\u00e9velopper notre propre solution avec des efforts similaires. Cependant, notre solution serait beaucoup plus simple \u00e0 exploiter et \u00e0 d\u00e9velopper \u2014 elle ne contient pas d'abstractions inutiles soutenant des fonctionnalit\u00e9s dont nous n'avons pas besoin. <\/p>\n<p><\/p>\n<p>\u00c0 ceux qui lisent ces derni\u00e8res lignes, merci pour votre patience et votre attention !<\/p>\n<p>Source : <a content=\"nofollow\" rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/odnoklassniki\/blog\/346868\/\">habr.com<\/a> <\/p>","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"excerpt":{"rendered":"<p>\u0410\u043b\u043e\u0445\u0430, \u043f\u0438\u043f\u043b! \u041c\u0435\u043d\u044f \u0437\u043e\u0432\u0443\u0442 \u041e\u043b\u0435\u0433 \u0410\u043d\u0430\u0441\u0442\u0430\u0441\u044c\u0435\u0432, \u044f \u0440\u0430\u0431\u043e\u0442\u0430\u044e \u0432 \u041e\u0434\u043d\u043e\u043a\u043b\u0430\u0441\u0441\u043d\u0438\u043a\u0430\u0445 \u0432 \u043a\u043e\u043c\u0430\u043d\u0434\u0435 \u041f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u044b. \u0410 \u043a\u0440\u043e\u043c\u0435 \u043c\u0435\u043d\u044f, \u0432 \u041e\u0434\u043d\u043e\u043a\u043b\u0430\u0441\u0441\u043d\u0438\u043a\u0430\u0445 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u043a\u0443\u0447\u0430 \u0436\u0435\u043b\u0435\u0437\u0430. \u0423 \u043d\u0430\u0441 \u0435\u0441\u0442\u044c \u0447\u0435\u0442\u044b\u0440\u0435 \u0426\u041e\u0414\u0430, \u0432 \u043d\u0438\u0445 \u043e\u043a\u043e\u043b\u043e 500 \u0441\u0442\u043e\u0435\u043a \u0431\u043e\u043b\u0435\u0435 \u0447\u0435\u043c \u0441 8 \u0442\u044b\u0441\u044f\u0447\u0430\u043c\u0438 \u0441\u0435\u0440\u0432\u0435\u0440\u043e\u0432. \u0412 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u043d\u044b\u0439 \u043c\u043e\u043c\u0435\u043d\u0442 \u043c\u044b \u043f\u043e\u043d\u044f\u043b\u0438, \u0447\u0442\u043e \u0432\u043d\u0435\u0434\u0440\u0435\u043d\u0438\u0435 \u043d\u043e\u0432\u043e\u0439 \u0441\u0438\u0441\u0442\u0435\u043c\u044b \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u043f\u043e\u0437\u0432\u043e\u043b\u0438\u0442 \u043d\u0430\u043c \u0431\u043e\u043b\u0435\u0435 \u044d\u0444\u0444\u0435\u043a\u0442\u0438\u0432\u043d\u043e \u0437\u0430\u0433\u0440\u0443\u0437\u0438\u0442\u044c \u0442\u0435\u0445\u043d\u0438\u043a\u0443, \u043e\u0431\u043b\u0435\u0433\u0447\u0438\u0442\u044c \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0435 [&hellip;]<\/p>\n","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"author":1,"featured_media":84115,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[688],"tags":[],"class_list":["post-84114","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-administrirovanie"],"aioseo_notices":[],"aioseo_head":"\n\t\t<!-- All in One SEO 5.0.2 - aioseo.com -->\n\t<meta name=\"description\" content=\"\u0410\u043b\u043e\u0445\u0430, \u043f\u0438\u043f\u043b!\" \/>\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\/one-cloud-os-urovnya-data-czentra-v-odnoklassnikah\" \/>\n\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 5.0.2\" \/>\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\udd47One-cloud \u2014 \u041e\u0421 \u0443\u0440\u043e\u0432\u043d\u044f \u0434\u0430\u0442\u0430-\u0446\u0435\u043d\u0442\u0440\u0430 \u0432 \u041e\u0434\u043d\u043e\u043a\u043b\u0430\u0441\u0441\u043d\u0438\u043a\u0430\u0445 | ProHoster\" \/>\n\t\t<meta property=\"og:description\" content=\"\u0410\u043b\u043e\u0445\u0430, \u043f\u0438\u043f\u043b!\" \/>\n\t\t<meta property=\"og:url\" content=\"https:\/\/prohoster.info\/fr\/blog\/administrirovanie\/one-cloud-os-urovnya-data-czentra-v-odnoklassnikah\" \/>\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=\"2020-06-05T05:42:55+00:00\" \/>\n\t\t<meta property=\"article:modified_time\" content=\"2020-06-05T05:42:55+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\udd47One-cloud \u2014 un syst\u00e8me d'exploitation de niveau centre de donn\u00e9es sur Odnoklassniki | ProHoster","description":"Aloha, tout le monde !","canonical_url":"https:\/\/prohoster.info\/fr\/blog\/administrirovanie\/one-cloud-os-urovnya-data-czentra-v-odnoklassnikah","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\udd47One-cloud \u2014 \u041e\u0421 \u0443\u0440\u043e\u0432\u043d\u044f \u0434\u0430\u0442\u0430-\u0446\u0435\u043d\u0442\u0440\u0430 \u0432 \u041e\u0434\u043d\u043e\u043a\u043b\u0430\u0441\u0441\u043d\u0438\u043a\u0430\u0445 | ProHoster","og:description":"\u0410\u043b\u043e\u0445\u0430, \u043f\u0438\u043f\u043b!","og:url":"https:\/\/prohoster.info\/fr\/blog\/administrirovanie\/one-cloud-os-urovnya-data-czentra-v-odnoklassnikah","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":"2020-06-05T05:42:55+00:00","article:modified_time":"2020-06-05T05:42:55+00:00","article:publisher":"https:\/\/www.facebook.com\/prohoster","article:author":"https:\/\/www.facebook.com\/prohoster"},"aioseo_meta_data":{"post_id":"84114","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":null,"breadcrumb_settings":null,"limit_modified_date":false,"reviewed_by":null,"ai":null,"created":"2021-02-28 15:04:42","updated":"2022-10-02 14:53:14","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\/84114","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=84114"}],"version-history":[{"count":0,"href":"https:\/\/prohoster.info\/fr\/wp-json\/wp\/v2\/posts\/84114\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/prohoster.info\/fr\/wp-json\/wp\/v2\/media\/84115"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/fr\/wp-json\/wp\/v2\/media?parent=84114"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/fr\/wp-json\/wp\/v2\/categories?post=84114"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/fr\/wp-json\/wp\/v2\/tags?post=84114"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}