{"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\/it\/blog\/administrirovanie\/one-cloud-os-urovnya-data-czentra-v-odnoklassnikah","title":{"rendered":"One-cloud \u2014 sistema operativo di livello data center in Odnoklassniki","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<p><img decoding=\"async\" alt=\"One-cloud \u2014 sistema operativo di livello data center in Odnoklassniki\" src=\"\/wp-content\/uploads\/2020\/06\/fa983acacec59ff2d4ed098f87223971.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Aloha, gente! Mi chiamo Oleg Anastas'ev, lavoro in Odnoklassniki nel team della Piattaforma. Oltre a me, in Odnoklassniki lavora un sacco di hardware. Abbiamo quattro data center, con circa 500 rack e oltre 8.000 server. A un certo punto abbiamo capito che l'implementazione di un nuovo sistema di gestione ci avrebbe permesso di utilizzare le attrezzature in modo pi\u00f9 efficace, semplificare la gestione degli accessi, automatizzare la (ri)distribuzione delle risorse di calcolo, accelerare il lancio di nuovi servizi e migliorare la reazione a gravi incidenti. <\/p>\n<p><\/p>\n<p>Cosa ne \u00e8 venuto fuori? <\/p>\n<p><noindex><a rel=\"nofollow\" name=\"habracut\"><\/a><\/noindex><\/p>\n<p>Oltre a me e a un sacco di hardware ci sono anche persone che lavorano con questo hardware: ingegneri che si trovano direttamente nei data center; specialisti di rete che configurano l'infrastruttura di rete; amministratori, o SRE, che garantiscono la resilienza dell'infrastruttura; e team di sviluppatori, ciascuno dei quali \u00e8 responsabile di una parte delle funzioni del portale. Il software creato da loro funziona pi\u00f9 o meno cos\u00ec:<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"One-cloud \u2014 sistema operativo di livello data center in Odnoklassniki\" src=\"\/wp-content\/uploads\/2020\/06\/592fd0acfa7322eb80fbb85601a92918.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Le richieste degli utenti arrivano sia ai front-end del portale principale <noindex><a rel=\"nofollow\" href=\"http:\/\/www.ok.ru\/\">www.ok.ru<\/a><\/noindex>, sia ad altri, per esempio ai front-end dell'API musicale. Per elaborare la logica di business, chiamano un server applicazioni che, durante l'elaborazione della richiesta, chiama i necessari microservizi specializzati: one-graph (grafico delle relazioni sociali), user-cache (cache dei profili utente) e cos\u00ec via.<\/p>\n<p><\/p>\n<p>Ognuno di questi servizi \u00e8 distribuito su pi\u00f9 macchine, e ciascuno di essi ha sviluppatori responsabili del funzionamento dei moduli, della loro manutenzione e dello sviluppo tecnologico. Tutti questi servizi vengono avviati su server fisici e fino a poco tempo fa avviavamo esattamente un'attivit\u00e0 su un server, cio\u00e8 era specializzato per un compito specifico.<\/p>\n<p><\/p>\n<p>Perch\u00e9 \u00e8 cos\u00ec? Questo approccio aveva diversi vantaggi:<\/p>\n<p><\/p>\n<ul>\n<li>Si semplifica <strong>la gestione di massa<\/strong>. Supponiamo che un compito richieda alcune librerie, alcune configurazioni. Allora il server viene assegnato a un gruppo specifico, si descrive una policy cfengine per questo gruppo (o \u00e8 gi\u00e0 stata descritta) e questa configurazione viene distribuita in modo centralizzato e automatico su tutti i server di quel gruppo.<\/li>\n<li>Si semplifica <strong>la diagnostica<\/strong>. Supponiamo che stiate monitorando un carico elevato della CPU centrale e comprendiate che questo carico pu\u00f2 essere generato solo dal compito che sta girando su questo processore hardware. Le ricerche del colpevole si concludono molto rapidamente.<\/li>\n<li>Si semplifica <strong>monitoraggio<\/strong>. Se c'\u00e8 qualcosa che non va con il server, il monitor lo segnala e sapete esattamente chi \u00e8 il colpevole.<\/li>\n<\/ul>\n<p><\/p>\n<p>A un servizio composto da pi\u00f9 repliche vengono assegnati diversi server \u2014 uno per ciascuna. Allora, la risorsa di calcolo per il servizio viene assegnata molto semplicemente: quante pi\u00f9 server ha il servizio, tanto pi\u00f9 pu\u00f2 consumare risorse al massimo. \"Semplice\" qui non significa che sia facile da usare, ma che la distribuzione delle risorse avviene manualmente.<\/p>\n<p><\/p>\n<p>Questo approccio ci ha anche permesso di realizzare <strong>configurazioni hardware specializzate<\/strong> per i compiti eseguiti su questo server. Se un compito memorizza grandi volumi di dati, utilizziamo un server 4U con chassis per 38 dischi. Se il compito \u00e8 puramente computazionale, possiamo acquistare un server 1U pi\u00f9 economico. Questo \u00e8 efficace dal punto di vista delle risorse di calcolo. Inoltre, questo approccio ci consente di utilizzare fino a quattro volte meno macchine con un carico paragonabile a quello di un nostro amico social network. <\/p>\n<p><\/p>\n<p>Tale efficienza nell'uso delle risorse di calcolo dovrebbe garantire anche l'efficienza economica, partendo dall'assunto che il costo maggiore riguarda i server. A lungo, i componenti hardware sono stati i pi\u00f9 costosi, e abbiamo investito molte energie nel ridurre il costo dell'hardware, ideando algoritmi per garantire la tolleranza ai guasti per ridurre le esigenze di affidabilit\u00e0 dell'attrezzatura. E oggi siamo giunti a un punto in cui il prezzo dei server ha smesso di essere determinante. A meno che non si consideri l'ultimissima esotica, la configurazione specifica dei server nel rack non ha importanza. Ora abbiamo un altro problema \u2014 il costo dello spazio occupato da un server nel data center, cio\u00e8 lo spazio nel rack.<\/p>\n<p><\/p>\n<p>Realizzando che \u00e8 cos\u00ec, abbiamo deciso di calcolare quanto efficientemente utilizziamo i rack.<br \/>\nAbbiamo preso il prezzo del server pi\u00f9 potente tra quelli economicamente giustificabili, calcolato quanti di questi server possiamo inserire negli rack, quante attivit\u00e0 potremmo avviare su di essi in base al vecchio modello \"un server = un'attivit\u00e0\" e quanto tali attivit\u00e0 potrebbero utilizzare l'hardware. I calcoli ci hanno fatto commuovere. \u00c8 emerso che l'efficienza di utilizzo dei rack \u00e8 circa dell'11%. La conclusione \u00e8 ovvia: \u00e8 necessario aumentare l'efficienza dei data center. Sembrerebbe che la soluzione sia chiara: bisogna eseguire pi\u00f9 attivit\u00e0 su un singolo server. Ma qui iniziano le complicazioni. <\/p>\n<p><\/p>\n<p>La configurazione massiva diventa rapidamente complessa: ora non \u00e8 possibile assegnare a un server un solo gruppo. Infatti, ora su un server possono essere eseguite pi\u00f9 attivit\u00e0 di diversi team. Inoltre, la configurazione potrebbe essere in conflitto per diverse applicazioni. Anche la diagnostica diventa pi\u00f9 complessa: se si osserva un aumento del consumo di CPU o dischi su un server, non si sa quale delle attivit\u00e0 sta causando problemi.<\/p>\n<p><\/p>\n<p>Ma la cosa principale \u00e8 che non c'\u00e8 isolamento tra le attivit\u00e0 eseguite sulla stessa macchina. Ad esempio, il grafico del tempo medio di risposta di un'attivit\u00e0 del server prima e dopo che sullo stesso server \u00e8 stata avviata un'altra applicazione di calcolo, del tutto non correlata alla prima, mostra che il tempo di risposta dell'attivit\u00e0 principale \u00e8 aumentato considerevolmente.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"One-cloud \u2014 sistema operativo di livello data center in Odnoklassniki\" src=\"\/wp-content\/uploads\/2020\/06\/c7c07359ae572ca8c84a4c63559e4083.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>\u00c8 evidente che \u00e8 necessario eseguire le attivit\u00e0 o in contenitori o in macchine virtuali. Poich\u00e9 praticamente tutte le attivit\u00e0 vengono eseguite sotto il controllo di un unico sistema operativo (Linux) o sono adattate a esso, non abbiamo bisogno di sostenere molteplici sistemi operativi diversi. Pertanto, la virtualizzazione non \u00e8 necessaria, e a causa dei costi indiretti sar\u00e0 meno efficace della containerizzazione.<\/p>\n<p><\/p>\n<p>Come implementazione dei container per eseguire compiti direttamente sui server Docker, un buon candidato \u00e8: le immagini dei file system risolvono bene i problemi delle configurazioni in conflitto. Il fatto che le immagini possano essere composte da pi\u00f9 strati ci consente di ridurre notevolmente il volume dei dati necessari per il loro dispiegamento sull'infrastruttura, separando le parti comuni in strati di base distinti. In questo modo, gli strati di base (e i pi\u00f9 voluminosi) verranno memorizzati nella cache rapidamente su tutta l'infrastruttura, e per la distribuzione di molti tipi diversi di applicazioni e versioni sar\u00e0 necessario trasferire solo piccoli strati di volume. <\/p>\n<p><\/p>\n<p>Inoltre, il registro e il tagging delle immagini in Docker ci forniscono primitive pronte per la versioning e la distribuzione del codice in produzione.<\/p>\n<p><\/p>\n<p>Docker, come qualsiasi altra tecnologia simile, ci fornisce un certo livello di isolamento dei container 'out of the box'. Ad esempio, l'isolamento della memoria: ogni container ha un limite sull'uso della memoria della macchina, oltre il quale non consumer\u00e0. \u00c8 possibile isolare i container anche per l'uso della CPU. Per noi, per\u00f2, l'isolamento standard non era sufficiente. Ma di questo parleremo pi\u00f9 avanti.<\/p>\n<p><\/p>\n<p>L'esecuzione diretta dei container sui server \u00e8 solo una parte dei problemi. Un'altra parte riguarda il posizionamento dei container sui server. \u00c8 necessario capire quale container pu\u00f2 essere posizionato su quale server. Non \u00e8 un compito semplice, poich\u00e9 i container devono essere distribuiti sui server il pi\u00f9 densamente possibile, senza compromettere la loro velocit\u00e0 operativa. Tale collocazione pu\u00f2 essere complessa anche dal punto di vista della tolleranza ai guasti. Spesso vogliamo posizionare repliche dello stesso servizio in rack diversi o addirittura in sale diverse del data center, affinch\u00e9 in caso di guasto di un rack o di una sala non perdiamo immediatamente tutte le repliche del servizio. <\/p>\n<p><\/p>\n<p>Distribuire manualmente i container non \u00e8 un'opzione, quando hai 8.000 server e 8-16.000 container. <\/p>\n<p><\/p>\n<p>Inoltre, volevamo dare agli sviluppatori maggiore autonomia nella distribuzione delle risorse, affinch\u00e9 potessero posizionare i propri servizi in produzione senza l'aiuto di un amministratore. Allo stesso tempo, desideravamo mantenere il controllo, in modo che un servizio secondario non consumasse tutte le risorse dei nostri data center. <\/p>\n<p><\/p>\n<p>\u00c8 evidente che \u00e8 necessario uno strato di gestione che si occupi di questo automaticamente.<\/p>\n<p><\/p>\n<p>Ecco, siamo arrivati a un'immagine semplice e chiara, amata da tutti gli architetti: tre quadrati. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"One-cloud \u2014 sistema operativo di livello data center in 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 \u00e8 un cluster a prova di errore responsabile dell'orchestrazione del cloud. Lo sviluppatore invia al master un manifesto che contiene tutte le informazioni necessarie per il deployment del servizio. Il master, sulla base di questo, invia comandi ai minion selezionati (macchine destinate all'esecuzione dei container). Nei minion c'\u00e8 il nostro agente, che riceve il comando, emette le proprie istruzioni a Docker e Docker configura il kernel Linux per avviare il container corrispondente. Oltre a eseguire i comandi, l'agente comunica continuamente al master le variazioni dello stato sia della macchina-minion che dei container avviati su di essa.<\/p>\n<p><\/p>\n<h2 id=\"raspredelenie-resursov\">Distribuzione delle risorse<\/h2>\n<p><\/p>\n<p>Ora affrontiamo il compito pi\u00f9 complesso della distribuzione delle risorse per pi\u00f9 minion.<\/p>\n<p><\/p>\n<p>La risorsa di calcolo in one-cloud \u00e8:<\/p>\n<p><\/p>\n<ul>\n<li>La potenza di elaborazione della CPU consumata da un compito specifico. <\/li>\n<li>La quantit\u00e0 di memoria disponibile per il compito. <\/li>\n<li>Traffico di rete. Ogni minion ha un'interfaccia di rete specifica con una larghezza di banda limitata, quindi non si possono assegnare compiti senza considerare il volume di dati trasmessi attraverso la rete. <\/li>\n<li>Dischi. Oltre, chiaramente, allo spazio per i dati del compito, diamo anche un tipo di disco: HDD o SSD. I dischi possono gestire un numero finito di richieste al secondo \u2014 IOPS. Pertanto, per i compiti che generano pi\u00f9 IOPS di quelli che un singolo disco pu\u00f2 gestire, riserviamo anche degli \"spindles\" \u2014 cio\u00e8 dispositivi di memorizzazione che devono essere strettamente riservati per il compito.<\/li>\n<\/ul>\n<p><\/p>\n<p>Quindi, per qualche servizio, ad esempio user-cache, possiamo registrare le risorse consumate in questo modo: 400 core della CPU, 2,5 TB di memoria, 50 Gb\/s di traffico in entrambe le direzioni, 6 TB di spazio su HDD, allocato su 100 spindles. Oppure in una forma pi\u00f9 familiari per noi cos\u00ec:<\/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>Le risorse del servizio user-cache consumano solo una parte delle risorse disponibili nell'infrastruttura di produzione. Pertanto, vogliamo assicurarci che, all'improvviso, a causa di un errore dell'operatore o meno, user-cache non consumi pi\u00f9 risorse di quelle che gli sono state allocate. In altre parole, dobbiamo limitare le risorse. Ma su cosa potremmo legare la quota?<\/p>\n<p><\/p>\n<p>Torniamo al nostro schema di interazione tra componenti molto semplificato e ridisegniamolo con pi\u00f9 dettagli \u2014 cos\u00ec: <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"One-cloud \u2014 sistema operativo di livello data center in Odnoklassniki\" src=\"\/wp-content\/uploads\/2020\/06\/27e5bfbffadd3d4b9fdc6bf138d135ed.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Ci\u00f2 che salta all'occhio:<\/p>\n<p><\/p>\n<ul>\n<li>Il web front-end e la musica utilizzano cluster isolati dello stesso server applicativo.<\/li>\n<li>Si possono individuare i livelli logici a cui appartengono questi cluster: fronti, cache, livello di archiviazione e gestione dei dati.<\/li>\n<li>Il front-end non \u00e8 omogeneo, \u00e8 composto da diversi sottosistemi funzionali. <\/li>\n<li>Le cache possono anche essere distribuite tra i sottosistemi di cui memorizzano i dati.<\/li>\n<\/ul>\n<p><\/p>\n<p>Disegniamo di nuovo l'immagine:<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"One-cloud \u2014 sistema operativo di livello data center in Odnoklassniki\" src=\"\/wp-content\/uploads\/2020\/06\/905dacc0aca859e65bd33ef751a557cf.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Ah! Vediamo un'gerarchia! Ci\u00f2 significa che possiamo distribuire le risorse in blocchi pi\u00f9 grandi: nominare uno sviluppatore responsabile per un nodo di questa gerarchia, corrispondente al sottosistema funzionale (come 'music' nell'immagine), e legare una quota a questo stesso livello di gerarchia. Questa gerarchia ci permette anche di organizzare i servizi in modo pi\u00f9 flessibile per facilitare la gestione. Ad esempio, tutto il web, essendo un raggruppamento molto grande di server, lo suddividiamo in diversi gruppi pi\u00f9 piccoli, mostrati nell'immagine come group1, group2.<\/p>\n<p><\/p>\n<p>Rimuovendo le linee superflue, possiamo annotare ogni nodo della nostra immagine in una forma pi\u00f9 piatta: <strong>group1.web.front<\/strong>, <strong>api.music.front<\/strong>, <strong>user-cache.cache<\/strong>.<\/p>\n<p><\/p>\n<p>Cos\u00ec arriviamo al concetto di \u2018coda gerarchica\u2019. Essa ha un nome, come \u2018group1.web.front\u2019. Viene assegnata una quota per le risorse e diritti degli utenti. A una persona del DevOps daremo il permesso di inviare il servizio in coda, e tale dipendente potr\u00e0 avviare qualcosa in coda, mentre a una persona dell'OpsDev \u2014 diritti di amministrazione, e ora potr\u00e0 gestire la coda, nominando persone, concedendo a queste persone diritti, eccetera. I servizi avviati in questa coda verranno eseguiti entro i limiti della quota della coda. Se la quota computazionale della coda non \u00e8 sufficiente per l'esecuzione simultanea di tutti i servizi, saranno eseguiti in sequenza, formando cos\u00ec la vera e propria coda. <\/p>\n<p><\/p>\n<p>Esaminiamo i servizi pi\u00f9 nel dettaglio. Un servizio ha un nome completo, che include sempre il nome della coda. Quindi il servizio web front avr\u00e0 il nome <strong>ok-web.group1.web.front<\/strong>. E il servizio del server applicativo a cui si rivolge diventer\u00e0 <strong>ok-app.group1.web.front<\/strong>. Ogni servizio ha un manifesto, in cui sono indicate tutte le informazioni necessarie per il posizionamento su macchine specifiche: quante risorse consuma questo compito, quale configurazione \u00e8 necessaria, quante repliche devono esserci, propriet\u00e0 per la gestione dei guasti di questo servizio. E dopo il posizionamento del servizio direttamente sulle macchine, appaiono le sue istanze. Anche queste sono nominate in modo univoco \u2014 con il numero dell'istanza e il nome del servizio: <strong>1.ok-web.group1.web.front, 2.ok-web.group1.web.front, \u2026<\/strong><\/p>\n<p><\/p>\n<p>\u00c8 molto comodo: guardando solo il nome del contenitore in esecuzione, possiamo subito capire molto.<\/p>\n<p><\/p>\n<p>E ora conosciamo meglio cosa fanno effettivamente queste istanze: i compiti.<\/p>\n<p><\/p>\n<h2 id=\"klassy-izolyacii-zadach\">Classi di isolamento dei compiti<\/h2>\n<p><\/p>\n<p>Tutti i compiti in OK (e probabilmente ovunque) possono essere divisi in gruppi:<\/p>\n<p><\/p>\n<ul>\n<li><strong>Compiti con ritardo breve \u2014 prod<\/strong>. Per tali compiti e servizi, il ritardo di risposta (latency) \u00e8 molto importante, quanto velocemente ogni richiesta sar\u00e0 elaborata dal sistema. Esempi di compiti: front-end web, cache, server di applicazioni, archivi OLTP, ecc.<\/li>\n<li><strong>Compiti di calcolo \u2014 batch<\/strong>. Qui la velocit\u00e0 di elaborazione di ciascuna richiesta specifica non \u00e8 importante. Ci\u00f2 che conta \u00e8 quanto calcolo totale questa attivit\u00e0 far\u00e0 in un determinato (grande) intervallo di tempo (throughput). Saranno tali qualsiasi compito MapReduce, Hadoop, machine learning, statistica.<\/li>\n<li><strong>Compiti in background \u2014 idle<\/strong>. Per tali compiti neither latency nor throughput sono molto importanti. Qui rientrano vari test, migrazioni, ricalcoli, conversioni di dati da un formato all'altro. Da un lato, assomigliano a quelli di calcolo, dall'altro \u2014 non ci interessa molto quanto velocemente si completano. <\/li>\n<\/ul>\n<p><\/p>\n<p>Vediamo come tali compiti consumano risorse, ad esempio, della CPU.<\/p>\n<p><\/p>\n<p><strong>Compiti con ritardo breve.<\/strong> Per tale compito, il pattern di consumo della CPU assomiglier\u00e0 a questo:<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"One-cloud \u2014 sistema operativo di livello data center in Odnoklassniki\" src=\"\/wp-content\/uploads\/2020\/06\/1ed82c0df76325eb30056ad9af86e86e.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Viene ricevendo una richiesta dall'utente, il compito inizia a utilizzare tutti i core CPU disponibili, elabora, restituisce una risposta, aspetta la successiva richiesta e si ferma. Arriva una nuova richiesta \u2014 di nuovo prende tutto ci\u00f2 che aveva, elabora, aspettiamo il successivo.<\/p>\n<p><\/p>\n<p>Per garantire un ritardo minimo per tale compito, dobbiamo prendere il massimo delle risorse consumate e riservare il numero necessario di core sulla minion (la macchina che eseguir\u00e0 il compito). Allora la formula di riservazione per il nostro compito sar\u00e0 la seguente:<\/p>\n<p><\/p>\n<pre><code>alloc: cpu = 4 (max)<\/code><\/pre>\n<p><\/p>\n<p>E se abbiamo una macchina-minion con 16 core, possiamo eseguire esattamente quattro di queste attivit\u00e0. \u00c8 importante notare che il consumo medio della CPU per queste attivit\u00e0 \u00e8 spesso molto basso \u2014 cosa evidente, poich\u00e9 gran parte del tempo l'attivit\u00e0 \u00e8 in attesa di una richiesta e non fa nulla.<\/p>\n<p><\/p>\n<p><strong>Attivit\u00e0 di calcolo.<\/strong> Il loro modello sar\u00e0 leggermente diverso:<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"One-cloud \u2014 sistema operativo di livello data center in Odnoklassniki\" src=\"\/wp-content\/uploads\/2020\/06\/35b37fa1d70a137287cafdbfe3bcfc2e.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Il consumo medio delle risorse della CPU per queste attivit\u00e0 \u00e8 piuttosto elevato. Spesso desideriamo che l'attivit\u00e0 di calcolo venga completata in un certo tempo, quindi \u00e8 necessario riservare un numero minimo di processori necessario affinch\u00e9 l'intero calcolo si concluda in un tempo accettabile. La sua formula di riservazione apparir\u00e0 cos\u00ec:<\/p>\n<p><\/p>\n<pre><code>alloc: cpu = [1,*)<\/code><\/pre>\n<p><\/p>\n<p><em>\"Per favore, posiziona su un minion dove ci sia almeno un core libero, e poi tutto il resto \u2014 prender\u00e0 tutto.\"<\/em><\/p>\n<p><\/p>\n<p>Qui l'efficienza dell'uso \u00e8 gi\u00e0 molto migliore rispetto alle attivit\u00e0 con bassa latenza. Ma il guadagno sar\u00e0 molto maggiore se combiniamo entrambi i tipi di attivit\u00e0 su una sola macchina-minion e distribuiamo le sue risorse on-the-fly. Quando un'attivit\u00e0 con bassa latenza richiede la CPU \u2014 la ottiene immediatamente, e quando le risorse non sono pi\u00f9 necessarie \u2014 vengono trasferite all'attivit\u00e0 di calcolo, cio\u00e8 pi\u00f9 o meno cos\u00ec:<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"One-cloud \u2014 sistema operativo di livello data center in Odnoklassniki\" src=\"\/wp-content\/uploads\/2020\/06\/875ad8d3f6a01e4fd0a89d0931e986c1.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Ma come si fa?<\/p>\n<p><\/p>\n<p>Iniziamo a esaminare prod e il suo alloc: cpu = 4. Dobbiamo riservare quattro core. In Docker run questo pu\u00f2 essere fatto in due modi: <\/p>\n<p><\/p>\n<ul>\n<li>Utilizzando l'opzione <code>--cpuset=1-4<\/code>, cio\u00e8 riservare all'attivit\u00e0 quattro core specifici sulla macchina.<\/li>\n<li>di utilizzare <code>--cpuquota=400_000 --cpuperiod=100_000<\/code>, assegnare una quota di tempo di CPU, cio\u00e8 specificare che ogni 100 ms di tempo reale l'attivit\u00e0 consuma non pi\u00f9 di 400 ms di tempo di CPU. Si ottengono comunque gli stessi quattro core. <\/li>\n<\/ul>\n<p><\/p>\n<p>Ma quale di questi metodi \u00e8 pi\u00f9 adatto?<\/p>\n<p><\/p>\n<p>Il cpuset sembra piuttosto attraente. Il task ha quattro core dedicati, il che significa che le cache del processore funzioneranno al massimo dell'efficienza. Tuttavia, c'\u00e8 anche un rovescio della medaglia: dovremmo assumerci il compito di distribuire i calcoli sui core non occupati della macchina anzich\u00e9 sull'OS, e questo \u00e8 un compito piuttosto non banale, specialmente se proviamo a distribuire compiti batch su tale macchina. I test hanno mostrato che qui \u00e8 meglio optare per la quota: in questo modo il sistema operativo ha pi\u00f9 libert\u00e0 nella scelta del core per eseguire il task in quel momento e il tempo di CPU viene distribuito in modo pi\u00f9 efficace.<\/p>\n<p><\/p>\n<p>Esaminiamo come in docker effettuare la riservazione per il numero minimo di core. La quota per i compiti batch non \u00e8 pi\u00f9 applicabile, poich\u00e9 non \u00e8 necessario limitare il massimo, \u00e8 sufficiente garantire solo il minimo. Qui ci si adatta bene l'opzione <code>docker run --cpushares<\/code>.<\/p>\n<p><\/p>\n<p>Abbiamo concordato che se un batch richiede la garanzia di un minimo di un core, specifichiamo <code>--cpushares=1024<\/code>, mentre se il minimo sono due core, allora specifichiamo <code>--cpushares=2048<\/code>. Le condivisioni di CPU non interferiscono nella distribuzione del tempo di CPU finch\u00e9 ce n'\u00e8 a sufficienza. Cos\u00ec, se il prod non utilizza attualmente tutti e quattro i suoi core, nulla limita i compiti batch, e possono utilizzare ulteriore tempo di CPU. Tuttavia, in caso di carenza di CPU, se il prod ha consumato tutti e quattro i suoi core e ha raggiunto la quota, il tempo di CPU rimanente sar\u00e0 suddiviso proporzionalmente alle cpushares, cio\u00e8 in una situazione di tre core liberi, un core andr\u00e0 al task con 1024 cpushares, mentre gli altri due andranno al task con 2048 cpushares.<\/p>\n<p><\/p>\n<p>Tuttavia, l'uso di quota e shares non \u00e8 sufficiente. Dobbiamo assicurarci che il task con bassa latenza abbia priorit\u00e0 rispetto al task batch nella distribuzione del tempo di CPU. Senza tale prioritizzazione, il task batch prender\u00e0 tutto il tempo di CPU quando necessario per il prod. In Docker run non ci sono opzioni per la prioritizzazione dei container, ma ci vengono in aiuto le politiche dello scheduler della CPU in Linux. Puoi leggere in dettaglio <noindex><a rel=\"nofollow\" href=\"http:\/\/man7.org\/linux\/man-pages\/man2\/sched_setscheduler.2.html\">qui<\/a><\/noindex>, mentre in questo articolo daremo solo una panoramica:<\/p>\n<p><\/p>\n<ul>\n<li><strong>SCHED_OTHER<\/strong><br \/>\nPer impostazione predefinita, vengono concessi a tutti i normali processi utente su una macchina Linux.<\/li>\n<li><strong>SCHED_BATCH<\/strong><br \/>\nDestinata a processi ad alta intensit\u00e0 di risorse. Quando un compito viene assegnato al processore, viene introdotta una sorta di penalit\u00e0 per l'attivazione: tale compito avr\u00e0 minori probabilit\u00e0 di ricevere risorse del processore se in quel momento \u00e8 in uso un compito con SCHED_OTHER<\/li>\n<li><strong>SCHED_IDLE<\/strong><br \/>\nProcesso in background con priorit\u00e0 molto bassa, anche inferiore a nice -19. Usiamo la nostra libreria open source <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/odnoklassniki\/one-nio\">one-nio<\/a><\/noindex>, per impostare la politica necessaria al momento dell'avvio del contenitore chiamando<\/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>Ma anche se non programmi in Java, puoi fare lo stesso usando il comando chrt:<\/p>\n<p><\/p>\n<pre><code class=\"bash\">chrt -i 0 $pid<\/code><\/pre>\n<p><\/p>\n<p>Riassumiamo tutti i nostri livelli di isolamento in una tabella per chiarezza:<\/p>\n<p><\/p>\n<p>Classe di isolamento<br \/>\nEsempio alloc<br \/>\nOpzioni 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 esegui chrt dall'interno del contenitore, potrebbe essere necessaria la capability sys_nice, poich\u00e9 per impostazione predefinita Docker revoca questa capability all'avvio del contenitore.<\/p>\n<p><\/p>\n<p>Ma i compiti consumano non solo il processore, ma anche il traffico, che influisce sulla latenza del compito di rete ancora di pi\u00f9 di un errato bilanciamento delle risorse del processore. Pertanto, naturalmente, vogliamo ottenere un'immagine altrettanto chiara del traffico. Cio\u00e8, quando il compito prod invia dei pacchetti in rete, limitiamo la velocit\u00e0 massima (formula <em>alloc: lan=[*,500mbps)<\/em> ), con cui prod pu\u00f2 farlo. E per batch garantiamo solo la banda minima, senza limitare quella massima (formula <em>alloc: lan=[10Mbps,*)<\/em> ) In questo modo il traffico prod deve avere priorit\u00e0 rispetto ai compiti batch.<br \/>\nQui Docker non ha primitivi che possiamo utilizzare. Ma abbiamo l'aiuto di <noindex><a rel=\"nofollow\" href=\"http:\/\/lartc.org\/\">Linux Traffic Control<\/a><\/noindex>. Siamo riusciti a raggiungere il risultato desiderato tramite la disciplina <noindex><a rel=\"nofollow\" href=\"http:\/\/linux-ip.net\/articles\/hfsc.en\/\">Hierarchical Fair Service Curve<\/a><\/noindex>. Con questa disciplina isoliamo due classi di traffico: alta priorit\u00e0 prod e bassa priorit\u00e0 batch\/idle. Alla fine, la configurazione per il traffico in uscita risulta cos\u00ec:<\/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 operativo di livello data center in Odnoklassniki\" src=\"\/wp-content\/uploads\/2020\/06\/3f52a968118b6021bd0c920af17a00c0.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/a><\/noindex><\/p>\n<p><\/p>\n<p>qui 1:0 \u2014 \u00abqdisc radice\u00bb della disciplina hsfc; 1:1 \u2014 classe secondaria hsfc con un limite di banda totale di 8 Gbit\/s, sotto la quale sono collocate le classi secondarie di tutti i contenitori; 1:2 \u2014 classe secondaria hsfc comune a tutti i batch e le attivit\u00e0 idle con un limite \u00abdinamico\u00bb, di cui si parler\u00e0 pi\u00f9 avanti. Le altre classi secondarie hsfc sono classi dedicate per i contenitori prod attualmente in esecuzione, con limiti corrispondenti ai loro manifesti \u2014 450 e 400 Mbit\/s. A ciascuna classe hsfc \u00e8 assegnata una coda qdisc fq o fq_codel, a seconda della versione del kernel linux, per evitare perdite di pacchetti durante i picchi di traffico. <\/p>\n<p><\/p>\n<p>Di solito, le discipline tc servono solo per la priorizzazione del traffico in uscita. Ma vogliamo dare priorit\u00e0 anche al traffico in ingresso \u2014 poich\u00e9 qualche compito batch pu\u00f2 facilmente occupare tutta la banda in ingresso, ricevendo, ad esempio, un grande pacchetto di dati in ingresso per map&amp;reduce. Per questo utilizziamo il modulo <noindex><a rel=\"nofollow\" href=\"https:\/\/serverfault.com\/questions\/350023\/tc-ingress-policing-and-ifb-mirroring\">ifb<\/a><\/noindex>, che crea un'interfaccia virtuale ifbX per ogni interfaccia di rete e reindirizza il traffico in ingresso dall'interfaccia a quella in uscita su ifbX. Successivamente, per ifbX funzionano tutte le stesse discipline per il controllo del traffico in uscita, per il quale la configurazione hsfc sar\u00e0 molto simile:<\/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 operativo di livello data center in Odnoklassniki\" src=\"\/wp-content\/uploads\/2020\/06\/967da9c0637cc70ba195af781db18adf.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/a><\/noindex><\/p>\n<p><\/p>\n<p>Durante gli esperimenti abbiamo scoperto che i migliori risultati di hsfc si ottengono quando la classe 1:2 del traffico batch\/idle non prioritario \u00e8 limitata sulle macchine minion a non pi\u00f9 di una certa banda libera. Altrimenti, il traffico non prioritario influisce troppo sulla latenza dei task prod. L'attuale grandezza della banda libera \u00e8 determinata da miniond ogni secondo, misurando il consumo medio di traffico da parte di tutti i task prod di quel minion <img decoding=\"async\" alt=\"One-cloud \u2014 sistema operativo di livello data center in Odnoklassniki\" src=\"\/wp-content\/uploads\/2020\/06\/9d6f38110d3b1693afe222b01430b9bb.jpg\" style=\"display:block;margin: 0 auto;\" \/> e sottraendola dalla capacit\u00e0 dell'interfaccia di rete <img decoding=\"async\" alt=\"One-cloud \u2014 sistema operativo di livello data center in Odnoklassniki\" src=\"\/wp-content\/uploads\/2020\/06\/d5608ec4c58e44b8571ab0b1d0cc7701.jpg\" style=\"display:block;margin: 0 auto;\" \/> con un piccolo margine, cio\u00e8.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"One-cloud \u2014 sistema operativo di livello data center in Odnoklassniki\" src=\"\/wp-content\/uploads\/2020\/06\/fb01347c2224bd5bbd82169861eeb7e4.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Le bande sono definite per il traffico in ingresso e in uscita in modo indipendente. E in base ai nuovi valori, miniond riconfigura il limite per la classe non prioritaria 1:2.<\/p>\n<p><\/p>\n<p>In questo modo abbiamo implementato tutte e tre le classi di isolamento: prod, batch e idle. Queste classi influenzano notevolmente le prestazioni dei task. Pertanto, abbiamo deciso di collocare questo attributo in cima all'gerarchia, in modo che guardando il nome della coda gerarchica sia immediatamente chiaro di cosa si tratta: <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"One-cloud \u2014 sistema operativo di livello data center in Odnoklassniki\" src=\"\/wp-content\/uploads\/2020\/06\/34dc89c461db711b19a0f4eccc50efce.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Tutti i nostri familiari <strong>web<\/strong> e <strong>music<\/strong> fronti vengono quindi collocati in gerarchia sotto prod. Per esempio, sotto batch poniamo il servizio <strong>music catalog<\/strong>, che periodicamente compila un catalogo di brani da un insieme di file mp3 caricati su \u00ab\u041e\u0434\u043d\u043e\u043a\u043b\u0430\u0441\u0441\u043d\u0438\u043a\u0438\u00bb. Un esempio di servizio in idle potrebbe essere <strong>music transformer<\/strong>, che normalizza il livello di volume della musica.<\/p>\n<p><\/p>\n<p>Rimuovendo di nuovo le righe superflue, possiamo scrivere i nomi dei nostri servizi in modo pi\u00f9 piatto, aggiungendo la classe di isolamento del compito alla fine del nome completo del servizio: <strong>web.front.prod<\/strong>, <strong>catalog.music.batch<\/strong>, <strong>transformer.music.idle<\/strong>.<\/p>\n<p><\/p>\n<p>E ora, guardando il nome del servizio, comprendiamo non solo quale funzione svolge, ma anche la sua classe di isolamento, e quindi la sua criticit\u00e0 e cos\u00ec via.<\/p>\n<p><\/p>\n<p>Tutto \u00e8 fantastico, ma c'\u00e8 una dura verit\u00e0. Isolare completamente i compiti che operano su una sola macchina \u00e8 impossibile.<\/p>\n<p><\/p>\n<p>Cosa siamo riusciti a ottenere: se il batch consuma intensamente <strong>solo<\/strong> risorse della CPU, il pianificatore integrato della CPU Linux svolge molto bene il suo compito, e non c'\u00e8 praticamente alcun impatto sulla task di prod. Ma se questo task batch inizia a lavorare attivamente con la memoria, allora l'influenza reciproca si manifesta gi\u00e0. Questo accade perch\u00e9 i cache della memoria della task di prod vengono 'svuotati' \u2014 di conseguenza, gli errori nel cache aumentano, e la CPU elabora la task di prod pi\u00f9 lentamente. Un task batch del genere pu\u00f2 aumentare i ritardi del nostro tipico container di prod del 10%.<\/p>\n<p><\/p>\n<p>Isolare il traffico \u00e8 ancora pi\u00f9 difficile perch\u00e9 le moderne schede di rete hanno una coda interna di pacchetti. Se un pacchetto da un task batch arriva prima in coda, significa che sar\u00e0 trasmesso per primo via cavo, e non c'\u00e8 nulla da fare.<\/p>\n<p><\/p>\n<p>Inoltre, finora siamo riusciti a risolvere solo la questione della priorizzazione del traffico TCP: per UDP l'approccio con hsfc non funziona. E anche nel caso del traffico TCP, se un task batch genera molto traffico, ci\u00f2 comporta anche un aumento di circa il 10% dei ritardi nella task di prod.<\/p>\n<p><\/p>\n<h2 id=\"otkazoustoychivost\">Resilienza<\/h2>\n<p><\/p>\n<p>Uno degli obiettivi nella progettazione di one-cloud era migliorare la resilienza di \u041e\u0434\u043d\u043e\u043a\u043b\u0430\u0441\u0441\u043d\u0438\u043a\u0438. Pertanto, vorrei esaminare pi\u00f9 dettagliatamente i possibili scenari di guasto e malfunzionamento. Iniziamo con uno scenario semplice: il guasto di un container. <\/p>\n<p><\/p>\n<p>Il contenitore pu\u00f2 fallire in diversi modi. Potrebbe essere un esperimento, un bug o un errore nel manifesto, che porta al fatto che il compito in produzione inizia a consumare pi\u00f9 risorse di quanto indicato nel manifesto. Abbiamo avuto un caso: un sviluppatore ha implementato un algoritmo complesso, lo ha modificato molte volte, si \u00e8 confuso e ha creato un ciclo non banale. Poich\u00e9 il compito in produzione \u00e8 pi\u00f9 prioritario di tutti gli altri sugli stessi nodi, ha iniziato a consumare tutte le risorse disponibili della CPU. In questa situazione, l'isolamento ha fatto la differenza, pi\u00f9 precisamente, il limite sul tempo della CPU. Se al compito viene assegnato un limite, non consumer\u00e0 di pi\u00f9. Pertanto, i compiti batch e altri compiti in produzione che lavoravano sulla stessa macchina non hanno notato nulla. <\/p>\n<p><\/p>\n<p>Un altro possibile problema \u00e8 il crash del contenitore. Qui ci salvano le politiche di riavvio, che tutti conoscono, e Docker si occupa perfettamente della cosa. Praticamente tutti i compiti in produzione hanno una politica di riavvio sempre attiva. A volte utilizziamo on_failure per i compiti batch o per il debugging dei contenitori di produzione.<\/p>\n<p><\/p>\n<p>E cosa si pu\u00f2 fare in caso di inattivit\u00e0 di un intero nodo?<\/p>\n<p><\/p>\n<p>Ovviamente, avviare il contenitore su un'altra macchina. La parte interessante qui \u00e8 cosa succede all'indirizzo IP (agli indirizzi) assegnati al contenitore. <\/p>\n<p><\/p>\n<p>Possiamo assegnare ai contenitori gli stessi indirizzi IP delle macchine nodi su cui vengono eseguiti. Quindi, quando avviamo un contenitore su un'altra macchina, il suo indirizzo IP cambia, e tutti i client devono comprendere che il contenitore si \u00e8 spostato, e ora devono accedere a un altro indirizzo, il che richiede un servizio di Service Discovery separato. <\/p>\n<p><\/p>\n<p>Il Service Discovery \u00e8 comodo. Sul mercato ci sono molte soluzioni di diversa resilienza per organizzare un registro dei servizi. Spesso in queste soluzioni viene implementata la logica di un bilanciatore di carico, conservazione di configurazioni aggiuntive in forma di KV-store, ecc.<br \/>\nTuttavia, ci piacerebbe fare a meno della necessit\u00e0 di implementare un registro separato, poich\u00e9 questo significherebbe introdurre un sistema critico, utilizzato da tutti i servizi in produzione. Significa che questo \u00e8 un potenziale punto di failure e bisogna scegliere o sviluppare una soluzione molto affidabile, il che, ovviamente, \u00e8 molto complesso, lungo e costoso. <\/p>\n<p><\/p>\n<p>E un altro grosso svantaggio: per far funzionare la nostra vecchia infrastruttura con la nuova, sarebbe stato necessario riscrivere assolutamente tutte le attivit\u00e0 per utilizzare qualche sistema di Service Discovery. Ci sono moltissimi lavori, a volte impossibili, soprattutto quando si tratta di dispositivi a basso livello che operano a livello del nucleo del sistema operativo o direttamente con l'hardware. Implementare questa funzionalit\u00e0 utilizzando schemi di soluzione consolidati, come ad esempio <noindex><a rel=\"nofollow\" href=\"https:\/\/linkerd.io\">side-car<\/a><\/noindex> significherebbe, in alcuni casi, un carico aggiuntivo e, in altri, una maggiore complessit\u00e0 nella gestione e scenari di guasto aggiuntivi. Non volevamo complicare le cose, quindi abbiamo deciso di rendere opzionale l'uso di Service Discovery. <\/p>\n<p><\/p>\n<p>In one-cloud, l'IP segue il contenitore, cio\u00e8 ogni istanza del task ha il proprio indirizzo IP. Questo indirizzo \u00e8 \"statico\": viene assegnato a ciascuna istanza al momento del primo invio del servizio nel cloud. Se nel corso della vita del servizio ci sono stati vari istanze, alla fine avr\u00e0 un numero di indirizzi IP pari al numero massimo di istanze esistite.<\/p>\n<p><\/p>\n<p>Successivamente, questi indirizzi non cambiano: vengono assegnati una sola volta e continuano ad esistere per tutta la vita del servizio in produzione. Gli indirizzi IP seguono i contenitori attraverso la rete. Se un contenitore viene spostato su un altro minion, anche l'indirizzo verr\u00e0 trasferito con esso. <\/p>\n<p><\/p>\n<p>Pertanto, l'associazione tra il nome del servizio e la lista dei suoi indirizzi IP cambia molto raramente. Se guardiamo di nuovo ai nomi delle istanze del servizio che abbiamo menzionato all'inizio dell'articolo (<strong>1.ok-web.group1.web.front.prod, 2.ok-web.group1.web.front.prod, \u2026<\/strong>), notiamo che assomigliano a FQDN utilizzati nel DNS. \u00c8 proprio cos\u00ec, per visualizzare i nomi degli istanti dei servizi nei loro indirizzi IP utilizziamo il protocollo DNS. Inoltre, questo DNS restituisce tutti gli indirizzi IP riservati di tutti i container \u2014 sia attivi che fermati (per esempio, se si utilizzano tre repliche e abbiamo cinque indirizzi riservati, tutti e cinque verranno restituiti). I client, ricevuta questa informazione, tenteranno di connettersi a tutte e cinque le repliche \u2014 e in questo modo identificheranno quelle attive. Questo metodo di determinazione della disponibilit\u00e0 \u00e8 notevolmente pi\u00f9 affidabile, poich\u00e9 non coinvolge n\u00e9 il DNS n\u00e9 il Service Discovery, il che significa che non ci sono problemi difficili da risolvere relativi all'aggiornamento delle informazioni e alla resilienza di questi sistemi. Inoltre, nei servizi critici, da cui dipende il funzionamento dell'intero portale, possiamo non utilizzare affatto il DNS, e semplicemente inserire gli indirizzi IP nella configurazione.<\/p>\n<p><\/p>\n<p>L'implementazione di questo trasferimento di IP dietro ai container pu\u00f2 non essere banale \u2014 e ci fermeremo a come funziona nel seguente esempio:<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"One-cloud \u2014 sistema operativo di livello data center in Odnoklassniki\" src=\"\/wp-content\/uploads\/2020\/06\/faf99c2609a57daa1bdc193cb0f4cb31.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Supponiamo che il master one-cloud dia il comando al minion M1 di avviare <strong>1.ok-web.group1.web.front.prod<\/strong> con l'indirizzo 1.1.1.1. Sul minion gira <noindex><a rel=\"nofollow\" href=\"https:\/\/en.wikipedia.org\/wiki\/Bird_Internet_routing_daemon\">BIRD<\/a><\/noindex>, che annuncia questo indirizzo a server specializzati <noindex><a rel=\"nofollow\" href=\"https:\/\/en.wikipedia.org\/wiki\/Route_reflector\">route reflector<\/a><\/noindex>. Ce ne sono tre di server route reflector, poich\u00e9 questa \u00e8 una parte molto critica dell'infrastruttura one-cloud \u2014 senza di essi, la rete in one-cloud non funzionerebbe. Li collocchiamo in diverse rack, per quanto possibile situati in diverse sale del data center, per ridurre la possibilit\u00e0 di un guasto simultaneo di tutti e tre.<\/p>\n<p><\/p>\n<p>Ora supponiamo che la connessione tra il master one-cloud e il minion M1 sia andata persa. Il master one-cloud agir\u00e0 ora sulla base dell'ipotesi che M1 sia completamente guasto. Cio\u00e8 dar\u00e0 il comando al minion M2 di avviare <strong>web.group1.web.front.prod<\/strong> con lo stesso indirizzo 1.1.1.1. Ora abbiamo due percorsi in conflitto nella rete per 1.1.1.1: su M1 e su M2. Per risolvere tali conflitti, utilizziamo il Multi Exit Discriminator, che viene specificato nell'annuncio BGP. Questo numero indica il peso del percorso annunciato. Verr\u00e0 scelto il percorso con il valore MED pi\u00f9 basso fra quelli in conflitto. Il master one-cloud supporta il MED come parte integrante degli indirizzi IP dei contenitori. La prima volta che l'indirizzo viene assegnato, ha un MED abbastanza alto = 1.000.000. In caso di un'emergenza di trasferimento del contenitore, il master diminuisce il MED, e M2 ricever\u00e0 l'istruzione di annunciare l'indirizzo 1.1.1.1 con MED = 999.999. L'istanza operante su M1 rimarr\u00e0 cos\u00ec disconnessa, e il suo destino ci interessa poco fino al momento in cui ripristineremo la connessione con il master, momento in cui verr\u00e0 fermata come vecchio duplicato.<\/p>\n<p><\/p>\n<h2 id=\"avarii\">Incidenti<\/h2>\n<p><\/p>\n<p>Tutti i sistemi di gestione dei data center gestiscono sempre in modo accettabile i piccoli guasti. L'uscita di un contenitore \u00e8 una norma praticamente ovunque.<\/p>\n<p><\/p>\n<p>Consideriamo come gestiamo un incidente, ad esempio un'interruzione di corrente in una o pi\u00f9 sale del data center.<\/p>\n<p><\/p>\n<p>Cosa significa incidente per un sistema di gestione di un data center? In primo luogo, si tratta di un guasto massivo simultaneo di molte macchine, e il sistema di gestione deve migrare simultaneamente un gran numero di contenitori. Ma se l'incidente \u00e8 molto esteso, pu\u00f2 succedere che tutte le attivit\u00e0 non possano essere riposizionate su altri minion, perch\u00e9 la capacit\u00e0 del data center scende sotto il 100% di carico. <\/p>\n<p><\/p>\n<p>Spesso gli incidenti sono accompagnati da un guasto dello strato di gestione. Questo pu\u00f2 accadere a causa del malfunzionamento dell'attrezzatura, ma pi\u00f9 spesso perch\u00e9 gli incidenti non vengono testati, e lo strato di gestione crolla a causa dell'aumentato carico. <\/p>\n<p><\/p>\n<p>Cosa si pu\u00f2 fare con tutto questo?<\/p>\n<p><\/p>\n<p>Le migrazioni di massa significano che nell'infrastruttura si verifica un gran numero di azioni, migrazioni e posizionamenti. Ogni migrazione pu\u00f2 richiedere un certo tempo, necessario per consegnare e decomprimere le immagini dei contenitori ai minion, avviare e inizializzare i contenitori, ecc. Pertanto, \u00e8 preferibile che le attivit\u00e0 pi\u00f9 importanti vengano avviate prima di quelle meno importanti.<\/p>\n<p><\/p>\n<p>Rivediamo nuovamente l'ormai familiare gerarchia dei servizi e cerchiamo di decidere quali attivit\u00e0 vogliamo avviare per prime.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"One-cloud \u2014 sistema operativo di livello data center in Odnoklassniki\" src=\"\/wp-content\/uploads\/2020\/06\/2e827271adb8d3ff3d385e53553aaacf.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Certo, questi sono i processi che partecipano direttamente all'elaborazione delle richieste degli utenti, cio\u00e8 prod. Lo indichiamo con <strong>priorit\u00e0 di assegnazione<\/strong> \u2014 un numero che pu\u00f2 essere assegnato alla coda. Se qualche coda ha una priorit\u00e0 pi\u00f9 alta, i suoi servizi vengono assegnati per primi.<\/p>\n<p><\/p>\n<p>Su prod diamo priorit\u00e0 pi\u00f9 elevate, 0; su batch \u2014 leggermente pi\u00f9 basse, 100; su idle \u2014 ancora pi\u00f9 basse, 200. Le priorit\u00e0 sono applicate in modo gerarchico. Tutte le attivit\u00e0 sotto nella gerarchia avranno la priorit\u00e0 corrispondente. Se vogliamo che all'interno di prod le cache vengano avviate prima dei frontend, allora assegniamo priorit\u00e0 a cache = 0 e a front sotto-coda = 1. Se, ad esempio, vogliamo che il portale principale venga avviato prima dai frontend e il frontend musicale dopo, possiamo assegnare una priorit\u00e0 pi\u00f9 bassa a quest'ultimo \u2014 10.<\/p>\n<p><\/p>\n<p>Il problema successivo \u00e8 la mancanza di risorse. Quindi, abbiamo avuto un guasto di un gran numero di attrezzature, intere sale del data center, e abbiamo avviato cos\u00ec tanti servizi che ora non ci sono abbastanza risorse per tutti. Dobbiamo decidere quali attivit\u00e0 sacrificare affinch\u00e9 i servizi critici principali funzionino. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"One-cloud \u2014 sistema operativo di livello data center in Odnoklassniki\" src=\"\/wp-content\/uploads\/2020\/06\/1b1ad3da16df6677dd0ba4b038cdd7d6.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>A differenza della priorit\u00e0 di assegnazione, non possiamo sacrificare indiscriminatamente tutte le attivit\u00e0 batch, alcune di esse sono importanti per il funzionamento del portale. Pertanto, abbiamo separato <strong>la priorit\u00e0 di preemption<\/strong> delle attivit\u00e0. Durante l'assegnazione, un'attivit\u00e0 con priorit\u00e0 pi\u00f9 alta pu\u00f2 preemption, cio\u00e8 fermare un'attivit\u00e0 con priorit\u00e0 pi\u00f9 bassa, se non ci sono pi\u00f9 minion disponibili. Allo stesso tempo, l'attivit\u00e0 a bassa priorit\u00e0 probabilmente rimarr\u00e0 non assegnata, cio\u00e8 non ci sar\u00e0 pi\u00f9 un minion adeguato con risorse sufficienti disponibili.<\/p>\n<p><\/p>\n<p>Nella nostra gerarchia \u00e8 molto semplice impostare tale priorit\u00e0 di preemption, affinch\u00e8 le attivit\u00e0 prod e batch preemptano o fermino le attivit\u00e0 idle, ma non tra di loro, impostando per idle una priorit\u00e0 pari a 200. Cos\u00ec come nel caso della priorit\u00e0 di assegnazione, possiamo utilizzare la nostra gerarchia per descrivere regole pi\u00f9 complesse. Ad esempio, indichiamo che sacrificiamo la funzione musicale se non abbiamo abbastanza risorse per il portale web principale, impostando una priorit\u00e0 pi\u00f9 bassa per i nodi corrispondenti: 10.<\/p>\n<p><\/p>\n<h2 id=\"avarii-dc-celikom\">Incidenti del DC in generale<\/h2>\n<p><\/p>\n<p>Perch\u00e9 potrebbe guastarsi l'intero data center? Cause naturali. C'era un buon post su come <noindex><a rel=\"nofollow\" href=\"https:\/\/habrahabr.ru\/company\/dataline\/blog\/333578\/\">l'uragano ha influenzato il funzionamento del data center<\/a><\/noindex>. Gli homeless possono essere considerati un elemento distruttivo, dato che hanno bruciato un giorno la fibra ottica in un collettore, causando la completa perdita di connettivit\u00e0 del data center con gli altri siti. Le cause di guasto possono includere anche il fattore umano: un operatore pu\u00f2 emettere un comando tale da far cadere l'intero data center. Questo pu\u00f2 succedere a causa di un grosso bug. In generale, i data center si bloccano \u2014 non \u00e8 una rarit\u00e0. Da noi, ci\u00f2 accade una volta ogni pochi mesi. <\/p>\n<p><\/p>\n<p>Ecco cosa facciamo per evitare che nessuno #okzhivi pubblichi sui Twitter.<\/p>\n<p><\/p>\n<p>La prima strategia \u00e8 l'isolamento. Ogni istanza di one-cloud \u00e8 isolata e pu\u00f2 gestire solo le macchine di un singolo data center. Quindi, la perdita di un cloud a causa di bug o di un comando incorretto dell'operatore comporta solo la perdita di un data center. Siamo pronti a questo: abbiamo una politica di riserva dove le repliche di applicazioni e dati sono distribuite in tutti i data center. Utilizziamo database a prova di guasto e testiamo regolarmente i malfunzionamenti.<br \/>\nPoich\u00e9 oggi abbiamo quattro data center, ci sono quindi quattro istanze separate e completamente isolate di one-cloud.<\/p>\n<p><\/p>\n<p>Questo approccio non solo protegge dai guasti fisici, ma pu\u00f2 anche tutelare dagli errori degli operatori.<\/p>\n<p><\/p>\n<p>Cosa si pu\u00f2 fare ancora riguardo al fattore umano? Quando un operatore d\u00e0 al cloud un comando strano o potenzialmente pericoloso, potrebbe improvvisamente essere richiesto di risolvere un piccolo compito per verificare quanto bene ha pensato. Ad esempio, se si tratta di un arresto di massa di molte repliche o semplicemente di un comando strano \u2014 ridurre il numero di repliche o cambiare il nome dell'immagine, non solo il numero di versione nel nuovo 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 operativo di livello data center in 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\">Conclusioni<\/h2>\n<p><\/p>\n<p>Caratteristiche distintive di one-cloud: <\/p>\n<p><\/p>\n<ul>\n<li><strong>Schema gerarchico e chiaro per la denominazione di servizi e contenitori<\/strong>, che consente di capire molto rapidamente di cosa si tratta, a cosa \u00e8 correlato e come funziona e chi ne \u00e8 responsabile. <\/li>\n<li>Applichiamo la nostra <strong>tecnica di combinazione di attivit\u00e0 prod- e batch-<\/strong>sui minions, per aumentare l'efficienza dell'uso condiviso delle macchine. Invece di cpuset, utilizziamo quote CPU, shares, politiche del piano di CPU e Linux QoS.<\/li>\n<li>Non siamo riusciti a isolare completamente i contenitori che lavorano su una singola macchina, ma la loro influenza reciproca rimane entro il 20%.<\/li>\n<li>L'organizzazione dei servizi in una gerarchia aiuta nella rimozione automatica delle emergenze tramite <strong>priorit\u00e0 di collocazione e di espulsione.<\/strong>.<\/li>\n<\/ul>\n<p><\/p>\n<h2 id=\"chavo\">FAQ<\/h2>\n<p><\/p>\n<p>Perch\u00e9 non abbiamo adottato una soluzione pronta.<\/p>\n<p><\/p>\n<ul>\n<li>Diverse classi di isolamento dei compiti richiedono logiche diverse per la distribuzione sui mini-server. Se i compiti di produzione possono essere distribuiti semplicemente riservando risorse, i compiti batch e idle devono essere distribuiti monitorando l'effettivo utilizzo delle risorse sui mini-server. <\/li>\n<li>La necessit\u00e0 di considerare le risorse consumate dai compiti, come: \n<ul>\n<li>la larghezza di banda della rete;<\/li>\n<li>tipi e \u2018spindles\u2019 dei dischi.<\/li>\n<\/ul>\n<\/li>\n<li>La necessit\u00e0 di specificare le priorit\u00e0 dei servizi durante la risoluzione di guasti, diritti e quote delle squadre sulle risorse, che pu\u00f2 essere gestita tramite code gerarchiche in one-cloud.<\/li>\n<li>La necessit\u00e0 di avere nomi umani per i container per ridurre il tempo di reazione a guasti e incidenti.<\/li>\n<li>L'impossibilit\u00e0 di implementare simultaneamente il Service Discovery ovunque; necessit\u00e0 di convivere a lungo con compiti distribuiti su server fisici, il che \u00e8 risolvibile tramite indirizzi IP 'statici' seguiti dai container, e conseguentemente la necessit\u00e0 di un'integrazione unica con una grande infrastruttura di rete.<\/li>\n<\/ul>\n<p><\/p>\n<p>Tutte queste funzioni richiederebbero significative modifiche alle soluzioni esistenti, e valutando il volume di lavoro, abbiamo capito che avremmo potuto sviluppare la nostra soluzione con circa lo stesso impiego di sforzi. Tuttavia, la nostra soluzione sar\u00e0 decisamente pi\u00f9 semplice da gestire e sviluppare: non contiene astrazioni non necessarie che supportano funzionalit\u00e0 superflue. <\/p>\n<p><\/p>\n<p>A coloro che leggono queste ultime righe, - grazie per la pazienza e l'attenzione!<\/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.1.1 - 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\/it\/blog\/administrirovanie\/one-cloud-os-urovnya-data-czentra-v-odnoklassnikah\" \/>\n\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 5.0.1.1\" \/>\n\t\t<meta property=\"og:locale\" content=\"it_IT\" \/>\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\/it\/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 - Un sistema operativo a livello di data center su Odnoklassniki | ProHoster","description":"Aloha, gente!","canonical_url":"https:\/\/prohoster.info\/it\/blog\/administrirovanie\/one-cloud-os-urovnya-data-czentra-v-odnoklassnikah","robots":"max-image-preview:large","keywords":"","webmasterTools":{"miscellaneous":""},"schema":null,"og:locale":"it_IT","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\/it\/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\/it\/wp-json\/wp\/v2\/posts\/84114","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/comments?post=84114"}],"version-history":[{"count":0,"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/posts\/84114\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/media\/84115"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/media?parent=84114"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/categories?post=84114"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/tags?post=84114"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}