A me sembra passata un'eternità. Intorno al 2004 si poteva utilizzare codice scritto per il Framework.Net su Linux con Mono. Da appassionato da moltissimi anni anche del mondo linux, la cosa mi era sembrata fin da subito interessante (alcuni punti li avevo trattati anche su questo mio blog) e mai avrei credito che di punto in bianco la stessa Microsoft si decidesse un giorno di supportare pienamente un suo diretto concorrente quando iniziò lo sviluppo di asp.net Core.
Lo sviluppo di applicazioni web su linux è ora più facile che mai e in rete si trovano parecchie guide che mostrano quanto sia alla portata del developer medio (ricordo che anche con mono e linux era possibile sviluppare applicazioni web con asp.net, ma personalmente trovavo la cosa come una dimostrazione delle potenzialità di mono e nulla da utilizzare realmente in produzione: mai mi sarei sognato di sviluppare web app in asp.net su linux). Un'ottima guida, in fase di miglioramento, riguardante la configurazione di asp-net core su Linux, la si può trovare in questo post di Pietro Libro.
Quest'apertura di Microsoft verso altri mondi non si è fermata solo a Linux, ma anche al mondo Apple, e, non accontentandosi, non si è fermata dinanzi neanche a novità come il mondo dei container dove Docker fa ormai da padrone, e ufficialmente rilascia immagini anche per questo mondo. Il suo uso è semplice, avviato Linux possiamo prendere una nostra soluzione appena realizzata con Visual Studio ed avviarla senza installare alcunché (se non lo stesso Docker, naturalmente). Esempio, scaricato in una directory il progetto, basta avviare docker in questo modo:
docker run -it --name azdotnet -v /home/az/Documents/docker/aspnetcorelinux/src/MVC5ForLinuxTest2:/app -p 5000:5000 microsoft/dotnet:1.0.1-sdk-projectjson
Scaricate le immagini indispensabili all'avvio, viene restituito il prompt all'interno del container di docker, dove possiamo scrivere:
dotnet restore dotnet run
Ecco che vengono scaricate le dipendenze e viene compilato il progetto. Alla fine:
Project MVC5ForLinuxTest (.NETCoreApp,Version=v1.0) will be compiled because the version or bitness of the CLI changed since the last build Compiling MVC5ForLinuxTest for .NETCoreApp,Version=v1.0 Compilation succeeded. 0 Warning(s) 0 Error(s) Time elapsed 00:00:02.8545851 Hosting environment: Production Content root path: /dotnet2/src/MVC5ForLinuxTest Now listening on: http://0.0.0.0:5000 Application started. Press Ctrl+C to shut down.
Dal browser:
Prima di proseguire due parole sui parametri utilizzati con docker. Il parametro -it serve per connettere il terminale attuale al contenuto del container. Avremmo potuto anche utilizzare:
docker run -d ...
Dove d sta per detach, in questo modo non avremo visto nulla sul terminale e saremmo rimasti nella shell di linux attuale. Di contro non avremmo visto l'output della compilazione e non avremmo potuto inviare i comandi di compilazione immediatamente. E' sempre possibile riconnettersi ad un container avviato in detach mode per controllare cosa sta succedendo, per esempio:
docker logs azdotnet
Questo comando visualizza il contenuto del terminale all'interno del container (aggiungendo il parametro -f il comando non ritornerebbe al prompt ma continuerebbe a rimanere in attesa di nuovi messaggi). Infine ci saremmo potuti riconnettere con il comando:
docker attach azdotnet
Il parametro -v serve per gestire i volumi all'interno dei container di docker. Riassumendo, in docker si possono definire due tipi di volumi, il primo, quello più semplice e utilizzato nel mio esempio, permette di creare un collegamento all'interno del container con il disco del compute host che ospita la sessione di docker. Nel mio esempio ci sono due path divisi da ":", a sinistra c'è la prima parte del path sul disco dell'host, a destra il path all'interno del container. Nell'esempio: /home/az/Documents/docker/aspnetcorelinux/src/MVC5ForLinuxTest2 è il percorso nell'host che sarà mappato come app all'interno di docker. Solo per completezza, il secondo tipo di volume è quello gestito internamente da docker: eventuali volumi montati in questo modo saranno gestiti in un suo path privato all'interno di docker; quest'ultimo tipo è comodo per condividere tra più container directory e file inseriti in altri container.
Il parametro -p viene utilizzato per definire quali porte docker deve aprire nel container verso l'host; così come il parametro per i volumi, anche questo accetta due valori suddivisi dal caratteri dei due punti in cui il valore a destra definisce quale porta sarà mappata nel container e a quale sarà mappata nell'host (parte sinistra del parametro).
Infine dobbiamo specificare il nome dell'immagine che dobbiamo utilizzare, essendo questa salvata nell'hub ufficiale di docker, possiamo definirla semplicemente con microsoft/dotnet; se fosse su un altro servizio di immagini di docker avremmo dovuto scrivere il path completo di dominio: miohost.com/docker/hub/microsoft/dotnet. Il parametro dopo i due punti è il tag che specifica quale versione vogiamo utilizzare. In questo esempio usiamo una versione specifica; avremmo potuto usare anche latest per avere l'ultima versione, ma nella pratica reale sconsiglio questa procedura perché, come mi è accaduto più volte, con il passaggio di versioni, si possono riscontrare anomalie che obbligano a mettere mano al tutto. In un primo test che avevo fatto, avevo specificato come tag latest, per poi scoprire, quando era uscita la versione 1.1 di asp.net core, che il progetto non era più compilabile per le differenze di versioni nelle dipendenze. Un altro caso che mi è successo di recente: utilizzando di base un'immagine ubuntu, precedentemente con la versione 14.04.4 era presente nell'immagine un comando per la decompressione di una formato particolare, comando che nell'ultima versione, la 16.04 è stato eliminato; al passaggio a quest'ultima versione di ubuntu il tutto si bloccava con un messaggio inizialmente incomprensibile che poi era basato sulla mancanza di quel comando.
Abbiamo usato spesso come valore nel parametro azdotnet, e questo è il nome che abbiamo dato al nostro container grazie al parametro --name: non assegnandolo noi da comando, docker avrebbe creato uno suo. Se siamo ancora nel terminale connesso a docker, possiamo uscirne con la sequenza Ctrl+P Ctrl+Q. Usando il comando docker ps possiamo vedere informazioni sui container che girano all'interno della nostra macchina:
$ docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES df65019f69a5 microsoft/dotnet:1.0.1-sdk-projectjson "/bin/bash" 15 seconds ago Up 11 seconds 0.0.0.0:5000->5000/tcp azdotnet
Se non avessi specificato il nome mi sarei ritrovato questo casuale goofy_shaw:
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 04c3276cfd73 microsoft/dotnet:1.0.1-sdk-projectjson "/bin/bash" 10 seconds ago Up 7 seconds 0.0.0.0:5000->5000/tcp goofy_shaw
Vogliamo fermare il processo in questo container (in entrambi i casi)?
docker stop azdotnet ... oppure ... docker stop goofy_shaw
Voglio cancellare il container e l'immagine?
docker rm azdotnet docker rmi azdotnet
Voglio essere distruttivo e cancellare qualsiasi costa presente in docker?
docker rm $(docker ps -qa) docker rmi $(docker images -qa)
La comodità non si ferma qui. Scopro che c'è un piccolo errore? Avendo il volume montato in locale posso fare (se ho l'editor VSCode di Microsoft, ma qualunque editor di testo fa la stessa cosa):
code .
Quindi, salvato il file, posso ricompilare e riavviare, all'interno del terminal in docker, dopo aver fermato con Ctrl+C
dotnet restore dotnet run
E vedere le modifiche. Potremmo creare anche un'immagine già pronta con la nostra app al suo interno. Il modo più semplice è scaricare quella di nostro interesse, salvarci all'interno i file della nostra app, quindi fare il commit delle modifiche e utilizzarla tutte le volte che vogliamo. Oppure, possiamo introdurre nel codice sorgente della nostra web app un file per la creazione automatica dell'immagine per docker. Ecco un esempio che sarà ripreso anche più tardi:
# Example from AZ FROM microsoft/dotnet:1.0.1-sdk-projectjson MAINTAINER "AZ" COPY ["./src/MVC5ForLinuxTest2/", "/app"] COPY ["./start.sh", "."] RUN chmod +x ./start.sh CMD ["./start.sh"]
Con questo file possiamo creare una immagine con questo comando:
docker build -t myexample/exampledotnet .
myexample/exampledotnet sarà il nome dell'immagine che possiamo usare per richiamare e avviare un container con il suo contenuto. Se provassimo ad avviare questo comando, vedremo che docker scarica, se non già presente, l'immagine di base per il dotnet, quindi, dopo la riga di informazione sul maintainer, verranno copiati i file locali dalla directory ./src/MVC5ForLinuxTest2/ nell'immagine e nel path /app. Lo stesso per il file start.sh. Quindi viene dato il flag di avvio a questo file e quando l'immagine sarà avviata, sarà eseguito proprio questo file. Il suo contenuto? E' questo:
#!/bin/sh cd app dotnet restore dotnet run
Naturalmente avremmo potuto creare già un'immagine compilata, ma questo caso ci aiuterà a comprendere un passaggio importante che vedremo più avanti.
La creazione di immagini non è lo scopo di questo post, quindi vado avanti anche perché la documentazione ufficiale è chiara a riguardo. Voglio proseguire perché il resto è una situazione che si sta evolvendo proprio in questo periodo che sto scrivendo questo post. Avevo trattato nei miei post precedenti il mondo dei micro service e sulla possibilità di distribuirli su più macchine. Proprio nell'ultimo post, prendevo in considerazione i vantaggi di Consul per il discovery dei servizi e altro. In quel periodo mi ero anche interessato sulla possibilità che anche docker potesse fare questo. Con la versione 1.1x, scopro che docker mette a disposizione in modo nativo la possibilità di un cluster di host dove saranno ospitati i vari container. Docker swarm mette a disposizione gli strumenti per fare questo ma solo dalla versione 1.12 il tutto è stato semplificato. Nelle versioni precedenti, dal mio punto di vista, era il delirio: nelle macchine che dovevano gestire il tutto dovevano essere collegate con Consul. Inoltre la configurazione di tutto era macchinosa e, per mie prove dirette, bastava un errore da niente nella configurazione per mandare all'aria il tutto - lo so, la colpa non è in docker ma è mia. Dalla versione 1.12 tutto è diventato banale anche se, lo dico subito, ci si ritrova con un bug subdolo che descriverò tra poco. Innanzitutto, cos'è Docker swarm? Non è nient'altro che la gestione di docker un cluster. Quello che abbiamo fatto prima su una singola macchina con i comandi di base di docker, con Docker swarm lo possiamo fare su più macchine senza preoccuparci di come configurare e il tutto. Tutto è semplice? Sì, eccome! Gli sviluppatori di Docker hanno creato un progetto interessante e veramente sbalorditivo per quello che promette e mantiene (al netto dei bug). Cominciando dall'inizio, cosa dobbiamo avere per mettere in piedi un cluster con Docker swarm? Una o più macchine che gestiranno tutti gli host collegati (nella documentazione ufficiale consigliano N/2+1 dove N è il numero di macchine ma scegliate oltre le sette macchine) definiti manager. Si può provare il tutto anche con macchine virtuali come ho fatto io per l'esempio di questo post ed è pressoché obbligatorio Linux (una qualsiasi distribuzione va bene, sconsigliate macchine Apple e Windows). Nel mio caso avevo due macchine con questi due ip:
192.168.0.15 192.168.0.16
La macchina che termina con 15 sarà il manager e la 16 la worker (di base anche la macchina manager sarà utilizzata per l'installazione dei container, anche se è possibile con un comando fare in modo che essa faccia solo da manager). Su questa macchina, da terminale, avviamo il tutto:
docker swarm init --advertise-addr 192.168.0.15
Se tutto funziona alla perfezione, la risposta sarà:
ReplY: swarm initialized: current node (83f6hk7nraat4ikews3tm9dgm) is now a manager. To add a worker to this swarm, run the following command: docker swarm join --token SWMTKN-1-0hmjrpgm14364r2kl2rkaxtm9tyy33217ew01yidn3l4qu3vaq-8e54w2m4mrwcljzbn9z2yzxrz 192.168.0.15:2377 To add a manager to this swarm, run 'docker swarm join-token manager' and follow the instructions.
Più chiaro di così non si può. La rete swarm è stata creata e possiamo aggiungere macchine manager o worker come descritto nel testo. Sulla macchina 16, dunque, per collegarla, scriviamo:
docker swarm join --token SWMTKN-1-0hmjrpgm14364r2kl2rkaxtm9tyy33217ew01yidn3l4qu3vaq-8e54w2m4mrwcljzbn9z2yzxrz 192.168.0.15:2377
Se la rete è configurata correttamente e se le porte necessarie non sono bloccate da firewall (verificare dalla documentazione di Docker swarm, a memoria non le ricordo), la risposta che avremo sarà:
This node joined a swarm as a worker.
Ora dalla manager, la 15, vediamo se è vero:
docker node ls ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS 83f6hk7nraat4ikews3tm9dgm * osboxes1 Ready Active Leader 897zy6vpbxzrvaif7sfq2rhe0 osboxes2 Ready Active
Vogliamo maggiori info tecniche?
docker info Containers: 0 Running: 0 Paused: 0 Stopped: 0 Images: 2 Server Version: 1.13.0-rc2 Storage Driver: aufs Root Dir: /var/lib/docker/aufs Backing Filesystem: extfs Dirs: 61 Dirperm1 Supported: true ... Kernel Version: 4.8.0-28-generic Operating System: Ubuntu 16.10 OSType: linux Architecture: x86_64 CPUs: 2 Total Memory: 1.445 GiB ...
Perfetto. Ora possiamo installare i nostri container e distribuirli in cluster. Per questo esempio ho creato una semplice web application con una web API che ritorna un codice univoco per ogni istanza. Il codice sorgete è pubblico e disponibile a questo url:
https://bitbucket.org/sbraer/aspnetcorelinux
Iscrivendosi gratuitamente in docker, potremo creare le nostre immagini, inoltre è stata introdotta da poco tempo la possibilità di eseguire build automatiche dai nostri dockerfile salvati in github o butbutcket. Ecco il link per l'esempio di questo post:
https://hub.docker.com/r/sbraer/aspnetcorelinux/
La comodità è che posso modificare il codice sorgente della mia app in locale, fare il commit su bitbucket dove ho un account gratuito, e dopo pochi minuti avere una immagine in docker pronta. E proprio quello di cui abbiamo bisogno per il nostro esempio.
docker service create --replicas 1 -p 5000:5000 --name app1 sbraer/aspnetcorelinux
Il comando in docker ora è leggermente differente. Si nota subito l'aggiunta di service: questo indica a docker che vogliamo lavorare nel cluster di swarm. Il comportamento è quasi simile a quello che abbiamo visto finora ma non potremmo collegarci da terminale nel metodo conosciuto. Prima di approfondire vediamo che è successo:
docker service ls ID NAME REPLICAS IMAGE COMMAND cx0n4fmzhnry app1 0/1 sbraer/aspnetcorelinux
E' stata scaricata l'immagine e sta per essere avviata. Dopo alcuni istanti potremo richiamare l'API e vedere il risultato:
curl localhost:5000/api/systeminfo [{"guid":"4160a903-dc66-4660-aafc-5ec8c9549869"}]
E lo potremo fare da tutte le macchine presenti nel cluster. E se volessimo installare più copie di questa app?
docker service scale app1=5
Ecco fatto: ora docker creerà altre quattro container che saranno distribuiti tra le due macchine:
docker service ps app1 ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR 6x8j50wn9475jc70fop0ezy7s app1.1 sbraer/aspnetcorelinux osboxes1 Running Running 6 minutes ago 1cydg0cr7re8suxluh2k7y0kc app1.2 sbraer/aspnetcorelinux osboxes2 Running Preparing 51 seconds ago dku0anrmfbscbrmxce9j7wcnn app1.3 sbraer/aspnetcorelinux osboxes2 Running Preparing 51 seconds ago 5vupi73j7jlbjmbzpmg1gsypr app1.4 sbraer/aspnetcorelinux osboxes1 Running Running 44 seconds ago e5a6xofjmxhcepn60xbm9ef7x app1.5 sbraer/aspnetcorelinux osboxes1 Running Running 44 seconds ago
Una volta avviate, vedremo che Docker swarm sarà in grado di bilanciare tutte le richieste (dal guid si può vedere la differenza di processo):
osboxes@osboxes2:~$ curl localhost:5000/api/systeminfo [{"guid":"4160a903-dc66-4660-aafc-5ec8c9549869"}] osboxes@osboxes2:~$ curl localhost:5000/api/systeminfo [{"guid":"6c9f1637-7990-4162-b69e-623afee378e6"}] osboxes@osboxes2:~$ curl localhost:5000/api/systeminfo [{"guid":"853b6cbb-6394-4a2e-87b9-2f9a7fa2af06"}] osboxes@osboxes2:~$ curl localhost:5000/api/systeminfo [{"guid":"4160a903-dc66-4660-aafc-5ec8c9549869"}] osboxes@osboxes2:~$ curl localhost:5000/api/systeminfo [{"guid":"6c9f1637-7990-4162-b69e-623afee378e6"}] osboxes@osboxes2:~$ curl localhost:5000/api/systeminfo [{"guid":"853b6cbb-6394-4a2e-87b9-2f9a7fa2af06"}] osboxes@osboxes2:~$ curl localhost:5000/api/systeminfo [{"guid":"4160a903-dc66-4660-aafc-5ec8c9549869"}] osboxes@osboxes2:~$ curl localhost:5000/api/systeminfo [{"guid":"6c9f1637-7990-4162-b69e-623afee378e6"}] osboxes@osboxes2:~$ curl localhost:5000/api/systeminfo [{"guid":"853b6cbb-6394-4a2e-87b9-2f9a7fa2af06"}] osboxes@osboxes2:~$ curl localhost:5000/api/systeminfo [{"guid":"4160a903-dc66-4660-aafc-5ec8c9549869"}]
Ora ho voglia di aggiungere una ulteriore informazione nella risposta dell'API. Decido di aggiungere anche data e ora. Creo un nuovo branch, master2, faccio la modifica, commit, creo una nuova immagine in docker con il tag dev. E se volessi aggiornare le cinque istanze che girano sulle mie macchine? Docker swarm fa tutto questo per me:
docker service update --image sbraer/aspnetcorelinux:dev app1
Ora docker fermerà una alla volta i container, lì aggiornerà e li avvierà ancora:
docker service ps app1 ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR 6x8j50wn9475jc70fop0ezy7s app1.1 sbraer/aspnetcorelinux osboxes1 Running Running 10 minutes ago 2g98f5qnf3tbtr83wf5yx0vcr app1.2 sbraer/aspnetcorelinux:dev osboxes2 Running Preparing 5 seconds ago 1cydg0cr7re8suxluh2k7y0kc \_ app1.2 sbraer/aspnetcorelinux osboxes2 Shutdown Shutdown 4 seconds ago dku0anrmfbscbrmxce9j7wcnn app1.3 sbraer/aspnetcorelinux osboxes2 Running Preparing 4 minutes ago 5vupi73j7jlbjmbzpmg1gsypr app1.4 sbraer/aspnetcorelinux osboxes1 Running Running 4 minutes ago e5a6xofjmxhcepn60xbm9ef7x app1.5 sbraer/aspnetcorelinux osboxes1 Running Running 4 minutes ago
Lasciandogli il tempo di aggiornare tutto, ecco il risultato:
curl localhost:5000/api/systeminfo [{"guid":"55d63afe-0b67-47d4-a1d2-4fb0b9b83bef","dateTime":"2016-11-26T21:14:20.411148+00:00"}] osboxes@osboxes2:~$ curl localhost:5000/api/systeminfo [{"guid":"e02997ad-ea05-418f-9be4-c1a9b71bff85","dateTime":"2016-11-26T21:14:25.617665+00:00"}] osboxes@osboxes2:~$ curl localhost:5000/api/systeminfo [{"guid":"ff0b1dfa-42e5-4725-ab11-6fdb83488ace","dateTime":"2016-11-26T21:14:27.157971+00:00"}] osboxes@osboxes2:~$ curl localhost:5000/api/systeminfo [{"guid":"0a7578fb-d7cf-4c6f-a1fa-07deb7cddbc0","dateTime":"2016-11-26T21:14:27.789131+00:00"}] osboxes@osboxes2:~$ curl localhost:5000/api/systeminfo [{"guid":"ce87341b-d445-49f6-ae44-0a62a844060e","dateTime":"2016-11-26T21:14:28.303101+00:00"}] osboxes@osboxes2:~$ curl localhost:5000/api/systeminfo [{"guid":"55d63afe-0b67-47d4-a1d2-4fb0b9b83bef","dateTime":"2016-11-26T21:14:28.873405+00:00"}]
Vogliamo fermare il tutto?
docker service rm app1
Interessante, inoltre, è la capacità di docker di prevenire eventuali disastri esterni. Se nel mio caso, spegnessi la macchina 16, docker se ne accorgerebbe, non invierebbe più richieste alle API presenti su quella macchina, e immediatamente avvierebbe lo stesso numero di container persi in quella macchina in altre presenti nel cluster.
E se volessi fare come nel primo esempio, vedere il log di un preciso container? Purtroppo questo non è proprio facile in docker. Innanzitutto è necessario andare sulla macchina dove è installato e scrivere:
docker ps -a
Quindi, come visto nel caso del parametro --name non assegnato, vedere l'output di questo comando per estrapolarne il nome e connettendosi poi. Non proprio comodo.
Tutto magnifico dunque... no, perché come qualcuno può avere intuito, c'è un problema di base nella gestione di cluster di immagini in docker swarm. Abbiamo visto che possiamo scalare un'immagine e automaticamente docker la installerà su quella o su altre macchine; ma, riprendendo l'esempio della nostra API, quando questa sarà disponibile dalla gestione di bilanciamento di docker? E qui nasce il problema: lui manterrà scollegata la macchina in creazione dal load balancer interno fino a quando questa sarà avviata: e il servizio, come in questo caso, è lento a partire perché scarica dipendenze e compila, che succede? Semplice, docker metterà a disposizione quelle macchine che non sapranno gestire la riposta:
curl localhost:5000/api/systeminfo [{"guid":"55d63afe-0b67-47d4-a1d2-4fb0b9b83bef","dateTime":"2016-11-26T21:14:20.411148+00:00"}] osboxes@osboxes2:~$ curl localhost:5000/api/systeminfo curl: (6) Couldn't resolve host 'localhost' osboxes@osboxes2:~$ curl localhost:5000/api/systeminfo curl: (6) Couldn't resolve host 'localhost' osboxes@osboxes2:~$ curl localhost:5000/api/systeminfo curl: (6) Couldn't resolve host 'localhost' osboxes@osboxes2:~$ curl localhost:5000/api/systeminfo [{"guid":"ce87341b-d445-49f6-ae44-0a62a844060e","dateTime":"2016-11-26T21:14:28.303101+00:00"}] osboxes@osboxes2:~$ curl localhost:5000/api/systeminfo curl: (6) Couldn't resolve host 'localhost'
Ed ecco il primo problema... Come risolverlo? Per fortuna c'è una soluzione semplice. Nel Dockerfile che crea l'immagine, possiamo usare un comando apposito che rende disponibile l'immagine solo se un comando dà risposta positiva. Ecco il nuovo Dockerfile:
# Example from AZ FROM microsoft/dotnet:1.0.1-sdk-projectjson MAINTAINER "AZ" COPY ["./src/MVC5ForLinuxTest2/", "/app"] COPY ["./start.sh", "."] RUN chmod +x ./start.sh HEALTHCHECK CMD curl --fail http://localhost:5000/api/systeminfo || exit 1 CMD ["./start.sh"]
HEALTHCHECK non fa altro che dire a docker se quel container funziona correttamente, e lo fa eseguendo il comando che verifica se il servizio funziona correttamente - nel mio caso fa una richiesta all'API e se solo risponde positivamente il container viene agganciato al load balancer di docker, questo è comodo anche per verificare che la nostra API non smetta di funzionare per motivi suoi e, in questo caso, può avvertire docker del problema. Perfetto... Proviamo il tutto ed ecco l'output dopo aver aggiunto altre istanze della stessa webapp:
curl localhost:5000/api/systeminfo [{"guid":"55d63afe-0b67-47d4-a1d2-4fb0b9b83bef","dateTime":"2016-11-26T21:14:20.411148+00:00"}] osboxes@osboxes2:~$ curl localhost:5000/api/systeminfo curl: (6) Couldn't resolve host 'localhost' osboxes@osboxes2:~$ curl localhost:5000/api/systeminfo curl: (6) Couldn't resolve host 'localhost'
Ma che succede? Purtroppo nella versione attuale, la 1.12, il controllo nel caso di cluster swarm non funziona correttamente. Facendo delle prove personali, sembra che l'healthcheck invii la richiesta a tutto il cluster che ovviamente risponderà positivamente... Purtroppo non ci sono scappatoie ma per fortuna questo bug è stato risolto con la versione 1.13 (ora in RC, ma che dovrebbe essere rilasciata entro metrà mese di dicembre). Infatti, installata la versione 1.13, questo problema scompare - ho verificato di persona. A proposito di quest'ultima versione, è stata rilasciata anche la funzionalità di fare rollback dell'immagine in automatico, ma per ora non ho potuto controllare di persona se la cosa funziona. Inoltre - ed era ora - in experimental è stato inserito il comando per la visualizzazione del log all'interno dello swarm.
E' ora di tirare qualche conclusione personale: con la versione 1.13 il tutto è così facile da far impallidire qualsiasi altra scelta per la distribuzione dei propri service; kubernetes di Google appare fin troppo complicato a riguardo, e anche la soluzione che avevo mostrato con Consul sembra molto più macchinosa. Inoltre sembra che il futuro sia nei containers (pure Microsoft in Azure sta implementando il tutto per renderne l'uso più facile possibile). Inutile dire che la procedura che ho descritto qui sopra, funziona perfettamente sia nel caso di una piccola web farm e sia che si decida di passare al mondo del cloud.
Interessante... altro che...
Per inserire un commento, devi avere un account.
Fai il login e torna a questa pagina, oppure registrati alla nostra community.
- Docker Swarm e constraint in un mondo reale, il 29 dicembre 2016 alle 18:04
- Docker + Consul + Registrator, il 23 dicembre 2016 alle 14:48
- AMD/UMD in javascript, tanto per ricordarmi, il 15 dicembre 2016 alle 18:54
- Seneca.js, message broker e infine Consul, il 3 agosto 2016 alle 20:59
- Cross apply con i campi XML, il 10 luglio 2009 alle 09:22