Distribuzione blu-verde con Docker e Nginx

Published Aug 26, 2016 Updated Aug 30, 2016

Distribuzione blu-verde con Docker e l'immagine di Nginx

In Klokan Technologies sviluppiamo principalmente servizi software e li eseguiamo come contenitori Docker. Per rilasciare nuove versioni, utilizziamo la tecnica di distribuzione blue-green. Questo riduce i tempi di inattività e limita l'impatto degli errori di configurazione. L'idea di base è semplice. Invece di avere un solo ambiente di produzione, ce ne sono due identici: blu e verde. Questi si alternano nell'esecuzione attiva del servizio. Una nuova versione viene distribuita nell'ambiente che non è attualmente attivo. Solo quando il servizio si avvia con successo e supera tutti i controlli di salute, quell'ambiente viene contrassegnato come attivo. Il vecchio ambiente attivo viene quindi fermato e preparato a ricevere la distribuzione successiva. Il passaggio da un ambiente attivo all'altro è un passaggio cruciale. Se non è atomico, ci sarà un breve periodo in cui nessuno dei due ambienti è attivo e qualsiasi richiesta in arrivo in quel momento fallirà. Utilizziamo Nginx per questo scopo perché ha questa capacità e perché lo abbiamo comunque come reverse proxy.

Esempio

Per illustrare l'intero processo, consideriamo un esempio. Distribuiremo un'applicazione Python in un file chiamato ciao.pyelencati di seguito. Si mette in ascolto per le richieste HTTP sulla porta 9000 e risponde con un saluto, fornendo un servizio semplice.

$ cat hello.py
da wsgiref.simple_server import make_server

GREETING = b'Hello, world!\n'

def hello(environ, start_response):
        start_response('200 OK', [('Content-Type', 'text/plain')])
    return [GREETING]

make_server('0.0.0.0', 9000, hello).serve_forever()

Avremo un contenitore per l'applicazione e uno per Nginx. Li metteremo entrambi sulla stessa rete Docker, in modo che possano vedersi a vicenda. Nel nostro ambiente di produzione, abbiamo reti separate per il backend e il frontend, ma qui non è necessario. Utilizzeremo immagini Docker ufficiali.

$ docker network create example
$ docker pull nginx
$ docker pull python:3

Per prima cosa avviamo l'applicazione stessa nell'ambiente BLUE. Si noti che il nome del contenitore è ciao-BLUE.

$ docker run \
    --nome hello-BLUE \
    -v $(pwd)/hello.py:/usr/local/src/hello.py \
    --net=esempio \
    -d \
    python:3 \
    python /usr/local/src/hello.py

Poi si inserisce la configurazione dell'applicazione per Nginx in un file chiamato nginx-conf.d/hello.conf. Imposta un proxy HTTP che inoltra tutte le richieste all'applicazione. Anche in questo caso, dobbiamo fare riferimento al contenitore dell'applicazione come ciao-BLUE.

$ cat nginx-conf.d/hello.conf
server {
    listen 80;
    location / {
            proxy_pass http://hello-BLUE:9000;
    }
}

Ora possiamo avviare Nginx. Leggerà il file di configurazione appena creato e pubblicherà il proxy dell'applicazione sulla porta 8080.

$ docker run \
    --nome nginx \
    -v $(pwd)/nginx-conf.d:/etc/nginx/conf.d \code(0144)\
    --net=esempio \
    -p 8080:80 \
    -d \
    nginx

Verificare che funzioni.

$ curl http://localhost:8080
Ciao, mondo!

Ora creiamo una nuova versione del servizio, cambiando il saluto nella cartella ciao.py file.

$ cat hello.py
from wsgiref.simple_server import make_server

GREETING = b'Hello, world! (VERSION 2)\n'  # <=== Change here

def hello(environ, start_response):
        start_response('200 OK', [('Content-Type', 'text/plain')])
    return [GREETING]

make_server('0.0.0.0', 9000, hello).serve_forever()

Avviamo nuovamente l'applicazione, questa volta nell'ambiente GREEN. Si noti la modifica del nome del contenitore. Per il resto, il comando è lo stesso di prima.

$ docker run \
    --name hello-GREEN \  # <=== Change here.
    -v $(pwd)/hello.py:/usr/local/src/hello.py \
    --net=example \
    -d \
    python:3 \
    python /usr/local/src/hello.py

Dobbiamo cambiare il nome del contenitore dell'applicazione anche nella configurazione di Nginx.

$ cat nginx-conf.d/hello.conf
server {
    listen 80;
    location / {
            proxy_pass http://hello-GREEN:9000;  # <=== Change here
    }
}

Prima di cambiare ambiente attivo, dobbiamo verificare che la configurazione sia corretta e che l'applicazione sia raggiungibile. Esiste un'opzione da riga di comando di Nginx per questo, quindi la eseguiamo in un contenitore temporaneo.

$ docker run \
    --rm \
    -v $(pwd)/nginx-conf.d:/etc/nginx/conf.d \
    --net=esempio \
    nginx
    nginx -t
nginx: la sintassi del file di configurazione /etc/nginx/nginx.conf è corretta
nginx: il test del file di configurazione /etc/nginx/nginx.conf ha avuto successo

Se il controllo ha avuto successo, inviamo al contenitore Nginx un segnale SIGHUP. In questo modo il contenitore rileggerà la configurazione e si riavvierà senza interrompere alcuna richiesta.

$ docker kill -s HUP nginx

E possiamo vedere che è stata distribuita una nuova versione.

$ curl http://localhost:8080
Ciao, mondo! (VERSIONE 2)

L'ambiente BLU non è più necessario, quindi lo rimuoviamo.

$ docker stop hello-BLUE
$ docker rm hello-BLUE

Conclusione

Nel nostro esempio, abbiamo un solo contenitore di applicazioni per il servizio. Potrebbero essercene altri e tutti verrebbero manipolati insieme. Potrebbero anche esserci più servizi in esecuzione sulla stessa macchina. Ognuno di essi avrebbe i propri ambienti BLU e VERDE. Il contenitore Nginx e altri contenitori di infrastruttura con stato non vengono distribuiti con questa tecnica. Ciò include i database e la maggior parte delle cache. Non è possibile arrestare o riavviare i database perché gli ambienti attivi li utilizzano anche durante il passaggio e di solito non vogliamo cancellare le cache a ogni distribuzione. C'è dell'altro per rendere questo approccio praticabile per la distribuzione automatica. Non abbiamo detto come determinare quale ambiente è attualmente attivo per un determinato servizio e macchina. Inoltre, la modifica manuale dei file di configurazione prima di ogni distribuzione non è chiaramente la strada da seguire. In Klokan Technologies utilizziamo Ansible con un modulo personalizzato per risolvere entrambi i problemi, ma questa è una storia per un altro giorno. Potrebbero anche esserci più servizi in esecuzione sulla stessa macchina. Ognuno di essi avrebbe i propri ambienti BLU e VERDE.

Vaclav Klusak

Senior Developer
Published on Aug 26, 2016

Scopri MapTiler in francese!

Visita il sito maptiler.fr

Přečtěte si více v češtině

Více na maptiler.cz

Leggi di più in spagnolo

Visita maptiler.es

Di più in olandese

Vai a maptiler.nl

日本語で詳細をみる

maptiler.jp へ

Altre informazioni sono disponibili

su MapTiler.de

ديزملا فشتكإ

maptiler.ae ىلإ لقتنا

Esplora MapTiler in Svizzera

Visita MapTiler.ch