
In un momento ho deciso di scrivere un articolo sulla distribuzione in forma di container Docker e pacchetti deb, ma quando ho iniziato, mi sono trovato a pensare ai tempi lontani dei primi computer personali e persino delle calcolatrici. Insomma, invece di un'analisi secca tra Docker e deb, sono venute fuori alcune riflessioni sull'evoluzione, che ora vi presento per il vostro giudizio.
Qualsiasi prodotto, qualunque esso sia, deve in qualche modo arrivare ai server di produzione, deve essere configurato e avviato. Questa sarà la questione centrale dell'articolo.
Rifletterò nel contesto storico, "quello che vedo - su quello canto", ciò che ho visto quando ho iniziato a programmare e cosa osservo ora, cosa usiamo attualmente e perché. L'articolo non ambisce a essere una ricerca completa, alcuni aspetti sono stati trascurati, è il mio punto di vista personale su ciò che c'era e su ciò che c'è ora.
Quindi, nei bei tempi di un tempo... il modo più primitivo di distribuzione che ho conosciuto erano le cassette dei registratori. Avevo un computer BK-0010.01...
L'era delle calcolatrici
No, c'era un momento ancora più antico, c'era una calcolatrice e .
Dunque, quando avevo , il modo per trasferire il programma era un normale foglio di carta a quadretti su cui era scritta la programmazione, che per necessità veniva inserita manualmente nella calcolatrice. Vuoi giocare (sì, sì, anche su quella calcolatrice preistorica c'erano dei giochi) — ti siedi e digiti il programma nella calcolatrice. Naturalmente, spegnendo la calcolatrice il programma andava nel nulla. Oltre ai codici scritti manualmente su carta, i programmi venivano pubblicati nelle riviste "Radio" e "Tecnica dei giovani", e stampati nei libri dell'epoca.
La modifica successiva era una calcolatrice , che già aveva una sorta di memoria non volatile. Ora non era più necessario inserire manualmente il gioco o il programma, ma, eseguendo alcune magie con i tasti, si caricava da solo.
La dimensione del programma più grande nella calcolatrice era di 105 istruzioni, e la memoria permanente del MK-52 era di 512 istruzioni.
A proposito, se ci sono fan di queste calcolatrici che leggono questo articolo — mentre scrivevo l'articolo ho trovato un emulatore di calcolatrice per Android, e programmi per essa. Avanti, nel passato!
Una piccola digressione su MK-52 (da wikipedia)
MK-52 è volato nello spazio a bordo della navetta "Soyuz TM-7". Doveva essere utilizzato per il calcolo della traiettoria di atterraggio nel caso in cui il computer di bordo si fosse guastato.
MK-52 con il modulo di espansione della memoria "Elettronica-Astro" è stato fornito alle navi della Marina Militare a partire dal 1988 come parte del complesso di calcolo per timonieri.
I primi computer personali
Torniamo indietro nel tempo . È chiaro che anche la memoria è aumentata, e inserire il codice da un foglio di carta non era più un'opzione (anche se inizialmente lo facevo, perché non c'era altro supporto disponibile). Il principale mezzo di archiviazione e distribuzione del software diventano le audiocassette per i registratori.
Il caricamento su cassetta avveniva solitamente sotto forma di uno o due file binari, mentre tutto il resto era contenuto all'interno. L'affidabilità era molto bassa, era necessario mantenere 2-3 copie del programma. Anche il tempo di caricamento non era affatto soddisfacente, gli appassionati sperimentavano con diversi codificatori di frequenza per superare questi inconvenienti. A quel tempo non mi occupavo ancora di sviluppo software professionale (a parte semplici programmi in BASIC), quindi purtroppo non posso raccontare nei dettagli come fosse strutturato tutto internamente. Il fatto che ci fosse solo RAM sul computer definiva per lo più la semplicità del sistema di archiviazione dei dati.
L'emergere di supporti informatici affidabili e di grandi dimensioni
Più tardi arrivano i dischetti, semplificando il processo di copia e aumentando l'affidabilità.
Ma la situazione cambia radicalmente solo quando compaiono supporti locali sufficientemente grandi sotto forma di HDD.
Cambia radicalmente il tipo di distribuzione: emergono programmi di installazione che gestiscono il processo di configurazione del sistema e la pulizia dopo la disinstallazione, poiché i programmi non vengono più semplicemente letti nella memoria, ma vengono già copiati nell'archiviazione locale, dalla quale è necessario anche eliminare i dati non necessari quando necessario.
Parallelamente, aumenta la complessità del software fornito.
Il numero di file nella distribuzione cresce da uno a centinaia e migliaia, iniziano i conflitti di versione delle librerie e altre gioie, quando diversi programmi utilizzano gli stessi dati.
In quei tempi non avevo ancora scoperto l'esistenza di Linux, vivevo nel mondo di MS DOS e, successivamente, Windows, e scrivevo in Borland Pascal e Delphi, dando a volte uno sguardo al C++. Per la distribuzione dei prodotti in quel periodo, molti utilizzavano InstallShield , che risolveva con successo tutte le questioni relative al deployment e alla configurazione del software.
L'era di Internet
Gradualmente la complessità dei sistemi software è aumentata, passando da applicazioni monolitiche e desktop a sistemi distribuiti, thin client e microservizi. Ora non è più necessario configurare un solo programma, ma un insieme di essi, in modo che funzionino bene insieme.
La concezione è cambiata completamente, è arrivato Internet, è iniziata l'era dei servizi cloud. Fino a quel momento eravamo ancora solo agli inizi, sotto forma di siti web, e nessuno sognava particolarmente i servizi. Ma questo è stato un momento di svolta nell'industria sia dello sviluppo che della distribuzione delle applicazioni.
Ho notato che in quel momento si è verificato un cambio di generazione tra gli sviluppatori (o era solo nel mio ambiente), e ho avuto l'impressione che tutti i vecchi metodi di distribuzione fossero stati dimenticati in un attimo e che tutto fosse ricominciato da capo: tutta la distribuzione è iniziata a essere fatta con script improvvisati e hanno chiamato questa pratica con orgoglio 'Continuous delivery'. Di fatto, è iniziato un certo periodo di confusione, in cui il vecchio è stato dimenticato e non utilizzato, e il nuovo semplicemente non esisteva.
Ricordo i tempi in cui nella nostra azienda, dove lavoravo (non dirò il nome), invece di fare una build tramite ant (maven all'epoca non era ancora popolare o non esisteva), la gente semplicemente compilava jar nell'IDE e lo committava serenamente in SVN. Di conseguenza, il deployment consisteva nel recuperare il file da SVN e copiarlo tramite SSH sulla macchina desiderata. Così semplice e rudimentale.
In quello stesso periodo, la distribuzione di semplici siti PHP avveniva in modo estremamente primitivo, copiando il file corretto tramite FTP sulla macchina di destinazione. A volte nemmeno ciò: si modificava il codice direttamente sul server di produzione, e era un vero lusso avere dei backup da qualche parte.
Pacchetti RPM e DEB
D'altra parte, con lo sviluppo di Internet, i sistemi simili a UNIX hanno cominciato a guadagnare popolarità, in particolare, proprio in quel periodo ho scoperto RedHat Linux 6, intorno al 2000. Naturalmente, anche lì c'erano determinati strumenti per la distribuzione del software; secondo Wikipedia, RPM come principale gestore di pacchetti è apparso nel 1995 con la versione RedHat Linux 2.0. E da allora e fino ai nostri giorni, il sistema è distribuito sotto forma di pacchetti RPM e continua ad esistere e svilupparsi con successo.
Le distribuzioni della famiglia Debian hanno seguito un percorso simile e hanno implementato la distribuzione sotto forma di pacchetti deb, il che è rimasto invariato fino ai giorni nostri.
I gestori di pacchetti consentono di distribuire i prodotti software, configurarli durante l'installazione, gestire le dipendenze tra diversi pacchetti e effettuare la rimozione dei prodotti e la pulizia degli elementi superflui durante la disinstallazione. Cioè, per la maggior parte, è tutto ciò che serve; per questo motivo sono rimasti in uso per diversi decenni praticamente senza modifiche.
Il cloud ha aggiunto ai gestori di pacchetti la possibilità di installare non solo da supporti fisici, ma anche da repository cloud, ma fondamentalmente è cambiato poco.
Vale la pena notare che attualmente ci sono alcuni tentativi di allontanarsi da deb e passare ai pacchetti snap, ma ne parleremo più tardi.
Quindi, questa nuova generazione di sviluppatori cloud, che non conosceva né DEB né RPM, stava anche crescendo lentamente, acquisendo esperienza; i prodotti diventavano più complessi e servivano modi di distribuzione più ragionevoli rispetto a FTP, a script bash e a simili lavori da studenti.
E qui entra in gioco Docker, una sorta di miscela di virtualizzazione, isolamento delle risorse e metodo di distribuzione. È attualmente di moda, giovanile, ma è davvero necessario per tutto? È una panacea?
Dalle mie osservazioni, molto spesso Docker viene proposto non come una scelta ragionevole, ma semplicemente perché, da un lato, se ne parla nella comunità e coloro che lo propongono lo conoscono solamente. Dall'altro lato, i sistemi di packaging buoni e vecchi sono in gran parte ignorati: esistono e svolgono il loro lavoro silenziosamente e senza attirare troppo l'attenzione. In una situazione del genere, non c'è molta scelta — la scelta è ovvia: Docker.
Proverò a condividere l'esperienza di come abbiamo implementato Docker e cosa ne è derivate.
Script personalizzati
Inizialmente c'erano script bash che distribuivano archivi jar sulle macchine necessarie. Questo processo era gestito da Jenkins. Ha funzionato con successo, dato che l'archivio jar stesso è già una build che contiene classi, risorse e persino configurazioni. Se si accumulano il massimo di elementi, è relativamente semplice estrarlo con uno script, non è la cosa più complicata da fare.
Ma gli script hanno alcuni svantaggi:
- Gli script di solito sono scritti in fretta e quindi sono così primitivi da contenere solo il più semplice dei casi. Questo è favorito dal fatto che lo sviluppatore è interessato a una rapida consegna, mentre uno script ben fatto richiede un notevole investimento di risorse.
- Di conseguenza, gli script non contengono procedure di disinstallazione.
- Non c'è una procedura di upgrade stabilita.
- Con l'arrivo di un nuovo prodotto, è necessario scrivere un nuovo script.
- Non c'è supporto per le dipendenze.
Certo, si può scrivere uno script complesso, ma, come ho detto prima, questo richiede tempo di sviluppo, e non poco, e come sappiamo, il tempo è sempre scarso.
Tutto ciò limita ovviamente l'uso di questo modo di distribuzione solo a sistemi molto semplici. È arrivato il momento di cambiare.
Docker
A un certo punto, abbiamo iniziato a ricevere nuovi programmatori pieni di idee e appassionati di Docker. Bene, prendi la bandiera e andiamo! Ci sono state due tentativi. Entrambi non riusciti, diciamo così, a causa di grandi ambizioni, ma poca esperienza reale. Era necessario forzare e completare le cose con ogni mezzo? Probabilmente no: il team deve evolversi fino al livello necessario prima di poter utilizzare gli strumenti appropriati. Inoltre, utilizzando immagini Docker pronte, abbiamo spesso riscontrato problemi con la rete che non funzionava correttamente (il che, forse, era dovuto alla gioventù di Docker stesso) o era difficile espandere contenitori altrui.
Quali inconvenienti abbiamo riscontrato?
- Problemi di rete in modalità bridge.
- Difficoltà a visualizzare i log nel contenitore (se non sono stati esportati separatamente nel file system della macchina host).
- Frequente blocco anomalo di ElasticSearch all'interno del contenitore, la causa non è stata mai identificata, contenitore ufficiale.
- Scomodo usare la shell all'interno del contenitore: molte funzionalità sono limitate, mancano strumenti familiari.
- Le grandi dimensioni dei contenitori raccolti rendono costoso lo stoccaggio
- A causa delle grandi dimensioni dei contenitori, è difficile mantenere più versioni
- Assemblaggio più lungo, diversamente da altri metodi (script o pacchetti deb)
D'altra parte, in cosa è peggio distribuire un servizio Spring in forma di archivio jar tramite lo stesso deb? È davvero necessaria l'isolamento delle risorse? Vale la pena rinunciare agli strumenti comodi del sistema operativo, mettendo il servizio in un contenitore seriamente ridotto?
Come ha dimostrato la pratica, in realtà questo non è necessario, un pacchetto deb è sufficiente nel 90% dei casi.
Quando il vecchio e caro deb non funziona e quando avevamo davvero bisogno di Docker?
Per noi è stato il dispiegamento di servizi in Python. Molte librerie necessarie per l'apprendimento automatico mancavano nella fornitura standard del sistema operativo (e quelle che c'erano non erano le versioni giuste), hack di configurazione, necessità di versioni diverse per servizi diversi, che vivono sullo stesso sistema host, hanno portato al fatto che l'unico modo ragionevole per fornire questa miscela fondamentale si è rivelato essere Docker. Il lavoro necessario per costruire un contenitore Docker si è rivelato inferiore all'idea di impacchettare tutto in pacchetti deb separati con dipendenze, e in effetti, nessuno in sano spirito si sarebbe preso cura di questo.
Il secondo punto in cui si prevede di utilizzare Docker è per il dispiegamento di servizi con schema blue-green. Ma qui si desidera una crescente complessità: prima si assemblano i pacchetti deb, e poi da essi si costruisce il contenitore Docker.
Pacchetti Snap
Torniamo ai pacchetti Snap. Sono apparsi ufficialmente per la prima volta in Ubuntu 16.04. A differenza dei tradizionali pacchetti deb e rpm, gli snap includono tutte le dipendenze. Da un lato, questo consente di evitare conflitti tra librerie, dall'altro lato, le dimensioni del pacchetto risultante sono maggiori. Inoltre, questo può influenzare la sicurezza del sistema: nel caso dell'offerta di snap, tutte le modifiche alle librerie incluse devono essere monitorate dallo stesso sviluppatore che crea il pacchetto. Insomma, non è tutto così semplice e la felicità generale dal loro utilizzo non si materializza. Tuttavia, è comunque un'alternativa ragionevole se Docker viene utilizzato solo come mezzo di imballaggio e non di virtualizzazione.
Alla fine, attualmente utilizziamo una combinazione ragionevole di pacchetti deb e container Docker, che, in alcuni casi, potremmo sostituire con pacchetti snap.
Solo gli utenti registrati possono partecipare al sondaggio. , per favore.
E voi, cosa usate per le consegne?
Script personalizzati
Copiamo manualmente su FTP
pacchetti deb
pacchetti rpm
pacchetti snap
immagini Docker
immagini di macchine virtuali
Cloniamo l'HDD per intero
puppet
ansible
Altro
Hanno votato 109 utenti. 32 utenti si sono astenuti.
Fonte: habr.com
