{"id":34841,"date":"2019-10-31T22:00:43","date_gmt":"2019-10-31T19:00:43","guid":{"rendered":"https:\/\/prohoster.info\/blog\/avtomatizatsiya-zameny-diskov-s-pomoshhyu-ansible\/"},"modified":"2019-10-31T22:00:43","modified_gmt":"2019-10-31T19:00:43","slug":"avtomatizatsiya-zameny-diskov-s-pomoshhyu-ansible","status":"publish","type":"post","link":"https:\/\/prohoster.info\/it\/blog\/administrirovanie\/avtomatizatsiya-zameny-diskov-s-pomoshhyu-ansible","title":{"rendered":"Automazione della sostituzione dei dischi tramite Ansible","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<p><img decoding=\"async\" alt=\"Automazione della sostituzione dei dischi tramite Ansible\" src=\"\/wp-content\/uploads\/2019\/06\/c60a2326ab13e7766eafda3ae5ac39c5.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nCiao a tutti. Lavoro come amministratore di sistema senior in OK e sono responsabile del funzionamento stabile del portale. Voglio raccontarvi come abbiamo costruito il processo di sostituzione automatica dei dischi e poi come abbiamo escluso l'amministratore da questo processo, sostituendolo con un bot.<\/p>\n<p>Questo articolo \u00e8 una sorta di traslitterazione <noindex><a rel=\"nofollow\" href=\"https:\/\/www.youtube.com\/watch?v=5WhbG3FQveE&amp;list=FLKN7KW1sxju7fWJvKuyKxEQ\">intervento<\/a><\/noindex> a HighLoad+ 2018<br \/>\n<noindex><a rel=\"nofollow\" name=\"habracut\"><\/a><\/noindex><\/p>\n<h2>Costruzione del processo di sostituzione dei dischi<\/h2>\n<p><\/p>\n<h3>Iniziamo con un po' di numeri<\/h3>\n<p>\nOK \u00e8 un servizio enorme che viene utilizzato da milioni di persone. \u00c8 sostenuto da circa 7.000 server, situati in 4 diversi data center. Nei server ci sono pi\u00f9 di 70.000 dischi. Se li sovrapponiamo, si ottiene una torre alta pi\u00f9 di 1 km. <\/p>\n<p>I dischi rigidi sono il componente del server che si guasta pi\u00f9 frequentemente. Con questi volumi, ci troviamo a dover cambiare circa 30 dischi a settimana, e questa procedura \u00e8 diventata una routine piuttosto sgradevole.<\/p>\n<p><img decoding=\"async\" alt=\"Automazione della sostituzione dei dischi tramite Ansible\" src=\"\/wp-content\/uploads\/2019\/06\/5e915e9077994efcc4e74a26fc6286fa.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<\/p>\n<h3>Incidenti<\/h3>\n<p>\nNella nostra azienda \u00e8 stato implementato un completo gestione degli incidenti. Ogni incidente viene registrato in Jira e poi risolto e analizzato. Se l'incidente ha avuto un impatto sugli utenti, ci riuniamo per discutere come reagire pi\u00f9 rapidamente in tali casi, come ridurre l'impatto e, naturalmente, come prevenire il ripetersi.<\/p>\n<p>I dispositivi di memorizzazione non fanno eccezione. La loro condizione \u00e8 monitorata da Zabbix. Monitoriamo i messaggi in Syslog per errori di scrittura\/lettura, analizziamo lo stato dei RAID HW\/SW, teniamo d'occhio SMART, calcoliamo l'usura per gli SSD. <\/p>\n<h3>Come venivano cambiati i dischi in passato<\/h3>\n<p>\nQuando in Zabbix si attiva un trigger, viene creato un incidente in Jira e assegnato automaticamente agli ingegneri responsabili nei data center. Lo facciamo per tutti gli incidenti HW, cio\u00e8 quelli che richiedono qualche lavoro fisico con l'hardware nel data center. <br \/>\nL'ingegnere del data center \u00e8 la persona che gestisce le questioni relative all'hardware, \u00e8 responsabile dell'installazione, della manutenzione e dello smantellamento dei server. Una volta ricevuto il ticket, l'ingegnere inizia a lavorare. Nelle scaffalature dei dischi, sostituisce i dischi da solo. Ma se non ha accesso all'apparecchiatura necessaria, l'ingegnere si rivolge agli amministratori di sistema di turno per assistenza. Prima di tutto, \u00e8 necessario escludere il disco dalla rotazione. Per fare ci\u00f2, \u00e8 necessario apportare le modifiche necessarie sul server, fermare le applicazioni e smontare il disco.<\/p>\n<p>L'amministratore di sistema di turno \u00e8 responsabile del funzionamento dell'intero portale durante il proprio turno di lavoro. Indaga sugli incidenti, esegue riparazioni e assiste gli sviluppatori nell'esecuzione di piccoli compiti. Non si occupa solo dei dischi rigidi.<\/p>\n<p>In passato, gli ingegneri dei data center comunicavano con l'amministratore di sistema tramite chat. Gli ingegneri inviavano link ai ticket di Jira, l'amministratore li esaminava e registrava il lavoro su un taccuino. Tuttavia, per tali compiti le chat risultavano poco pratiche: le informazioni non erano strutturate e si perdevano rapidamente. Inoltre, l'amministratore poteva semplicemente allontanarsi dal computer e non rispondere alle richieste per un certo periodo, mentre l'ingegnere era davanti al server con un pacchetto di dischi e aspettava.<\/p>\n<p>Ma la cosa peggiore era che gli amministratori non vedevano l'intero quadro: quali incidenti riguardavano i dischi esistenti e dove potrebbe sorgere un problema. Questo \u00e8 dovuto al fatto che tutti gli incidenti hardware vengono gestiti dagli ingegneri. Certo, si potrebbe visualizzare tutti gli incidenti sul dashboard dell'amministratore. Ma ce ne sono davvero troppi e l'amministratore veniva coinvolto solo in alcuni di essi.<\/p>\n<p>Inoltre, l'ingegnere non poteva stabilire correttamente le priorit\u00e0, poich\u00e9 non sapeva nulla riguardo allo scopo dei singoli server o alla distribuzione delle informazioni tra i dispositivi di archiviazione.<\/p>\n<h3>Nuova procedura di sostituzione<\/h3>\n<p>\nLa prima cosa che abbiamo fatto \u00e8 stata creare un tipo separato di incidente per tutti gli incidenti riguardanti i dischi denominato \"HW-disco\" e aggiungere ai ticket i campi \"nome del dispositivo a blocchi\", \"dimensione\" e \"tipo di disco\", affinch\u00e9 queste informazioni fossero conservate nel ticket e non dovessimo continuamente scambiarle nella chat. <\/p>\n<p><img decoding=\"async\" alt=\"Automazione della sostituzione dei dischi tramite Ansible\" src=\"\/wp-content\/uploads\/2019\/06\/c4526bf668e31d90e0fbd061de44f1a7.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\nAbbiamo inoltre concordato che all'interno di un singolo incidente sostituiremo solo un disco. Questo ha semplificato notevolmente il processo di automazione, la raccolta delle statistiche e il lavoro futuro. <\/p>\n<p>Inoltre, abbiamo aggiunto il campo \"amministratore responsabile\". Qui viene automaticamente inserito l'amministratore di sistema di turno. Questo \u00e8 molto comodo, perch\u00e9 ora l'ingegnere vede sempre chi \u00e8 il responsabile. Non \u00e8 necessario consultare il calendario e cercare. Proprio grazie a questo campo, \u00e8 stato possibile visualizzare nel dashboard dell'amministratore i ticket in cui potrebbe esserci bisogno del suo aiuto.<\/p>\n<p><img decoding=\"async\" alt=\"Automazione della sostituzione dei dischi tramite Ansible\" src=\"\/wp-content\/uploads\/2019\/06\/5097e5dcca1fddd68d1e5f296c09f60a.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\nAffinch\u00e9 tutti i partecipanti potessero trarne il massimo beneficio dalle novit\u00e0 introdotte, abbiamo creato filtri e dashboard, e abbiamo spiegato loro il funzionamento. Quando le persone comprendono i cambiamenti, non si distaccano da essi come se si trattasse di qualcosa di superfluo. Per un ingegnere \u00e8 importante conoscere il numero del rack in cui si trova il server, le dimensioni e il tipo di disco. Un amministratore deve, prima di tutto, capire che tipo di gruppo di server ha a che fare e quale potrebbe essere l'effetto della sostituzione del disco.<\/p>\n<p>Avere campi e la loro visualizzazione \u00e8 conveniente, ma non ci ha liberato dalla necessit\u00e0 di utilizzare le chat. A tale scopo, \u00e8 stato necessario modificare il processo lavorativo. <\/p>\n<p>Prima era cos\u00ec:<\/p>\n<p><img decoding=\"async\" alt=\"Automazione della sostituzione dei dischi tramite Ansible\" src=\"\/wp-content\/uploads\/2019\/06\/2b79cdb7ec88b5ae3d2917ad8b164c6d.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\nOggi gli ingegneri continuano a lavorare in questo modo quando non hanno bisogno dell'assistenza di un amministratore.<\/p>\n<p>La prima cosa che abbiamo fatto \u00e8 stata introdurre un nuovo stato <b>Investigate<\/b>. In questo stato si trova il ticket quando l'ingegnere non ha ancora deciso se avr\u00e0 bisogno di un amministratore o meno. Attraverso questo stato, l'ingegnere pu\u00f2 trasferire il ticket all'amministratore. Inoltre, utilizziamo questo stato per contrassegnare i ticket in cui \u00e8 necessaria la sostituzione del disco, ma il disco stesso non \u00e8 disponibile sul sito. Questo pu\u00f2 verificarsi nel caso di CDN e siti remoti.<\/p>\n<p>Abbiamo anche aggiunto lo stato <b>Pronto<\/b>. In questo stato, il ticket viene trasferito dopo la sostituzione del disco. Ovvero, tutto \u00e8 gi\u00e0 stato fatto, ma sul server HW\/SW RAID \u00e8 in fase di sincronizzazione. Questo pu\u00f2 richiedere abbastanza tempo.<\/p>\n<p>Se l'amministratore \u00e8 coinvolto nel lavoro, lo schema si complica leggermente.<\/p>\n<p><img decoding=\"async\" alt=\"Automazione della sostituzione dei dischi tramite Ansible\" src=\"\/wp-content\/uploads\/2019\/06\/5b6aacbb0d4049e62e7cb9ee28eb6498.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\nDallo stato <b>Apri<\/b> il ticket pu\u00f2 essere trasferito sia dall'amministratore di sistema che dall'ingegnere. Nello stato <b>In progress<\/b> l'amministratore estrae il disco dalla rotazione affinch\u00e9 l'ingegnere possa semplicemente estrarlo: accende la luce, smonta il disco, ferma le applicazioni, a seconda del gruppo specifico di server.<\/p>\n<p>Successivamente, il ticket viene trasferito a <b>Ready to change<\/b>: questo \u00e8 un segnale per l'ingegnere che il disco pu\u00f2 essere rimosso. Tutti i campi in Jira sono gi\u00e0 stati compilati, e l'ingegnere sa quale tipo e dimensione di disco \u00e8 richiesto. Questi dati vengono inseriti automaticamente nello stato precedente o dall'amministratore.<\/p>\n<p>Dopo la sostituzione del disco, il ticket viene trasferito allo stato <b>Changed<\/b>. Viene verificato che sia stato inserito il disco giusto, si esegue la configurazione, si avvia l'applicazione e si eseguono alcune operazioni per il recupero dei dati. Inoltre, il ticket pu\u00f2 essere trasferito allo stato <b>Pronto<\/b>, in questo caso la responsabilit\u00e0 rimane all'amministratore, poich\u00e9 \u00e8 stato lui a introdurre il disco nella rotazione. Lo schema completo \u00e8 il seguente.<\/p>\n<p><img decoding=\"async\" alt=\"Automazione della sostituzione dei dischi tramite Ansible\" src=\"\/wp-content\/uploads\/2019\/06\/32f8d488e2ff6a28a3341114b66de0a3.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\nL'aggiunta di nuovi campi ha notevolmente semplificato la nostra vita. I ragazzi hanno iniziato a lavorare con informazioni strutturate, ed \u00e8 diventato chiaro cosa e quando deve essere fatto. Le priorit\u00e0 sono diventate molto pi\u00f9 pertinenti, poich\u00e9 ora vengono impostate dall'amministratore.<\/p>\n<p>Non c'\u00e8 pi\u00f9 bisogno di chat. Certo, l'amministratore pu\u00f2 scrivere all'ingegnere \"qui \u00e8 necessario sostituire pi\u00f9 velocemente\", o \"\u00e8 gi\u00e0 sera, riuscirai a sostituire?\". Ma non comunichiamo pi\u00f9 quotidianamente in chat riguardo a queste questioni.<\/p>\n<p>I dischi sono stati cambiati a gruppi. Se l'amministratore arriva al lavoro un po' prima, ha del tempo libero, e non \u00e8 successo nulla, pu\u00f2 preparare una serie di server per la sostituzione: impostare i campi, rimuovere i dischi dalla rotazione e trasferire il compito all'ingegnere. L'ingegnere arriva un po' pi\u00f9 tardi nel data center, vede il compito, prende i dischi necessari dal magazzino e li sostituisce immediatamente. Di conseguenza, la velocit\u00e0 di sostituzione \u00e8 aumentata.<\/p>\n<h3>Esperienza acquisita nella costruzione del Workflow<\/h3>\n<p><\/p>\n<ul>\n<li><b>Nella costruzione della procedura \u00e8 necessario raccogliere informazioni da diverse fonti.<\/b><br \/>\nAlcuni dei nostri amministratori non sapevano che l'ingegnere sostituisce i dischi da solo. Alcuni pensavano che la sincronizzazione del RAID MD fosse gestita da ingegneri, anche se alcuni di loro non avevano accesso per farlo. Alcuni ingegneri senior lo facevano, ma non sempre, perch\u00e9 il processo non era descritto da nessuna parte.<\/li>\n<li><b>La procedura deve essere semplice e chiara.<\/b><br \/>\n\u00c8 difficile per una persona tenere a mente numerosi passaggi. Gli stati pi\u00f9 importanti e vicini in Jira devono essere visualizzati sulla schermata principale. Possono essere rinominati, ad esempio, In progress lo chiamiamo Pronto per cambiare. Altri stati possono essere nascosti nel menu a discesa, in modo che non diano fastidio. Ma \u00e8 meglio non limitare le persone, dare loro la possibilit\u00e0 di fare la transizione.<br \/>\nSpiega il valore delle novit\u00e0. Quando le persone capiscono, accettano meglio la nuova procedura. Per noi era molto importante che le persone non cliccassero su tutto il processo, ma lo seguissero. Successivamente abbiamo costruito su questo l'automazione.<\/li>\n<li><b>Aspettare, analizzare, capire.<\/b><br \/>\nCi sono voluti circa un mese per costruire la procedura, la realizzazione tecnica, incontri e discussioni. E per l'implementazione \u2014 pi\u00f9 di tre mesi. Ho visto come le persone iniziano gradualmente a utilizzare la novit\u00e0. Nelle fasi iniziali c'era molto scetticismo. Ma questo non dipendeva affatto dalla procedura in s\u00e9, dalla sua realizzazione tecnica. Ad esempio, un amministratore utilizzava non Jira, ma un plugin di Jira in Confluence, e alcune cose non erano per lui disponibili. Gli abbiamo mostrato Jira, e la produttivit\u00e0 dell'amministratore \u00e8 aumentata sia nei compiti generali sia nelle sostituzioni dei dischi.<\/li>\n<\/ul>\n<p><\/p>\n<h2>Automazione della sostituzione dei dischi<\/h2>\n<p>\nCi siamo avvicinati all'automazione della sostituzione dei dischi pi\u00f9 volte. Avevamo gi\u00e0 realizzato script, ma tutti funzionavano o in modalit\u00e0 interattiva o manuale, richiedevano un avvio. Solo dopo l'implementazione della nuova procedura abbiamo capito che proprio questo ci mancava.<\/p>\n<p>Ora che il processo di sostituzione \u00e8 suddiviso in fasi, ognuna con un esecutore designato e un elenco di azioni, possiamo implementare l'automazione progressivamente, invece di farlo tutto in una volta. Ad esempio, la fase pi\u00f9 semplice \u2014 Ready (verifica della sincronizzazione RAID\/dati) pu\u00f2 essere facilmente delegata a un bot. Quando il bot avr\u00e0 acquisito un po' di esperienza, possiamo affidargli compiti pi\u00f9 complessi \u2014 come l'introduzione del disco in rotazione, ecc.<\/p>\n<h3>Zoo di configurazioni<\/h3>\n<p>\nPrima di parlare del bot, facciamo un breve excursus nel nostro zoo di installazioni. Prima di tutto, ci\u00f2 \u00e8 dovuto alle dimensioni enormi della nostra infrastruttura. In secondo luogo, cerchiamo di abbinare una configurazione hardware ottimale per ogni servizio. Abbiamo circa 20 modelli di RAID hardware, principalmente LSI e Adaptec, ma ci sono anche HP e DELL di varie versioni. Ogni controller RAID ha il proprio strumento di gestione. Il set di comandi e l'output possono variare da versione a versione per ogni controller RAID. Dove non vengono utilizzati HW-RAID, potrebbe esserci mdraid.<\/p>\n<p>Praticamente tutte le nuove installazioni vengono effettuate senza riserva di disco. Cerchiamo di non utilizzare pi\u00f9 RAID hardware e software, poich\u00e9 riserviamo i nostri sistemi a livello di data center, non di server. Ma ci sono molti server legacy che devono essere supportati.<\/p>\n<p>In alcuni casi, i dischi nei controller RAID vengono utilizzati come dispositivi raw, in altri si utilizza JBOD. Ci sono configurazioni con un singolo disco di sistema nel server, e se deve essere sostituito, \u00e8 necessario reinstallare il server con il sistema operativo e le applicazioni, inclusi gli stessi versioni, poi aggiungere i file di configurazione e avviare le applicazioni. Ci sono anche molti gruppi di server, in cui il backup avviene non a livello del sottosistema disco, ma direttamente nelle stesse applicazioni.<\/p>\n<p>In totale, abbiamo oltre 400 gruppi unici di server, su cui funzionano circa 100 diverse applicazioni. Per coprire una cos\u00ec vasta gamma di varianti, avevamo bisogno di uno strumento di automazione multifunzionale. Preferibilmente con un DSL semplice, in modo che potesse essere mantenuto anche da chi non l'ha scritto.<\/p>\n<p>Abbiamo scelto Ansible perch\u00e9 \u00e8 agentless: non era necessario preparare l'infrastruttura, avvio rapido. Inoltre, \u00e8 scritto in Python, che \u00e8 considerato uno standard nel team.<\/p>\n<h3>Schema generale<\/h3>\n<p>\nDiamo un'occhiata allo schema generale di automazione prendendo come esempio un incidente. Zabbix rileva che il disco sdb \u00e8 guasto, si attiva un trigger, viene creato un ticket in Jira. L'amministratore lo controlla, capisce che non \u00e8 un duplicato o un false positive, cio\u00e8 che il disco deve essere sostituito, e trasferisce il ticket in In progress.<\/p>\n<p><img decoding=\"async\" alt=\"Automazione della sostituzione dei dischi tramite Ansible\" src=\"\/wp-content\/uploads\/2019\/06\/673df0fe9600bc65633841222f436d37.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\nL'applicazione DiskoBot, scritta in Python, interroga periodicamente Jira per nuovi ticket. Nota che \u00e8 apparso un nuovo ticket In progress, si attiva il thread corrispondente, che avvia il playbook in Ansible (questo viene fatto per ogni stato in Jira). In questo caso viene avviato Prepare2change.<\/p>\n<p>Ansible viene inviato all'host, estrae il disco dalla rotazione e riporta lo stato all'applicazione tramite Callbacks. <\/p>\n<p><img decoding=\"async\" alt=\"Automazione della sostituzione dei dischi tramite Ansible\" src=\"\/wp-content\/uploads\/2019\/06\/8bfc13129f8deca640eb63ea81f616c7.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\nIn base ai risultati, il bot trasferisce automaticamente il ticket in Ready to change. L'ingegnere riceve una notifica e si prepara a sostituire il disco, dopodich\u00e9 trasferisce il ticket in Changed. <\/p>\n<p><img decoding=\"async\" alt=\"Automazione della sostituzione dei dischi tramite Ansible\" src=\"\/wp-content\/uploads\/2019\/06\/eeda06b6966f435e2172d3f9c61b341e.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\nSecondo lo schema sopra descritto, il ticket torna al bot, che avvia un altro playbook, si connette all'host e reinserisce il disco nella rotazione. Il bot chiude il ticket. Evviva!<\/p>\n<p><img decoding=\"async\" alt=\"Automazione della sostituzione dei dischi tramite Ansible\" src=\"\/wp-content\/uploads\/2019\/06\/51b8c7050b0c10c16ad6a6d4974c3ebf.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\nOra parliamo di alcuni componenti del sistema.<\/p>\n<h3>Diskobot<\/h3>\n<p>\nQuesta applicazione \u00e8 scritta in Python. Seleziona ticket da Jira in base a JQL. A seconda dello stato del ticket, esso viene inviato al corrispondente gestore, il quale a sua volta avvia il playbook Ansible corrispondente allo stato.<\/p>\n<p>JQL e gli intervalli di interrogazione sono definiti nel file di configurazione dell'applicazione.<\/p>\n<pre><code class=\"plaintext\">jira_states:\n  investigate:\n    jql: '\u2026 stato = Aperto e \"Dimensione Disco\" \u00e8 VUOTO'\n    interval: 180\n\n  inprogress:\n    jql: '\u2026 e \"Dimensione Disco\" non \u00e8 VUOTO e \"Nome Dispositivo\" non \u00e8 VUOTO'\n \n  ready:\n    jql: '\u2026 e (etichette non in (\"dbot_ignore\") o etichette \u00e8 VUOTO)'\n    interval: 7200\n<\/code><\/pre>\n<p>\nAd esempio, tra i ticket nello stato In progress, vengono selezionati solo quelli in cui sono compilati i campi Dimensione disco e Nome dispositivo. Nome dispositivo \u00e8 il nome del dispositivo a blocchi necessario per eseguire il playbook. Dimensione disco \u00e8 necessaria affinch\u00e9 l'ingegnere sappia che dimensione di disco \u00e8 necessario.<\/p>\n<p>E tra i ticket con stato Ready vengono filtrati i ticket con etichetta dbot_ignore. A proposito, utilizziamo le etichette di Jira sia per tale filtraggio che per contrassegnare i ticket duplicati e raccogliere statistiche.<\/p>\n<p>In caso di errore del playbook, Jira assegna l'etichetta dbot_failed in modo da poter esaminare in seguito. <\/p>\n<h3>Interazione con Ansible<\/h3>\n<p>\nL'applicazione interagisce con Ansible tramite <noindex><a rel=\"nofollow\" href=\"https:\/\/docs.ansible.com\/ansible\/latest\/dev_guide\/developing_api.html\">Ansible Python API<\/a><\/noindex>. Nel playbook_executor passiamo il nome del file e un insieme di variabili. Questo consente di mantenere il progetto Ansible in forma di normali file yml, invece di descriverlo in codice Python. <\/p>\n<p>Inoltre, in Ansible tramite *extra_vars* vengono passati il nome del dispositivo a blocchi, lo stato del ticket, e anche callback_url, in cui \u00e8 incorporato il chiave dell'issue \u2014 che viene utilizzato per la callback in HTTP.<\/p>\n<p>Per ogni esecuzione viene generato un inventario temporaneo, composto da un singolo host e un gruppo che include questo host, affinch\u00e9 vengano applicati group_vars.<\/p>\n<p>Ecco un esempio di task in cui \u00e8 implementato il callback HTTP.<\/p>\n<p>I risultati dell'esecuzione dei playbook vengono ottenuti tramite callback(-s). Questi sono di due tipi:<\/p>\n<ul>\n<li><noindex><a rel=\"nofollow\" href=\"https:\/\/docs.ansible.com\/ansible\/latest\/plugins\/callback.html\">Ansible callback plugin<\/a><\/noindex>, fornisce dati sui risultati dell'esecuzione del playbook. Descrive i task che sono stati avviati, completati con successo o meno. Questo callback viene chiamato al termine dell'esecuzione del playbook.<\/li>\n<li>Callback HTTP per ottenere informazioni durante l'esecuzione del playbook. Nel task Ansible eseguiamo una richiesta POST\/GET verso la nostra applicazione.<\/li>\n<\/ul>\n<p>\nTramite i callback HTTP vengono passate le variabili che sono state definite durante l'esecuzione del playbook e che vogliamo conservare e utilizzare nei successivi run. Questi dati vengono scritti in sqlite.<\/p>\n<p>Inoltre, attraverso il callback HTTP lasciamo commenti e cambiamo lo stato del ticket.<\/p>\n<p><b class=\"spoiler_title\">Callback HTTP<\/b><\/p>\n<pre><code class=\"plaintext\"># Make callback to Diskobot App\n# Variables:\n#    callback_post_body: # A dict with follow keys. All keys are optional\n#       msg: If exist it would be posted to Jira as comment\n#       data: If exist it would be saved in Incident.variables\n#       desire_state: Set desire_state for incident\n#       status: If exist Proceed issue to that status\n\n  - name: Callback to Diskobot app (jira comment\/status)\n    uri:\n      url: \"{{ callback_url }}\/{{ devname }}\"\n      user: \"{{ diskobot_user }}\"\n      password: \"{{ diskobot_pass }}\"\n      force_basic_auth: True\n      method: POST\n      body: \"{{ callback_post_body | to_json }}\"\n      body_format: json\n    delegate_to: 127.0.0.1\n<\/code><\/pre>\n<p>Come molte altre attivit\u00e0 simili, l'abbiamo estratto in un file comune e lo includiamo se necessario, per non ripeterlo continuamente nei playbook. Qui figura il callback_url, in cui sono incorporati la chiave del problema e il nome dell'host. Quando Ansible esegue questa richiesta POST, il bot comprende che \u00e8 arrivata nell'ambito di un certo incidente.<\/p>\n<p>Ecco un esempio da un playbook in cui abbiamo espulso un disco dall'unit\u00e0 MD:<\/p>\n<pre><code class=\"plaintext\">  # Save mdadm configuration\n  - include: common\/callback.yml\n    vars:\n      callback_post_body:\n        status: 'Ready to change'\n        msg: \"Removed disk from mdraid {{ mdadm_remove_disk.msg | comment_jira }}\"\n        data:\n          mdadm_data: \"{{ mdadm_remove_disk.removed }}\"\n          parted_info: \"{{ parted_info | default() }}\"\n    when:\n      - mdadm_remove_disk | changed\n      - mdadm_remove_disk.removed\n<\/code><\/pre>\n<p>\nQuesto compito trasforma il ticket Jira nello stato \"Pronto per il cambio\" e aggiunge un commento. Inoltre, nella variabile mdam_data viene salvato l'elenco dei dispositivi md da cui \u00e8 stato rimosso il disco, mentre in parted_info si trova il dump della partizione da parted. <\/p>\n<p>Quando l'ingegnere inserisce un nuovo disco, possiamo utilizzare queste variabili per ripristinare il dump delle partizioni e anche per registrare il disco nelle unit\u00e0 md da cui \u00e8 stato rimosso.<\/p>\n<h3>Modalit\u00e0 di controllo Ansible<\/h3>\n<p>\nEra spaventoso attivare l'automazione. Quindi abbiamo deciso di eseguire tutti i playbook in modalit\u00e0 <br \/>\n<noindex><a rel=\"nofollow\" href=\"https:\/\/docs.ansible.com\/ansible\/latest\/user_guide\/playbooks_checkmode.html\">dry run<\/a><\/noindex>, in cui Ansible non esegue alcuna azione sui server, ma semplicemente le emula. <\/p>\n<p>Tale esecuzione viene gestita tramite un modulo di callback separato e il risultato dell'esecuzione del playbook viene salvato in Jira sotto forma di commento.<\/p>\n<p><img decoding=\"async\" alt=\"Automazione della sostituzione dei dischi tramite Ansible\" src=\"\/wp-content\/uploads\/2019\/06\/b02d7f1dc428f2797ae8556cd496b115.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nInnanzitutto, questo ha permesso di convalidare il funzionamento del bot e dei playbook. In secondo luogo, ha aumentato la fiducia degli amministratori nel bot. <\/p>\n<p>Una volta che abbiamo superato la convalida e capito che si poteva eseguire Ansible non solo in modalit\u00e0 dry run, abbiamo creato in Jira il pulsante Esegui Diskobot per avviare lo stesso playbook con le stesse variabili sullo stesso host, ma in modalit\u00e0 normale. <\/p>\n<p>Inoltre, il pulsante viene utilizzato per rieseguire il playbook in caso di fallimento.<\/p>\n<h3>Struttura dei Playbook<\/h3>\n<p>\nHo gi\u00e0 accennato che a seconda dello stato del ticket Jira, il bot avvia diversi playbook.<\/p>\n<p>In primo luogo, cos\u00ec \u00e8 molto pi\u00f9 semplice organizzare l'ingresso. <br \/>\nIn secondo luogo, in alcuni casi \u00e8 semplicemente necessario. <\/p>\n<p>Ad esempio, durante la sostituzione di un disco di sistema, \u00e8 necessario prima accedere al sistema di distribuzione, creare un'attivit\u00e0 e, dopo una distribuzione corretta, il server diventa accessibile tramite ssh e possiamo installare l'applicazione. Se avessimo fatto tutto ci\u00f2 in un unico playbook, Ansible non sarebbe riuscito a eseguirlo a causa dell'inaccessibilit\u00e0 dell'host.<\/p>\n<p>Utilizziamo i ruoli Ansible per ogni gruppo di server. Qui si pu\u00f2 vedere come sono organizzati i playbook in uno di essi. <\/p>\n<p><img decoding=\"async\" alt=\"Automazione della sostituzione dei dischi tramite Ansible\" src=\"\/wp-content\/uploads\/2019\/06\/7a14035392b33f01d3182d5fff779321.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\n\u00c8 comodo perch\u00e9 \u00e8 subito chiaro dove sono collocati i vari task. In main.yml, che \u00e8 l'input per il ruolo Ansible, possiamo avere semplicemente un'include in base allo stato del ticket o task generali necessari per tutti, come l'identificazione o il recupero del token.<\/p>\n<h4>Investigation.yml<\/h4>\n<p>\nViene avviato per i ticket negli stati Investigation e Open. La cosa pi\u00f9 importante per questo playbook \u00e8 il nome del dispositivo di blocco. Questa informazione non \u00e8 sempre disponibile. <\/p>\n<p>Per ottenerla analizziamo il riassunto di Jira, l'ultimo valore dal trigger di Zabbix. Potrebbe contenere il nome del dispositivo di blocco \u2014 fortuna. Potrebbe contenere anche il mount point, in tal caso bisogna andare sul server, analizzarlo e calcolare il disco necessario. Inoltre, il trigger potrebbe fornire l'indirizzo scsi o qualche altra informazione. Ma a volte non ci sono indizi e bisogna analizzare.<\/p>\n<p>Una volta scoperto il nome del dispositivo di blocco, raccogliamo informazioni su tipo e dimensione del disco per riempire i campi in Jira. Recuperiamo inoltre informazioni sul venditore, modello, firmware, ID, SMART e inseriamo tutto ci\u00f2 nel commento del ticket Jira. L'amministratore e l'ingegnere non devono pi\u00f9 cercare questi dati. \ud83d\ude42<\/p>\n<p><img decoding=\"async\" alt=\"Automazione della sostituzione dei dischi tramite Ansible\" src=\"\/wp-content\/uploads\/2019\/06\/259bf8712c013ee00d238f111b4280fb.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<h4>prepare2change.yml<\/h4>\n<p>\nUscita del disco dalla rotazione, preparazione alla sostituzione. La fase pi\u00f9 complessa e delicata. Proprio qui si pu\u00f2 fermare un'applicazione quando non dovrebbe essere fermata. Oppure estrarre un disco che non ha abbastanza repliche, influenzando cos\u00ec gli utenti e perdendo alcuni dati. Qui abbiamo il maggior numero di controlli e notifiche in chat.<\/p>\n<p>Nel caso pi\u00f9 semplice, si tratta della rimozione del disco da HW\/MD RAID. <\/p>\n<p>In situazioni pi\u00f9 complesse (nei nostri sistemi di archiviazione), quando la mutua \u00e8 effettuata a livello applicativo, \u00e8 necessario andare all'applicazione via API, informare dell'uscita del disco, disattivarlo e avviare il ripristino.<\/p>\n<p>Stiamo attualmente migrando massivamente in <noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/company\/odnoklassniki\/blog\/346868\">cloud<\/a><\/noindex>, e se il server \u00e8 nel cloud, Diskobot si rivolge all'API del cloud, comunica che intende lavorare con questo minion \u2014 il server su cui sono in esecuzione i container \u2014 e chiede \"migra tutti i container da questo minion\". E accende anche l'illuminazione del disco, cos\u00ec l'ingegnere vede subito quale deve rimuovere.<\/p>\n<h4>changed.yml<\/h4>\n<p>\nDopo la sostituzione del disco, controlliamo innanzitutto la sua disponibilit\u00e0. <\/p>\n<p>Gli ingegneri non installano sempre nuovi dischi, quindi abbiamo aggiunto un controllo sui valori SMART che ci soddisfano.<\/p>\n<p><b class=\"spoiler_title\">Quali attributi stiamo esaminando<\/b>Conteggio settori riallocati (5) &lt; 100<br \/>\nConteggio settori in attesa (107) == 0<\/p>\n<p>Se il disco non supera il controllo, l'ingegnere viene informato per una sostituzione. Se tutto \u00e8 a posto, la luce si spegne, vengono effettuate le marcature e il disco viene inserito in rotazione.<\/p>\n<h4>ready.yml<\/h4>\n<p>\nIl caso pi\u00f9 semplice: verifica della sincronizzazione tra HW\/SW raid o conclusione della sincronizzazione dei dati nell'app.<\/p>\n<h3>API delle applicazioni<\/h3>\n<p>\nHo menzionato pi\u00f9 volte che il bot accede frequentemente alle API delle applicazioni. Certamente, non tutte le applicazioni avevano i metodi necessari, quindi \u00e8 stato necessario svilupparli. Ecco i metodi pi\u00f9 importanti che utilizziamo:<\/p>\n<ul>\n<li>Status. Stato del cluster o del disco, per capire se \u00e8 possibile lavorare con esso;\n<\/li>\n<li>Start\/stop. Attivazione\/disattivazione del disco;\n<\/li>\n<li>Migrate\/restore. Migrazione e ripristino dei dati durante e dopo la sostituzione.\n<\/li>\n<\/ul>\n<p><\/p>\n<h3>Esperienza acquisita su Ansible<\/h3>\n<p>\nAmo molto Ansible. Ma spesso, quando guardo diversi progetti open source e vedo come le persone scrivono playbook, mi sento un po' spaventato. Complessi intrecci logici di when\/loop, mancanza di flessibilit\u00e0 e idempotenza a causa del frequente utilizzo di shell\/command.<\/p>\n<p>Abbiamo deciso di semplificare tutto il pi\u00f9 possibile, sfruttando i vantaggi di Ansible: la modularit\u00e0. Al livello pi\u00f9 alto ci sono i playbook, che possono essere scritti da qualsiasi amministratore, sviluppatore esterno che conosce un po' Ansible.<\/p>\n<pre><code class=\"plaintext\">- name: Blink disk\n  become: True\n  register: locate_action\n  disk_locate:\n      locate: '{{ locate }}'\n      devname: '{{ devname }}'\n      ids: '{{ locate_ids | default(pd_id) | default(omit) }}'\n<\/code><\/pre>\n<p>Se qualche logica \u00e8 difficile da implementare nei playbook, la spostiamo in un modulo o filtro Ansible. Gli script possono essere scritti sia in Python che in qualsiasi altra lingua. <\/p>\n<p>Sono facili e veloci da scrivere. Ad esempio, il modulo di indicazione del disco, il cui esempio d'uso \u00e8 stato fornito sopra, consiste di 265 righe.<\/p>\n<p><img decoding=\"async\" alt=\"Automazione della sostituzione dei dischi tramite Ansible\" src=\"\/wp-content\/uploads\/2019\/06\/08e0384bfad24f3ee61e0643ca087852.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nAl livello pi\u00f9 basso c'\u00e8 la libreria. Per questo progetto abbiamo scritto un'applicazione separata, una sorta di astrazione sopra RAID hardware e software, che esegue le richieste appropriate. <\/p>\n<p><img decoding=\"async\" alt=\"Automazione della sostituzione dei dischi tramite Ansible\" src=\"\/wp-content\/uploads\/2019\/06\/0edda3182026ce6279bd84c99613e3d6.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nI punti di forza di Ansible sono la semplicit\u00e0 e i playbook chiari. Credo sia utile sfruttarli e non generare terribili file yaml e un'enorme quantit\u00e0 di condizioni, codice shell e loop.<\/p>\n<p>Se desiderate ripetere la nostra esperienza con Ansible API, tenete presente due cose:<\/p>\n<ul>\n<li>Non \u00e8 possibile passare un timeout a playbook_executor e in generale al playbook. C'\u00e8 un timeout per le sessioni SSH, ma non c'\u00e8 un timeout per il playbook. Se proviamo a smontare un disco che non esiste pi\u00f9 nel sistema, il playbook continuer\u00e0 a essere eseguito all'infinito, quindi \u00e8 stato necessario racchiudere il suo avvio in un wrapper separato e terminare il tutto in base al timeout.\n<\/li>\n<li>Ansible si basa su processi fork, quindi la sua API non \u00e8 thread-safe. Eseguiamo tutti i nostri playbook in modalit\u00e0 single-thread.\n<\/li>\n<\/ul>\n<p>\nIn definitiva, siamo riusciti ad automatizzare la sostituzione di circa l'80% dei dischi. In generale, la velocit\u00e0 di sostituzione \u00e8 raddoppiata. Oggi l'amministratore deve solo dare un'occhiata all'incidente e decidere se sostituire il disco oppure no, per poi effettuare un clic.<\/p>\n<p>Ma ora stiamo iniziando a incontrare un altro problema: alcuni nuovi amministratori non sanno come sostituire i dischi. \ud83d\ude42<br \/>\n<br \/>Fonte: <a content=\"nofollow\" rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/odnoklassniki\/blog\/452110\/\">habr.com<\/a><\/p>","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"excerpt":{"rendered":"<p>\u0412\u0441\u0435\u043c \u043f\u0440\u0438\u0432\u0435\u0442. \u042f \u0440\u0430\u0431\u043e\u0442\u0430\u044e \u0432\u0435\u0434\u0443\u0449\u0438\u043c \u0441\u0438\u0441\u0442\u0435\u043c\u043d\u044b\u043c \u0430\u0434\u043c\u0438\u043d\u0438\u0441\u0442\u0440\u0430\u0442\u043e\u0440\u043e\u043c \u0432 \u041e\u041a \u0438 \u043e\u0442\u0432\u0435\u0447\u0430\u044e \u0437\u0430 \u0441\u0442\u0430\u0431\u0438\u043b\u044c\u043d\u0443\u044e \u0440\u0430\u0431\u043e\u0442\u0443 \u043f\u043e\u0440\u0442\u0430\u043b\u0430. \u0425\u043e\u0447\u0443 \u0440\u0430\u0441\u0441\u043a\u0430\u0437\u0430\u0442\u044c \u043e \u0442\u043e\u043c, \u043a\u0430\u043a \u043c\u044b \u0432\u044b\u0441\u0442\u0440\u043e\u0438\u043b\u0438 \u043f\u0440\u043e\u0446\u0435\u0441\u0441 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u043e\u0439 \u0437\u0430\u043c\u0435\u043d\u044b \u0434\u0438\u0441\u043a\u043e\u0432, \u0430 \u0437\u0430\u0442\u0435\u043c, \u043a\u0430\u043a \u0438\u0441\u043a\u043b\u044e\u0447\u0438\u043b\u0438 \u0438\u0437 \u044d\u0442\u043e\u0433\u043e \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u0430 \u0430\u0434\u043c\u0438\u043d\u0438\u0441\u0442\u0440\u0430\u0442\u043e\u0440\u0430 \u0438 \u0437\u0430\u043c\u0435\u043d\u0438\u043b\u0438 \u0435\u0433\u043e \u0431\u043e\u0442\u043e\u043c. \u042d\u0442\u0430 \u0441\u0442\u0430\u0442\u044c\u044f \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0441\u0432\u043e\u0435\u0433\u043e \u0440\u043e\u0434\u0430 \u0442\u0440\u0430\u043d\u0441\u043b\u0438\u0442\u0435\u0440\u0430\u0446\u0438\u0435\u0439 \u0432\u044b\u0441\u0442\u0443\u043f\u043b\u0435\u043d\u0438\u044f \u043d\u0430 HighLoad+ 2018 \u041f\u043e\u0441\u0442\u0440\u043e\u0435\u043d\u0438\u0435 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u0430 \u043f\u043e \u0437\u0430\u043c\u0435\u043d\u0435 \u0434\u0438\u0441\u043a\u043e\u0432 \u0421\u043d\u0430\u0447\u0430\u043b\u0430 \u043d\u0435\u043c\u043d\u043e\u0433\u043e [&hellip;]<\/p>\n","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"author":1,"featured_media":26233,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[688],"tags":[],"class_list":["post-34841","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=\"\u0412\u0441\u0435\u043c \u043f\u0440\u0438\u0432\u0435\u0442.\" \/>\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\/avtomatizatsiya-zameny-diskov-s-pomoshhyu-ansible\" \/>\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\udd47\u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0437\u0430\u0446\u0438\u044f \u0437\u0430\u043c\u0435\u043d\u044b \u0434\u0438\u0441\u043a\u043e\u0432 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e Ansible | ProHoster\" \/>\n\t\t<meta property=\"og:description\" content=\"\u0412\u0441\u0435\u043c \u043f\u0440\u0438\u0432\u0435\u0442.\" \/>\n\t\t<meta property=\"og:url\" content=\"https:\/\/prohoster.info\/it\/blog\/administrirovanie\/avtomatizatsiya-zameny-diskov-s-pomoshhyu-ansible\" \/>\n\t\t<meta property=\"og:image\" content=\"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg\" \/>\n\t\t<meta property=\"og:image:secure_url\" content=\"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg\" \/>\n\t\t<meta property=\"og:image:width\" content=\"350\" \/>\n\t\t<meta property=\"og:image:height\" content=\"350\" \/>\n\t\t<meta property=\"article:published_time\" content=\"2019-10-31T19:00:43+00:00\" \/>\n\t\t<meta property=\"article:modified_time\" content=\"2019-10-31T19:00:43+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\udd47Automazione della sostituzione dei dischi con Ansible | ProHoster","description":"Ciao a tutti.","canonical_url":"https:\/\/prohoster.info\/it\/blog\/administrirovanie\/avtomatizatsiya-zameny-diskov-s-pomoshhyu-ansible","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\udd47\u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0437\u0430\u0446\u0438\u044f \u0437\u0430\u043c\u0435\u043d\u044b \u0434\u0438\u0441\u043a\u043e\u0432 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e Ansible | ProHoster","og:description":"\u0412\u0441\u0435\u043c \u043f\u0440\u0438\u0432\u0435\u0442.","og:url":"https:\/\/prohoster.info\/it\/blog\/administrirovanie\/avtomatizatsiya-zameny-diskov-s-pomoshhyu-ansible","og:image":"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg","og:image:secure_url":"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg","og:image:width":350,"og:image:height":350,"article:published_time":"2019-10-31T19:00:43+00:00","article:modified_time":"2019-10-31T19:00:43+00:00","article:publisher":"https:\/\/www.facebook.com\/prohoster","article:author":"https:\/\/www.facebook.com\/prohoster"},"aioseo_meta_data":{"post_id":"34841","title":null,"description":null,"keywords":null,"keyphrases":null,"primary_term":null,"canonical_url":null,"og_title":null,"og_description":null,"og_object_type":"default","og_image_type":"default","og_image_url":null,"og_image_width":null,"og_image_height":null,"og_image_custom_url":null,"og_image_custom_fields":null,"og_video":null,"og_custom_url":null,"og_article_section":null,"og_article_tags":null,"twitter_use_og":false,"twitter_card":"default","twitter_image_type":"default","twitter_image_url":null,"twitter_image_custom_url":null,"twitter_image_custom_fields":null,"twitter_title":null,"twitter_description":null,"schema":{"blockGraphs":[],"customGraphs":[],"default":{"data":{"Article":[],"Course":[],"Dataset":[],"FAQPage":[],"Movie":[],"Person":[],"Product":[],"ProductReview":[],"Car":[],"Recipe":[],"Service":[],"SoftwareApplication":[],"WebPage":[]},"graphName":"","isEnabled":true},"graphs":[]},"schema_type":null,"schema_type_options":null,"pillar_content":false,"robots_default":true,"robots_noindex":false,"robots_noarchive":false,"robots_nosnippet":false,"robots_nofollow":false,"robots_noimageindex":false,"robots_noodp":false,"robots_notranslate":false,"robots_max_snippet":null,"robots_max_videopreview":null,"robots_max_imagepreview":"large","priority":null,"frequency":null,"local_seo":null,"seo_analyzer_scan_date":"2026-01-21 20:48:19","breadcrumb_settings":null,"limit_modified_date":false,"reviewed_by":null,"ai":null,"created":"2021-03-01 02:14:05","updated":"2026-01-21 20:48:19","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\/34841","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=34841"}],"version-history":[{"count":0,"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/posts\/34841\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/media\/26233"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/media?parent=34841"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/categories?post=34841"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/tags?post=34841"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}