{"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\/es\/blog\/administrirovanie\/one-cloud-os-urovnya-data-czentra-v-odnoklassnikah","title":{"rendered":"One-cloud \u2014 Sistema de nivel de centro de datos en Odnoklassniki","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<p><img decoding=\"async\" alt=\"One-cloud \u2014 Sistema de nivel de centro de datos en Odnoklassniki\" src=\"\/wp-content\/uploads\/2020\/06\/fa983acacec59ff2d4ed098f87223971.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>\u00a1Aloha, gente! Me llamo Oleg Anastasiev, trabajo en Odnoklassniki en el equipo de la Plataforma. Adem\u00e1s de m\u00ed, en Odnoklassniki hay un mont\u00f3n de hardware. Tenemos cuatro centros de datos, con alrededor de 500 racks y m\u00e1s de 8,000 servidores. En un momento determinado, entendimos que la implementaci\u00f3n de un nuevo sistema de gesti\u00f3n nos permitir\u00eda cargar el hardware de manera m\u00e1s eficiente, facilitar la gesti\u00f3n de accesos, automatizar (re)distribuir los recursos computacionales, acelerar el lanzamiento de nuevos servicios y mejorar las respuestas ante fallos masivos. <\/p>\n<p><\/p>\n<p>\u00bfQu\u00e9 hemos logrado con esto? <\/p>\n<p><noindex><a rel=\"nofollow\" name=\"habracut\"><\/a><\/noindex><\/p>\n<p>Adem\u00e1s de m\u00ed y un mont\u00f3n de hardware, hay personas que trabajan con este hardware: ingenieros que est\u00e1n directamente en los centros de datos; especialistas en redes que configuran la infraestructura de red; administradores, o SRE, que aseguran la resiliencia de la infraestructura; y equipos de desarrolladores, cada uno responsable de ciertas funciones del portal. El software que crean funciona m\u00e1s o menos as\u00ed:<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"One-cloud \u2014 Sistema de nivel de centro de datos en Odnoklassniki\" src=\"\/wp-content\/uploads\/2020\/06\/592fd0acfa7322eb80fbb85601a92918.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Las solicitudes de los usuarios llegan tanto a los frontales del portal principal <noindex><a rel=\"nofollow\" href=\"http:\/\/www.ok.ru\/\">www.ok.ru<\/a><\/noindex>, como a otros, por ejemplo a los frontales de la API de m\u00fasica. Para procesar la l\u00f3gica del negocio, hacen llamadas a un servidor de aplicaciones, que al procesar la solicitud invoca los necesarios microservicios especializados: one-graph (grafo de relaciones sociales), user-cache (cach\u00e9 de perfiles de usuario), etc.<\/p>\n<p><\/p>\n<p>Cada uno de estos servicios est\u00e1 desplegado en m\u00faltiples m\u00e1quinas, y cada uno de ellos tiene desarrolladores responsables de su funcionamiento, operaci\u00f3n y evoluci\u00f3n tecnol\u00f3gica. Todos estos servicios se ejecutan en servidores f\u00edsicos, y hasta hace poco, ejecut\u00e1bamos exactamente una tarea en un servidor, es decir, estaba especializado para una tarea espec\u00edfica.<\/p>\n<p><\/p>\n<p>\u00bfPor qu\u00e9 era as\u00ed? Este enfoque ten\u00eda varias ventajas:<\/p>\n<p><\/p>\n<ul>\n<li>Facilita <strong>la gesti\u00f3n masiva<\/strong>. Supongamos que una tarea requiere ciertas bibliotecas, ciertas configuraciones. Entonces, el servidor se asigna a un grupo espec\u00edfico, se describe una pol\u00edtica de cfengine para este grupo (o ya est\u00e1 descrita), y esta configuraci\u00f3n se despliega de manera centralizada y autom\u00e1tica en todos los servidores de este grupo.<\/li>\n<li>Simplifica <strong>el diagn\u00f3stico<\/strong>. Supongamos que est\u00e1 observando una carga elevada en la CPU y se da cuenta de que solo una tarea que se ejecuta en este procesador puede haber generado esa carga. La b\u00fasqueda del culpable termina muy r\u00e1pido.<\/li>\n<li>Simplifica <strong>monitoreo<\/strong>. Si hay algo mal con el servidor, el monitor lo informa y sabe exactamente qui\u00e9n es el culpable.<\/li>\n<\/ul>\n<p><\/p>\n<p>A un servicio que consta de m\u00faltiples r\u00e9plicas se le asignan varios servidores, uno para cada uno. As\u00ed, es muy f\u00e1cil asignar recursos de c\u00f3mputo al servicio: puede consumir tantos recursos como servidores tiene. \u201cF\u00e1cil\u201d aqu\u00ed no significa que sea sencillo de usar, sino que la distribuci\u00f3n de recursos se realiza manualmente.<\/p>\n<p><\/p>\n<p>Este enfoque tambi\u00e9n nos permiti\u00f3 hacer <strong>configuraciones de hardware especializadas<\/strong> para la tarea que se ejecuta en este servidor. Si la tarea implica almacenar grandes vol\u00famenes de datos, usamos un servidor 4U con chasis para 38 discos. Si la tarea es puramente computacional, podemos comprar un servidor 1U m\u00e1s barato. Esto es eficiente desde el punto de vista de los recursos de c\u00f3mputo. Adem\u00e1s, este enfoque nos permite utilizar cuatro veces menos m\u00e1quinas con una carga comparable a la de una red social que nos es amigable. <\/p>\n<p><\/p>\n<p>Tal eficiencia en el uso de recursos de c\u00f3mputo deber\u00eda garantizar tambi\u00e9n eficiencia econ\u00f3mica, si partimos de la premisa de que lo m\u00e1s caro son los servidores. Durante mucho tiempo, el hardware fue lo m\u00e1s costoso, y hemos invertido muchos esfuerzos en reducir el costo del hardware, ideando algoritmos que aseguran la tolerancia a fallos para disminuir los requisitos de fiabilidad del equipo. Y hoy hemos llegado a un punto en el que el precio del servidor ya no es determinante. Si no consideramos las excentricidades m\u00e1s recientes, la configuraci\u00f3n espec\u00edfica de los servidores en el rack no tiene importancia. Ahora tenemos otro problema: el costo del espacio que ocupa un servidor en el centro de datos, es decir, el espacio en el rack.<\/p>\n<p><\/p>\n<p>Al darnos cuenta de esto, decidimos calcular cu\u00e1n eficientemente estamos utilizando los racks.<br \/>\nTomamos el precio del servidor m\u00e1s potente que es econ\u00f3micamente viable, calculamos cu\u00e1ntos de esos servidores podemos colocar en los racks, cu\u00e1ntas tareas podr\u00edamos ejecutar en ellos bas\u00e1ndonos en el antiguo modelo \"un servidor = una tarea\" y cu\u00e1n eficientemente podr\u00edan aprovechar el equipo. Realizamos los c\u00e1lculos y nos conmocionamos. Resulta que la eficiencia en el uso de los racks es de aproximadamente el 11%. La conclusi\u00f3n es clara: necesitamos mejorar la eficiencia en el uso de los centros de datos. A primera vista, la soluci\u00f3n parece obvia: deber\u00edamos ejecutar m\u00faltiples tareas en un solo servidor. Pero aqu\u00ed comienzan las complicaciones. <\/p>\n<p><\/p>\n<p>La configuraci\u00f3n masiva se complica dr\u00e1sticamente: ahora no es posible asignar al servidor un \u00fanico grupo. De hecho, en un mismo servidor pueden ejecutarse varias tareas de diferentes equipos. Adem\u00e1s, la configuraci\u00f3n puede ser conflictiva para diferentes aplicaciones. La diagnosis tambi\u00e9n se complica: si ves un aumento en el consumo de procesadores o discos en el servidor, no sabes cu\u00e1l de las tareas est\u00e1 causando problemas.<\/p>\n<p><\/p>\n<p>Pero lo m\u00e1s importante es que no hay aislamiento entre las tareas que se ejecutan en una misma m\u00e1quina. Por ejemplo, el gr\u00e1fico del tiempo de respuesta medio de una tarea de servidor antes y despu\u00e9s de que se ejecutara en el mismo servidor otra aplicaci\u00f3n de c\u00e1lculo no relacionada, muestra que el tiempo de respuesta de la tarea principal aument\u00f3 significativamente.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"One-cloud \u2014 Sistema de nivel de centro de datos en Odnoklassniki\" src=\"\/wp-content\/uploads\/2020\/06\/c7c07359ae572ca8c84a4c63559e4083.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Es evidente que necesitamos ejecutar las tareas ya sea en contenedores o en m\u00e1quinas virtuales. Dado que pr\u00e1cticamente todas nuestras tareas se ejecutan bajo un solo sistema operativo (Linux) o est\u00e1n adaptadas para \u00e9l, no necesitamos soportar m\u00faltiples sistemas operativos diferentes. Por lo tanto, la virtualizaci\u00f3n no es necesaria, ya que, debido a los costos adicionales, ser\u00e1 menos eficiente que la contenedorizaci\u00f3n.<\/p>\n<p><\/p>\n<p>Como implementaci\u00f3n de contenedores para ejecutar tareas directamente en servidores, Docker es un buen candidato: las im\u00e1genes de sistemas de archivos resuelven bien los problemas de configuraciones conflictivas. El hecho de que las im\u00e1genes se puedan componer de varias capas nos permite reducir significativamente la cantidad de datos necesarios para su despliegue en la infraestructura, al desplazar las partes comunes a capas base separadas. As\u00ed, las capas base (y m\u00e1s pesadas) se almacenar\u00e1n en cach\u00e9 r\u00e1pidamente en toda la infraestructura, y para enviar m\u00faltiples tipos de aplicaciones y versiones s\u00f3lo ser\u00e1 necesario transferir capas de menor volumen. <\/p>\n<p><\/p>\n<p>Adem\u00e1s, el registro listo y la etiquetaci\u00f3n de im\u00e1genes en Docker nos dan primitivos listos para la versionado y entrega de c\u00f3digo a producci\u00f3n.<\/p>\n<p><\/p>\n<p>Docker, al igual que cualquier otra tecnolog\u00eda similar, nos proporciona cierto nivel de aislamiento de contenedores de forma nativa. Por ejemplo, el aislamiento de memoria: a cada contenedor se le asigna un l\u00edmite de uso de memoria de la m\u00e1quina, que no puede exceder. Tambi\u00e9n es posible aislar contenedores en cuanto al uso de CPU. Sin embargo, para nosotros, el aislamiento est\u00e1ndar no era suficiente. Pero de esto hablaremos m\u00e1s adelante.<\/p>\n<p><\/p>\n<p>El lanzamiento directo de contenedores en servidores es s\u00f3lo parte de los problemas. La otra parte est\u00e1 relacionada con la colocaci\u00f3n de contenedores en los servidores. Es necesario entender qu\u00e9 contenedor se puede colocar en qu\u00e9 servidor. Esta no es una tarea tan simple, ya que los contenedores deben ser colocados en los servidores de manera lo m\u00e1s densa posible, sin reducir su velocidad de funcionamiento. Esta colocaci\u00f3n puede ser complicada tambi\u00e9n desde el punto de vista de la tolerancia a fallos. A menudo queremos colocar r\u00e9plicas del mismo servicio en diferentes racks o incluso en diferentes salas del centro de datos, para que al fallar un rack o sala no perdamos todas las r\u00e9plicas del servicio. <\/p>\n<p><\/p>\n<p>Distribuir los contenedores manualmente no es una opci\u00f3n cuando tienes 8 mil servidores y de 8 a 16 mil contenedores. <\/p>\n<p><\/p>\n<p>Adem\u00e1s, quer\u00edamos dar a los desarrolladores m\u00e1s autonom\u00eda en la distribuci\u00f3n de recursos, para que pudieran ubicar sus servicios en producci\u00f3n sin ayuda de un administrador. Al mismo tiempo, quer\u00edamos mantener el control para que un servicio secundario no consumiera todos los recursos de nuestros centros de datos. <\/p>\n<p><\/p>\n<p>Es evidente que se necesita una capa de gesti\u00f3n que se encargue de esto de forma autom\u00e1tica.<\/p>\n<p><\/p>\n<p>Aqu\u00ed llegamos a una imagen simple y clara, que todos los arquitectos adoran: tres cuadrados. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"One-cloud \u2014 Sistema de nivel de centro de datos en 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 cl\u00faster de alta disponibilidad encargado de la orquestaci\u00f3n de la nube. El desarrollador env\u00eda al m\u00e1ster un manifiesto, que contiene toda la informaci\u00f3n necesaria para desplegar el servicio. El m\u00e1ster, sobre la base de esto, da \u00f3rdenes a los minions seleccionados (m\u00e1quinas destinadas a ejecutar contenedores). En los minions est\u00e1 nuestro agente, que recibe la orden, emite sus propias \u00f3rdenes a Docker, y Docker configura el kernel de Linux para iniciar el contenedor correspondiente. Adem\u00e1s de ejecutar \u00f3rdenes, el agente informa continuamente al m\u00e1ster sobre los cambios en el estado tanto de la m\u00e1quina-minion como de los contenedores que se ejecutan en ella.<\/p>\n<p><\/p>\n<h2 id=\"raspredelenie-resursov\">Distribuci\u00f3n de recursos<\/h2>\n<p><\/p>\n<p>Ahora abordemos el problema de una distribuci\u00f3n m\u00e1s compleja de recursos para m\u00faltiples minions.<\/p>\n<p><\/p>\n<p>El recurso computacional en one-cloud es:<\/p>\n<p><\/p>\n<ul>\n<li>La potencia de CPU consumida por una tarea espec\u00edfica. <\/li>\n<li>El volumen de memoria disponible para la tarea. <\/li>\n<li>Tr\u00e1fico de red. Cada uno de los minions tiene una interfaz de red espec\u00edfica con un ancho de banda limitado, por lo que no se pueden distribuir las tareas sin tener en cuenta el volumen de datos que transmiten por la red. <\/li>\n<li>Discos. Aparte de, evidentemente, el espacio para los datos de la tarea, tambi\u00e9n asignamos el tipo de disco: HDD o SSD. Los discos pueden atender una cantidad limitada de solicitudes por segundo \u2014 IOPS. Por lo tanto, para tareas que generan m\u00e1s IOPS de las que puede manejar un solo disco, tambi\u00e9n asignamos 'spindles' \u2014 es decir, dispositivos de disco que deben reservarse exclusivamente para la tarea.<\/li>\n<\/ul>\n<p><\/p>\n<p>Entonces, para alg\u00fan servicio, digamos para user-cache, podemos anotar los recursos consumidos de la siguiente manera: 400 n\u00facleos de CPU, 2.5 TB de memoria, 50 Gbps de tr\u00e1fico en ambas direcciones, 6 TB de espacio en HDD, distribuido en 100 spindles. O en una forma m\u00e1s familiar para nosotros as\u00ed:<\/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>Los recursos del servicio user-cache consumen solo una parte de todos los recursos disponibles en la infraestructura de producci\u00f3n. Por lo tanto, queremos asegurarnos de que, inesperadamente, debido a un error del operador o no, user-cache no consuma m\u00e1s recursos de los que se le han asignado. Es decir, debemos limitar los recursos. Pero \u00bfa qu\u00e9 podr\u00edamos vincular la cuota?<\/p>\n<p><\/p>\n<p>Regresemos a nuestro esquema simplificado de interacci\u00f3n de componentes y dibujemos con m\u00e1s detalles: as\u00ed: <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"One-cloud \u2014 Sistema de nivel de centro de datos en Odnoklassniki\" src=\"\/wp-content\/uploads\/2020\/06\/27e5bfbffadd3d4b9fdc6bf138d135ed.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Lo que llama la atenci\u00f3n:<\/p>\n<p><\/p>\n<ul>\n<li>El frontend web y la m\u00fasica utilizan cl\u00fasteres aislados del mismo servidor de aplicaciones.<\/li>\n<li>Podemos identificar las capas l\u00f3gicas a las que pertenecen estos cl\u00fasteres: frontends, cach\u00e9s, capa de almacenamiento y gesti\u00f3n de datos.<\/li>\n<li>El frontend no es homog\u00e9neo, son diferentes subsistemas funcionales. <\/li>\n<li>Los cach\u00e9s tambi\u00e9n se pueden distribuir entre el subsistema cuyos datos est\u00e1n almacenando.<\/li>\n<\/ul>\n<p><\/p>\n<p>Dibujemos de nuevo la imagen:<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"One-cloud \u2014 Sistema de nivel de centro de datos en Odnoklassniki\" src=\"\/wp-content\/uploads\/2020\/06\/905dacc0aca859e65bd33ef751a557cf.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>\u00a1Vaya! \u00a1Vemos una jerarqu\u00eda! Esto significa que se pueden distribuir los recursos en bloques m\u00e1s grandes: asignar un desarrollador responsable a un nodo de esta jerarqu\u00eda, correspondiente a un subsistema funcional (como 'music' en la imagen), y vincular una cuota a este mismo nivel de jerarqu\u00eda. Esta jerarqu\u00eda tambi\u00e9n nos permite organizar m\u00e1s flexiblemente los servicios para facilitar la gesti\u00f3n. Por ejemplo, todos los web, ya que es un grupo muy grande de servidores, los subdividimos en varios grupos m\u00e1s peque\u00f1os, mostrados en la imagen como group1, group2.<\/p>\n<p><\/p>\n<p>Al eliminar l\u00edneas innecesarias, podemos escribir cada nodo de nuestra imagen de manera m\u00e1s plana: <strong>group1.web.front<\/strong>, <strong>api.music.front<\/strong>, <strong>user-cache.cache<\/strong>.<\/p>\n<p><\/p>\n<p>As\u00ed llegamos al concepto de 'cola jer\u00e1rquica'. Esta tiene un nombre, como 'group1.web.front'. A ella se le asigna una cuota de recursos y derechos de usuario. A una persona de DevOps le daremos derechos para enviar servicios a la cola, y esa persona puede iniciar algo en la cola, mientras que a una persona de OpsDev se le otorgar\u00e1n derechos de administraci\u00f3n, y ahora puede gestionar la cola, asignar personas a la misma, dar derechos a esas personas, etc. Los servicios que se inicien en esta cola se ejecutar\u00e1n dentro de la cuota de la cola. Si la cuota computacional de la cola no es suficiente para ejecutar todos los servicios simult\u00e1neamente, se ejecutar\u00e1n de manera secuencial, formando as\u00ed la cola propiamente dicha. <\/p>\n<p><\/p>\n<p>Veamos los servicios en m\u00e1s detalle. Un servicio tiene un nombre completo, que siempre incluye el nombre de la cola. Entonces, el servicio del frontend web tendr\u00e1 el nombre <strong>ok-web.group1.web.front<\/strong>. Y el servicio del servidor de aplicaciones al que se dirige se llamar\u00e1 <strong>ok-app.group1.web.front<\/strong>. Cada servicio tiene un manifiesto que especifica toda la informaci\u00f3n necesaria para su implementaci\u00f3n en m\u00e1quinas concretas: cu\u00e1nto recurso consume esta tarea, qu\u00e9 configuraci\u00f3n requiere, cu\u00e1ntas r\u00e9plicas deben existir y las propiedades para el manejo de fallos de este servicio. Despu\u00e9s de implementar el servicio en las m\u00e1quinas, surgen sus instancias, que tambi\u00e9n se nombran de manera \u00fanica \u2014 como el n\u00famero de la instancia y el nombre del servicio: <strong>1.ok-web.group1.web.front, 2.ok-web.group1.web.front, \u2026<\/strong><\/p>\n<p><\/p>\n<p>Esto es muy conveniente: al observar solo el nombre del contenedor en ejecuci\u00f3n, podemos deducir mucho de inmediato.<\/p>\n<p><\/p>\n<p>Ahora nos familiarizaremos m\u00e1s con lo que estas instancias, en realidad, realizan: las tareas.<\/p>\n<p><\/p>\n<h2 id=\"klassy-izolyacii-zadach\">Clases de aislamiento de tareas<\/h2>\n<p><\/p>\n<p>Todas las tareas en OK (y probablemente en todas partes) se pueden dividir en grupos:<\/p>\n<p><\/p>\n<ul>\n<li><strong>Tareas con baja latencia \u2014 prod<\/strong>. Para estas tareas y servicios, es muy importante la latencia, es decir, qu\u00e9 tan r\u00e1pido se procesar\u00e1 cada una de las solicitudes por el sistema. Ejemplos de tareas: frontend web, cach\u00e9s, servidores de aplicaciones, almacenes OLTP, etc.<\/li>\n<li><strong>Tareas de c\u00e1lculo \u2014 batch<\/strong>. Aqu\u00ed, la velocidad de procesamiento de cada solicitud espec\u00edfica no es importante. Lo que importa es cu\u00e1ntos c\u00e1lculos en total realizar\u00e1 esta tarea en un determinado (gran) per\u00edodo de tiempo (throughput). Esto incluir\u00e1 cualquier tarea en MapReduce, Hadoop, aprendizaje autom\u00e1tico, estad\u00edsticas.<\/li>\n<li><strong>Tareas en segundo plano \u2014 idle<\/strong>. Para estas tareas, ni la latencia ni el throughput son muy importantes. Incluyen diversas pruebas, migraciones, rec\u00e1lculos, conversiones de datos de un formato a otro. Por un lado, son similares a las tareas de c\u00e1lculo; por el otro, no nos preocupa mucho la rapidez con que se completan. <\/li>\n<\/ul>\n<p><\/p>\n<p>Veamos c\u00f3mo estas tareas consumen recursos, por ejemplo, el CPU.<\/p>\n<p><\/p>\n<p><strong>Tareas con baja latencia.<\/strong> El patr\u00f3n de consumo de CPU de esta tarea ser\u00e1 similar a este:<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"One-cloud \u2014 Sistema de nivel de centro de datos en Odnoklassniki\" src=\"\/wp-content\/uploads\/2020\/06\/1ed82c0df76325eb30056ad9af86e86e.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Recibe una solicitud del usuario, la tarea comienza a utilizar todos los n\u00facleos disponibles del CPU, procesa, devuelve la respuesta, espera la siguiente solicitud y permanece en espera. Llega la siguiente solicitud \u2014 de nuevo usa todo lo que tiene, realiza el c\u00e1lculo, espera la siguiente.<\/p>\n<p><\/p>\n<p>Para garantizar una latencia m\u00ednima para esta tarea, debemos tomar el m\u00e1ximo de recursos consumidos por ella y reservar la cantidad necesaria de n\u00facleos en el minion (la m\u00e1quina que llevar\u00e1 a cabo la tarea). Entonces, la f\u00f3rmula de reserva para nuestra tarea ser\u00e1 la siguiente:<\/p>\n<p><\/p>\n<pre><code>alloc: cpu = 4 (max)<\/code><\/pre>\n<p><\/p>\n<p>Y si tenemos una m\u00e1quina-minion con 16 n\u00facleos, podemos colocar exactamente cuatro de estas tareas en ella. Cabe destacar que el consumo promedio del procesador para estas tareas suele ser muy bajo, lo cual es evidente, ya que gran parte del tiempo la tarea se encuentra a la espera de una solicitud y no hace nada.<\/p>\n<p><\/p>\n<p><strong>Tareas de c\u00e1lculo.<\/strong> Su patr\u00f3n ser\u00e1 algo diferente:<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"One-cloud \u2014 Sistema de nivel de centro de datos en Odnoklassniki\" src=\"\/wp-content\/uploads\/2020\/06\/35b37fa1d70a137287cafdbfe3bcfc2e.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>El consumo promedio de recursos del procesador para estas tareas es bastante alto. A menudo queremos que la tarea de c\u00e1lculo se realice en un tiempo determinado, por lo que necesitamos reservar el m\u00ednimo n\u00famero de procesadores que necesite para que todo el c\u00e1lculo termine en un tiempo aceptable. Su f\u00f3rmula de reserva se ver\u00e1 as\u00ed:<\/p>\n<p><\/p>\n<pre><code>alloc: cpu = [1,*)<\/code><\/pre>\n<p><\/p>\n<p><em>\u00abColoca, por favor, en el minion donde haya al menos un n\u00facleo libre, y luego todo lo que haya \u2014 se lo llevar\u00e1 todo\u00bb.<\/em><\/p>\n<p><\/p>\n<p>Aqu\u00ed, la eficiencia del uso ya es significativamente mejor que en tareas con un corto retraso. Pero la ganancia ser\u00e1 mucho mayor si combinamos ambos tipos de tareas en una sola m\u00e1quina-minion y distribuimos sus recursos sobre la marcha. Cuando una tarea con un corto retraso requiere el procesador, lo obtiene inmediatamente, y cuando los recursos ya no son necesarios, se transfieren a la tarea de c\u00e1lculo, es decir, as\u00ed:<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"One-cloud \u2014 Sistema de nivel de centro de datos en Odnoklassniki\" src=\"\/wp-content\/uploads\/2020\/06\/875ad8d3f6a01e4fd0a89d0931e986c1.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Pero, \u00bfc\u00f3mo se hace esto?<\/p>\n<p><\/p>\n<p>Para empezar, analicemos prod y su alloc: cpu = 4. Necesitamos reservar cuatro n\u00facleos. En Docker run, esto se puede hacer de dos maneras: <\/p>\n<p><\/p>\n<ul>\n<li>Con la opci\u00f3n <code>--cpuset=1-4<\/code>, es decir, asignar a la tarea cuatro n\u00facleos espec\u00edficos en la m\u00e1quina.<\/li>\n<li>Usar <code>--cpuquota=400_000 --cpuperiod=100_000<\/code>, asignar una cuota de tiempo de CPU, es decir, indicar que cada 100 ms de tiempo real la tarea consume no m\u00e1s de 400 ms de tiempo de CPU. Se obtienen los mismos cuatro n\u00facleos. <\/li>\n<\/ul>\n<p><\/p>\n<p>Pero, \u00bfcu\u00e1l de estos m\u00e9todos es el adecuado?<\/p>\n<p><\/p>\n<p>La cpuset parece bastante atractiva. La tarea tiene cuatro n\u00facleos dedicados, lo que significa que las cach\u00e9s del procesador funcionar\u00e1n de manera \u00f3ptima. Sin embargo, esto tiene un lado negativo: tendr\u00edamos que asumir la tarea de distribuir los c\u00e1lculos entre n\u00facleos no utilizados de la m\u00e1quina en lugar de hacerlo el sistema operativo, lo cual es una tarea bastante no trivial, especialmente si intentamos ejecutar trabajos en batch en dicha m\u00e1quina. Las pruebas mostraron que aqu\u00ed es mejor la opci\u00f3n de cuota: as\u00ed, el sistema operativo tiene m\u00e1s libertad para elegir el n\u00facleo en el que ejecutar la tarea en el momento actual y el tiempo de CPU se distribuye de manera m\u00e1s eficiente.<\/p>\n<p><\/p>\n<p>Vamos a ver c\u00f3mo crear reservas en Docker con la m\u00ednima cantidad de n\u00facleos. La cuota para trabajos en batch ya no es aplicable, porque no es necesario limitar el m\u00e1ximo, solo se debe garantizar un m\u00ednimo. Y aqu\u00ed encaja bien la opci\u00f3n <code>docker run --cpushares<\/code>.<\/p>\n<p><\/p>\n<p>Acuerdamos que si un trabajo en batch requiere garant\u00eda de al menos un n\u00facleo, entonces indicamos <code>--cpushares=1024<\/code>, y si el m\u00ednimo son dos n\u00facleos, entonces indicamos <code>--cpushares=2048<\/code>. Las shares de CPU no intervienen en la distribuci\u00f3n del tiempo de CPU siempre que haya suficiente. As\u00ed, si el proceso principal no utiliza en este momento sus cuatro n\u00facleos \u2014 nada limita a los trabajos en batch, y pueden usar tiempo de CPU adicional. Pero en una situaci\u00f3n de escasez de procesador, si el proceso principal ha consumido todos sus cuatro n\u00facleos y ha alcanzado la cuota \u2014 el tiempo de CPU restante se dividir\u00e1 proporcionalmente a las cpushares, es decir, en una situaci\u00f3n de tres n\u00facleos libres, uno recibir\u00e1 la tarea con 1024 cpushares, y los otros dos recibir\u00e1n la tarea con 2048 cpushares.<\/p>\n<p><\/p>\n<p>Pero el uso de cuota y shares no es suficiente. Necesitamos asegurarnos de que las tareas de baja latencia tengan prioridad sobre las tareas en batch en la distribuci\u00f3n del tiempo de CPU. Sin tal priorizaci\u00f3n, una tarea en batch consumir\u00e1 todo el tiempo de CPU en el momento en que lo necesite el proceso principal. En Docker run no hay opciones para priorizar contenedores, pero las pol\u00edticas del planificador de CPU en Linux vienen al rescate. Puedes leer m\u00e1s sobre ellas <noindex><a rel=\"nofollow\" href=\"http:\/\/man7.org\/linux\/man-pages\/man2\/sched_setscheduler.2.html\">aqu\u00ed<\/a><\/noindex>, y en este art\u00edculo las abordaremos brevemente:<\/p>\n<p><\/p>\n<ul>\n<li><strong>SCHED_OTHER<\/strong><br \/>\nPor defecto, todos los procesos de usuario normales en una m\u00e1quina Linux reciben esto.<\/li>\n<li><strong>SCHED_BATCH<\/strong><br \/>\nDestinada a procesos que consumen muchos recursos. Al asignar una tarea al procesador, se introduce una llamada penalizaci\u00f3n por activaci\u00f3n: es menos probable que una tarea obtenga recursos del procesador si en ese momento est\u00e1 siendo utilizada por una tarea con SCHED_OTHER.<\/li>\n<li><strong>SCHED_IDLE<\/strong><br \/>\nProceso en segundo plano con una prioridad muy baja, incluso m\u00e1s baja que nice -19. Utilizamos nuestra biblioteca de c\u00f3digo abierto. <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/odnoklassniki\/one-nio\">one-nio<\/a><\/noindex>, para aplicar la pol\u00edtica necesaria al iniciar el contenedor mediante la llamada<\/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>Pero incluso si no programas en Java, puedes hacer lo mismo con el comando chrt:<\/p>\n<p><\/p>\n<pre><code class=\"bash\">chrt -i 0 $pid<\/code><\/pre>\n<p><\/p>\n<p>Resumimos todos nuestros niveles de aislamiento en una tabla para mayor claridad:<\/p>\n<p><\/p>\n<p>Clase de aislamiento<br \/>\nEjemplo de alloc<br \/>\nOpciones de 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 realizas chrt desde dentro del contenedor, puede ser necesario el capability sys_nice, ya que por defecto Docker retira este capability al iniciar el contenedor.<\/p>\n<p><\/p>\n<p>Pero las tareas consumen no solo el procesador, sino tambi\u00e9n el tr\u00e1fico, lo que afecta la latencia de la tarea de red incluso m\u00e1s que la distribuci\u00f3n incorrecta de recursos del procesador. Por lo tanto, naturalmente queremos obtener una imagen exactamente igual para el tr\u00e1fico. Es decir, cuando una tarea prod env\u00eda paquetes a la red, limitamos la velocidad m\u00e1xima (f\u00f3rmula <em>alloc: lan=[*,500mbps)<\/em> ), con la que prod puede hacerlo. Y para batch garantizamos solo un ancho de banda m\u00ednimo, pero no limitamos el m\u00e1ximo (f\u00f3rmula <em>alloc: lan=[10Mbps,*)<\/em> ) En este caso, el tr\u00e1fico prod debe tener prioridad sobre las tareas batch.<br \/>\nAqu\u00ed Docker no tiene primitivas que podamos usar. Pero nos ayuda <noindex><a rel=\"nofollow\" href=\"http:\/\/lartc.org\/\">Linux Traffic Control<\/a><\/noindex>. Pudimos lograr el resultado deseado con la disciplina <noindex><a rel=\"nofollow\" href=\"http:\/\/linux-ip.net\/articles\/hfsc.en\/\">Hierarchical Fair Service Curve<\/a><\/noindex>. Con ella separamos dos clases de tr\u00e1fico: prod de alta prioridad y batch\/idle de baja prioridad. Como resultado, la configuraci\u00f3n para el tr\u00e1fico saliente queda as\u00ed:<\/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 de nivel de centro de datos en Odnoklassniki\" src=\"\/wp-content\/uploads\/2020\/06\/3f52a968118b6021bd0c920af17a00c0.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/a><\/noindex><\/p>\n<p><\/p>\n<p>aqu\u00ed 1:0 \u2014 \u00abqdisc ra\u00edz\u00bb de la disciplina hsfc; 1:1 \u2014 clase hija hsfc con un l\u00edmite de ancho de banda total de 8 Gbit\/s, debajo de la cual se agrupan las clases hijas de todos los contenedores; 1:2 \u2014 clase hija hsfc com\u00fan para todas las tareas batch e idle con un l\u00edmite \u00abdin\u00e1mico\u00bb, del cual se hablar\u00e1 m\u00e1s adelante. Las dem\u00e1s clases hijas hsfc son clases dedicadas para los contenedores prod en funcionamiento con l\u00edmites que corresponden a sus manifiestos, \u2014 450 y 400 Mbit\/s. A cada clase hsfc se le asigna una cola qdisc fq o fq_codel, dependiendo de la versi\u00f3n del n\u00facleo de linux, para evitar p\u00e9rdidas de paquetes durante picos de tr\u00e1fico. <\/p>\n<p><\/p>\n<p>Normalmente, las disciplinas tc se utilizan solo para priorizar el tr\u00e1fico saliente. Pero queremos priorizar tambi\u00e9n el tr\u00e1fico entrante, ya que alguna tarea batch puede f\u00e1cilmente consumir todo el ancho de banda entrante cuando recibe, por ejemplo, un gran paquete de datos para map&amp;reduce. Para ello utilizamos el m\u00f3dulo <noindex><a rel=\"nofollow\" href=\"https:\/\/serverfault.com\/questions\/350023\/tc-ingress-policing-and-ifb-mirroring\">ifb<\/a><\/noindex>, que crea una interfaz virtual ifbX para cada interfaz de red y redirige el tr\u00e1fico entrante desde la interfaz al tr\u00e1fico saliente en ifbX. A partir de ah\u00ed, todas las mismas disciplinas se aplican a ifbX para controlar el tr\u00e1fico saliente, para el cual la configuraci\u00f3n hsfc ser\u00e1 muy similar:<\/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 de nivel de centro de datos en Odnoklassniki\" src=\"\/wp-content\/uploads\/2020\/06\/967da9c0637cc70ba195af781db18adf.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/a><\/noindex><\/p>\n<p><\/p>\n<p>Durante los experimentos, descubrimos que hsfc da mejores resultados cuando la clase 1:2 de tr\u00e1fico batch\/idle no prioritario se limita en las m\u00e1quinas minion a no m\u00e1s que a un cierto ancho de banda libre. De lo contrario, el tr\u00e1fico no prioritario afecta demasiado la latencia de las tareas prod. El actual valor del ancho de banda libre es determinado cada segundo por miniond, midiendo el consumo promedio de tr\u00e1fico de todas las tareas prod en ese minion <img decoding=\"async\" alt=\"One-cloud \u2014 Sistema de nivel de centro de datos en Odnoklassniki\" src=\"\/wp-content\/uploads\/2020\/06\/9d6f38110d3b1693afe222b01430b9bb.jpg\" style=\"display:block;margin: 0 auto;\" \/> y rest\u00e1ndolo del ancho de banda de la interfaz de red <img decoding=\"async\" alt=\"One-cloud \u2014 Sistema de nivel de centro de datos en Odnoklassniki\" src=\"\/wp-content\/uploads\/2020\/06\/d5608ec4c58e44b8571ab0b1d0cc7701.jpg\" style=\"display:block;margin: 0 auto;\" \/> con un peque\u00f1o margen, es decir,<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"One-cloud \u2014 Sistema de nivel de centro de datos en Odnoklassniki\" src=\"\/wp-content\/uploads\/2020\/06\/fb01347c2224bd5bbd82169861eeb7e4.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Los anchos de banda se determinan de manera independiente para el tr\u00e1fico entrante y saliente. Y de acuerdo con los nuevos valores, miniond reconfigura el l\u00edmite de la clase no prioritaria 1:2.<\/p>\n<p><\/p>\n<p>De este modo, hemos implementado las tres clases de aislamiento: prod, batch e idle. Estas clases influyen significativamente en las caracter\u00edsticas de ejecuci\u00f3n de las tareas. Por lo tanto, decidimos colocar esta caracter\u00edstica en la parte superior de la jerarqu\u00eda, para que al mirar el nombre de la cola jer\u00e1rquica, quede claro de inmediato con qu\u00e9 estamos tratando: <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"One-cloud \u2014 Sistema de nivel de centro de datos en Odnoklassniki\" src=\"\/wp-content\/uploads\/2020\/06\/34dc89c461db711b19a0f4eccc50efce.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Todos nuestros conocidos <strong>web<\/strong> y <strong>m\u00fasica<\/strong> los frentes se colocan entonces en la jerarqu\u00eda bajo prod. Por ejemplo, busquemos colocar el servicio bajo batch <strong>cat\u00e1logo de m\u00fasica<\/strong>, que peri\u00f3dicamente compila un cat\u00e1logo de pistas de un conjunto de archivos mp3 subidos en \u00abOdnoklassniki\u00bb. Un ejemplo de servicio inactivo podr\u00eda ser <strong>transformador de m\u00fasica<\/strong>, que normaliza el nivel de volumen de la m\u00fasica.<\/p>\n<p><\/p>\n<p>De nuevo, al eliminar l\u00edneas innecesarias, podemos escribir los nombres de nuestros servicios de manera m\u00e1s plana, a\u00f1adiendo la clase de aislamiento de la tarea al final del nombre completo del servicio: <strong>web.front.prod<\/strong>, <strong>catalog.music.batch<\/strong>, <strong>transformer.music.idle<\/strong>.<\/p>\n<p><\/p>\n<p>Y ahora, al mirar el nombre del servicio, entendemos no solo qu\u00e9 funci\u00f3n desempe\u00f1a, sino tambi\u00e9n su clase de aislamiento, lo que implica su criticidad, etc.<\/p>\n<p><\/p>\n<p>Todo es maravilloso, pero hay una amarga verdad. No es posible aislar completamente las tareas que funcionan en una misma m\u00e1quina.<\/p>\n<p><\/p>\n<p>Lo que hemos logrado: si el batch consume intensamente <strong>solo<\/strong> recursos de la CPU, el planificador de CPU de Linux integrado cumple muy bien con su tarea, y la influencia en la tarea prod es pr\u00e1cticamente nula. Pero si esta tarea batch comienza a trabajar activamente con la memoria, entonces la influencia mutua ya se manifiesta. Esto ocurre porque las cach\u00e9s de procesador de la tarea prod se \u00abvac\u00edan\u00bb \u2014 como resultado, aumentan los fallos en la cach\u00e9, y el procesador procesa la tarea prod m\u00e1s lentamente. Tal tarea batch puede aumentar en un 10 % la latencia de nuestro t\u00edpico contenedor prod.<\/p>\n<p><\/p>\n<p>Aislar el tr\u00e1fico es a\u00fan m\u00e1s dif\u00edcil debido a que las tarjetas de red modernas tienen una cola interna de paquetes. Si un paquete de la tarea batch entra primero, significa que ser\u00e1 el primero en ser enviado por el cable, y no hay nada que se pueda hacer al respecto.<\/p>\n<p><\/p>\n<p>Adem\u00e1s, hasta ahora solo hemos logrado resolver el problema de priorizaci\u00f3n del tr\u00e1fico TCP: el enfoque con hsfc no funciona para UDP. E incluso en el caso del tr\u00e1fico TCP, si la tarea batch genera mucho tr\u00e1fico, esto tambi\u00e9n provoca un aumento de aproximadamente el 10 % en la latencia de la tarea prod.<\/p>\n<p><\/p>\n<h2 id=\"otkazoustoychivost\">Tolerancia a fallos<\/h2>\n<p><\/p>\n<p>Uno de los objetivos al desarrollar one-cloud fue mejorar la resistencia a fallos de Odnoklassniki. Por lo tanto, a continuaci\u00f3n me gustar\u00eda analizar m\u00e1s a fondo los posibles escenarios de fallos y emergencias. Comencemos con un escenario simple: la falla de un contenedor. <\/p>\n<p><\/p>\n<p>Un contenedor por s\u00ed mismo puede fallar de varias maneras. Esto puede ser un experimento, un error o un problema en el manifiesto, que hace que la tarea de producci\u00f3n comience a consumir m\u00e1s recursos de los que se especifican en el manifiesto. Tuvimos un caso en el que un desarrollador implement\u00f3 un algoritmo complicado, lo modific\u00f3 varias veces, se complic\u00f3 a s\u00ed mismo y se confundi\u00f3 tanto que, al final, la tarea qued\u00f3 atrapada en un bucle bastante no trivial. Y dado que la tarea de producci\u00f3n tiene m\u00e1s prioridad que todas las dem\u00e1s en los mismos minions, comenz\u00f3 a consumir todos los recursos de CPU disponibles. En esta situaci\u00f3n, la aislamiento fue salvador, o m\u00e1s bien, la cuota de tiempo de CPU. Si a una tarea se le asigna una cuota, no consumir\u00e1 m\u00e1s. Por lo tanto, las tareas por lotes y otras tareas de producci\u00f3n que trabajaban en la misma m\u00e1quina no notaron nada. <\/p>\n<p><\/p>\n<p>El segundo problema posible es la ca\u00edda del contenedor. Y aqu\u00ed nos ayudan las pol\u00edticas de reinicio, que todos conocen, y Docker lo maneja muy bien. Pr\u00e1cticamente todas las tareas de producci\u00f3n tienen una pol\u00edtica de reinicio siempre. A veces utilizamos on_failure para tareas por lotes o para depurar contenedores de producci\u00f3n.<\/p>\n<p><\/p>\n<p>\u00bfY qu\u00e9 se puede hacer si un minion entero no est\u00e1 disponible?<\/p>\n<p><\/p>\n<p>Obviamente, lanzar el contenedor en otra m\u00e1quina. Lo m\u00e1s interesante aqu\u00ed es qu\u00e9 pasa con la direcci\u00f3n IP (las direcciones) asignadas al contenedor. <\/p>\n<p><\/p>\n<p>Podemos asignar a los contenedores las mismas direcciones IP que tienen las m\u00e1quinas-minions donde se ejecutan estos contenedores. Entonces, al lanzar un contenedor en otra m\u00e1quina, su direcci\u00f3n IP cambia, y todos los clientes deben entender que el contenedor se ha trasladado, ahora tienen que ir a otra direcci\u00f3n, lo que requiere un servicio adicional de Descubrimiento de Servicios. <\/p>\n<p><\/p>\n<p>El Descubrimiento de Servicios es conveniente. Hay muchas soluciones en el mercado con diferentes grados de tolerancia a fallos para organizar un registro de servicios. A menudo, en tales soluciones se implementa la l\u00f3gica del balanceador de carga, el almacenamiento de configuraci\u00f3n adicional en forma de almacenamiento KV, etc.<br \/>\nSin embargo, nos gustar\u00eda prescindir de la necesidad de implementar un registro separado, ya que esto significar\u00eda introducir un sistema cr\u00edtico que es utilizado por todos los servicios en producci\u00f3n. Esto representa un punto de fallo potencial, y se debe elegir o desarrollar una soluci\u00f3n muy resistente a fallos, lo cual, evidentemente, es muy complicado, largo y costoso. <\/p>\n<p><\/p>\n<p>Y otro gran inconveniente: para que nuestra antigua infraestructura funcionara con la nueva, tendr\u00edamos que reescribir absolutamente todas las tareas para utilizar alg\u00fan sistema de Service Discovery. Hay MUCHO trabajo, y en algunos casos es casi imposible, especialmente cuando se trata de dispositivos de bajo nivel que operan a nivel del n\u00facleo del sistema operativo o directamente con el hardware. La implementaci\u00f3n de esta funcionalidad utilizando patrones establecidos de soluciones, como por ejemplo <noindex><a rel=\"nofollow\" href=\"https:\/\/linkerd.io\">side-car<\/a><\/noindex> significar\u00eda a veces una carga adicional, en ocasiones \u2014 una complicaci\u00f3n de la explotaci\u00f3n y escenarios adicionales de fallos. No quer\u00edamos complicar las cosas, por lo que decidimos que el uso de Service Discovery fuera opcional. <\/p>\n<p><\/p>\n<p>En one-cloud, la IP sigue al contenedor, es decir, cada instancia de la tarea tiene su propia direcci\u00f3n IP. Esta direcci\u00f3n es \"est\u00e1tica\": se asigna a cada instancia en el momento del primer env\u00edo del servicio a la nube. Si durante la vida del servicio tuvo diversas instancias, al final se le asignar\u00e1n tantas direcciones IP como m\u00e1ximo haya habido instancias.<\/p>\n<p><\/p>\n<p>Posteriormente, estas direcciones no cambian: se asignan una vez y contin\u00faan existiendo durante toda la vida del servicio en producci\u00f3n. Las direcciones IP siguen a los contenedores por la red. Si un contenedor se mueve a otro mini\u00f3n, la direcci\u00f3n tambi\u00e9n se trasladar\u00e1 con \u00e9l. <\/p>\n<p><\/p>\n<p>De este modo, la correspondencia entre el nombre del servicio y su lista de direcciones IP cambia con muy poca frecuencia. Si miramos nuevamente los nombres de las instancias del servicio que mencionamos al inicio del art\u00edculo (<strong>1.ok-web.group1.web.front.prod, 2.ok-web.group1.web.front.prod, \u2026<\/strong>), notamos que se asemejan a FQDN, que se utilizan en DNS. As\u00ed es, para mostrar los nombres de las instancias de servicios en sus direcciones IP utilizamos el protocolo DNS. De hecho, este DNS devuelve todas las direcciones IP reservadas de todos los contenedores, tanto en funcionamiento como detenidos (supongamos que se utilizan tres r\u00e9plicas y tenemos cinco direcciones reservadas: las cinco ser\u00e1n devueltas). Los clientes, al recibir esta informaci\u00f3n, intentar\u00e1n establecer conexi\u00f3n con las cinco r\u00e9plicas, y as\u00ed determinar\u00e1n cu\u00e1les est\u00e1n operativas. Esta forma de determinar la disponibilidad es considerablemente m\u00e1s confiable, ya que no involucra ni DNS ni Service Discovery, lo que significa que no hay problemas dif\u00edciles de resolver relacionados con la actualizaci\u00f3n de informaci\u00f3n y la resistencia a fallos de estos sistemas. M\u00e1s a\u00fan, en servicios cr\u00edticos de los cuales depende el funcionamiento de todo el portal, podemos no usar DNS en absoluto, y simplemente introducir las direcciones IP en la configuraci\u00f3n.<\/p>\n<p><\/p>\n<p>La implementaci\u00f3n de esta transferencia de IP entre contenedores puede no ser trivial \u2014 y nos detendremos en c\u00f3mo funciona con el siguiente ejemplo:<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"One-cloud \u2014 Sistema de nivel de centro de datos en Odnoklassniki\" src=\"\/wp-content\/uploads\/2020\/06\/faf99c2609a57daa1bdc193cb0f4cb31.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Supongamos que el maestro de one-cloud da la orden al minion M1 de iniciar <strong>1.ok-web.group1.web.front.prod<\/strong> con la direcci\u00f3n 1.1.1.1. En el minion funciona <noindex><a rel=\"nofollow\" href=\"https:\/\/en.wikipedia.org\/wiki\/Bird_Internet_routing_daemon\">BIRD<\/a><\/noindex>, que anuncia esta direcci\u00f3n a servidores especiales <noindex><a rel=\"nofollow\" href=\"https:\/\/en.wikipedia.org\/wiki\/Route_reflector\">route reflector<\/a><\/noindex>. Estos \u00faltimos tienen una sesi\u00f3n BGP con el equipo de red, al que se transmite la ruta de la direcci\u00f3n 1.1.1.1 hacia M1. M1, a su vez, enruta los paquetes dentro del contenedor ya utilizando herramientas de Linux. Hay tres servidores route reflector, ya que esta es una parte muy cr\u00edtica de la infraestructura de one-cloud \u2014 sin ellos, la red de one-cloud no funcionar\u00e1. Los ubicamos en diferentes racks, preferiblemente ubicados en diferentes salas del centro de datos, para reducir la probabilidad de una falla simult\u00e1nea de los tres.<\/p>\n<p><\/p>\n<p>Ahora supongamos que la conexi\u00f3n entre el maestro de one-cloud y el minion M1 se ha perdido. El maestro de one-cloud ahora actuar\u00e1 bajo la suposici\u00f3n de que M1 ha fallado completamente. Es decir, dar\u00e1 la orden al minion M2 de iniciar <strong>web.group1.web.front.prod<\/strong> con la misma direcci\u00f3n 1.1.1.1. Ahora tenemos dos rutas en conflicto en la red para 1.1.1.1: en M1 y en M2. Para resolver tales conflictos, utilizamos el Multi Exit Discriminator, que se especifica en el anuncio de BGP. Este es un n\u00famero que indica el peso de la ruta anunciada. Se seleccionar\u00e1 la ruta con el valor m\u00e1s bajo de MED entre las en conflicto. El maestro one-cloud soporta MED como parte integral de las direcciones IP de los contenedores. La primera vez, la direcci\u00f3n se emite con un MED bastante alto = 1,000,000. En una situaci\u00f3n de falla de este tipo del contenedor, el maestro reduce el MED, y M2 recibir\u00e1 la orden de anunciar la direcci\u00f3n 1.1.1.1 con MED = 999,999. El instance que trabaja en M1 quedar\u00e1 sin conexi\u00f3n y su futuro no nos interesa hasta que se restaure la conexi\u00f3n con el maestro, momento en el cual se detendr\u00e1 como un viejo duplicado.<\/p>\n<p><\/p>\n<h2 id=\"avarii\">Fallas<\/h2>\n<p><\/p>\n<p>Todos los sistemas de gesti\u00f3n de centros de datos manejan adecuadamente las peque\u00f1as fallas. La ca\u00edda de un contenedor es algo normal casi en cualquier lugar.<\/p>\n<p><\/p>\n<p>Veamos c\u00f3mo manejamos una falla, por ejemplo, un corte de energ\u00eda en una o m\u00e1s salas del centro de datos.<\/p>\n<p><\/p>\n<p>\u00bfQu\u00e9 significa una falla para el sistema de gesti\u00f3n del centro de datos? En primer lugar, es un fallo masivo y simult\u00e1neo de muchas m\u00e1quinas, y el sistema de gesti\u00f3n necesita migrar muchos contenedores al mismo tiempo. Pero si la falla es muy extensa, puede suceder que no todas las tareas puedan ser redistribuidas a otros minions, porque la capacidad de recursos del centro de datos cae por debajo del 100% de carga. <\/p>\n<p><\/p>\n<p>A menudo, las fallas vienen acompa\u00f1adas de la ca\u00edda de la capa de gesti\u00f3n. Esto puede ocurrir debido a la falla de su hardware, pero m\u00e1s com\u00fanmente ocurre porque las fallas no se prueban, y la capa de gesti\u00f3n colapsa bajo la carga aumentada. <\/p>\n<p><\/p>\n<p>\u00bfQu\u00e9 se puede hacer con todo esto?<\/p>\n<p><\/p>\n<p>Las migraciones masivas significan que en la infraestructura surgen una gran cantidad de acciones, migraciones y despliegues. Cada una de las migraciones puede llevar un tiempo para la entrega y descompresi\u00f3n de las im\u00e1genes de los contenedores a los minions, el inicio y la inicializaci\u00f3n de contenedores, etc. Por lo tanto, es preferible que las tareas m\u00e1s importantes se inicien antes que las menos importantes.<\/p>\n<p><\/p>\n<p>Volvamos a revisar la jerarqu\u00eda de servicios que conocemos y intentemos decidir qu\u00e9 tareas queremos iniciar primero.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"One-cloud \u2014 Sistema de nivel de centro de datos en Odnoklassniki\" src=\"\/wp-content\/uploads\/2020\/06\/2e827271adb8d3ff3d385e53553aaacf.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Por supuesto, estos son los procesos que participan directamente en el manejo de las solicitudes de los usuarios, es decir, prod. Lo indicamos utilizando <strong>la prioridad de colocaci\u00f3n<\/strong> \u2014 un n\u00famero que puede ser asignado a la cola. Si una cola tiene una prioridad m\u00e1s alta, sus servicios se colocan en primer lugar.<\/p>\n<p><\/p>\n<p>En prod, asignamos prioridades m\u00e1s altas, 0; en batch \u2014 un poco m\u00e1s bajas, 100; en idle \u2014 a\u00fan m\u00e1s bajas, 200. Las prioridades se aplican jer\u00e1rquicamente. Todas las tareas m\u00e1s bajas en la jerarqu\u00eda tendr\u00e1n la prioridad correspondiente. Si queremos que dentro de prod las cach\u00e9s se ejecuten antes que los frontales, entonces asignamos prioridades a cache = 0 y a front de subtareas = 1. Si, por ejemplo, queremos que entre los frontales se ejecute primero el portal principal y luego el frontal musical, al \u00faltimo podemos asignar una prioridad m\u00e1s baja \u2014 10.<\/p>\n<p><\/p>\n<p>El siguiente problema es la falta de recursos. As\u00ed que hemos perdido un gran n\u00famero de equipos, salas enteras del centro de datos, y hemos lanzado tantos servicios que ahora no hay suficientes recursos para todos. Necesitamos decidir cu\u00e1les tareas sacrificar para que funcionen los servicios cr\u00edticos principales. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"One-cloud \u2014 Sistema de nivel de centro de datos en Odnoklassniki\" src=\"\/wp-content\/uploads\/2020\/06\/1b1ad3da16df6677dd0ba4b038cdd7d6.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>A diferencia de la prioridad de colocaci\u00f3n, no podemos sacrificar todas las tareas batch sin pensar, algunas de ellas son importantes para el funcionamiento del portal. Por lo tanto, hemos destacado por separado <strong>la prioridad de desalojo<\/strong> de las tareas. Al colocar una tarea con una prioridad m\u00e1s alta puede desalojar, es decir, detener la tarea con una prioridad m\u00e1s baja, si no hay m\u00e1s minions libres. En este caso, es probable que la tarea con baja prioridad permanezca sin asignar, es decir, no habr\u00e1 un minion adecuado con suficientes recursos libres.<\/p>\n<p><\/p>\n<p>En nuestra jerarqu\u00eda, es muy f\u00e1cil establecer una prioridad de desalojo donde las tareas prod y batch desalojen o detengan las tareas idle, pero no entre ellas, asignando a idle una prioridad de 200. As\u00ed como en el caso de la prioridad de colocaci\u00f3n, podemos utilizar nuestra jerarqu\u00eda para describir reglas m\u00e1s complejas. Por ejemplo, indicaremos que sacrificamos la funci\u00f3n musical si nos faltan recursos para el portal web principal, estableciendo para los nodos correspondientes una prioridad m\u00e1s baja: 10.<\/p>\n<p><\/p>\n<h2 id=\"avarii-dc-celikom\">Fallas del DC en su totalidad<\/h2>\n<p><\/p>\n<p>\u00bfPor qu\u00e9 puede fallar todo el centro de datos? Fuerza de la naturaleza. Hubo una buena publicaci\u00f3n sobre c\u00f3mo <noindex><a rel=\"nofollow\" href=\"https:\/\/habrahabr.ru\/company\/dataline\/blog\/333578\/\">el hurac\u00e1n afect\u00f3 el funcionamiento del centro de datos.<\/a><\/noindex>Se puede considerar que la causa de los problemas son los indigentes que alguna vez incendiaron la fibra \u00f3ptica en un pozo, lo que hizo que el centro de datos perdiera completamente la conexi\u00f3n con otras ubicaciones. La causa del fallo tambi\u00e9n puede ser el factor humano: un operador puede dar una orden que cause la ca\u00edda de todo el centro de datos. Esto puede ocurrir debido a un gran error. En resumen, los centros de datos caen; no es raro. Esto nos ocurre una vez cada pocos meses. <\/p>\n<p><\/p>\n<p>Y esto es lo que hacemos para que nadie #NoVivasNoPoste en Twitter.<\/p>\n<p><\/p>\n<p>La primera estrategia es la aislamiento. Cada instancia de one-cloud est\u00e1 aislada y solo puede gestionar m\u00e1quinas de un \u00fanico centro de datos. Es decir, la p\u00e9rdida de la nube debido a errores o a una orden incorrecta de un operador solo afecta a un centro de datos. Estamos preparados para ello: existe una pol\u00edtica de reserva, en la cual las r\u00e9plicas de aplicaciones y datos se distribuyen en todos los centros de datos. Utilizamos bases de datos tolerantes a fallos y realizamos pruebas de fallos peri\u00f3dicamente.<br \/>\nDado que hoy tenemos cuatro centros de datos, esto significa que hay cuatro instancias separadas y completamente aisladas de one-cloud.<\/p>\n<p><\/p>\n<p>Este enfoque no solo protege contra fallos f\u00edsicos, sino que tambi\u00e9n puede proteger contra errores del operador.<\/p>\n<p><\/p>\n<p>\u00bfQu\u00e9 m\u00e1s se puede hacer respecto al factor humano? Cuando un operador da a la nube un comando extra\u00f1o o potencialmente peligroso, puede requer\u00edrsele inesperadamente que resuelva una peque\u00f1a tarea para comprobar cu\u00e1n bien ha reflexionado. Por ejemplo, si se trata de una detenci\u00f3n masiva de muchas r\u00e9plicas o simplemente un comando extra\u00f1o \u2014 reducci\u00f3n del n\u00famero de r\u00e9plicas o cambio en el nombre de la imagen, y no solo del n\u00famero de versi\u00f3n en un nuevo manifiesto.<\/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 de nivel de centro de datos en 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 de one-cloud: <\/p>\n<p><\/p>\n<ul>\n<li><strong>Un esquema jer\u00e1rquico y visual para nombrar servicios y contenedores<\/strong>, que permite conocer r\u00e1pidamente de qu\u00e9 se trata la tarea, a qu\u00e9 se relaciona y c\u00f3mo funciona, y qui\u00e9n es el responsable de ella. <\/li>\n<li>Aplicamos nuestra <strong>t\u00e9cnica de combinaci\u00f3n de tareas prod- y batch-<\/strong>en minions para aumentar la eficiencia del uso compartido de m\u00e1quinas. En lugar de cpuset, utilizamos cuotas de CPU, shares, pol\u00edticas del planificador de CPU y Linux QoS.<\/li>\n<li>No conseguimos aislar completamente los contenedores que operan en una sola m\u00e1quina, pero su influencia mutua se mantiene dentro del 20%.<\/li>\n<li>La organizaci\u00f3n de servicios en una jerarqu\u00eda ayuda en la eliminaci\u00f3n autom\u00e1tica de emergencias mediante <strong>prioridades de colocaci\u00f3n y desalojo.<\/strong>.<\/li>\n<\/ul>\n<p><\/p>\n<h2 id=\"chavo\">FAQ<\/h2>\n<p><\/p>\n<p>Por qu\u00e9 no optamos por una soluci\u00f3n ya preparada.<\/p>\n<p><\/p>\n<ul>\n<li>Las diferentes clases de aislamiento de tareas requieren l\u00f3gicas distintas al distribuirse en los nodos. Mientras que las tareas de producci\u00f3n pueden asignarse simplemente mediante la reserva de recursos, las tareas en lote e inactivas necesitan distribuirse siguiendo la utilizaci\u00f3n real de los recursos en los nodos. <\/li>\n<li>La necesidad de tener en cuenta recursos utilizados por las tareas tales como: \n<ul>\n<li>ancho de banda de red;<\/li>\n<li>tipos y \"spindles\" de discos.<\/li>\n<\/ul>\n<\/li>\n<li>La necesidad de especificar prioridades de servicio al manejar emergencias, derechos y cuotas de equipo sobre recursos, lo que se resuelve mediante colas jer\u00e1rquicas en one-cloud.<\/li>\n<li>La necesidad de contar con nombres humanos para los contenedores, para reducir el tiempo de respuesta ante emergencias e incidentes.<\/li>\n<li>La imposibilidad de implementar simult\u00e1neamente Service Discovery en todos lados; la necesidad de coexistir durante mucho tiempo con tareas alojadas en servidores f\u00edsicos, lo que se resuelve mediante direcciones IP \"est\u00e1ticas\" que siguen a los contenedores, y, como consecuencia, la necesidad de una integraci\u00f3n \u00fanica con una gran infraestructura de red.<\/li>\n<\/ul>\n<p><\/p>\n<p>Todas estas funciones requerir\u00edan modificaciones significativas de las soluciones existentes para ajustarlas, y, tras evaluar la cantidad de trabajo, nos dimos cuenta de que podr\u00edamos desarrollar nuestra propia soluci\u00f3n con aproximadamente el mismo esfuerzo. Pero nuestra soluci\u00f3n ser\u00e1 mucho m\u00e1s f\u00e1cil de operar y desarrollar, ya que carece de abstracciones innecesarias que sostienen funcionalidades no deseadas. <\/p>\n<p><\/p>\n<p>A aquellos que leen las \u00faltimas l\u00edneas, \u00a1gracias por su paciencia y atenci\u00f3n!<\/p>\n<p>Fuente: <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\/es\/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=\"es_ES\" \/>\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\/es\/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 operativo de nivel de centro de datos en Odnoklassniki | ProHoster","description":"\u00a1Aloha, gente!","canonical_url":"https:\/\/prohoster.info\/es\/blog\/administrirovanie\/one-cloud-os-urovnya-data-czentra-v-odnoklassnikah","robots":"max-image-preview:large","keywords":"","webmasterTools":{"miscellaneous":""},"schema":null,"og:locale":"es_ES","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\/es\/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\/es\/wp-json\/wp\/v2\/posts\/84114","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/prohoster.info\/es\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/prohoster.info\/es\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/prohoster.info\/es\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/prohoster.info\/es\/wp-json\/wp\/v2\/comments?post=84114"}],"version-history":[{"count":0,"href":"https:\/\/prohoster.info\/es\/wp-json\/wp\/v2\/posts\/84114\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/prohoster.info\/es\/wp-json\/wp\/v2\/media\/84115"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/es\/wp-json\/wp\/v2\/media?parent=84114"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/es\/wp-json\/wp\/v2\/categories?post=84114"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/es\/wp-json\/wp\/v2\/tags?post=84114"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}