{"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\/pt\/blog\/administrirovanie\/one-cloud-os-urovnya-data-czentra-v-odnoklassnikah","title":{"rendered":"One-cloud \u2014 sistema operacional de n\u00edvel de data center no Odnoklassniki","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<p><img decoding=\"async\" alt=\"One-cloud \u2014 sistema operacional de n\u00edvel de data center no Odnoklassniki\" src=\"\/wp-content\/uploads\/2020\/06\/fa983acacec59ff2d4ed098f87223971.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Aloha, pessoal! Meu nome \u00e9 Oleg Anastasev, trabalho no Odnoklassniki na equipe da Plataforma. Al\u00e9m de mim, h\u00e1 muitos equipamentos no Odnoklassniki. Temos quatro centros de dados, com cerca de 500 racks e mais de 8 mil servidores. Em determinado momento, percebemos que a implementa\u00e7\u00e3o de um novo sistema de gerenciamento nos permitiria usar a tecnologia de forma mais eficiente, facilitar a gest\u00e3o de acessos, automatizar a (re)distribui\u00e7\u00e3o de recursos computacionais, acelerar o lan\u00e7amento de novos servi\u00e7os e aumentar a velocidade de resposta a grandes falhas. <\/p>\n<p><\/p>\n<p>O que resultou disso? <\/p>\n<p><noindex><a rel=\"nofollow\" name=\"habracut\"><\/a><\/noindex><\/p>\n<p>Al\u00e9m de mim e de muitos equipamentos, h\u00e1 tamb\u00e9m pessoas que trabalham com esse hardware: engenheiros que est\u00e3o diretamente nos data centers; especialistas em redes que configuram a infraestrutura de rede; administradores, ou SREs, que garantem a resili\u00eancia da infraestrutura; e equipes de desenvolvedores, cada uma respons\u00e1vel por uma parte das funcionalidades do portal. O software que eles desenvolvem funciona assim:<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"One-cloud \u2014 sistema operacional de n\u00edvel de data center no Odnoklassniki\" src=\"\/wp-content\/uploads\/2020\/06\/592fd0acfa7322eb80fbb85601a92918.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>As solicita\u00e7\u00f5es dos usu\u00e1rios chegam tanto nas interfaces do portal principal <noindex><a rel=\"nofollow\" href=\"http:\/\/www.ok.ru\/\">www.ok.ru<\/a><\/noindex>, quanto em outras, por exemplo, nas interfaces da API de m\u00fasica. Para processar a l\u00f3gica de neg\u00f3cios, elas chamam o servidor de aplica\u00e7\u00f5es, que ao processar a solicita\u00e7\u00e3o chama os microservi\u00e7os especializados necess\u00e1rios \u2014 one-graph (rede de conex\u00f5es sociais), user-cache (cache de perfis de usu\u00e1rios) e assim por diante.<\/p>\n<p><\/p>\n<p>Cada um desses servi\u00e7os est\u00e1 implantado em v\u00e1rias m\u00e1quinas, e cada um deles tem desenvolvedores respons\u00e1veis pelo funcionamento dos m\u00f3dulos, sua opera\u00e7\u00e3o e desenvolvimento tecnol\u00f3gico. Todos esses servi\u00e7os s\u00e3o executados em servidores f\u00edsicos, e at\u00e9 recentemente, n\u00f3s execut\u00e1vamos exatamente uma tarefa em cada servidor, ou seja, ele era especializado para uma tarefa espec\u00edfica.<\/p>\n<p><\/p>\n<p>Por que assim? Essa abordagem tinha algumas vantagens:<\/p>\n<p><\/p>\n<ul>\n<li>Facilita <strong>a gest\u00e3o em massa<\/strong>. Suponha que a tarefa exija certas bibliotecas e configura\u00e7\u00f5es. Ent\u00e3o o servidor \u00e9 atribu\u00eddo a exatamente um determinado grupo, uma pol\u00edtica cfengine \u00e9 descrita para este grupo (ou j\u00e1 est\u00e1 descrita), e essa configura\u00e7\u00e3o \u00e9 centralizada e automaticamente distribu\u00edda para todos os servidores desse grupo.<\/li>\n<li>Facilita <strong>o diagn\u00f3stico<\/strong>. Suponha que voc\u00ea esteja observando uma carga alta na CPU e entenda que essa carga s\u00f3 pode ter sido gerada pela tarefa que est\u00e1 sendo executada nesse processador espec\u00edfico. A busca pelo culpado termina muito rapidamente.<\/li>\n<li>Facilita <strong>monitoramento<\/strong>. Se algo est\u00e1 errado com o servidor, o monitor avisa e voc\u00ea sabe exatamente quem \u00e9 o respons\u00e1vel.<\/li>\n<\/ul>\n<p><\/p>\n<p>Um servi\u00e7o composto por v\u00e1rias r\u00e9plicas \u00e9 alocado em v\u00e1rios servidores \u2014 um para cada r\u00e9plica. Assim, o recurso computacional para o servi\u00e7o \u00e9 alocado de forma muito simples: quantos servidores o servi\u00e7o tem, essa \u00e9 a quantidade m\u00e1xima de recursos que pode consumir. O 'simples' aqui n\u00e3o significa que \u00e9 f\u00e1cil de usar, mas que a distribui\u00e7\u00e3o de recursos ocorre manualmente.<\/p>\n<p><\/p>\n<p>Essa abordagem tamb\u00e9m nos permitiu criar <strong>configura\u00e7\u00f5es de hardware especializadas<\/strong> para tarefas que s\u00e3o executadas nesse servidor. Se a tarefa armazena grandes volumes de dados, usamos um servidor 4U com chassi para 38 discos. Se a tarefa \u00e9 puramente computacional, podemos adquirir um servidor 1U mais barato. Isso \u00e9 eficiente em termos de recursos computacionais. Al\u00e9m disso, essa abordagem nos permite usar quatro vezes menos m\u00e1quinas com uma carga compar\u00e1vel \u00e0 de uma rede social que nos \u00e9 favor\u00e1vel. <\/p>\n<p><\/p>\n<p>Essa efici\u00eancia na utiliza\u00e7\u00e3o dos recursos computacionais deve garantir tamb\u00e9m uma efici\u00eancia econ\u00f4mica, partindo do princ\u00edpio de que o mais caro s\u00e3o os servidores. Durante muito tempo, o que mais custava era precisamente o hardware, e investimos muito esfor\u00e7o na redu\u00e7\u00e3o de custos desse hardware, desenvolvendo algoritmos de toler\u00e2ncia a falhas para diminuir as exig\u00eancias de confiabilidade do equipamento. E hoje chegamos a um ponto em que o pre\u00e7o do servidor deixou de ser o fator determinante. A menos que consideremos ex\u00f3ticos muito novos, a configura\u00e7\u00e3o espec\u00edfica dos servidores em um rack n\u00e3o tem import\u00e2ncia. Agora, temos outro problema \u2014 o custo do espa\u00e7o ocupado pelo servidor no data center, ou seja, o espa\u00e7o no rack.<\/p>\n<p><\/p>\n<p>Percebendo isso, decidimos calcular o qu\u00e3o eficientemente estamos utilizando os racks.<br \/>\nPegamos o pre\u00e7o do servidor mais potente que \u00e9 economicamente vi\u00e1vel, calculamos quantos desses servidores caberiam nos racks, quantas tarefas poder\u00edamos executar com base no antigo modelo \"um servidor = uma tarefa\" e qu\u00e3o bem essas tarefas poderiam utilizar o equipamento. Calculamos e ficamos emocionados. A efici\u00eancia da utiliza\u00e7\u00e3o dos racks ficou em cerca de 11%. A conclus\u00e3o \u00e9 clara: precisamos aumentar a efici\u00eancia do uso dos data centers. Parece que a solu\u00e7\u00e3o \u00e9 \u00f3bvia: devemos executar v\u00e1rias tarefas em um \u00fanico servidor. Mas aqui come\u00e7am as dificuldades. <\/p>\n<p><\/p>\n<p>A configura\u00e7\u00e3o em massa se torna drasticamente mais complexa \u2014 agora n\u00e3o \u00e9 poss\u00edvel atribuir um \u00fanico grupo a um servidor. Afinal, v\u00e1rias tarefas de diferentes equipes podem ser executadas no mesmo servidor. Al\u00e9m disso, a configura\u00e7\u00e3o pode ser conflitante para diferentes aplica\u00e7\u00f5es. O diagn\u00f3stico tamb\u00e9m se complica: se voc\u00ea observa um consumo elevado de CPU ou disco em um servidor, n\u00e3o sabe qual tarefa est\u00e1 causando problemas.<\/p>\n<p><\/p>\n<p>Mas o mais importante \u00e9 que n\u00e3o h\u00e1 isolamento entre as tarefas executadas em uma \u00fanica m\u00e1quina. Por exemplo, o gr\u00e1fico de tempo m\u00e9dio de resposta de uma tarefa no servidor antes e depois de executar outro aplicativo de c\u00e1lculo n\u00e3o relacionado \u2014 o tempo de resposta da tarefa principal aumentou significativamente.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"One-cloud \u2014 sistema operacional de n\u00edvel de data center no Odnoklassniki\" src=\"\/wp-content\/uploads\/2020\/06\/c7c07359ae572ca8c84a4c63559e4083.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>\u00c9 claro que precisamos executar as tarefas em cont\u00eaineres ou em m\u00e1quinas virtuais. Como praticamente todas as tarefas s\u00e3o executadas sob um \u00fanico sistema operacional (Linux) ou adaptadas a ele, n\u00e3o precisamos suportar uma variedade de sistemas operacionais diferentes. Portanto, a virtualiza\u00e7\u00e3o n\u00e3o \u00e9 necess\u00e1ria; devido aos custos adicionais, ser\u00e1 menos eficiente do que a conteineriza\u00e7\u00e3o.<\/p>\n<p><\/p>\n<p>Como uma implementa\u00e7\u00e3o de cont\u00eaineres para executar tarefas diretamente nos servidores, o Docker \u00e9 um bom candidato: as imagens de sistema de arquivos resolvem bem os problemas de configura\u00e7\u00f5es conflitantes. O fato de as imagens poderem ser compostas de v\u00e1rias camadas nos permite reduzir significativamente o volume de dados necess\u00e1rios para sua implanta\u00e7\u00e3o na infraestrutura, destacando partes comuns em camadas b\u00e1sicas separadas. Assim, as camadas b\u00e1sicas (e mais volumosas) ser\u00e3o rapidamente armazenadas em cache em toda a infraestrutura, e para entregar muitos tipos diferentes de aplicativos e vers\u00f5es, ser\u00e1 necess\u00e1rio transferir apenas camadas menores. <\/p>\n<p><\/p>\n<p>Al\u00e9m disso, o reposit\u00f3rio pronto e a marca\u00e7\u00e3o de imagens no Docker nos fornecem primitivas prontas para vers\u00e3o e entrega de c\u00f3digo em produ\u00e7\u00e3o.<\/p>\n<p><\/p>\n<p>O Docker, assim como qualquer outra tecnologia semelhante, nos oferece um certo n\u00edvel de isolamento de cont\u00eaineres por padr\u00e3o. Por exemplo, o isolamento de mem\u00f3ria \u2014 cada cont\u00eainer recebe um limite de uso da mem\u00f3ria da m\u00e1quina, al\u00e9m do qual n\u00e3o consumir\u00e1 mais. Tamb\u00e9m \u00e9 poss\u00edvel isolar cont\u00eaineres pelo uso de CPU. Para n\u00f3s, contudo, o isolamento padr\u00e3o foi insuficiente. Mas isso ser\u00e1 abordado adiante.<\/p>\n<p><\/p>\n<p>Executar cont\u00eaineres diretamente nos servidores \u00e9 apenas parte dos problemas. A outra parte est\u00e1 relacionada ao posicionamento dos cont\u00eaineres nos servidores. Precisamos entender qual cont\u00eainer pode ser colocado em qual servidor. Essa n\u00e3o \u00e9 uma tarefa t\u00e3o simples, pois os cont\u00eaineres precisam ser posicionados nos servidores o mais densamente poss\u00edvel, sem reduzir a velocidade de funcionamento. Esse posicionamento pode ser complicado tamb\u00e9m em termos de toler\u00e2ncia a falhas. Frequentemente, queremos colocar r\u00e9plicas do mesmo servi\u00e7o em diferentes racks ou at\u00e9 mesmo em diferentes salas de datacenters, para que, em caso de falha de um rack ou sala, n\u00e3o percamos todas as r\u00e9plicas do servi\u00e7o de uma s\u00f3 vez. <\/p>\n<p><\/p>\n<p>Distribuir cont\u00eaineres manualmente n\u00e3o \u00e9 uma op\u00e7\u00e3o quando se tem 8 mil servidores e 8 a 16 mil cont\u00eaineres. <\/p>\n<p><\/p>\n<p>Al\u00e9m disso, quer\u00edamos dar aos desenvolvedores mais autonomia na distribui\u00e7\u00e3o de recursos, para que eles pudessem colocar seus servi\u00e7os em produ\u00e7\u00e3o, sem a ajuda de um administrador. Ao mesmo tempo, quer\u00edamos manter o controle para que algum servi\u00e7o secund\u00e1rio n\u00e3o consumisse todos os recursos dos nossos datacenters. <\/p>\n<p><\/p>\n<p>\u00c9 evidente que precisamos de uma camada de gerenciamento que lide com isso automaticamente.<\/p>\n<p><\/p>\n<p>Finalmente chegamos a uma imagem simples e clara, que todos os arquitetos adoram: tr\u00eas quadrados. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"One-cloud \u2014 sistema operacional de n\u00edvel de data center no 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 um cluster tolerante a falhas, respons\u00e1vel pela orquestra\u00e7\u00e3o da nuvem. O desenvolvedor envia ao master um manifesto que cont\u00e9m todas as informa\u00e7\u00f5es necess\u00e1rias para a hospedagem do servi\u00e7o. Com base nele, o master emite comandos para os minions selecionados (m\u00e1quinas designadas para executar cont\u00eaineres). Nos minions, temos nosso agente, que recebe as instru\u00e7\u00f5es, emite seus pr\u00f3prios comandos para o Docker, e o Docker configura o n\u00facleo do Linux para executar o cont\u00eainer correspondente. Al\u00e9m de executar comandos, o agente informa continuamente o master sobre as mudan\u00e7as de estado, tanto da m\u00e1quina minion quanto dos cont\u00eaineres em execu\u00e7\u00e3o nela.<\/p>\n<p><\/p>\n<h2 id=\"raspredelenie-resursov\">Distribui\u00e7\u00e3o de recursos<\/h2>\n<p><\/p>\n<p>Agora vamos lidar com a tarefa mais complexa de distribui\u00e7\u00e3o de recursos para m\u00faltiplos minions.<\/p>\n<p><\/p>\n<p>O recurso computacional no one-cloud \u00e9:<\/p>\n<p><\/p>\n<ul>\n<li>O poder de processamento do CPU consumido por uma tarefa espec\u00edfica. <\/li>\n<li>A quantidade de mem\u00f3ria dispon\u00edvel para a tarefa. <\/li>\n<li>Tr\u00e1fego de rede. Cada um dos minions possui uma interface de rede espec\u00edfica com largura de banda limitada, portanto, n\u00e3o \u00e9 poss\u00edvel distribuir tarefas sem considerar o volume de dados que est\u00e3o sendo transmitidos pela rede. <\/li>\n<li>Discos. Al\u00e9m, evidentemente, do espa\u00e7o para os dados da tarefa, tamb\u00e9m alocamos o tipo de disco: HDD ou SSD. Os discos podem atender a um n\u00famero final de solicita\u00e7\u00f5es por segundo \u2014 IOPS. Portanto, para tarefas que geram mais IOPS do que um \u00fanico disco pode suportar, tamb\u00e9m alocamos \"spindles\" \u2014 ou seja, dispositivos de disco que devem ser exclusivamente reservados para a tarefa.<\/li>\n<\/ul>\n<p><\/p>\n<p>Assim, para um determinado servi\u00e7o, por exemplo, para o user-cache, podemos registrar os recursos consumidos da seguinte forma: 400 n\u00facleos de CPU, 2,5 TB de mem\u00f3ria, 50 Gbps de tr\u00e1fego em ambas as dire\u00e7\u00f5es, 6 TB de espa\u00e7o em HDD, alocados em 100 spindles. Ou de uma forma mais familiar para n\u00f3s:<\/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>Os recursos do servi\u00e7o user-cache consomem apenas parte de todos os recursos dispon\u00edveis na infraestrutura de produ\u00e7\u00e3o. Portanto, \u00e9 desej\u00e1vel evitar que, repentinamente, devido a um erro do operador ou n\u00e3o, o user-cache consuma mais recursos do que os atribu\u00eddos a ele. Ou seja, devemos limitar os recursos. Mas a que poder\u00edamos vincular a cota?<\/p>\n<p><\/p>\n<p>Vamos voltar ao nosso esquema simplificado de intera\u00e7\u00e3o entre componentes e redesenhar com mais detalhes \u2014 assim: <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"One-cloud \u2014 sistema operacional de n\u00edvel de data center no Odnoklassniki\" src=\"\/wp-content\/uploads\/2020\/06\/27e5bfbffadd3d4b9fdc6bf138d135ed.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>O que se destaca:<\/p>\n<p><\/p>\n<ul>\n<li>O frontend da web e a m\u00fasica utilizam clusters isolados do mesmo servidor de aplicativos.<\/li>\n<li>Podemos identificar camadas l\u00f3gicas, que incluem esses clusters: frontends, caches, camada de armazenamento e gest\u00e3o de dados.<\/li>\n<li>O frontend \u00e9 heterog\u00eaneo, consistindo em diferentes subsistemas funcionais. <\/li>\n<li>Os caches tamb\u00e9m podem ser distribu\u00eddos entre os subsistemas cujos dados eles armazenam.<\/li>\n<\/ul>\n<p><\/p>\n<p>Vamos redesenhar a imagem mais uma vez:<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"One-cloud \u2014 sistema operacional de n\u00edvel de data center no Odnoklassniki\" src=\"\/wp-content\/uploads\/2020\/06\/905dacc0aca859e65bd33ef751a557cf.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Uau! Estamos vendo uma hierarquia! Isso significa que podemos alocar recursos em por\u00e7\u00f5es maiores: designar um desenvolvedor respons\u00e1vel para um n\u00f3 dessa hierarquia, correspondente ao subsistema funcional (como 'music' na imagem), e vincular uma cota a esse mesmo n\u00edvel de hierarquia. Essa hierarquia tamb\u00e9m nos permite organizar servi\u00e7os de maneira mais flex\u00edvel para facilitar a gest\u00e3o. Por exemplo, todo o web, sendo uma grande agrupa\u00e7\u00e3o de servidores, dividimos em v\u00e1rios grupos menores, mostrados na imagem como group1, group2.<\/p>\n<p><\/p>\n<p>Removendo linhas desnecess\u00e1rias, podemos escrever cada n\u00f3 da nossa imagem de uma forma mais plana: <strong>group1.web.front<\/strong>, <strong>api.music.front<\/strong>, <strong>user-cache.cache<\/strong>.<\/p>\n<p><\/p>\n<p>Assim, chegamos ao conceito de 'fila hier\u00e1rquica'. Ela possui um nome, como 'group1.web.front'. A ela \u00e9 atribu\u00edda uma cota de recursos e direitos de usu\u00e1rios. Para uma pessoa da DevOps, daremos direitos para enviar servi\u00e7os \u00e0 fila, e esse colaborador pode iniciar algo na fila, enquanto uma pessoa da OpsDev ter\u00e1 direitos administrativos, podendo agora gerenciar a fila, designar pessoas a ela, conceder direitos e assim por diante. Os servi\u00e7os iniciados nessa fila ser\u00e3o executados dentro da cota da fila. Se a cota computacional da fila n\u00e3o for suficiente para a execu\u00e7\u00e3o simult\u00e2nea de todos os servi\u00e7os, eles ser\u00e3o executados sequencialmente, formando assim a fila propriamente dita. <\/p>\n<p><\/p>\n<p>Vamos analisar os servi\u00e7os com mais detalhes. Um servi\u00e7o tem um nome completo que sempre inclui o nome da fila. Ent\u00e3o, o servi\u00e7o web front ter\u00e1 o nome <strong>ok-web.group1.web.front<\/strong>. E o servi\u00e7o do servidor de aplicativos ao qual ele se conecta ser\u00e1 chamado de <strong>ok-app.group1.web.front<\/strong>. Cada servi\u00e7o possui um manifesto que cont\u00e9m todas as informa\u00e7\u00f5es necess\u00e1rias para a aloca\u00e7\u00e3o em m\u00e1quinas espec\u00edficas: quantos recursos essa tarefa consome, qual configura\u00e7\u00e3o \u00e9 necess\u00e1ria, quantas r\u00e9plicas devem existir, propriedades para o tratamento de falhas desse servi\u00e7o. E, ap\u00f3s a aloca\u00e7\u00e3o do servi\u00e7o diretamente nas m\u00e1quinas, surgem suas inst\u00e2ncias. Elas tamb\u00e9m s\u00e3o nomeadas de forma \u00fanica \u2014 como o n\u00famero da inst\u00e2ncia e o nome do servi\u00e7o: <strong>1.ok-web.group1.web.front, 2.ok-web.group1.web.front, \u2026<\/strong><\/p>\n<p><\/p>\n<p>Isso \u00e9 muito conveniente: ao olhar apenas para o nome do cont\u00eainer em execu\u00e7\u00e3o, podemos imediatamente descobrir muitas coisas.<\/p>\n<p><\/p>\n<p>Agora vamos conhecer melhor o que essas inst\u00e2ncias realmente executam: as tarefas.<\/p>\n<p><\/p>\n<h2 id=\"klassy-izolyacii-zadach\">Classes de isolamento de tarefas<\/h2>\n<p><\/p>\n<p>Todas as tarefas em OK (e provavelmente em qualquer lugar) podem ser divididas em grupos:<\/p>\n<p><\/p>\n<ul>\n<li><strong>Tarefas com atraso curto \u2014 prod<\/strong>. Para essas tarefas e servi\u00e7os, a lat\u00eancia (delay) \u00e9 muito importante, ou seja, qu\u00e3o rapidamente cada uma das solicita\u00e7\u00f5es ser\u00e1 processada pelo sistema. Exemplos de tarefas: front-end web, caches, servidores de aplicativos, armazenamentos OLTP, etc.<\/li>\n<li><strong>Tarefas de c\u00e1lculo \u2014 batch<\/strong>. Aqui, a velocidade de processamento de cada solicita\u00e7\u00e3o espec\u00edfica n\u00e3o \u00e9 importante. O que importa \u00e9 quantos c\u00e1lculos totais essa tarefa realiza em um determinado (grande) intervalo de tempo (throughput). Isso inclui quaisquer tarefas MapReduce, Hadoop, aprendizado de m\u00e1quina, estat\u00edstica.<\/li>\n<li><strong>Tarefas em segundo plano \u2014 idle<\/strong>. Para essas tarefas, nem a lat\u00eancia nem o throughput s\u00e3o muito importantes. Elas incluem v\u00e1rios testes, migra\u00e7\u00f5es, contagens, convers\u00f5es de dados de um formato para outro. Por um lado, elas s\u00e3o semelhantes \u00e0s tarefas de c\u00e1lculo; por outro, n\u00e3o nos importa muito qu\u00e3o r\u00e1pido elas s\u00e3o conclu\u00eddas. <\/li>\n<\/ul>\n<p><\/p>\n<p>Vamos ver como essas tarefas consomem recursos, por exemplo, o processador central.<\/p>\n<p><\/p>\n<p><strong>Tarefas com atraso curto.<\/strong> Para tal tarefa, o padr\u00e3o de consumo de CPU ser\u00e1 semelhante a este:<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"One-cloud \u2014 sistema operacional de n\u00edvel de data center no Odnoklassniki\" src=\"\/wp-content\/uploads\/2020\/06\/1ed82c0df76325eb30056ad9af86e86e.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Uma solicita\u00e7\u00e3o do usu\u00e1rio \u00e9 recebida, a tarefa come\u00e7a a usar todos os n\u00facleos de CPU dispon\u00edveis, processa, retorna uma resposta, aguarda a pr\u00f3xima solicita\u00e7\u00e3o e permanece ociosa. Uma nova solicita\u00e7\u00e3o chega \u2014 novamente, utiliza tudo o que estava dispon\u00edvel, processa, e aguarda a pr\u00f3xima.<\/p>\n<p><\/p>\n<p>Para garantir uma lat\u00eancia m\u00ednima para essa tarefa, devemos pegar o m\u00e1ximo de recursos que ela consome e reservar o n\u00famero necess\u00e1rio de n\u00facleos na minion (m\u00e1quina que ir\u00e1 executar a tarefa). Assim, a f\u00f3rmula de reserva para a nossa tarefa ser\u00e1:<\/p>\n<p><\/p>\n<pre><code>alloc: cpu = 4 (max)<\/code><\/pre>\n<p><\/p>\n<p>E se tivermos uma m\u00e1quina minion com 16 n\u00facleos, podemos alocar exatamente quatro dessas tarefas. \u00c9 importante destacar que o consumo m\u00e9dio de CPU para essas tarefas \u00e9 frequentemente muito baixo \u2014 o que \u00e9 evidente, uma vez que grande parte do tempo a tarefa est\u00e1 aguardando uma solicita\u00e7\u00e3o e n\u00e3o est\u00e1 fazendo nada.<\/p>\n<p><\/p>\n<p><strong>Tarefas de c\u00e1lculo.<\/strong> O padr\u00e3o delas ser\u00e1 um pouco diferente:<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"One-cloud \u2014 sistema operacional de n\u00edvel de data center no Odnoklassniki\" src=\"\/wp-content\/uploads\/2020\/06\/35b37fa1d70a137287cafdbfe3bcfc2e.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>O consumo m\u00e9dio de recursos de CPU para essas tarefas \u00e9 bastante alto. Frequentemente, queremos que a tarefa de c\u00e1lculo seja conclu\u00edda dentro de um determinado tempo, por isso \u00e9 necess\u00e1rio reservar a quantidade m\u00ednima de processadores que ela precisa para que todo o c\u00e1lculo seja finalizado dentro de um tempo aceit\u00e1vel. A f\u00f3rmula de reserva ser\u00e1 assim:<\/p>\n<p><\/p>\n<pre><code>alloc: cpu = [1,*)<\/code><\/pre>\n<p><\/p>\n<p><em>\u201cPor favor, aloque em um minion onde h\u00e1 pelo menos um n\u00facleo livre, e quantos mais puder, levar\u00e1 tudo.\u201d<\/em><\/p>\n<p><\/p>\n<p>Aqui a efici\u00eancia de uso j\u00e1 \u00e9 significativamente melhor do que nas tarefas com atraso curto. Mas o ganho ser\u00e1 muito maior se combinarmos ambos os tipos de tarefas em uma \u00fanica m\u00e1quina minion e distribuirmos seus recursos em tempo real. Quando uma tarefa com atraso curto requer CPU \u2014 ela a recebe imediatamente, e quando os recursos n\u00e3o s\u00e3o mais necess\u00e1rios \u2014 eles s\u00e3o transferidos para a tarefa de c\u00e1lculo, ou seja, em resumo:<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"One-cloud \u2014 sistema operacional de n\u00edvel de data center no Odnoklassniki\" src=\"\/wp-content\/uploads\/2020\/06\/875ad8d3f6a01e4fd0a89d0931e986c1.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Mas como fazer isso?<\/p>\n<p><\/p>\n<p>Primeiro, vamos entender com prod e seu alloc: cpu = 4. Precisamos reservar quatro n\u00facleos. No Docker run, isso pode ser feito de duas maneiras: <\/p>\n<p><\/p>\n<ul>\n<li>Com a op\u00e7\u00e3o <code>--cpuset=1-4<\/code>, ou seja, alocar quatro n\u00facleos espec\u00edficos para a tarefa na m\u00e1quina.<\/li>\n<li>Usar <code>--cpuquota=400_000 --cpuperiod=100_000<\/code>, designar uma cota de tempo de CPU, ou seja, especificar que a cada 100 ms de tempo real, a tarefa consome no m\u00e1ximo 400 ms de tempo de CPU. Isso resulta nos mesmos quatro n\u00facleos. <\/li>\n<\/ul>\n<p><\/p>\n<p>Mas qual desses m\u00e9todos \u00e9 o mais adequado?<\/p>\n<p><\/p>\n<p>O cpuset parece bastante atraente. A tarefa tem quatro n\u00facleos dedicados, o que significa que os caches do processador funcionar\u00e3o de forma mais eficaz. No entanto, isso tem um lado negativo: ter\u00edamos que assumir a responsabilidade de distribuir os c\u00e1lculos pelos n\u00facleos n\u00e3o carregados da m\u00e1quina em vez do sistema operacional, e isso \u00e9 uma tarefa bastante n\u00e3o trivial, especialmente se tentarmos alocar tarefas em lote nessa m\u00e1quina. Os testes mostraram que a op\u00e7\u00e3o com cota \u00e9 a mais adequada: assim, o sistema operacional tem mais liberdade para escolher o n\u00facleo em que executar a tarefa no momento e o tempo de processador \u00e9 distribu\u00eddo de forma mais eficiente.<\/p>\n<p><\/p>\n<p>Vamos entender como fazer a reserva do n\u00famero m\u00ednimo de n\u00facleos no Docker. A cota para tarefas em lote j\u00e1 n\u00e3o \u00e9 aplic\u00e1vel, porque n\u00e3o \u00e9 necess\u00e1rio limitar um m\u00e1ximo, basta garantir um m\u00ednimo. E aqui se encaixa bem a op\u00e7\u00e3o <code>docker run --cpushares<\/code>.<\/p>\n<p><\/p>\n<p>N\u00f3s acordamos que se o lote requer uma garantia m\u00ednima em um n\u00facleo, ent\u00e3o devemos especificar <code>--cpushares=1024<\/code>, e se o m\u00ednimo for dois n\u00facleos, especificamos <code>--cpushares=2048<\/code>. As cpu shares n\u00e3o interferem na distribui\u00e7\u00e3o do tempo de processador at\u00e9 que haja o suficiente. Assim, se o prod n\u00e3o estiver usando todos os seus quatro n\u00facleos no momento \u2014 nada limita as tarefas em lote, e elas podem usar tempo de processador adicional. Mas na situa\u00e7\u00e3o em que h\u00e1 falta de processador, se o prod consumiu todos os seus quatro n\u00facleos e atingiu o limite \u2014 o tempo de processador restante ser\u00e1 dividido proporcionalmente entre as cpu shares, ou seja, na situa\u00e7\u00e3o de tr\u00eas n\u00facleos livres, uma receber\u00e1 a tarefa com 1024 cpu shares, e as outras duas \u2014 a tarefa com 2048 cpu shares.<\/p>\n<p><\/p>\n<p>Mas usar quota e shares n\u00e3o \u00e9 suficiente. Precisamos garantir que a tarefa com baixa lat\u00eancia tenha prioridade sobre a tarefa em lote na distribui\u00e7\u00e3o do tempo de processador. Sem tal prioriza\u00e7\u00e3o, a tarefa em lote consumir\u00e1 todo o tempo de processador no momento em que ele \u00e9 necess\u00e1rio para o prod. No Docker run, n\u00e3o h\u00e1 op\u00e7\u00f5es de prioriza\u00e7\u00e3o de cont\u00eaineres, mas as pol\u00edticas do escalonador de CPU no Linux v\u00eam em nosso aux\u00edlio. Detalhes sobre isso podem ser lidos <noindex><a rel=\"nofollow\" href=\"http:\/\/man7.org\/linux\/man-pages\/man2\/sched_setscheduler.2.html\">aqui<\/a><\/noindex>, mas neste artigo, vamos abord\u00e1-las brevemente:<\/p>\n<p><\/p>\n<ul>\n<li><strong>SCHED_OTHER<\/strong><br \/>\nPor padr\u00e3o, todos os processos de usu\u00e1rio comuns em uma m\u00e1quina Linux recebem essa op\u00e7\u00e3o.<\/li>\n<li><strong>SCHED_BATCH<\/strong><br \/>\nDestinada a processos intensivos em recursos. Ao alocar uma tarefa no processador, aplica-se uma chamada penalidade de ativa\u00e7\u00e3o: essa tarefa tem menor probabilidade de receber os recursos do processador se, no momento, uma tarefa com SCHED_OTHER estiver utilizando esses recursos.<\/li>\n<li><strong>SCHED_IDLE<\/strong><br \/>\nProcesso em segundo plano com prioridade muito baixa, ainda mais baixa do que o nice \u201319. Usamos nossa biblioteca de c\u00f3digo aberto <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/odnoklassniki\/one-nio\">one-nio<\/a><\/noindex>, para definir a pol\u00edtica necess\u00e1ria ao iniciar o cont\u00eainer atrav\u00e9s da chamada<\/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>Mas mesmo que voc\u00ea n\u00e3o esteja programando em Java, o mesmo pode ser feito com o comando chrt:<\/p>\n<p><\/p>\n<pre><code class=\"bash\">chrt -i 0 $pid<\/code><\/pre>\n<p><\/p>\n<p>Vamos consolidar todos os nossos n\u00edveis de isolamento em uma tabela para facilitar a visualiza\u00e7\u00e3o:<\/p>\n<p><\/p>\n<p>Classe de isolamento<br \/>\nExemplo alloc<br \/>\nOp\u00e7\u00f5es 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>*Se voc\u00ea executar chrt de dentro do cont\u00eainer, pode precisar da capability sys_nice, porque por padr\u00e3o o Docker remove essa capability ao iniciar o cont\u00eainer.<\/p>\n<p><\/p>\n<p>Mas as tarefas consomem n\u00e3o apenas CPU, mas tamb\u00e9m tr\u00e1fego, o que afeta ainda mais a lat\u00eancia da tarefa de rede do que a distribui\u00e7\u00e3o incorreta de recursos do processador. Portanto, queremos obter exatamente a mesma vis\u00e3o para o tr\u00e1fego. Ou seja, quando uma tarefa prod envia alguns pacotes para a rede, limitamos a velocidade m\u00e1xima (f\u00f3rmula <em>alloc: lan=[*,500mbps)<\/em> ), com a qual o prod pode fazer isso. E para os batch, garantimos apenas o throughput m\u00ednimo, mas n\u00e3o limitamos o m\u00e1ximo (f\u00f3rmula <em>alloc: lan=[10Mbps,*)<\/em> ) Nesse caso, o tr\u00e1fego prod deve ter prioridade sobre as tarefas batch.<br \/>\nAqui, o Docker n\u00e3o possui primitivas que poder\u00edamos usar. Mas temos a ajuda do <noindex><a rel=\"nofollow\" href=\"http:\/\/lartc.org\/\">Linux Traffic Control<\/a><\/noindex>. Conseguimos alcan\u00e7ar o resultado desejado usando a disciplina <noindex><a rel=\"nofollow\" href=\"http:\/\/linux-ip.net\/articles\/hfsc.en\/\">Hierarchical Fair Service Curve<\/a><\/noindex>. Com isso, separamos duas classes de tr\u00e1fego: de alto-prioridade prod e de baixa-prioridade batch\/idle. Assim, a configura\u00e7\u00e3o para o tr\u00e1fego de sa\u00edda fica assim:<\/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 sistema operacional de n\u00edvel de data center no Odnoklassniki\" src=\"\/wp-content\/uploads\/2020\/06\/3f52a968118b6021bd0c920af17a00c0.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/a><\/noindex><\/p>\n<p><\/p>\n<p>aqui 1:0 \u2014 &#171;qdisc raiz&#187; da disciplina hsfc; 1:1 \u2014 classe filha hsfc com um limite total de largura de banda de 8 Gbit\/s, sob a qual s\u00e3o colocadas classes filhas de todos os containers; 1:2 \u2014 classe filha hsfc comum para todas as tarefas em lote (batch) e em espera (idle) com um limite &#171;din\u00e2mico&#187;, que ser\u00e1 descrito abaixo. As outras classes filhas hsfc s\u00e3o classes dedicadas para containers prod atualmente em funcionamento, com limites correspondentes aos seus manifestos, \u2013 450 e 400 Mbit\/s. Cada classe hsfc \u00e9 atribu\u00edda a uma fila qdisc fq ou fq_codel, dependendo da vers\u00e3o do n\u00facleo do linux, para evitar a perda de pacotes durante picos de tr\u00e1fego. <\/p>\n<p><\/p>\n<p>Normalmente, as disciplinas tc servem apenas para priorizar o tr\u00e1fego de sa\u00edda. Mas queremos priorizar tamb\u00e9m o tr\u00e1fego de entrada \u2014 j\u00e1 que alguma tarefa batch pode facilmente consumir toda a largura de banda de entrada, recebendo, por exemplo, um grande pacote de dados de entrada para map&amp;reduce. Para isso, usamos o m\u00f3dulo <noindex><a rel=\"nofollow\" href=\"https:\/\/serverfault.com\/questions\/350023\/tc-ingress-policing-and-ifb-mirroring\">ifb<\/a><\/noindex>, que cria uma interface virtual ifbX para cada interface de rede e redireciona o tr\u00e1fego de entrada da interface para a sa\u00edda em ifbX. Em seguida, para ifbX funcionam todas as mesmas disciplinas de controle de tr\u00e1fego de sa\u00edda, para as quais a configura\u00e7\u00e3o hsfc ser\u00e1 muito semelhante:<\/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 sistema operacional de n\u00edvel de data center no Odnoklassniki\" src=\"\/wp-content\/uploads\/2020\/06\/967da9c0637cc70ba195af781db18adf.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/a><\/noindex><\/p>\n<p><\/p>\n<p>Durante os experimentos, descobrimos que os melhores resultados do hsfc s\u00e3o alcan\u00e7ados quando a classe 1:2 do tr\u00e1fego batch\/idle n\u00e3o priorit\u00e1rio \u00e9 limitada nas m\u00e1quinas-minion a n\u00e3o mais do que uma largura de banda livre determinada. Caso contr\u00e1rio, o tr\u00e1fego n\u00e3o priorit\u00e1rio afeta muito a lat\u00eancia das tarefas prod. O valor atual da largura de banda livre \u00e9 determinado a cada segundo pelo miniond, medindo o consumo m\u00e9dio de tr\u00e1fego de todas as tarefas prod desse minion <img decoding=\"async\" alt=\"One-cloud \u2014 sistema operacional de n\u00edvel de data center no Odnoklassniki\" src=\"\/wp-content\/uploads\/2020\/06\/9d6f38110d3b1693afe222b01430b9bb.jpg\" style=\"display:block;margin: 0 auto;\" \/> e subtraindo isso da largura de banda da interface de rede <img decoding=\"async\" alt=\"One-cloud \u2014 sistema operacional de n\u00edvel de data center no Odnoklassniki\" src=\"\/wp-content\/uploads\/2020\/06\/d5608ec4c58e44b8571ab0b1d0cc7701.jpg\" style=\"display:block;margin: 0 auto;\" \/> com uma pequena margem, ou seja,<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"One-cloud \u2014 sistema operacional de n\u00edvel de data center no Odnoklassniki\" src=\"\/wp-content\/uploads\/2020\/06\/fb01347c2224bd5bbd82169861eeb7e4.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>As larguras s\u00e3o definidas para o tr\u00e1fego de entrada e sa\u00edda de forma independente. E de acordo com os novos valores, o miniond reconfigura o limite da classe n\u00e3o priorit\u00e1ria 1:2.<\/p>\n<p><\/p>\n<p>Assim, implementamos todas as tr\u00eas classes de isolamento: prod, batch e idle. Essas classes afetam fortemente o desempenho das tarefas. Portanto, decidimos colocar esse recurso no topo da hierarquia, para que ao olhar para o nome da fila hier\u00e1rquica, fique claro imediatamente com o que estamos lidando: <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"One-cloud \u2014 sistema operacional de n\u00edvel de data center no Odnoklassniki\" src=\"\/wp-content\/uploads\/2020\/06\/34dc89c461db711b19a0f4eccc50efce.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Todos os nossos conhecidos <strong>web<\/strong> e <strong>music<\/strong> front-end s\u00e3o ent\u00e3o colocados na hierarquia sob prod. Para exemplo, sob batch vamos colocar o servi\u00e7o <strong>cat\u00e1logo de m\u00fasicas<\/strong>, que periodicamente compila um cat\u00e1logo de faixas a partir de um conjunto de arquivos mp3 carregados no \"Odnoklassniki\". Um exemplo de servi\u00e7o em idle pode ser <strong>transformador de m\u00fasica<\/strong>, que normaliza o n\u00edvel de volume da m\u00fasica.<\/p>\n<p><\/p>\n<p>Removendo novamente as linhas desnecess\u00e1rias, podemos escrever os nomes de nossos servi\u00e7os de forma mais plana, adicionando a classe de isolamento da tarefa ao final do nome completo do servi\u00e7o: <strong>web.front.prod<\/strong>, <strong>catalog.music.batch<\/strong>, <strong>transformer.music.idle<\/strong>.<\/p>\n<p><\/p>\n<p>E agora, olhando para o nome do servi\u00e7o, entendemos n\u00e3o apenas qual fun\u00e7\u00e3o ele desempenha, mas tamb\u00e9m sua classe de isolamento, e, portanto, sua criticidade etc.<\/p>\n<p><\/p>\n<p>Tudo \u00e9 maravilhoso, mas h\u00e1 uma amarga verdade. \u00c9 imposs\u00edvel isolar completamente as tarefas que operam em uma \u00fanica m\u00e1quina.<\/p>\n<p><\/p>\n<p>O que conseguimos alcan\u00e7ar: se o batch consome intensivamente <strong>apenas<\/strong> recursos da CPU, o agendador embutido do Linux gerencia muito bem sua tarefa, e a influ\u00eancia sobre a tarefa prod \u00e9 praticamente inexistente. Mas se essa tarefa de batch come\u00e7a a trabalhar ativamente com a mem\u00f3ria, ent\u00e3o a influ\u00eancia m\u00fatua j\u00e1 aparece. Isso acontece porque os caches de CPU da tarefa prod s\u00e3o \"esvaziados\" \u2014 no final, aumentam os misses no cache e o processador processa a tarefa prod mais lentamente. Tal tarefa de batch pode aumentar em 10% as lat\u00eancias do nosso t\u00edpico container prod.<\/p>\n<p><\/p>\n<p>Isolar o tr\u00e1fego \u00e9 ainda mais dif\u00edcil devido ao fato de que as modernas placas de rede possuem uma fila interna de pacotes. Se um pacote da tarefa de batch foi o primeiro a entrar, ele ser\u00e1 o primeiro a ser transmitido pelo cabo, e isso n\u00e3o pode ser alterado.<\/p>\n<p><\/p>\n<p>Al\u00e9m disso, at\u00e9 agora conseguimos resolver apenas a tarefa de prioriza\u00e7\u00e3o do tr\u00e1fego TCP: para o UDP, a abordagem com hsfc n\u00e3o funciona. E mesmo no caso do tr\u00e1fego TCP, se a tarefa de batch gerar muito tr\u00e1fego, isso tamb\u00e9m resulta em um aumento de aproximadamente 10% na lat\u00eancia da tarefa prod.<\/p>\n<p><\/p>\n<h2 id=\"otkazoustoychivost\">Resili\u00eancia<\/h2>\n<p><\/p>\n<p>Um dos objetivos ao desenvolver o one-cloud foi melhorar a resist\u00eancia a falhas do Odnoklassniki. Portanto, a seguir, gostaria de examinar mais detalhadamente poss\u00edveis cen\u00e1rios de falhas e emerg\u00eancias. Vamos come\u00e7ar com um cen\u00e1rio simples \u2014 a falha de um container. <\/p>\n<p><\/p>\n<p>Um cont\u00eainer pode falhar de v\u00e1rias maneiras. Pode ser um experimento, um bug ou um erro no manifesto que faz com que a tarefa de produ\u00e7\u00e3o comece a consumir mais recursos do que especificado. T\u00ednhamos um caso em que um desenvolvedor implementou um algoritmo complexo e, ao recri\u00e1-lo v\u00e1rias vezes, se confundiu tanto que, no final, a tarefa entrou em um loop que n\u00e3o era trivial. E como a tarefa de produ\u00e7\u00e3o tem prioridade sobre todas as outras nas mesmas m\u00e1quinas, ela come\u00e7ou a consumir todos os recursos dispon\u00edveis da CPU. Nesta situa\u00e7\u00e3o, a isola\u00e7\u00e3o ajudou, mais especificamente, uma cota de tempo de CPU. Se uma tarefa tiver uma cota atribu\u00edda, ela n\u00e3o consumir\u00e1 mais que isso. Portanto, as tarefas em lote e outras tarefas de produ\u00e7\u00e3o que estavam na mesma m\u00e1quina n\u00e3o notaram nada. <\/p>\n<p><\/p>\n<p>O segundo problema poss\u00edvel \u00e9 a falha do cont\u00eainer. E aqui as pol\u00edticas de rein\u00edcio nos salvam, todos conhecem isso, o Docker se sai muito bem. Quase todas as tarefas de produ\u00e7\u00e3o t\u00eam a pol\u00edtica de rein\u00edcio sempre. \u00c0s vezes usamos on_failure para tarefas em lote ou para depura\u00e7\u00e3o de cont\u00eaineres de produ\u00e7\u00e3o.<\/p>\n<p><\/p>\n<p>E o que pode ser feito quando um minion inteiro fica indispon\u00edvel?<\/p>\n<p><\/p>\n<p>Obviamente, executar o cont\u00eainer em outra m\u00e1quina. O mais interessante aqui \u00e9 o que acontece com o endere\u00e7o IP atribu\u00eddo ao cont\u00eainer. <\/p>\n<p><\/p>\n<p>Podemos atribuir aos cont\u00eaineres os mesmos endere\u00e7os IP que as m\u00e1quinas minions nas quais esses cont\u00eaineres est\u00e3o sendo executados. Assim, ao executar um cont\u00eainer em outra m\u00e1quina, seu endere\u00e7o IP muda e todos os clientes devem entender que o cont\u00eainer foi movido, agora \u00e9 necess\u00e1rio acessar outro endere\u00e7o, o que requer um servi\u00e7o separado de Descoberta de Servi\u00e7o. <\/p>\n<p><\/p>\n<p>A Descoberta de Servi\u00e7o \u00e9 conveniente. H\u00e1 muitas solu\u00e7\u00f5es no mercado com diferentes graus de toler\u00e2ncia a falhas para organizar o registro de servi\u00e7os. Muitas vezes, essas solu\u00e7\u00f5es implementam a l\u00f3gica do balanceador de carga, armazenam configura\u00e7\u00f5es adicionais na forma de um armazenamento KV, etc.<br \/>\nNo entanto, gostar\u00edamos de evitar a necessidade de implementar um registro separado, pois isso significaria a introdu\u00e7\u00e3o de um sistema cr\u00edtico que \u00e9 usado por todos os servi\u00e7os em produ\u00e7\u00e3o. Isso representa um ponto de falha potencial, e \u00e9 necess\u00e1rio escolher ou desenvolver uma solu\u00e7\u00e3o muito resiliente, o que, obviamente, \u00e9 bastante complicado, demorado e caro. <\/p>\n<p><\/p>\n<p>E mais uma grande desvantagem: para que nossa antiga infraestrutura funcionasse com a nova, seria necess\u00e1rio reescrever absolutamente todas as tarefas para utilizar algum sistema de Service Discovery. O trabalho \u00e9 MUITO, e em alguns pontos chega a ser imposs\u00edvel, principalmente quando se trata de dispositivos de baixo n\u00edvel que operam no n\u00facleo do sistema operacional ou diretamente com o hardware. A implementa\u00e7\u00e3o dessa funcionalidade por meio de padr\u00f5es de solu\u00e7\u00f5es estabelecidas, como por exemplo <noindex><a rel=\"nofollow\" href=\"https:\/\/linkerd.io\">side-car<\/a><\/noindex> terminaria significando, em alguns casos, uma carga adicional, e em outros \u2014 uma complexidade na opera\u00e7\u00e3o e novos cen\u00e1rios de falha. N\u00e3o quer\u00edamos complicar as coisas, ent\u00e3o decidimos tornar o uso do Service Discovery opcional. <\/p>\n<p><\/p>\n<p>No one-cloud, o IP segue o cont\u00eainer, ou seja, cada inst\u00e2ncia da tarefa tem seu pr\u00f3prio endere\u00e7o IP. Esse endere\u00e7o \u00e9 \"est\u00e1tico\": ele \u00e9 atribu\u00eddo a cada inst\u00e2ncia no momento do primeiro envio do servi\u00e7o para a nuvem. Se durante a vida do servi\u00e7o houver um n\u00famero diferente de inst\u00e2ncias, no final, ser\u00e3o atribu\u00eddos tantos endere\u00e7os IP quantas foram as inst\u00e2ncias m\u00e1ximas.<\/p>\n<p><\/p>\n<p>Posteriormente, esses endere\u00e7os n\u00e3o mudam: s\u00e3o atribu\u00eddos uma vez e continuam existindo durante toda a vida do servi\u00e7o em produ\u00e7\u00e3o. Os endere\u00e7os IP seguem os cont\u00eaineres pela rede. Se um cont\u00eainer for movido para outro minion, o endere\u00e7o tamb\u00e9m seguir\u00e1 sua transfer\u00eancia. <\/p>\n<p><\/p>\n<p>Assim, a correspond\u00eancia entre o nome do servi\u00e7o e a lista de seus endere\u00e7os IP muda raramente. Se olharmos novamente para os nomes das inst\u00e2ncias de servi\u00e7os que mencionamos no in\u00edcio do artigo (<strong>1.ok-web.group1.web.front.prod, 2.ok-web.group1.web.front.prod, \u2026<\/strong>), ent\u00e3o perceberemos que eles lembram FQDNs usados no DNS. E realmente, para exibir os nomes das inst\u00e2ncias de servi\u00e7os em seus endere\u00e7os IP, utilizamos o protocolo DNS. Ali\u00e1s, esse DNS retorna todos os endere\u00e7os IP reservados de todos os cont\u00eaineres \u2014 tanto os em funcionamento quanto os parados (digamos que s\u00e3o usadas tr\u00eas r\u00e9plicas e temos cinco endere\u00e7os reservados \u2014 todos os cinco ser\u00e3o retornados). Os clientes, ao receber essas informa\u00e7\u00f5es, tentar\u00e3o estabelecer conex\u00e3o com todas as cinco r\u00e9plicas \u2014 e assim determinar\u00e3o aquelas que est\u00e3o ativas. Esse m\u00e9todo de verifica\u00e7\u00e3o de disponibilidade \u00e9 significativamente mais confi\u00e1vel, pois n\u00e3o envolve nem DNS, nem Service Discovery, o que significa que n\u00e3o h\u00e1 tarefas dif\u00edceis relacionadas \u00e0 atualiza\u00e7\u00e3o das informa\u00e7\u00f5es e \u00e0 resili\u00eancia desses sistemas. Al\u00e9m disso, em servi\u00e7os cr\u00edticos dos quais depende o funcionamento de todo o portal, podemos at\u00e9 n\u00e3o utilizar DNS, mas simplesmente inserir na configura\u00e7\u00e3o os endere\u00e7os IP.<\/p>\n<p><\/p>\n<p>A implementa\u00e7\u00e3o dessa transfer\u00eancia de IP para os cont\u00eaineres pode ser n\u00e3o trivial \u2014 e pararemos para ver como isso funciona no pr\u00f3ximo exemplo:<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"One-cloud \u2014 sistema operacional de n\u00edvel de data center no Odnoklassniki\" src=\"\/wp-content\/uploads\/2020\/06\/faf99c2609a57daa1bdc193cb0f4cb31.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Suponhamos que o mestre one-cloud d\u00ea a ordem para o minion M1 iniciar <strong>1.ok-web.group1.web.front.prod<\/strong> com o endere\u00e7o 1.1.1.1. No minion, est\u00e1 em execu\u00e7\u00e3o <noindex><a rel=\"nofollow\" href=\"https:\/\/en.wikipedia.org\/wiki\/Bird_Internet_routing_daemon\">BIRD<\/a><\/noindex>, que anuncia esse endere\u00e7o para servidores especiais <noindex><a rel=\"nofollow\" href=\"https:\/\/en.wikipedia.org\/wiki\/Route_reflector\">route reflector<\/a><\/noindex>. Estes \u00faltimos t\u00eam uma sess\u00e3o BGP com o equipamento de rede, para o qual se transmite a rota do endere\u00e7o 1.1.1.1 para o M1. O M1 roteia os pacotes para dentro do cont\u00eainer utilizando os recursos do Linux. Existem tr\u00eas servidores route reflector, pois essa \u00e9 uma parte muito cr\u00edtica da infraestrutura one-cloud \u2014 sem eles, a rede do one-cloud n\u00e3o funcionar\u00e1. N\u00f3s os colocamos em diferentes racks, se poss\u00edvel localizados em diferentes salas do data center, para reduzir a probabilidade de falha simult\u00e2nea de todos os tr\u00eas.<\/p>\n<p><\/p>\n<p>Agora, vamos supor que a conex\u00e3o entre o mestre one-cloud e o minion M1 foi perdida. O mestre one-cloud agora atuar\u00e1 sob a suposi\u00e7\u00e3o de que o M1 falhou completamente. Ou seja, dar\u00e1 a ordem para o minion M2 iniciar <strong>web.group1.web.front.prod<\/strong> com o mesmo endere\u00e7o 1.1.1.1. Agora temos duas rotas conflitantes na rede para 1.1.1.1: em M1 e em M2. Para resolver esses conflitos, utilizamos o Multi Exit Discriminator, que \u00e9 especificado no an\u00fancio BGP. Esse n\u00famero indica o peso da rota anunciada. A rota com o menor valor de MED ser\u00e1 escolhida entre as conflitantes. O mestre one-cloud suporta MED como parte integral dos endere\u00e7os IP dos cont\u00eaineres. Na primeira vez, o endere\u00e7o \u00e9 anunciado com um MED bastante alto = 1.000.000. Na situa\u00e7\u00e3o de um deslocamento emergencial do cont\u00eainer, o mestre reduz o MED, e M2 receber\u00e1 ent\u00e3o a ordem de anunciar o endere\u00e7o 1.1.1.1 com MED = 999.999. O exemplar que est\u00e1 atuando em M1 ficar\u00e1 sem conex\u00e3o at\u00e9 que a conex\u00e3o com o mestre seja restabelecida, momento em que ser\u00e1 desativado como um antigo duplicado.<\/p>\n<p><\/p>\n<h2 id=\"avarii\">Acidentes<\/h2>\n<p><\/p>\n<p>Todos os sistemas de gerenciamento de data centers gerenciam adequadamente pequenas falhas. A queda de um cont\u00eainer \u00e9 normal em praticamente qualquer lugar.<\/p>\n<p><\/p>\n<p>Vamos considerar como tratamos um acidente, por exemplo, uma falha de energia em uma ou mais salas do data center.<\/p>\n<p><\/p>\n<p>O que significa um acidente para o sistema de gerenciamento do data center? Em primeiro lugar, \u00e9 uma falha massiva e simult\u00e2nea de v\u00e1rias m\u00e1quinas, e o sistema de gerenciamento precisa migrar ao mesmo tempo muitos cont\u00eaineres. Mas se o acidente for muito grande, pode acontecer que todas as tarefas n\u00e3o consigam ser redistribu\u00eddas para outros minions, porque a capacidade do data center cai abaixo de 100% de carga. <\/p>\n<p><\/p>\n<p>Frequentemente, os acidentes s\u00e3o acompanhados pela falha da camada de gerenciamento. Isso pode ocorrer devido \u00e0 falha do equipamento, mas mais frequentemente acontece porque os acidentes n\u00e3o s\u00e3o testados, e a camada de gerenciamento falha devido \u00e0 carga elevada. <\/p>\n<p><\/p>\n<p>O que pode ser feito a respeito?<\/p>\n<p><\/p>\n<p>Migra\u00e7\u00f5es em massa significam que h\u00e1 um grande n\u00famero de a\u00e7\u00f5es, migra\u00e7\u00f5es e aloca\u00e7\u00f5es na infraestrutura. Cada migra\u00e7\u00e3o pode levar algum tempo necess\u00e1rio para a entrega e descompacta\u00e7\u00e3o das imagens dos cont\u00eaineres para os minions, start e inicializa\u00e7\u00e3o dos cont\u00eaineres, etc. Portanto, \u00e9 desej\u00e1vel que as tarefas mais importantes sejam iniciadas antes das menos importantes.<\/p>\n<p><\/p>\n<p>Vamos olhar novamente para a hierarquia de servi\u00e7os que j\u00e1 conhecemos e tentar decidir quais tarefas queremos iniciar primeiro.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"One-cloud \u2014 sistema operacional de n\u00edvel de data center no Odnoklassniki\" src=\"\/wp-content\/uploads\/2020\/06\/2e827271adb8d3ff3d385e53553aaacf.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Claro, esses s\u00e3o os processos que est\u00e3o diretamente envolvidos no processamento de solicita\u00e7\u00f5es dos usu\u00e1rios, ou seja, prod. N\u00f3s indicamos isso por meio de <strong>prioridade de aloca\u00e7\u00e3o<\/strong> \u2014 um n\u00famero que pode ser atribu\u00eddo a uma fila. Se uma fila tiver uma prioridade mais alta, seus servi\u00e7os s\u00e3o alocados primeiro.<\/p>\n<p><\/p>\n<p>No prod, atribu\u00edmos prioridades mais altas, 0; no batch \u2014 um pouco mais baixas, 100; no idle \u2014 ainda mais baixas, 200. As prioridades s\u00e3o aplicadas de forma hier\u00e1rquica. Todas as tarefas de uma hierarquia inferior ter\u00e3o a prioridade correspondente. Se quisermos que os caches dentro do prod sejam executados antes dos frontends, ent\u00e3o atribuiremos prioridades ao cache = 0 e aos frontends de subordina\u00e7\u00e3o = 1. Se, por exemplo, quisermos que dentro dos frontends o portal principal seja executado primeiro, e o frontend de m\u00fasica depois, podemos atribuir \u00e0 \u00faltima uma prioridade mais baixa \u2014 10.<\/p>\n<p><\/p>\n<p>O pr\u00f3ximo problema \u00e9 a falta de recursos. Portanto, tivemos uma grande falha em v\u00e1rios equipamentos, salas inteiras do data center, e n\u00f3s iniciamos servi\u00e7os suficientes para que agora n\u00e3o haja recursos para todos. Precisamos decidir quais tarefas sacrificar para que os principais servi\u00e7os cr\u00edticos funcionem. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"One-cloud \u2014 sistema operacional de n\u00edvel de data center no Odnoklassniki\" src=\"\/wp-content\/uploads\/2020\/06\/1b1ad3da16df6677dd0ba4b038cdd7d6.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Diferente da prioridade de aloca\u00e7\u00e3o, n\u00e3o podemos simplesmente sacrificar todas as tarefas de batch, algumas delas s\u00e3o importantes para o funcionamento do portal. Por isso, destacamos separadamente <strong>prioridade de despejo<\/strong> tarefa. Ao alocar, uma tarefa com prioridade mais alta pode despejar, ou seja, parar uma tarefa com prioridade mais baixa, se n\u00e3o houver mais minions dispon\u00edveis. Nesse caso, a tarefa com prioridade mais baixa provavelmente permanecer\u00e1 n\u00e3o alocada, ou seja, n\u00e3o haver\u00e1 mais um minion adequado com recursos livres suficientes.<\/p>\n<p><\/p>\n<p>Em nossa hierarquia, \u00e9 muito simples indicar tal prioridade de despejo, para que tarefas prod e batch despejem ou parem tarefas idle, mas n\u00e3o umas \u00e0s outras, definindo a prioridade para idle como 200. Assim como no caso da prioridade de aloca\u00e7\u00e3o, podemos usar nossa hierarquia para descrever regras mais complexas. Por exemplo, podemos indicar que sacrificamos a fun\u00e7\u00e3o de m\u00fasica se n\u00e3o tivermos recursos para o portal web principal, estabelecendo uma prioridade mais baixa para os n\u00f3s correspondentes: 10.<\/p>\n<p><\/p>\n<h2 id=\"avarii-dc-celikom\">Falhas completas do Data Center<\/h2>\n<p><\/p>\n<p>Por que todo o data center pode falhar? Fen\u00f4menos naturais. Houve um bom post sobre como <noindex><a rel=\"nofollow\" href=\"https:\/\/habrahabr.ru\/company\/dataline\/blog\/333578\/\">o furac\u00e3o afetou o funcionamento do data center<\/a><\/noindex>. Pode-se considerar o fator humano, como aqueles que queimaram um cabo de fibra \u00f3ptica em um po\u00e7o de acesso, fazendo com que todo o data center perdesse a conex\u00e3o com outras localiza\u00e7\u00f5es. A falha pode ser causada por humanos: um operador pode emitir um comando que faz todo o data center parar. Isso pode ocorrer devido a um grande bug. Em geral, data centers caem \u2014 isso n\u00e3o \u00e9 raro. Isso acontece conosco a cada poucos meses. <\/p>\n<p><\/p>\n<p>E \u00e9 isso que fazemos para garantir que ningu\u00e9m #okviva poste no Twitter.<\/p>\n<p><\/p>\n<p>A primeira estrat\u00e9gia \u00e9 a isola\u00e7\u00e3o. Cada inst\u00e2ncia one-cloud \u00e9 isolada e pode gerenciar m\u00e1quinas apenas de um \u00fanico data center. Ou seja, a perda da nuvem devido a bugs ou a um comando incorreto do operador resulta apenas na perda de um data center. Estamos preparados para isso: temos uma pol\u00edtica de reserva, onde as r\u00e9plicas de aplicativos e dados s\u00e3o hospedadas em todos os data centers. Utilizamos bancos de dados tolerantes a falhas e testamos falhas periodicamente.<br \/>\nComo hoje temos quatro data centers, tamb\u00e9m temos quatro inst\u00e2ncias one-cloud separadas e completamente isoladas.<\/p>\n<p><\/p>\n<p>Essa abordagem n\u00e3o s\u00f3 protege contra falhas f\u00edsicas, mas tamb\u00e9m pode proteger contra erros de operadores.<\/p>\n<p><\/p>\n<p>E o que mais podemos fazer sobre o fator humano? Quando um operador emite um comando estranho ou potencialmente perigoso para a nuvem, pode-se exigir que ele resolva uma pequena tarefa para verificar o qu\u00e3o bem ele pensou. Por exemplo, se for uma parada em massa de muitas r\u00e9plicas ou apenas um comando estranho \u2014 redu\u00e7\u00e3o no n\u00famero de r\u00e9plicas ou altera\u00e7\u00e3o do nome da imagem, e n\u00e3o apenas o n\u00famero da vers\u00e3o em um novo manifesto.<\/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 sistema operacional de n\u00edvel de data center no 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\">Resultados<\/h2>\n<p><\/p>\n<p>Caracter\u00edsticas distintivas do one-cloud: <\/p>\n<p><\/p>\n<ul>\n<li><strong>Um esquema de nomea\u00e7\u00e3o hier\u00e1rquica e claro para servi\u00e7os e cont\u00eaineres<\/strong>, que permite saber rapidamente qual \u00e9 a tarefa, a que se refere e como funciona, e quem \u00e9 respons\u00e1vel por ela. <\/li>\n<li>Aplicamos a nossa <strong>t\u00e9cnica de mesclagem de tarefas prod- e batch-<\/strong>em minions para aumentar a efici\u00eancia do compartilhamento de m\u00e1quinas. Em vez de cpuset, utilizamos cotas de CPU, shares, pol\u00edticas de escalonamento de CPU e QoS do Linux.<\/li>\n<li>N\u00e3o conseguimos isolar completamente os cont\u00eaineres que rodam em uma mesma m\u00e1quina, mas sua influ\u00eancia m\u00fatua permanece dentro de 20%.<\/li>\n<li>A organiza\u00e7\u00e3o dos servi\u00e7os em uma hierarquia ajuda na elimina\u00e7\u00e3o autom\u00e1tica de falhas usando <strong>prioridades de aloca\u00e7\u00e3o e exclus\u00e3o.<\/strong>.<\/li>\n<\/ul>\n<p><\/p>\n<h2 id=\"chavo\">PERGUNTAS FREQUENTES<\/h2>\n<p><\/p>\n<p>Por que n\u00e3o adotamos uma solu\u00e7\u00e3o pronta.<\/p>\n<p><\/p>\n<ul>\n<li>Diferentes classes de isolamento de tarefas exigem l\u00f3gicas variadas ao serem alocadas em minions. Enquanto tarefas de produ\u00e7\u00e3o podem ser alocadas simplesmente por meio da reserva de recursos, tarefas em lote e ociosas precisam ser alocadas monitorando a real utiliza\u00e7\u00e3o dos recursos nas m\u00e1quinas-minions. <\/li>\n<li>A necessidade de contabilizar recursos consumidos pelas tarefas, como: \n<ul>\n<li>largura de banda da rede;<\/li>\n<li>tipos e \u2018spindles\u2019 de discos.<\/li>\n<\/ul>\n<\/li>\n<li>A necessidade de definir prioridades de servi\u00e7os durante a resolu\u00e7\u00e3o de falhas, direitos e cotas de equipes sobre recursos, o que \u00e9 resolvido atrav\u00e9s de filas hier\u00e1rquicas na one-cloud.<\/li>\n<li>A necessidade de ter nomes humanos para cont\u00eaineres a fim de reduzir o tempo de resposta a falhas e incidentes.<\/li>\n<li>A impossibilidade de uma implementa\u00e7\u00e3o geral simult\u00e2nea do Service Discovery; a necessidade de coexistir por um longo tempo com tarefas alocadas em hosts f\u00edsicos \u2014 o que \u00e9 resolvido com endere\u00e7os IP \u2018est\u00e1ticos\u2019 que acompanham os cont\u00eaineres, e, como consequ\u00eancia, a necessidade de uma integra\u00e7\u00e3o \u00fanica com uma grande infraestrutura de rede.<\/li>\n<\/ul>\n<p><\/p>\n<p>Todas essas fun\u00e7\u00f5es exigiriam significativas adapta\u00e7\u00f5es das solu\u00e7\u00f5es existentes, e, ao avaliarmos a quantidade de trabalho, percebemos que conseguir\u00edamos desenvolver nossa pr\u00f3pria solu\u00e7\u00e3o com aproximadamente o mesmo esfor\u00e7o. Por\u00e9m, nossa solu\u00e7\u00e3o ser\u00e1 significativamente mais f\u00e1cil de operar e desenvolver \u2014 nela n\u00e3o h\u00e1 abstra\u00e7\u00f5es desnecess\u00e1rias que suportam funcionalidades que n\u00e3o precisamos. <\/p>\n<p><\/p>\n<p>Agrade\u00e7o a todos que leram at\u00e9 as \u00faltimas linhas pela paci\u00eancia e aten\u00e7\u00e3o!<\/p>\n<p>Fonte: <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.3 - 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\/pt\/blog\/administrirovanie\/one-cloud-os-urovnya-data-czentra-v-odnoklassnikah\" \/>\n\t\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 5.0.3\" \/>\n\t\t<meta property=\"og:locale\" content=\"pt_PT\" \/>\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\/pt\/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 Sistema operacional de n\u00edvel de data center no Odnoklassniki | ProHoster","description":"Aloha, pessoal!","canonical_url":"https:\/\/prohoster.info\/pt\/blog\/administrirovanie\/one-cloud-os-urovnya-data-czentra-v-odnoklassnikah","robots":"max-image-preview:large","keywords":"","webmasterTools":{"miscellaneous":""},"schema":null,"og:locale":"pt_PT","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\/pt\/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\/pt\/wp-json\/wp\/v2\/posts\/84114","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/prohoster.info\/pt\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/prohoster.info\/pt\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/prohoster.info\/pt\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/prohoster.info\/pt\/wp-json\/wp\/v2\/comments?post=84114"}],"version-history":[{"count":0,"href":"https:\/\/prohoster.info\/pt\/wp-json\/wp\/v2\/posts\/84114\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/prohoster.info\/pt\/wp-json\/wp\/v2\/media\/84115"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/pt\/wp-json\/wp\/v2\/media?parent=84114"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/pt\/wp-json\/wp\/v2\/categories?post=84114"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/pt\/wp-json\/wp\/v2\/tags?post=84114"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}