{"id":32217,"date":"2019-10-31T21:45:43","date_gmt":"2019-10-31T18:45:43","guid":{"rendered":"https:\/\/prohoster.info\/blog\/net-core-na-linux-devops-na-kone\/"},"modified":"2019-10-31T21:45:43","modified_gmt":"2019-10-31T18:45:43","slug":"net-core-na-linux-devops-na-kone","status":"publish","type":"post","link":"https:\/\/prohoster.info\/it\/blog\/administrirovanie\/net-core-na-linux-devops-na-kone","title":{"rendered":".NET Core su Linux, DevOps al top","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<p>Abbiamo sviluppato DevOps come potevamo. Eravamo 8 persone e Vasya era il migliore su Windows. Improvvisamente Vasya se n'\u00e8 andato e ho dovuto affrontare il compito di avviare un nuovo progetto per la fornitura di sviluppo Windows. Quando ho messo sul tavolo tutto il stack di sviluppo Windows, mi sono reso conto che la situazione era critica...<\/p>\n<p>Cos\u00ec inizia la storia <b>Alexander Sinchinov<\/b> in <noindex><a rel=\"nofollow\" href=\"https:\/\/devopsconf.io\/\">DevOpsConf<\/a><\/noindex>. Quando il principale specialista Windows ha lasciato l'azienda, Alexander si \u00e8 chiesto cosa fare ora. Passare a Linux, naturalmente! Alexander racconter\u00e0 come \u00e8 riuscito a creare un precedente e a trasferire parte dello sviluppo Windows su Linux, utilizzando un progetto realizzato per 100.000 utenti finali.<\/p>\n<p><img decoding=\"async\" alt=\".NET Core su Linux, DevOps al top\" src=\"\/wp-content\/uploads\/2019\/04\/3c944351864df95217e133236542c9b1.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nCome \u00e8 facile e senza sforzo consegnare un progetto in RPM, utilizzando TFS, Puppet, Linux .NET core? Come mantenere il versionamento del database di un progetto se gli sviluppatori sentono per la prima volta parole come Postgres e Flyway, e la scadenza \u00e8 dopodomani? Come integrare con Docker? Come motivare gli sviluppatori .NET ad abbandonare Windows e i frullati a favore di Puppet e Linux? Come risolvere i conflitti ideologici quando non ci sono n\u00e9 forze n\u00e9 desiderio n\u00e9 risorse per mantenere Windows in produzione? Di questo, oltre a Web Deploy, testing, CI, pratiche di utilizzo di TFS in progetti esistenti, e ovviamente di stampelle rotte e soluzioni funzionanti, parler\u00e0 la relazione di Alexander.<br \/>\n<noindex><a rel=\"nofollow\" name=\"habracut\"><\/a><\/noindex><br \/>\n<center><div class=\"youtube-placeholder\" data-id=\"tZH9Ro9j9KQ\" onclick=\"loadVideo(this)\">\r\n        <img decoding=\"async\" src=\"https:\/\/img.youtube.com\/vi\/tZH9Ro9j9KQ\/hqdefault.jpg\" alt=\"Guarda il video\" loading=\"lazy\" width=\"480\" height=\"360\" style=\"width:100%;height:auto;\">\r\n        <div class=\"play-button\"><\/div>\r\n    <\/div><\/center><br \/>\nDunque, Vasya \u00e8 andato, il compito \u00e8 mio e gli sviluppatori attendono con le forche impazienti. Quando ho finalmente realizzato che non avrei potuto riportare Vasya, mi sono messo al lavoro. Per prima cosa ho valutato la percentuale di VM Windows nel nostro parco. I risultati non erano a favore di Windows.<\/p>\n<p><img decoding=\"async\" alt=\".NET Core su Linux, DevOps al top\" src=\"\/wp-content\/uploads\/2019\/04\/836e47372126b6ba369ac494b91c7d3c.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nPoich\u00e9 stiamo sviluppando attivamente DevOps, ho capito che era necessario cambiare approccio per l'implementazione di una nuova applicazione. La decisione \u00e8 stata chiara: se possibile, trasferire tutto su Linux. Google mi ha aiutato: a quel tempo .Net era gi\u00e0 stato portato su Linux e ho capito che era questa la soluzione!<\/p>\n<h2>Perch\u00e9 .NET core in combinazione con Linux?<\/h2>\n<p>\nCi sono state diverse ragioni. Tra \"pagare\" e \"non pagare\" la maggior parte sceglie la seconda opzione, come me. Una licenza per MSDB costa circa 1.000 $, mentre il mantenimento di un parco di macchine virtuali Windows si traduce in centinaia di dollari. Per una grande azienda, sono spese significative. Perci\u00f2 <b>il risparmio\u00a0<\/b>\u2014<b> \u00e8 la prima ragione<\/b>. Non la pi\u00f9 importante, ma certamente una delle pi\u00f9 significative.<\/p>\n<p>Le macchine virtuali Windows richiedono pi\u00f9 risorse rispetto ai loro equivalenti Linux - <b>sono pesanti<\/b>. Considerando le dimensioni di una grande azienda, abbiamo scelto Linux.<\/p>\n<p><b>Il sistema si integra semplicemente nel CI esistente<\/b>. Ci consideriamo sviluppatori DevOps all'avanguardia, utilizziamo Bamboo, Jenkins e GitLab CI, pertanto gran parte del nostro lavoro si basa su Linux.<\/p>\n<p>L'ultima ragione \u00e8 <b>la facilit\u00e0 di supporto. <\/b>Dovevamo abbattere la soglia di ingresso per i \"supporters\" \u2013 ragazzi che comprendono la parte tecnica, garantiscono la continuit\u00e0 e gestiscono i servizi di secondo livello. Erano gi\u00e0 familiari con il stack Linux, quindi per loro \u00e8 molto pi\u00f9 semplice comprendere il nuovo prodotto, supportarlo e assisterlo piuttosto che spendere risorse aggiuntive per capire una funzionalit\u00e0 analoga del software per la piattaforma Windows.<\/p>\n<h2>Requisiti<\/h2>\n<p>\nPrima di tutto <b>la praticit\u00e0 di una nuova soluzione per gli sviluppatori<\/b>. Non tutti si sono mostrati pronti ai cambiamenti, soprattutto dopo aver sentito la parola Linux. Gli sviluppatori vogliono il loro amato Visual Studio, TFS con test automatici sui build e smoothie. Come avviene la consegna in produzione non \u00e8 importante per loro. Pertanto, abbiamo deciso di non cambiare il processo abituale e mantenere tutto invariato per lo sviluppo su Windows. <\/p>\n<p>Il nuovo progetto deve <b>essere integrato nel CI esistente<\/b>. I binari erano gi\u00e0 presenti e tutto il lavoro doveva essere eseguito tenendo conto dei parametri del sistema di gestione della configurazione, degli standard di consegna adottati e dei sistemi di monitoraggio.<\/p>\n<p><b>Semplicit\u00e0 di supporto e funzionamento<\/b>, come condizione per una soglia minima di ingresso per tutti i nuovi partecipanti provenienti dai diversi reparti e dal dipartimento di supporto.<\/p>\n<p><b>Il termine ultimo era ieri<\/b>.<\/p>\n<h2>Il gruppo di sviluppo Win<\/h2>\n<p>\nCon cosa lavorava quindi il team di Windows?<\/p>\n<p><img decoding=\"async\" alt=\".NET Core su Linux, DevOps al top\" src=\"\/wp-content\/uploads\/2019\/04\/6e6e128ef3d49410c260d05114f819a4.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nOra posso dire con certezza che <b>IdentityServer4<\/b>\u00a0\u00e8 una fantastica alternativa gratuita ad ADFS con funzionalit\u00e0 simili, oppure che <b>Entity Framework Core<\/b>\u00a0\u00e8 un paradiso per gli sviluppatori, dove si pu\u00f2 smettere di preoccuparsi di scrivere script SQL e descrivere le query nel database in termini di OOP. Ma allora, nella discussione sul piano d'azione, guardavo a questo stack come se fosse una scrittura cuneiforme sumera, riconoscendo solo PostgreSQL e Git.<\/p>\n<p>A quel tempo utilizzavamo attivamente <b>Puppet<\/b> come sistema di gestione della configurazione. Nella maggior parte dei nostri progetti applicavamo <b>GitLab CI<\/b>, <b>Elastic<\/b>, bilanciavamo i servizi altamente caricati con l'aiuto di <b>HAProxy,<\/b> tutte le osservazioni venivano fatte usando <b>Zabbix<\/b>, la combinazione <b>Grafana<\/b> e\u00a0<b>Prometheus<\/b>, <b>Jaeger<\/b>, e tutto ci\u00f2 girava su dei macchinari\u00a0<b>HP<\/b> c\u00a0<b>ESXi<\/b> in\u00a0<b>VMware<\/b>. \u00c8 conosciuto da tutti \u2013 un classico del genere.<\/p>\n<p><img decoding=\"async\" alt=\".NET Core su Linux, DevOps al top\" src=\"\/wp-content\/uploads\/2019\/04\/f4ffcac7a7fbb4fa48d47f07bed52610.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nVediamo e cerchiamo di capire cosa stava succedendo prima che avessimo intrapreso tutti questi interventi.<\/p>\n<h2>Cosa c'era<\/h2>\n<p>\nTFS \u00e8 un sistema piuttosto potente che non solo distribuisce il codice dallo sviluppatore alla macchina di produzione finale, ma offre anche un set per una integrazione molto flessibile con vari servizi, al fine di garantire CI a livello cross-platform.<\/p>\n<p><img decoding=\"async\" alt=\".NET Core su Linux, DevOps al top\" src=\"\/wp-content\/uploads\/2019\/04\/ea448b38e321a8350468d69f3e45e429.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\nIn passato c'erano solo finestre. TFS utilizzava diversi agenti di Build, sui quali erano raccolti molti progetti. In ogni agente c'erano 3-4 worker per parallelizzare i task e ottimizzare il processo. Poi, secondo i piani di rilascio, TFS consegnava il Build appena sfornato su un server Windows per applicazioni.<\/p>\n<h2>A cosa volevamo arrivare<\/h2>\n<p>\nPer la consegna e lo sviluppo utilizziamo TFS, mentre l'applicazione viene eseguita su un server applicativo Linux, e tra di loro c'\u00e8 una sorta di magia. Questa <b>Magic Box<\/b> \u00e8 il fulcro del lavoro futuro. Prima di esaminare i dettagli, mi permetto una digressione per dire un paio di parole sull'applicazione.<\/p>\n<h2>Progetto<\/h2>\n<p>\nL'applicazione fornisce funzionalit\u00e0 per gestire carte prepagate. <\/p>\n<p><img decoding=\"async\" alt=\".NET Core su Linux, DevOps al top\" src=\"\/wp-content\/uploads\/2019\/04\/c93aa67b340c45ad279330466fc4f776.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<\/p>\n<h3>Cliente<\/h3>\n<p>\nC'erano due tipi di utenti. <b>Primo<\/b> accedeva autenticandosi con un certificato SSL SHA-2. A\u00a0<b>secondo<\/b> aveva accesso tramite login e password.<\/p>\n<h3>HAProxy<\/h3>\n<p>\nSuccessivamente, la richiesta del cliente arrivava a HAProxy, che svolgeva i seguenti compiti:<\/p>\n<ul>\n<li>autenticazione primaria;\n<\/li>\n<li>terminazione SSL;\n<\/li>\n<li>ottimizzazione delle richieste HTTP;\n<\/li>\n<li>traduzione delle richieste.\n<\/li>\n<\/ul>\n<p>\nIl controllo del certificato del cliente avveniva lungo una catena. Noi siamo <b>authority <\/b>e possiamo permettercelo, poich\u00e9 emettiamo i certificati per i clienti del servizio.<\/p>\n<p>Fai attenzione al terzo punto, ci torneremo tra poco.<\/p>\n<h3>Backend<\/h3>\n<p>\nIl backend era pianificato per essere realizzato su Linux. Il backend interagisce con il database, carica l'elenco necessario di privilegi e poi, in base ai privilegi dell'utente autenticato, fornisce accesso alla firma di documenti finanziari e alla loro invio per l'esecuzione, oppure alla generazione di un certo report.<\/p>\n<h2>Risparmi con HAProxy<\/h2>\n<p>\nOltre ai due contesti attraverso i quali transitavano ciascuno dei clienti, esisteva anche il contesto identity. <b>IdentityServer4<\/b> che consente l'autenticazione, \u00e8 un'alternativa gratuita e potente per <b>ADFS\u00a0<\/b>\u2014<b> Active Directory Federation Services<\/b>.<\/p>\n<p>La richiesta in identity veniva elaborata in diversi passaggi. Il primo passaggio - <b>un client<\/b> <b>arrivava nel backend<\/b>, che scambiava dati con questo server e controllava la presenza di un token per il cliente. Se non lo trovava, la richiesta veniva restituita al contesto da cui proveniva, ma gi\u00e0 con il reindirizzamento, e il reindirizzamento andava su identity.<\/p>\n<p>Il secondo passo - la richiesta arrivava <b>alla pagina di autorizzazione in IdentityServer,<\/b> dove il cliente si registrava, e nel database di IdentityServer compariva quel tanto atteso token. <\/p>\n<p>Il terzo passo - <b>il cliente veniva reindirizzato di nuovo <\/b>al contesto da cui era venuto.<\/p>\n<p><img decoding=\"async\" alt=\".NET Core su Linux, DevOps al top\" src=\"\/wp-content\/uploads\/2019\/04\/e052c408d67485ab9aa10d0fd25df57e.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nIdentityServer4 ha una caratteristica: <b>la risposta alla richiesta di ritorno viene restituita tramite HTTP<\/b>. Non importa quanto ci siamo sforzati di configurare il server, quanto ci siamo istruiti sulla documentazione, ma ogni volta ricevevamo la richiesta originale del cliente con un URL arrivato tramite HTTPS, e IdentityServer restituiva lo stesso contesto, ma tramite HTTP. Siamo rimasti scioccati! E abbiamo inoltrato tutto questo attraverso il contesto identity su HAProxy, e negli header abbiamo dovuto modificare il protocollo HTTP in HTTPS. <\/p>\n<p>Qual \u00e8 il miglioramento e dove abbiamo risparmiato?<\/p>\n<blockquote><p>Abbiamo risparmiato denaro utilizzando una soluzione gratuita per l'autorizzazione di un gruppo di utenti, risorse, poich\u00e9 non abbiamo separato IdentityServer4 come nodo distinto in un segmento separato, ma lo abbiamo utilizzato insieme al backend sullo stesso server dove gira il backend dell'applicazione.<\/p><\/blockquote>\n<p><\/p>\n<h2>Come dovrebbe funzionare<\/h2>\n<p>\nQuindi, come promesso - Magic Box. Comprendiamo gi\u00e0 che ci stiamo muovendo in modo garantito verso Linux. Formuliamo le specifiche esigenze che richiedevano una soluzione.<\/p>\n<p><img decoding=\"async\" alt=\".NET Core su Linux, DevOps al top\" src=\"\/wp-content\/uploads\/2019\/04\/cc59632aa0e5c65fe0efc754311ecf5e.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\n<b>Manifesti Puppet. <\/b>Per distribuire e gestire la configurazione del servizio e dell'applicazione, era necessario scrivere ricette di alta qualit\u00e0. Un rotolo con una matita mostra eloquentemente quanto velocemente e con qualit\u00e0 sia stato fatto.<\/p>\n<p><b>Modalit\u00e0 di consegna. <\/b>Lo standard \u00e8 RPM. Tutti capiscono che su Linux non si pu\u00f2 fare a meno, ma il progetto stesso, dopo la compilazione, consisteva in un insieme di file DLL eseguibili. Ce n'erano circa 150, il progetto \u00e8 abbastanza pesante. L'unica soluzione armoniosa \u00e8 stata confezionare questo insieme binario in RPM e gi\u00e0 da l\u00ec distribuire l'applicazione.<\/p>\n<p><b>Versioning. <\/b>Dovevamo rilasciare molto frequentemente e bisognava decidere come formare il nome del pacchetto. Questa \u00e8 una questione di integrazione con TFS. L'agente di build era su Linux. Quando TFS invia un compito al gestore \u2014 worker \u2014 sull'agente di build, gli passa anche un insieme di variabili che vanno nell'ambiente del processo del gestore. In queste variabili di ambiente vengono passati il nome della build, il numero di versione e altre variabili. Maggiori dettagli su questo nel capitolo \"generazione del pacchetto RPM\".<\/p>\n<p><b>Configurazione TFS<\/b> consisteva nella configurazione del Pipeline. Prima raccoglievamo tutti i progetti Windows sugli agenti Windows, e ora sta arrivando un agente Linux \u2014 l'agente di build, che deve essere incluso nel gruppo di build, arricchito con vari artefatti, specificare che tipo di progetti verranno costruiti su questo agente di build e in qualche modo modificare il Pipeline.<\/p>\n<p><b>IdentityServer. <\/b>ADFS non \u00e8 la nostra strada, sosteniamo l'Open Source.<\/p>\n<p>Esaminiamo i componenti.<\/p>\n<h2>Magic Box<\/h2>\n<p>\n\u00c8 composto da quattro parti.<\/p>\n<p><img decoding=\"async\" alt=\".NET Core su Linux, DevOps al top\" src=\"\/wp-content\/uploads\/2019\/04\/22ea63bcf184046c15e034ec093352bb.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\n<b>Agente di build Linux. <\/b>Linux, perch\u00e9 stiamo costruendo per esso \u2014 \u00e8 logico. Questa parte \u00e8 stata eseguita in tre fasi.<\/p>\n<ul>\n<li><b>Configurare i worker<\/b> e non uno solo, poich\u00e9 si prevedeva un lavoro distribuito sul progetto.\n<\/li>\n<li><b>Installare .NET Core 1.x<\/b>. Perch\u00e9 proprio 1.x, quando gi\u00e0 \u00e8 disponibile la 2.0 nel repository standard? Perch\u00e9, quando abbiamo iniziato lo sviluppo, la versione stabile era 1.09, e il progetto \u00e8 stato deciso di realizzarlo per essa.\n<\/li>\n<li><b>Git 2.x<\/b>.\n<\/li>\n<\/ul>\n<p>\n<b>repository RPM. <\/b>I pacchetti RPM dovevano essere memorizzati da qualche parte. Si prevedeva che avremmo usato lo stesso repository RPM aziendale, accessible da tutti gli host Linux. \u00c8 cos\u00ec che abbiamo proceduto. Sul server del repository \u00e8 stato configurato <b>webhook<\/b> che scaricava il pacchetto RPM richiesto dal luogo specificato. La versione del pacchetto era comunicata al webhook dall'agente di build.<\/p>\n<p><b>GitLab. <\/b>Attenzione! GitLab qui non \u00e8 usato dagli sviluppatori, ma dal reparto operazioni per il controllo delle versioni dell'applicazione, delle versioni dei pacchetti, del monitoraggio dello stato di tutte le macchine Linux, e contiene la ricetta \u2014 tutti i manifesti Puppet. <\/p>\n<p><b>Puppet<\/b>\u00a0gestisce tutte le questioni controverse e fornisce esattamente la configurazione che vogliamo, da GitLab.<\/p>\n<p>Iniziamo a immergerci. Come avviene la consegna delle DLL in RPM?<\/p>\n<h3>Consegna delle DLL in RPM<\/h3>\n<p>\nSupponiamo di avere una rock star dello sviluppo su .NET. Usa Visual Studio e crea un ramo di rilascio. Poi lo carica su Git, e Git qui \u00e8 un'entit\u00e0 TFS, cio\u00e8 \u00e8 il repository dell'applicazione con cui lavora lo sviluppatore.<\/p>\n<p><img decoding=\"async\" alt=\".NET Core su Linux, DevOps al top\" src=\"\/wp-content\/uploads\/2019\/04\/978240886981d41fc6d7b17d0a4fcb05.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nDopo di che TFS vede che \u00e8 arrivato un nuovo commit. Quale applicazione? Nelle impostazioni di TFS c'\u00e8 un'etichetta che indica quali risorse ha ogni Build-agent. In questo caso, vede che stiamo compilando un progetto .NET Core e sceglie un Build-agent Linux dal pool. <\/p>\n<p>Il Build-agent riceve i sorgenti, scarica i necessari <b>dependencies<\/b> dal repository .NET, npm, ecc. e dopo la compilazione dell'applicazione e il successivo imballaggio invia un pacchetto RPM nel repository RPM.<\/p>\n<p>Dall'altra parte avviene quanto segue. L'ingegnere del dipartimento operativo si occupa direttamente del rilascio del progetto: cambia le versioni dei pacchetti in\u00a0<b>Hiera<\/b> nel repository, dove \u00e8 conservata la ricetta dell'applicazione, dopodich\u00e9 Puppet attiva <b>Yum<\/b>, prende il nuovo pacchetto dal repository e la nuova versione dell'applicazione \u00e8 pronta per l'uso.<\/p>\n<p><img decoding=\"async\" alt=\".NET Core su Linux, DevOps al top\" src=\"\/wp-content\/uploads\/2019\/04\/6c2db3ce4bd7d4268e88c6c3d3ecbeba.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nA parole tutto \u00e8 semplice, ma cosa succede dentro il Build-agent?<\/p>\n<h3>Imballaggio DLL RPM<\/h3>\n<p>\nI sorgenti del progetto sono stati ricevuti e l'istruzione di compilazione da TFS. Il Build-agent <b>inizia la compilazione del progetto stesso dai sorgenti.<\/b>Il progetto compilato \u00e8 accessibile sotto forma di numerosi <b>file DLL<\/b>, che sono stati imballati in un archivio zip per ridurre il carico sul file system.<\/p>\n<p>L'archivio ZIP viene inviato <b>nella directory di compilazione del pacchetto RPM.<\/b> Successivamente, uno script Bash inizializza le variabili d'ambiente, trova la versione di Build, la versione del progetto, il percorso della directory di compilazione e avvia RPM-build. Una volta conclusa la compilazione, il pacchetto viene pubblicato in\u00a0<b>un repository locale<\/b>, che si trova sul Build-agent.<\/p>\n<p>Dopo di che, dal Build-agent al server nei repository RPM <b>viene inviata una richiesta JSON<\/b> indicando il nome della versione e del Build. Il Webhook di cui parlavo prima preleva questo pacchetto dal repository locale sul Build-agent e rende una nuova compilazione disponibile per l'installazione.<\/p>\n<p><img decoding=\"async\" alt=\".NET Core su Linux, DevOps al top\" src=\"\/wp-content\/uploads\/2019\/04\/b69cacdadd171f4cbc9913b2ff4b7a79.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nPerch\u00e9 proprio questa schema di consegna del pacchetto nel repository RPM? Perch\u00e9 non \u00e8 possibile inviare direttamente il pacchetto compilato nel repository? La questione \u00e8 che questa \u00e8 una condizione per garantire la sicurezza. Questo scenario limita la possibilit\u00e0 di caricamenti non autorizzati di pacchetti RPM da parte di persone esterne al server, che \u00e8 accessibile a tutte le macchine Linux.<\/p>\n<h2>Versioning del DB<\/h2>\n<p>\nDurante il consiglio di sviluppo, \u00e8 emerso che ai ragazzi piace di pi\u00f9 MS SQL, ma nella maggior parte dei progetti non Windows stavamo gi\u00e0 utilizzando PostgreSQL. Poich\u00e9 abbiamo gi\u00e0 deciso di rinunciare a tutto ci\u00f2 che \u00e8 a pagamento, abbiamo iniziato a usare PostgreSQL anche qui.<\/p>\n<p><img decoding=\"async\" alt=\".NET Core su Linux, DevOps al top\" src=\"\/wp-content\/uploads\/2019\/04\/6b6c081344f2408c399248a70a63dccc.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nIn questa parte voglio raccontare come abbiamo realizzato la gestione delle versioni del database e come abbiamo scelto tra Flyway ed Entity Framework Core. Esaminiamo i loro pro e contro.<\/p>\n<h3>Contro<\/h3>\n<p>\nFlyway opera solo in un verso, noi\u00a0<b>non possiamo tornare indietro<\/b>\u00a0\u2014 questo \u00e8 un difetto significativo. Con Entity Framework Core possiamo confrontarlo su altri parametri \u2014 dal punto di vista della comodit\u00e0 per il sviluppatore. Ricordate che abbiamo posto questo al centro della nostra attenzione, e il criterio principale era non modificare nulla per lo sviluppo su Windows.<\/p>\n<p>Per Flyway avevamo bisogno di qualche tipo di wrapper <b>, in modo che i ragazzi non scrivessero<\/b>. \u00c8 molto pi\u00f9 vicino per loro operare in termini di OOP. Abbiamo scritto istruzioni per lavorare con gli oggetti del database, \u00e8 stata formata una query SQL e eseguita. Una nuova versione del database \u00e8 pronta, \u00e8 stata testata \u2014 tutto va bene, tutto funziona. <b>query SQL<\/b>Entity Framework Core ha un difetto \u2014 con carichi elevati<\/p>\n<p>crea query SQL non ottimali\u00a0<b>, e il calo delle prestazioni del database pu\u00f2 essere significativo. Ma poich\u00e9 il nostro servizio non \u00e8 ad alta intensit\u00e0, non misuriamo il carico in centinaia di RPS, abbiamo accettato questi rischi e abbiamo delegato il problema al nostro futuro.<\/b>funziona out of the box ed \u00e8 conveniente per lo sviluppo<\/p>\n<h3>Pro<\/h3>\n<p>\nEntity Framework Core <b>, mentre Flyway<\/b>si integra facilmente nel CI esistente <b>. Ma noi stiamo cercando di rendere la vita pi\u00f9 facile per gli sviluppatori :)<\/b>La procedura di applicazione<\/p>\n<h3>Puppet vede che arriva una modifica della versione dei pacchetti, tra cui quello che si occupa della migrazione. Per prima cosa installa il pacchetto che contiene gli script di migrazione e le funzionalit\u00e0 collegate al database. Dopo di ci\u00f2 l'applicazione che interagisce con il database viene riavviata. Poi viene effettuata l'installazione degli altri componenti. L'ordine di installazione dei pacchetti e di avvio delle applicazioni \u00e8 descritto nel manifesto Puppet.<\/h3>\n<p>\nLe applicazioni utilizzano dati sensibili, come token, password del database; tutto questo viene tirato dentro la configurazione dal Puppet master, dove sono conservati in forma crittografata.<\/p>\n<p>Problemi TFS<\/p>\n<h2>Dopo che ci siamo definiti e abbiamo capito che tutto funziona davvero, ho deciso di controllare cosa stesse succedendo con le build in TFS in generale per il team di sviluppo Win su altri progetti \u2014 se riusciamo a costruire\/rilasciare rapidamente o meno, e ho scoperto problemi significativi con la velocit\u00e0.<\/h2>\n<p>\nUno dei principali progetti ci mette 12-15 minuti per compilarsi \u2014 \u00e8 troppo, non pu\u00f2 andare avanti cos\u00ec. Un'analisi rapida ha mostrato un grave calo delle prestazioni I\/O, e questo su array.<\/p>\n<p>Analizzando a livello di componente, ho identificato tre focolaio. Il primo \u2014<\/p>\n<p>\u00abKaspersky antivirus\u00bb <b>\u00abAntivirus Kaspersky\u00bb<\/b>, che scansiona le sorgenti su tutti gli agenti di compilazione Windows. Secondo - <b>Windows<\/b> <b>Indexer.<\/b> Non \u00e8 stato disabilitato e tutto \u00e8 stato indicizzato in tempo reale sugli agenti di compilazione durante il processo di deployment. <\/p>\n<p>Terzo - <b>Npm install. <\/b>Si \u00e8 rivelato che in gran parte dei Pipeline abbiamo utilizzato proprio questo scenario. Qual \u00e8 il problema? La procedura Npm install si avvia durante la formazione dell'albero delle dipendenze in\u00a0<b>package-lock.json<\/b>, dove vengono registrate le versioni dei pacchetti che saranno utilizzate per la compilazione del progetto. Il difetto \u00e8 che Npm install ogni volta scarica versioni aggiornate dei pacchetti da Internet, e questo richiede molto tempo nel caso di un progetto esteso.<\/p>\n<blockquote><p>Gli sviluppatori a volte sperimentano sulla macchina locale per verificare il funzionamento di una parte specifica o del progetto nel suo insieme. A volte accadeva che localmente tutto funzionasse bene, ma durante la compilazione e il deployment - nulla funzionava. Iniziamo a capire qual \u00e8 il problema - ah, versioni diverse di pacchetti con dipendenze.<\/p><\/blockquote>\n<p><\/p>\n<h3>Soluzione<\/h3>\n<p><\/p>\n<ul>\n<li>Sorgenti escluse AV.\n<\/li>\n<li>Disabilitazione dell'indicizzazione.\n<\/li>\n<li>Passaggio a\u00a0<b>npm ci<\/b>.\n<\/li>\n<\/ul>\n<p>\nI vantaggi di npm ci sono che noi\u00a0<b>costruiamo l'albero delle dipendenze una sola volta<\/b>, e otteniamo la possibilit\u00e0 di fornire allo sviluppatore <b>un elenco aggiornato di pacchetti<\/b>, con cui pu\u00f2 sperimentare quanto vuole in locale. Questo <b>fa risparmiare tempo<\/b> agli sviluppatori che scrivono codice.<\/p>\n<h3>Configurazione<\/h3>\n<p>\nAdesso parliamo un po' della configurazione del repository. Storicamente utilizziamo <b>Nexus<\/b> per la gestione dei repository, compreso <b>Internal REPO<\/b>. In questo repository interno vengono forniti tutti i componenti che utilizziamo per scopi interni, ad esempio monitoraggi personalizzati.<\/p>\n<p><img decoding=\"async\" alt=\".NET Core su Linux, DevOps al top\" src=\"\/wp-content\/uploads\/2019\/04\/147d7e80bf20e03a232f8b533be316eb.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nUtilizziamo anche <b>NuGet<\/b>, poich\u00e9 gestisce meglio la cache rispetto ad altri gestori di pacchetti.<\/p>\n<h3>Risultato<\/h3>\n<p>\nDopo aver ottimizzato gli agenti di compilazione, il tempo medio di compilazione si \u00e8 ridotto da 12 minuti a 7.<\/p>\n<blockquote><p>Se calcolassimo tutte le macchine che avremmo potuto utilizzare per Windows, ma che abbiamo trasferito su Linux in questo progetto, abbiamo risparmiato circa $10.000. E questo solo per le licenze, e se consideriamo i costi di mantenimento - di pi\u00f9.<\/p><\/blockquote>\n<p><\/p>\n<h2>Piani<\/h2>\n<p>\nPer il prossimo trimestre abbiamo pianificato il lavoro sull'ottimizzazione della consegna del codice.<\/p>\n<p><b>Passaggio a un'immagine Docker precompilata<\/b>. TFS \u00e8 una cosa fantastica con molti plugin che consentono di integrare nel Pipeline, anche la compilazione tramite trigger, ad esempio, di un'immagine Docker. Questo trigger vogliamo realizzarlo per quello specifico <b>package-lock.json<\/b>. Se in qualche modo cambia la composizione dei componenti utilizzati per assemblare il progetto, viene creato un nuovo Docker image. Questo viene poi utilizzato per il dispiegamento del container con l'applicazione assemblata. Al momento non \u00e8 cos\u00ec, ma pianifichiamo di passare a un\u2019architettura a microservizi in Kubernetes, che si sta sviluppando attivamente nella nostra azienda e da tempo supporta soluzioni di produzione.<\/p>\n<h2>Riepilogo<\/h2>\n<p>\nInvito tutti a gettare via Windows, ma non perch\u00e9 non sappia usarlo. La ragione \u00e8 che gran parte delle soluzioni Opensource sono <b>stack Linux<\/b>. Risparmierete notevolmente <b>su risorse<\/b>. A mio avviso, il futuro appartiene alle soluzioni Open Source su Linux con una comunit\u00e0 forte.<\/p>\n<p><i>Profilo del relatore Aleksandr Sinchinov <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/alextuning\">su GitHub<\/a><\/noindex>.<\/i><\/p>\n<blockquote><p><noindex><a rel=\"nofollow\" href=\"https:\/\/devopsconf.io\/\">DevOps Conf<\/a><\/noindex>\u00a0\u00e8 una conferenza sull'integrazione dei processi di sviluppo, testing e operativit\u00e0 per professionisti da professionisti. Proprio per questo il progetto di cui ha parlato Aleksandr \u00e8 stato realizzato e funziona, e nel giorno della sua presentazione sono state effettuate due release di successo. Al\u00a0<noindex><a rel=\"nofollow\" href=\"http:\/\/devopsconf.io\/moscow-rit\/2019\">DevOps Conf a RIT++<\/a><\/noindex> il 27 e 28 maggio ci saranno ancora pi\u00f9 casi simili da parte dei praticanti. \u00c8 ancora possibile salire sull'ultimo treno e <noindex><a rel=\"nofollow\" href=\"https:\/\/conf.ontico.ru\/lectures\/propose\/?conference=dc2019-rit\">inviare una relazione<\/a><\/noindex> o senza fretta <noindex><a rel=\"nofollow\" href=\"https:\/\/conf.ontico.ru\/conference\/join\/rit2019.html?popup=3\">prenotare<\/a><\/noindex> un biglietto. Ci vediamo a Skolkovo!<\/p><\/blockquote>\n<p>Fonte: <a content=\"nofollow\" rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/oleg-bunin\/blog\/448496\/\">habr.com<\/a><\/p>","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"excerpt":{"rendered":"<p>\u041c\u044b\u00a0\u0440\u0430\u0437\u0432\u0438\u0432\u0430\u043b\u0438 DevOps \u043a\u0430\u043a \u043c\u043e\u0433\u043b\u0438. \u041d\u0430\u0441 \u0431\u044b\u043b\u043e 8\u00a0\u0447\u0435\u043b\u043e\u0432\u0435\u043a, \u0438\u00a0\u0412\u0430\u0441\u044f \u0431\u044b\u043b \u0441\u0430\u043c\u044b\u043c \u043a\u0440\u0443\u0442\u044b\u043c \u043f\u043e\u00a0Windows. \u0412\u043d\u0435\u0437\u0430\u043f\u043d\u043e \u0412\u0430\u0441\u044f \u0443\u0448\u0435\u043b, \u0430\u00a0\u0443\u00a0\u043c\u0435\u043d\u044f \u043f\u043e\u044f\u0432\u0438\u043b\u0430\u0441\u044c \u0437\u0430\u0434\u0430\u0447\u0430 \u0432\u044b\u0432\u0435\u0441\u0442\u0438 \u043d\u043e\u0432\u044b\u0439 \u043f\u0440\u043e\u0435\u043a\u0442, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 Windows-\u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0430. \u041a\u043e\u0433\u0434\u0430 \u044f\u00a0\u0432\u044b\u0441\u044b\u043f\u0430\u043b \u043d\u0430\u00a0\u0441\u0442\u043e\u043b \u0432\u0435\u0441\u044c \u0441\u0442\u0435\u043a Windows-\u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438, \u0442\u043e\u00a0\u043f\u043e\u043d\u044f\u043b, \u0447\u0442\u043e \u0441\u0438\u0442\u0443\u0430\u0446\u0438\u044f\u00a0\u2014 \u0431\u043e\u043b\u044c\u2026 \u0422\u0430\u043a \u043d\u0430\u0447\u0438\u043d\u0430\u0435\u0442\u0441\u044f \u0438\u0441\u0442\u043e\u0440\u0438\u044f \u0410\u043b\u0435\u043a\u0441\u0430\u043d\u0434\u0440\u0430 \u0421\u0438\u043d\u0447\u0438\u043d\u043e\u0432\u0430 \u043d\u0430 DevOpsConf. \u041a\u043e\u0433\u0434\u0430 \u0438\u0437\u00a0\u043a\u043e\u043c\u043f\u0430\u043d\u0438\u0438 \u0443\u0448\u0435\u043b \u0432\u0435\u0434\u0443\u0449\u0438\u0439 \u0441\u043f\u0435\u0446\u0438\u0430\u043b\u0438\u0441\u0442 \u043f\u043e\u00a0Windows, \u0410\u043b\u0435\u043a\u0441\u0430\u043d\u0434\u0440 \u0437\u0430\u0434\u0430\u043b\u0441\u044f \u0432\u043e\u043f\u0440\u043e\u0441\u043e\u043c, \u0447\u0442\u043e \u0442\u0435\u043f\u0435\u0440\u044c \u0434\u0435\u043b\u0430\u0442\u044c. \u041f\u0435\u0440\u0435\u0445\u043e\u0434\u0438\u0442\u044c \u043d\u0430\u00a0Linux, [&hellip;]<\/p>\n","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"author":1,"featured_media":24043,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[688],"tags":[],"class_list":["post-32217","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=\"\u041c\u044b \u0440\u0430\u0437\u0432\u0438\u0432\u0430\u043b\u0438 DevOps \u043a\u0430\u043a \u043c\u043e\u0433\u043b\u0438. \u041d\u0430\u0441 \u0431\u044b\u043b\u043e 8 \u0447\u0435\u043b\u043e\u0432\u0435\u043a, \u0438 \u0412\u0430\u0441\u044f \u0431\u044b\u043b \u0441\u0430\u043c\u044b\u043c \u043a\u0440\u0443\u0442\u044b\u043c \u043f\u043e Windows. \u0412\u043d\u0435\u0437\u0430\u043f\u043d\u043e \u0412\u0430\u0441\u044f \u0443\u0448\u0435\u043b, \u0430 \u0443 \u043c\u0435\u043d\u044f \u043f\u043e\u044f\u0432\u0438\u043b\u0430\u0441\u044c \u0437\u0430\u0434\u0430\u0447\u0430 \u0432\u044b\u0432\u0435\u0441\u0442\u0438 \u043d\u043e\u0432\u044b\u0439 \u043f\u0440\u043e\u0435\u043a\u0442, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 Windows-\u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0430.\" \/>\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\/net-core-na-linux-devops-na-kone\" \/>\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.NET Core \u043d\u0430 Linux, DevOps \u043d\u0430 \u043a\u043e\u043d\u0435 | ProHoster\" \/>\n\t\t<meta property=\"og:description\" content=\"\u041c\u044b \u0440\u0430\u0437\u0432\u0438\u0432\u0430\u043b\u0438 DevOps \u043a\u0430\u043a \u043c\u043e\u0433\u043b\u0438. \u041d\u0430\u0441 \u0431\u044b\u043b\u043e 8 \u0447\u0435\u043b\u043e\u0432\u0435\u043a, \u0438 \u0412\u0430\u0441\u044f \u0431\u044b\u043b \u0441\u0430\u043c\u044b\u043c \u043a\u0440\u0443\u0442\u044b\u043c \u043f\u043e Windows. \u0412\u043d\u0435\u0437\u0430\u043f\u043d\u043e \u0412\u0430\u0441\u044f \u0443\u0448\u0435\u043b, \u0430 \u0443 \u043c\u0435\u043d\u044f \u043f\u043e\u044f\u0432\u0438\u043b\u0430\u0441\u044c \u0437\u0430\u0434\u0430\u0447\u0430 \u0432\u044b\u0432\u0435\u0441\u0442\u0438 \u043d\u043e\u0432\u044b\u0439 \u043f\u0440\u043e\u0435\u043a\u0442, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 Windows-\u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0430.\" \/>\n\t\t<meta property=\"og:url\" content=\"https:\/\/prohoster.info\/it\/blog\/administrirovanie\/net-core-na-linux-devops-na-kone\" \/>\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-31T18:45:43+00:00\" \/>\n\t\t<meta property=\"article:modified_time\" content=\"2019-10-31T18:45: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\udd47.NET Core su Linux, DevOps in sella | ProHoster","description":"Abbiamo sviluppato il DevOps come meglio potevamo. Eravamo 8 persone, e Vasya era il migliore in Windows. Improvvisamente Vasya se n'\u00e8 andato, e ho dovuto avviare un nuovo progetto che fornisce sviluppo Windows.","canonical_url":"https:\/\/prohoster.info\/it\/blog\/administrirovanie\/net-core-na-linux-devops-na-kone","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.NET Core \u043d\u0430 Linux, DevOps \u043d\u0430 \u043a\u043e\u043d\u0435 | ProHoster","og:description":"\u041c\u044b \u0440\u0430\u0437\u0432\u0438\u0432\u0430\u043b\u0438 DevOps \u043a\u0430\u043a \u043c\u043e\u0433\u043b\u0438. \u041d\u0430\u0441 \u0431\u044b\u043b\u043e 8 \u0447\u0435\u043b\u043e\u0432\u0435\u043a, \u0438 \u0412\u0430\u0441\u044f \u0431\u044b\u043b \u0441\u0430\u043c\u044b\u043c \u043a\u0440\u0443\u0442\u044b\u043c \u043f\u043e Windows. \u0412\u043d\u0435\u0437\u0430\u043f\u043d\u043e \u0412\u0430\u0441\u044f \u0443\u0448\u0435\u043b, \u0430 \u0443 \u043c\u0435\u043d\u044f \u043f\u043e\u044f\u0432\u0438\u043b\u0430\u0441\u044c \u0437\u0430\u0434\u0430\u0447\u0430 \u0432\u044b\u0432\u0435\u0441\u0442\u0438 \u043d\u043e\u0432\u044b\u0439 \u043f\u0440\u043e\u0435\u043a\u0442, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 Windows-\u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0430.","og:url":"https:\/\/prohoster.info\/it\/blog\/administrirovanie\/net-core-na-linux-devops-na-kone","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-31T18:45:43+00:00","article:modified_time":"2019-10-31T18:45:43+00:00","article:publisher":"https:\/\/www.facebook.com\/prohoster","article:author":"https:\/\/www.facebook.com\/prohoster"},"aioseo_meta_data":{"post_id":"32217","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 09:49:20","breadcrumb_settings":null,"limit_modified_date":false,"reviewed_by":null,"ai":null,"created":"2021-03-01 03:02:47","updated":"2026-01-21 09:49:20","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\/32217","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=32217"}],"version-history":[{"count":0,"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/posts\/32217\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/media\/24043"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/media?parent=32217"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/categories?post=32217"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/tags?post=32217"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}