Dockerized Apache Hadoop
Website http://dassia.crs4.it
Address CRS4 - Centro di Ricerche, Sviluppo e Studi Superiori della Sardegna
POLARIS, Edificio 1, 09010 PULA (CA), Italia
Sommario Esempio di dockerizzazione del framework Apache Hadoop e
configurazione dell’infrastruttura Docker per eseguirlo.
Indice
1
Introduzione
2
Apache Hadoop Dockerization
2.1 Definizione Dockerfiles . . . . . . . . . . . . . . .
2.2 Compilazione delle immagini Docker . . . . . .
2.3 Eseguire un’immagine Docker . . . . . . . . . .
2.4 Esecuzione multi-container con Docker Compose
2.5 Esecuzione distribuita su cluster Docker Swarm .
2.5.1 Creazione di un cluster Docker Swarm .
2
.
.
.
.
.
.
2
2
7
8
11
15
15
3
Docker Cluster Setup: Weave + Swarm
3.1 Creazione di una Weave Network . . . . . . . . . . . . . . . . . . . . . . . .
3.2 Swarm Cluster su Weave Network . . . . . . . . . . . . . . . . . . . . . . . .
19
20
23
4
Guida all’esempio completo
4.1 Prerequisiti . . . . . . . . . . . . . . . . . . . . . . .
4.1.1 Configurazione del cluster AWS . . . . . .
4.1.2 Requisiti Software . . . . . . . . . . . . . .
4.2 Creazione del cluster Swarm su rete Weave . . . .
4.3 Esecuzione dockerized Hadoop su cluster Swarm
23
23
24
24
25
25
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
Copyright © 2015 CRS4.
1
Introduzione
La disponibilità di cluster di calcolatori costituisce un prerequisito indispensabile per poter sfruttare i vantaggi offerti dalla potenza di calcolo dei tool specificatamente progettati
per l’elaborazione di BigData. I sempre più numerosi player che si affacciano sul mercato
per offrire nuove soluzioni commerciali di infrastrutture di calcolo sul cloud (i.e., Infrastructure as a Service (IaaS), quali Amazon Web Services (AWS), IBM SmartCloud Enterprise,
Google Cloud Computing Engine, etc.) costituiscono sempre più una valida e conveniente
alternativa al cluster proprietario.
Le procedure di configurazione e deployment dei tool software per l’elaborazione di
Big Data risultano spesso lunghe e complesse, per via della loro natura intrinsecamente
distribuita e della conseguente potenziale eterogeneità degli ambienti software e delle
macchine fisiche impiegate per la loro esecuzione. In quest’ottica, soluzioni che consentano di definire in modo standardizzato un ambiente software per poterlo eseguire su
piattaforme HW/SW eterogenee risultano essere di grande aiuto.
In questo tutorial, prendiamo in esame i principali passi per ‘predisporre‘ uno dei più
importanti e noti tool per l’elaborazione dei Big Data perché ne si possa facilmente effettuare il deployment su una generica piattaforma per il calcolo distribuito, eventualmente
ospitata sul cloud. In particolare, le principali tecnologie oggetto di questo tutorial sono:
– Apache Hadoop [5], come software per l’elaborazione di Big Data;
– Docker [13], come tecnologia per standardizzare e semplificare il processo di deployment ed esecuzione del menzionato tool, con finalità di sviluppo e test;
– AWS [1], come piattaforma distribuita di cloud computing per il deployment test.
2
Apache Hadoop Dockerization
In questa sezione descriviamo come predisporre Hadoop e i suoi servizi affinché possano
essere eseguiti sull’infrastruttura Docker. Ciò consiste nel definire l’ambiente in cui tali
servizi dovranno essere eseguiti attraverso un Dockerfile.
2.1
Definizione Dockerfiles
Un Dockerfile definisce la sequenza di comandi che automatizzano la costruzione dell’ambiente ottimale per l’esecuzione di un’applicazione o servizio. Esso assume una forma
del tipo di quella riportata nello snippet di codice 1:
2
1
2
# Set Ubuntu as base image
FROM ubuntu : latest
3
4
5
# Set noninteractive mode
# ENV DEBIAN_FRONTEND noninteractive
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# Install basic devtools
RUN apt - get update && \
apt - get install -y - qq build - essential \
software - properties - common \
python - setuptools \
python - all - dev \
python - pip \
ipython \
libssl - dev zip \
wget git \
openssh - server openssh - client \
dnsutils nano \
nfs - common inotify - tools
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
# Install Java8 and set JAVA_HOME
# - Java version to be installed
ENV JAVA_VERSION 8
# --> accept license
RUN echo debconf shared / accepted - oracle - license - v1 -1 select true
| \
sudo debconf - set - selections && \
echo debconf shared / accepted - oracle - license - v1 -1 seen true |
\
sudo debconf - set - selections
# --> install
RUN add - apt - repository ppa : webupd8team / java && \
apt - get update && \
apt - get install -y oracle - java$ { JAVA_VERSION } - installer
# --> set JAVA_HOME
ENV JAVA_HOME / usr / lib / jvm / java - $ { JAVA_VERSION } - oracle
RUN echo " export JAVA_HOME = $ { JAVA_HOME }" >> / etc / profile
Snippet 1: "Esempio di Dockerfile: l’immagine hadoop-base"
Senza entrare nel dettaglio della sintassi per la definizione di un Dockerfile (per la
3
images
base
hadoop
v2
version
2.6.0
Figura 1: Gerarchia delle immagine Docker utilizzate nel tutorial
quale si rimanda a [15]), osserviamo le seguenti proprietà del Dockerfile dello snippet 1:
– l’immagine deriva direttamente da una distribuzione Linux Ubuntu (istruzione
FROM alla riga 2);
– contiene una serie di software di base, e.g., Python, git, etc., (istruzioni RUN alle
righe 8-19, 26-29, etc.);
– imposta una serie di variabili d’ambiente (istruzioni ENV alle righe 5, 24, 35).
La possibilità di definire una nuova immagine a partire da una preesistente favorisce
la modularizzazione, il riuso e la costruzione incrementale delle immagini. L’immagine
costruita mediante il Dockerfile nello snippet 1, ad esempio, si caratterizza per una
tale genericità1 da poter essere utilizzata come base per ulteriori estensioni e può essere
impiegato in molteplici scenari d’uso: in particolare, costituirà la base per le ulteriori
immagini presentate in questo tutorial.
Le immagini di riferimento per questo tutorial sono organizzate come mostra la figura
1, dove l’immagine base viene progressivamente estesa con script di utilità e vari file di
configurazione necessari al funzionamento dell’immagine finale hadoop-apache-2.6.0
contenente l’installazione completa di Apache Hadoop 2.6.0.
In particolare:
– l’immagine hadoop-apache-v2 (snippet 2) soddisfa, rispetto a quella base, alcuni
ulteriori requisiti di Apache Hadoop e utilities:
1. Si tratta, infatti, di un ambiente Ubuntu base con pochi pacchetti aggiuntivi di sviluppo
installati.
4
· settaggi d’ambiente (e.g., le istruzioni ENV che riguardano le variabili d’ambiente HADOOP_CONF_DIR, HADOOP_HOME e PATH, sulla quale vengono aggiunti
gli eseguibili Hadoop, etc.);
· vari script necessari all’avvio dei servizi dell’HDFS (i.e., Namenode, Datanode)
e del MapReduce di Hadoop (i.e., Resourcemanager, Nodemanager, etc.);
1
2
# Set hadoop -2. x as base image
FROM crs4 / hadoop - apache - base
3
4
5
6
7
8
9
10
# Set HADOOP ENV
ENV HADOOP_HOME / opt / hadoop
ENV HADOOP_CONF_DIR $ { HADOOP_HOME }/ etc / hadoop
ENV HADOOP_DATA_DIR $ { HADOOP_HOME }/ data
ENV HADOOP_LOG_DIR $ { HADOOP_HOME }/ logs
ENV HDFS_DATA_DIR $ { HADOOP_DATA_DIR }/ hdfs
ENV YARN_DATA_DIR $ { HADOOP_DATA_DIR }/ yarn
11
12
13
RUN echo " export HADOOP_HOME = $ { HADOOP_HOME }" >> / home / $ {
DEFAULT_USER }/. profile
RUN echo " export HADOOP_CONF_DIR = $ { HADOOP_CONF_DIR }" >> / home / $
{ DEFAULT_USER }/. profile
14
15
16
17
18
# Update $PATH to include $ { HADOOP_HOME }/ bin
ENV PATH $ { PATH }: $ { HADOOP_HOME }/ bin : $ { HADOOP_HOME }/ sbin
RUN echo " export PATH = $ { PATH }: $ { HADOOP_HOME }/ bin : $ { HADOOP_HOME
}/ sbin " >> / etc / profile
RUN echo " export PATH = $ { PATH }: $ { HADOOP_HOME }/ bin : $ { HADOOP_HOME
}/ sbin :/ home / $ { DEFAULT_USER }/. local / bin " >> / home / $ {
DEFAULT_USER }/. profile
19
20
21
22
23
24
25
# Copy ’ hadoop - admin ’ scripts
ADD scripts / start - resourcemanager . sh $ { H A D O O P _ A D M I N _ S C R I P T S }/
start - resourcemanager . sh
ADD scripts / start - nodemanager . sh $ { H A D O O P _ A D M I N _ S C R I P T S }/ start nodemanager . sh
ADD scripts / start - namenode . sh $ { H A D O O P _ A D M I N _ S C R I P T S }/ start namenode . sh
ADD scripts / start - datanode . sh $ { H A D O O P _ A D M I N _ S C R I P T S }/ start datanode . sh
ADD scripts / start - historyserver . sh $ { H A D O O P _ A D M I N _ S C R I P T S }/
start - historyserver . sh
5
26
27
ADD scripts / init - hdfs - folders . sh $ { H A D O O P _ A D M I N _ S C R I P T S }/ init hdfs - folders . sh
ADD scripts / start - hadoop - services . sh $ { H A D O O P _ A D M I N _ S C R I P T S }/
start - hadoop - services
28
29
30
# Set PATH of the default Apache Hadoop v2 configuration
ENV H A D O O P _ C U S T O M _ C O N F _ D I R / opt / hadoop - v2 - conf - base
31
32
33
# Copy configuration files ( hadoop v2 )
COPY config /* $ { H A D O O P _ C U S T O M _ C O N F _ D I R }/
34
35
36
# Set the default command
CMD [" start - hadoop - services "]
Snippet 2: Dockerfile per l’immagine hadoop-apache-v2
– l’immagine finale hadoop-apache-2.6.0 (snippet 2) è il risultato dell’installazione
e deployment dell’archivio contenente la distribuzione della specifica di Hadoop
di riferimento in questo tutorial, i.e., Hadoop 2.6.0.
1
2
# Set hadoop -2. x as base image
FROM crs4 / hadoop - apache - v2
3
4
5
# set hadoop version
ENV HADOOP_VERSION 2.6.0
6
7
8
# set hadoop tar . gz archivename
ENV H A D O O P _ A R C H I V E _ T A R G Z hadoop - $ { HADOOP_VERSION }. tar . gz
9
10
11
# copy temp files ( e . g . , the optional H A D O O P _ A R C H I V E _ T A R G Z )
COPY * ./
12
13
14
# download hadoop distro
RUN $ { H A D O O P _ A D M I N _ S C R I P T S }/ deploy - hadoop . sh . $ {
H A D O O P _ A R C H I V E _ T A R G Z } $ { HADOOP_VERSION } $ { HADOOP_HOME }
15
16
17
# Copy configuration files ( hadoop v2 )
RUN cp $ { H A D O O P _ C U S T O M _ C O N F _ D I R }/* $ { HADOOP_CONF_DIR }/
Snippet 3: Dockerfile per l’immagine hadoop-2.6.0
6
2.2
Compilazione delle immagini Docker
A partire dai Dockerfile definiti nella sezione 2.1 è possibile ottenere le corrispondente
immagini mediante il seguente comando Docker2 :
docker build -t < IMAGE_NAME > < PATH_TO_DOCKERFILE >
Snippet 4: Comando per la creazione di un immagine Docker a partire da un Dockerfile.
. . . dove:
– IMAGE_NAME è il nome che si vuole assegnare all’immagine (e.g., hadoop-apache-2.6.0);
– PATH_TO_DOCKERFILE è il path del Dockerfile che definisce l’immagine da creare.
Una volta compilate, le immagini possono essere caricate su repository specializzati nell’ospitare immagini Docker, offrendo, inoltre, strumenti per gestirne il versioning.
Esistono principalmente due tipologie di Docker repository:
– Docker Hub3 , il Docker repository pubblico, gestito direttamente da Docker Inc;
– Docker Registry (DR) e Docker Trusted Registry (DTR)4 , repository privati ospitabili e
gestibili all’interno della propria organizzazione.
L’interazione con un Docker Repository avviene mediante i due seguenti comandi:
1. docker pull <IMAGE_NAME>: consente di scaricare un’immagine, così da poterla
’eseguire’;
2. docker push <IMAGE_NAME>: consente di caricare un’immagine su un Docker registry.
Le immagini utilizzate in questo tutorial sono reperibili dal repository publico del
CRS4 sul Docker Hub, il cui contenuto può essere listato mediante il comando:
docker search crs4
Snippet 5: Produce l’elenco delle immagini presenti nel repository del CRS4 sul Docker Hub.
2. Si rimanda a [14] per ulteriori dettagli sul comando docker build.
3. Il sito ufficiale del Docker Hub è raggiungibile all’indirizzo https://hub.docker.com
4. Informazioni dettagliate su come installare e configurare un Docker Registry sono reperibili agli indirizzi https://docs.docker.com/registry/deploying/ ([7]) e https://docs.docker.
com/docker-trusted-registry/([19]).
7
. . . il cui output è del seguente tipo:
NAME
c r s 4 /hadoop−apache−v2
c r s 4 /hadoop−apache − 2 . 7 . 1
c r s 4 /hadoop−apache − 2 . 2 . 0
c r s 4 /hadoop−apache − 2 . 6 . 0
c r s 4 /hadoop−apache − 2 . 4 . 1
c r s 4 /hadoop−apache − 2 . 3 . 0
c r s 4 /hadoop−apache − 2 . 5 . 2
c r s 4 /hadoop−apache−base
c r s 4 /hadoop−base
DESCRIPTION
A b a s i c image f o r Apache Hadoop V2 s e r v i c e s
Dockerized Apache Hadoop 2 . 7 . 1
Dockerized Apache Hadoop 2 . 2 . 0
Dockerized Apache Hadoop 2 . 6 . 0
Dockerized Apache Hadoop 2 . 4 . 1
Dockerized Apache Hadoop 2 . 3 . 0
Dockerized Apache Hadoop 2 . 5 . 2
A b a s i c image f o r Apache Hadoop s e r v i c e s
A b a s i c machine with j a v a and o t h e r develo . . .
STARS
0
0
0
0
0
0
0
0
0
OFFICIAL
AUTOMATED
[OK]
[OK]
[OK]
[OK]
[OK]
[OK]
[OK]
[OK]
[OK]
Snippet 6: Elenco delle immagini presenti nel repository del CRS4 sul Docker Hub.
É possibile ottenere l’elenco delle immagini presenti nel proprio sistema (localmente
create o scaricate da repository) mediante il comando:
docker images
Snippet 7: Comando Docker per ottenere la lista delle immagini.
. . . il cui output è della seguente forma:
$ docker images
REPOSITORY
c r s 4 /hadoop−apache − 2 . 6 . 0
c r s 4 /hadoop−apache−v2
c r s 4 /hadoop−apache−base
c r s 4 /hadoop−nfs −s e r v e r
c r s 4 /hadoop−base
weaveworks/scope
weaveworks/weaveexec
weaveworks/weave
ubuntu
ubuntu
TAG
latest
latest
latest
latest
latest
0.8.0
v1 . 1 . 0
v1 . 1 . 0
latest
IMAGE ID
7 a68d024f28a
8573 f59b1cd5
144 f 2 7 4 5 7 e b 8
605 c52d13fd7
16 c 0 f f 1 d 5 8 b 2
3 ad67db96d92
69 c 6 b f a 7 9 3 4 f
5 dccf0533147
91 e54dfb1179
CREATED
31 hours ago
31 hours ago
31 hours ago
31 hours ago
31 hours ago
5 days ago
4 weeks ago
4 weeks ago
6 weeks ago
VIRTUAL SIZE
1 . 5 7 4 GB
1 . 0 6 6 GB
1 . 0 6 6 GB
1 . 0 9 3 GB
1 . 0 6 6 GB
5 7 . 5 8 MB
5 8 . 1 8 MB
1 7 . 5 3 MB
1 8 8 . 4 MB
Snippet 8: Lista delle immagini Docker presenti sul sistema.
2.3
Eseguire un’immagine Docker
L’esecuzione di un’immagine Docker può avvenire secondo due principali differenti
modalità:
– foreground (modalità interattiva): all’avvio dell’immagine nel container, una console
viene collegata (attached) a quest’ultimo e l’utente può direttamente impartire i
comandi da eseguire sul container;
8
– background o detached(-d): il contenuto dell’immagine viene eseguito in background,
senza nessun output diretto sulla console da cui viene eseguito.
La sintassi generale per avviare l’esecuzione di un’immagine su un container Docker
è la seguente:
$ docker run [ OPTIONS ] IMAGE [: TAG | @DIGEST ] [ COMMAND ] [ ARG ...]
Snippet 9: Sintassi generale del comando docker run.
. . . in cui:
– IMAGE[:TAG|@DIGEST] è l’identificatore dell’immagine (i.e., nome + eventuale tag
o digest);
– OPTIONS, è un insieme di opzioni per l’avvio del container, tra cui è interessante
ricordare le seguenti principali5 :
· -it, predispone il container perché possa essere utilizzato in modalità interattiva:
· -d, avvia il container in background mode;
· -p [HOST_PORT:]<CONTAINER_PORT>, espone la porta CONTAINER_PORT del container sulla porta HOST_PORT del Docker host. Nel caso in cui la HOST_PORT
non venga specificata, viene utilizzata un porta scelta casualmente fra quelle
disponibili nel docker host.
– COMMAND [ARG...] è il comando (con i suoi eventuali argomenti) che può essere
fornito perché venga eseguito all’avvio del container.
Nel caso dell’immagine principale associata a questo tutorial, i.e., crs4/hadoop-apache-2.6.0,
è possibile eseguirla all’interno di un singolo container Docker mediante il seguente
comando:
$ docker run - it \
-- name hadoop -2.6.0 - single - container \
-p 8088:8088 \
-p 8042:8042 \
-p 19888:19888 \
-p 50070:50070 \
5. Si rimanda al sito https://docs.docker.com/reference/run [9] per maggiori informazioni
sulla sintassi e le opzioni disponibili per il comando docker run.
9
crs4 / docker - hadoop -2.6.0 start - hadoop - services
Snippet 10: Esecuzione in modalità interattiva dell’immagine crs4/hadoop-apache-2.6.0 su
singolo container.
. . . al termine del quale l’utente si ritrova davanti ad una shell bash, con tutti i servizi
Hadoop in esecuzione. L’utente di default è hduser, con password hadoop.
Si noti, inoltre, come, nell’avviare il container, sia stato anche richiesto il mapping
delle porte utili all’amministrazione e monitoring dei principali servizi offerti da Hadoop,
ovvero:
– ResourceManager, la cui WebConsole è raggiungibile sulla porta 8088 del container
o docker host;
– il NodeManager, la cui interfaccia Web di monitoraggio è accessibile alla porta 8042
del container o docker host;
– il NameNode, che, alla porta 50070 del container o docker host, consente di navigare
l’HDFS;
– l’HistoryServer, che consente la consultazione dello storico dei job MapReduce
eseguiti, sulla porta 19888 del container o docker host.
All’uscita dalla shell bash il container viene fermato e passa nello stato di Exited, da
cui può tornare a quello di Running mediante il comando:
docker restart < CONTAINER_ID | CONTAINER_NAME >
Snippet 11: Comando per il riavvio di un Docker Container.
o essere definitamente rimosso mediante il comando:
docker rm < CONTAINER_ID > | < CONTAINER_NAME >
Snippet 12: Comando per la rimozione di un Docker Container
Maggiori informazioni sul ciclo di vita di un Docker Container e sui comandi per la
sua gestione possono essere reperite all’indirizzo https://docs.docker.com/userguide/
usingdocker/ [20].
Due comandi utili per verificare quali container siano attivi ed il loro stato sono:
– docker ps [-a], il quale mostra l’elenco dei container che sono stati mandati in
esecuzione, fornendone varie informazioni (si veda 13) quali l’identificatore (ID),
10
l’immagine associata (IMAGE), il comando eseguito all’avvio del container (COMMAND),
il mapping delle porte container–>host (PORT) ed il nome del container (NAME);
– docker logs <CONTAINER_ID | CONTAINER_NAME>, il quale mostra l’output prodotto dall’esecuzione dell’immagine all’interno del container (utile, in particolare,
nel caso di container detached, ovvero eseguiti in background).
CONTAINER ID
IMAGE
COMMAND
CREATED
83 a 3 f 3 6 1 a c a 8
c r s 4 /hadoop−apache − 2 . 6 . 0 " s t a r t −hadoop− s e r v i c e " 25 seconds ago
0.0.0.0:8088 − >8088/ tcp
happy_wright
STATUS
PORTS
NAMES
Up 24 seconds
Snippet 13: Esempio di output del comando docker ps.
2.4
Esecuzione multi-container con Docker Compose
Nei casi in cui l’applicazione che si desideri virtualizzare mediante Docker sia composta
da più servizi (disponibili sotto forma di una o più immagini Docker), è possibile organizzare la loro esecuzione su più container (e.g., uno o più per servizio) mediante un
ulteriore strumento che fa parte dell’ecosistema Docker: Docker Compose.
Docker Compose essenzialmente consente di “definire ed eseguire applicazioni multicontainer con Docker.”, ovvero di “[..] definire un’applicazione multi-container in un singolo
file e far girare l’applicazione con un singolo comando che fa ogni ogni cosa necessaria alla sua
esecuzione”[18].
La specifica di come i diversi servizi (dockerizzati in altrettante immagini) devono
essere messi insieme e collegati è definita mediante un singolo file YAML, il cui nome di
default6 è docker-compose.yml.
Rimandando a [8] per la documentazione di riferimento per la redazione di un
docker-compose.yml sintatticamente e semanticamente corretto, riportiamo, di seguito, un frammento di possibile docker-compose file per l’esecuzione multi-container dei
servizi Hadoop presenti nella già menzionata immagine crs4/hadoop-apache-2.6.0.
namenode :
image : crs4 / hadoop - apache -2.6.0
name : namenode
hostname : namenode
domainname : hadoop . docker . local
6. É possibile scegliere un qualsiasi nome per il docker-compose file a patto di precisarlo
esplicitamente quando si usi il comand docker-compose
11
container_name : namenode
privileged : true
volumes_from :
- client
ports :
- " 9000:9000 "
- " 50070:50070 "
environment :
- SERVICE_NAME = namenode
- SERVICE_REGION = hadoop
- " affinity : container !=* datanode * "
dns : 172.17.42.1
dns_search : hadoop . docker . local
command : start - namenode . sh
datanode :
image : crs4 / hadoop - apache -2.6.0
name : datanode
# hostname : datanode
domainname : hadoop . docker . local
# container_name : datanode
privileged : true
volumes_from :
- client
environment :
- SERVICE_NAME = datanode
- SERVICE_REGION = hadoop
- " affinity : container !=* namenode * "
- " affinity : container !=* datanode * "
dns : 172.17.42.1
dns_search : hadoop . docker . local
command : start - datanode . sh
resourcemanager :
image : crs4 / hadoop - apache -2.6.0
name : resourcemanager
hostname : resourcemanager
domainname : hadoop . docker . local
container_name : resourcemanager
privileged : true
volumes_from :
12
- client
ports :
- " 8088:8088 "
- " 8021:8021 "
- " 8031:8031 "
- " 8033:8033 "
environment :
- SERVICE_NAME = resourcemanager
- SERVICE_REGION = hadoop
- " affinity : container !=* nodemanager * "
dns : 172.17.42.1
dns_search : hadoop . docker . local
command : start - resourcemanager . sh
nodemanager :
image : crs4 / hadoop - apache -2.6.0
name : nodemanager
# hostname : nodemanager
domainname : hadoop . docker . local
# container_name : nodemanager
privileged : true
environment :
- SERVICE_NAME = nodemanager
- SERVICE_REGION = hadoop
- " affinity : container !=* resourcemanager * "
- " affinity : container !=* nodemanager * "
ports :
- " 8042:8042 "
dns : 172.17.42.1
dns_search : hadoop . docker . local
volumes_from :
- client
command : start - nodemanager . sh
historyserver :
image : crs4 / hadoop - apache -2.6.0
name : historyserver
hostname : historyserver
domainname : hadoop . docker . local
container_name : historyserver
privileged : true
volumes_from :
13
- client
ports :
- " 10020:10020 "
- " 19888:19888 "
environment :
- SERVICE_NAME = historyserver
- SERVICE_REGION = hadoop
dns : 172.17.42.1
dns_search : hadoop . docker . local
command : start - historyserver . sh
Snippet 14: Frammento di docker-compose.yml file per l’esecuzione multi-container dei
servizi Hadoop presenti nell’immagine crs4/hadoop-apache-2.6.0.
Una volta definito il file docker-compose.yml è possibile avviare i vari container
posizionandosi nella cartella contenente tale file7 e lanciando il comando:
docker - compose up [ - d ]
Snippet 15: Esecuzione multi-container dei servizi Hadoop presenti nell’immagine
crs4/hadoop-apache-2.6.0. L’opzione -d forza l’esecuzione in background dei container.
La gestione ed il monitoraggio dei container eseguiti mediante docker-compose può
essere effettuato mediante comandi equivalenti a quelli forniti da Docker per la gestione
di singoli container. Ad esempio:
– è possibile ottenere l’elenco dei container gestiti tramite docker-compose mediante
il comando:
docker - compose ps
Snippet 16: Elenco servizi eseguiti mediante docker-compose
– ottenere i log di uno o più container mediante il comando:
docker - compose logs [ CONT_ID_1 | CONT_NAME_2 ] [...]
Snippet 17: Output prodotto dai container gestiti da docker-compose
7. Più in generale è possibile avviare i container da qualsiasi posizione a patto
di specificare esplicitamente il path del file docker-compose.yml tramite l’opzione -f
<DOCKER-COMPOSE-YAML-PATH> del comando docker-compose.
14
– arrestare l’esecuzione di uno o più container mediante il comando:
docker - compose stop [ CONT_ID_1 | CONT_NAME_2 ] [...]
Snippet 18: Arresta uno o più container gestiti da docker-compose
– rimuovere uno o più container precedentemente arrestati mediante il comando:
docker - compose rm [ CONT_ID_1 | CONT_NAME_2 ] [...]
Snippet 19: Rimuove uno o più container gestiti da docker-compose
2.5
Esecuzione distribuita su cluster Docker Swarm
Nel Dicembre del 2014, la comunità degli sviluppatori che ruota attorno a Docker, ha
messo a disposizione un nuovo strumento che consente di gestire in modo trasparente
container Docker dislocati su differenti host. Mentre Docker Compose, che abbiamo visto
nella sezione 2.4, gestisce applicazioni distribuite su container multipli ospitati da un
singolo Docker host, Swarm consente di distribuire i Docker container su molteplici host.
Un cluster Swarm è costituito da una molteplicità Swarm Node, ovvero di Docker host
su cui è in esecuzione un’immagine Swarm (su un apposito container). Ciascuno di questi
nodi resta in ascolto, su una specifica porta (tipicamente la 2375 o 2376), dei comandi che
gli vengono impartiti da un ulteriore nodo centrale, detto Swarm Manager. Lo Swarm
Manager è un agente server che espone il medesimo set di funzionalità supportato da
un server Docker, ciò che rende possibile interagire con esso esattamente come si farebbe
con un normale server Docker (vedi la sezione 2.5.1).
2.5.1
Creazione di un cluster Docker Swarm
Esistono diverse modalità secondo cui mettere in piedi un cluster Docker Swarm, ben
documentate in [11], cui rimandiamo per ulteriori dettagli. Di seguito ci limitiamo a
riportare i passi fondamentali necessari alla creazione ‘manuale’ di un ambiente cluster
Swarm di test o sviluppo (si veda [6]).
1. Prerequisito per poter creare il cluster Swarm sono un set di macchine su cui poter installare Docker (si veda [10] per le piattaforme supportate e le corrispondenti
procedure di installazione). Docker deve essere eseguito in modo tale da essere
15
Figura 2: Docker Swarm Architecture
‘in ascolto’ su una specifica porta (e.g., tipicamente la 2375), ciò che può essere ottenuto specificando l’opzione -H tcp://0.0.0.0:2375 al momento del suo
avvio. Tale opzione può anche essere direttamente inserita nel file di configurazione di Docker, all’interno della variabile di configurazione DOCKER_OPTS (e.g.,
DOCKER_OPTS="-H tcp://0.0.0.0:2375").
2. Occorre, dunque, procedere alla creazione di un token identificativo del cluster,
mediante l’esecuzione del seguente comando su una delle macchine designate:
docker run -- rm swarm create
Snippet 20: Comando per la creazione del token
. . . il cui output costituisce il TOKEN utile alle fasi successive.
3. Utilizzando il token, è possibile procedere all’avvio dei nodi Swarm, eseguendo, su
ciascuna delle macchine componenti il cluster, il seguente comando:
16
Figura 3: Multiple containers managed by Docker Swarm
docker run -d swarm join -- addr < NODE_IP >:2375 token :// < TOKEN >
Snippet 21: Comando per l’avvio di uno Swarm Node.
4. E’, infine, possibile avviare lo Swarm Manager sulla macchina designata come
master, mediante il seguente comando:
docker run -d -p < SWARM_MANAGER_PORT >:2375 swarm manage \
token :// < TOKEN >
Snippet 22: Comando per l’avvio dello Swarm Manager.
. . . dove SWARM_MANAGER_PORT è una qualsiasi porta disponibile sul Docker host
designato ad ospitare lo Swarm Manager.
Eseguiti i quattro passi sopra descritti, il cluster Swarm è attivo e l’utente può immediatamente utilizzarlo attraverso gli strumenti da console offerti dal Docker Engine, (i.e., principalmente il comando docker), con l’accortezza di specificare il parametro -H tcp://<SWARM_MANAGER_IP>:<SWARM_MANAGER_PORT>. Ad esempio, eseguendo il
comando:
docker -H tcp ://0.0.0.0: < SWARM_MANAGER_PORT > info
Snippet 23: Comando per ottenere informazioni sullo stato del cluster Swarm.
si ottengo informazioni sullo stato del cluster (e.g., nodi attivi e, per ciascun nodo attivo,
informazioni sulle sue risorse disponibili, container attivi, etc...), come mostra la figura 4:
17
Figura 4: Esempio di output del comando docker -H tcp://:<SWARM_MANAGER_PORT> info .
L’avvio di un container su un cluster Swarm avviene secondo le medesime modalità di esecuzione su singolo Docker host: occorre, però, specificare nel comando docker,
l’opzione -H tcp://:<SWARM_MANAGER_PORT> per rendere lo Swarm Manager l’esecutore effettivo delle richieste impartite tramite tale comando. In particolare, all’atto della
richiesta di avvio di un nuovo container, lo Swarm Scheduler entra in funzione e, secondo una delle sue strategie di scheduling8 , sceglie il prossimo nodo su cui eseguire il
container. Tale nodo può anche essere esplicitamente definito mediante specifici vincoli
(constraints) che vengono processati da appositi filtri9 interni allo Swarm Scheduler. Tali
vincoli possono essere specificati mediante l’opzione ‘-e’ del comando docker run, la
quale ha, in generale, la funziona principale di definire l’environment del container, ma
viene anche utilizzata (come in questo caso) per passare informazioni all’infrastruttura
Docker. Diversi esempi di constraint sono presenti nel file docker-compose mostrato in
14, come ad esempio, l’affinity constraint mostrato nello snippet 24, il quale impone
che un datanode non possa essere eseguito su un nodo in cui è contemporaneamente in
8. Si veda [12] per l’esame delle strategie di scheduling supportate dallo Swarm Scheduler.
9. L’elenco dei filtri supportati è riportato in [16].
18
esecuzione un nodemanager.
" affinity : container !=* nodemanager * "
Snippet 24: Esempio di constraint per l’esecuzione di un datanode: il vincolo impone che il
datanode non possa essere eseguito su un nodo in cui è contemporaneamente in esecuzione
un nodemanager.
Docker Swarm consente, dunque, semplifica l’esecuzione di applicazioni o servizi distribuiti su un cluster di Docker host, attraverso un’interfaccia di gestione dei container
(quella del Docker Engine) che nasconde i dettagli del cluster. É, però, importante sottolineare che i container in esecuzione su Docker host distinti appartengono a reti logiche
differenti e non possono direttamente comunicare: l’unico modo per rendere visibile ad
un container su una macchina (sia A) un servizio in esecuzione su un’altra macchina (sia
B) consiste nell’esporre pubblicamente sulla macchina B il servizio, tramite il meccanismo
di port mapping cui si è accennato nella sezione 10. Nella sezione 3 vedremo come tale
limitazione possa essere superata.
3
Docker Cluster Setup: Weave + Swarm
La limitazione relativa all’impossibilità dei container distribuiti su Docker host differenti
di comunicare direttamente come se fossero appartenenti ad una stessa rete può essere
superata mediante un tool che nasce proprio con l’obiettivo rispondere a tale esigenza.
Tale strumento, prodotto da Weaveworks, prende il nome di Weave e si propone come
strumento per semplificare la creazione di reti costituite da molteplici Docker container
distribuiti su differenti Docker Host.
Le features offerte da Weave sono numerose10 e, tra queste, le due che più ci sono
utili ai fini di questo tutorial sono:
– virtual ethernet switch, ovvero la capacità di Weave di offrire ai Docker container
un switch virtuale attraverso cui comunicare, come se fossero appartenenti ad una
stessa rete Ethernet;
– Naming and Discovery Service, reso possibile dall’integrato servizio WeaveDNS che,
distribuito fra i Docker host, consente ai container che vi vengono eseguiti, di poter
risolvere gli uni gli hostname degli altri.
10. Un elenco completo delle features offerte da Weave si può trovare in [22].
19
Figura 5: Weave Network di Docker hosts.
3.1
Creazione di una Weave Network
La creazione di una Weave Network è semplicissima e consiste nell’esecuzione di due
specifici Docker container all’interno dei vari Docker host scelti come nodi della rete.
L’esecuzione di tali container è mediata e semplificata da un apposito script (i.e., weave),
che può essere scaricato ed installato seguendo le indicazioni presenti sul repository
ufficiale del progetto, reperibile all’indirizzo https://github.com/weaveworks/weave.
Una volta eseguita l’installazione dello script weave è possibile procedere alla costruzione della rete, eseguendo nell’ordine le seguenti due operazioni:
1. avvio dello weave router, responsabile per lo smistamento del traffico della Weave
network, in ingresso ed in uscita dal Docker node, tramite il comando:
weave launch - router [ options ]
Snippet 25: Comando per avviare lo weave router.
20
Tale comando consente, anche, di attivare il supporto per il Domain Name Server
di WeaveDNS, raggiungibile localmente al nodo all’indirizzo 172.17.42.1. Tra le
varie opzioni, ricordiamo --dns-domain=<YOUR_CUSTOM_COMAIN>, che consente di
specificare il dominio in uso nella Weave Network (per default è weave.local,
mentre nell’esempio in esame in questo tutorial hadoop.docker.local);
2. avvio dello weave proxy, tramite il comando:
weave launch - proxy [ options ]
Snippet 26: Comando per avviare lo weave proxy.
Esso costituisce un wrapper del Docker server, verso cui possono essere indirizzate11 le chiamate del comando docker per sfruttare le funzionalità offerte da Weave.
La porta di default dello Weave Proxy è 12375, ma può essere ridefinita mediante
l’opzione già vista -H tcp://<ADDR>:<PORT>.
3. I comandi sopra descritti vanno eseguiti su ciascun nodo candidato della Weave network. Su tutti i nodi, all’infuori del primo, va inoltre eseguito l’ulteriore
comando:
weave connect < IP_FIRST_WEAVE_NODE >
Snippet 27: Comando per stabilire le connessioni fisiche fra i nodi.
. . . dove IP_FIRST_WEAVE_NODE è l’IP di uno dei nodi della Weave network designato come iniziale.
Eseguiti i passi 1,2 e 3, la rete Weave è attiva e se ne può verificare lo stato di
funzionamento attraverso il comando:
weave status
Snippet 28: Comando per verificare lo stato della weave network.
. . . il cui output è del seguente tipo:
11. Si ricorda che è possibile scegliere l’endpoint delle chiamate eseguite tramite il comando
docker specificando l’opzione -H tcp://<ADDR>:<PORT> con indirizzo e porta dell’endpoint di
interesse.
21
Version : v1 .1.0
Service :
Protocol :
Name :
Encryption :
PeerDiscovery :
Targets :
Connections :
Peers :
router
weave 1..2
52:46:01:82: af : e1 ( ip -172 -31 -2 -200)
disabled
enabled
0
2 (2 established )
3 ( with 6 established connections between them )
Service :
Consensus :
Range :
DefaultSubnet :
ipam
achieved
[10.32.0.0 -10.48.0.0)
10.32.0.0/12
Service :
Domain :
TTL :
Entries :
dns
hadoop . docker . local .
1
6
Service : proxy
Address : tcp : / / 1 7 2 . 3 1 . 2 . 2 0 0 : 1 2 3 7 5
Snippet 29: Output del comando per verificare lo stato della weave network.
Per utilizzare il proxy weave in luogo del docker server e sfruttare, quindi, tutti i
vantaggi offerti da Weave, è possibile adottare una della seguenti strategie:
– specificare l’opzione -H tcp://<WEAVE_ADDR>:<WEAVE_PORT> direttamente sul comando docker;
– impostare l’ambiente della shell corrente perché punti all’endpoint weave tramite
il comando eval $(weave env).
Così facendo, ogni nuovo container sarà dotato di un’interfaccia di rete aggiuntiva,
chiamata weave, attraverso cui potrà direttamente contattare tutti gli altri container della
Weave Network. Inoltre, il nome del container diventerà il nome dell’host (con l’aggiunta
del dominio scelto nella rete Weave), risolvibile da qualsiasi nodo/container della rete
Weave.
22
3.2
Swarm Cluster su Weave Network
E’ possibile combinare i benefici di Swarm e Weave attraverso un piccolo accorgimento in
fase di creazione del cluster Swarm. Una volta correttamente creata la rete Weave (secondo quanto descritto nella sezione 3.1), è possibile procedere all’istanziazione del cluster
Swarm su rete Weave seguendo la guida descritta nella sezione 2.5.1, con la seguente
unica variante:
=⇒ al punto 3, su ogni nodo, occorre specificare come porta Swarm quella del proxy
Weave in esecuzione sul nodo, ovvero:
1
docker run -d swarm join -- addr < NODE_IP >: < WEAVE_PROXY_PORT >
token :// < TOKEN >
Snippet 30: Comando per l’inizializzazione di nodi Swarm su rete Weave.
dove WEAVE_PROXY_PORT sostituisce (rispetto a quanto mostrato in 2.5.1 al punto 3)
la porta del server Docker in esecuzione sul nodo.
4
Guida all’esempio completo
In questa sezione finale del documento vediamo come eseguire l’immagine Docker di
Apache Hadoop descritta in questo tutorial, mediante un cluster di calcolatori ‘virtualizzato‘ come cluster Docker Swarm su rete Weave (vedi 2.5.1). Si ricorda che l’immagine
Docker di Apache Hadoop cui si fa riferimento in questo tutorial è direttamente reperibile
dal repository del CRS4 sul DockerHub12 oppure può essere generata a partire dal codice
(i.e., Dockerfile, scripts, etc.) reperibile presso il repository github del CRS4 ospitato all’indirizzo https://github.com/crs4/docker-hadoop.git. La documentazione contenuta in tale repository contiene informazioni aggiuntive utili all’esecuzione dell’immagine
Docker di Apache Hadoop cui si fa riferimento in questo tutorial.
4.1
Prerequisiti
Come visto nella sezione 2.5.1, la creazione di un cluster Docker Swarm non richiede, di
per sé, macchine con caratteristiche “speciali”: possono, cioè, essere utilizzate macchine
Linux/Unix qualsiasi, sulle quali sia installato, e propriamente configurato, Docker ed
12. Mediante il comando docker search crs4 è possibile ottenere l’elenco delle immagini del
repository del CRS4 ospitate presso il Docker Hub.
23
altri pochi tool (vedi la sezione 4.1.2). A dettare le caratteristiche HW delle macchine
componenti il cluster è, invece, la capacità di elaborazione che si intende supportare,
funzione, a sua volta, delle specifiche applicazioni di calcolo che si vogliono, su di esso,
mandare in esecuzione. E, nell’ottica della scelta della infrastruttura dimensionalmente
più adatta, una più che valida risorsa è costituita dai servizi Infrastructure as a Service (IaaS)
di Amazon, noti come Amazon Web Services (AWS). Essi costituisco una valida soluzione
infrastrutturale per la creazione del cluster, offrendo risorse ed infrastrutture di calcolo
‘elastiche‘, ovvero facilmente scalabili, e disponibili a noleggio sul cloud. Nelle prossime
sezioni elenchiamo, brevemente, i passi necessari alla creazione e configurazione di un
cluster AWS adatto ad essere utilizzato come cluster Docker Swarm.
4.1.1
Configurazione del cluster AWS
Senza entrare nei dettagli per ottenere i nodi AWS (per i quali si rimanda a [3]), elenchiamo i passi di configurazione che portano a rendere il cluster AWS adatto all’esecuzione di
un cluster Docker Swarm e, quindi, all’esecuzione della versione dockerizzata di Hadoop
contenuta nell’immagine menzionata in questo tutorial.
In particolare, ottenute le istanze di calcolo13 , occorre assicurare che:
– il traffico della rete ‘interna’ (i.e., quella cui appartengono le macchine del cluster)
sia abilitato, in modo tale che le macchine del cluster possano fra loro comunicare
liberamente (tutte le porte aperte in ingresso ed uscita);
– il traffico di rete da/verso l’esterno sia abilitato per tutti e soli i servizi Hadoop che
interessa rendere accessibili dall’esterno (vedi quelli descritti nella sezione 2.4: e.g.,
Namenode, ResourceManager, etc...).
4.1.2
Requisiti Software
Su ogni nodo del cluster deve essere installato il seguente software di base:
– docker >1.6.0 (guida di installazione in [10]);
– docker-compose >1.3.0 (guida di installazione in [17]);
13. E’ necessario disporre di un account AWS, con privilegi di amministratore per poter autonomamente creare le macchine EC2 di interesse. L’account free tier offerto da Amazon costituisce
un buon punto di partenza per verificare la corretta configurazione dell’ambiente, sebbene inadeguato per l’esecuzione di applicazioni di calcolo reali. Le macchine possono essere basate su una
qualsiasi distribuzione Linux: si segnalano, in particolare, alcune distribuzioni che integrano già
installato molto del software necessario elencato in 4.1.2 Informazioni su come installare Docker
su AWS sono reperibili in [2].
24
– weave >1.1.0 (guida di installazione in [21]);
– swarm >0.4.0 (guida di installazione in [11]);
– gli script di utilità associati all’immagine docker-hadoop descritta in questo tutorial e
reperibile all’indirizzo https://github.com/crs4/hadoop-docker.
4.2
Creazione del cluster Swarm su rete Weave
Per inizializzare la rete Weave ed il cluster Swarm si può utilizzare lo script
weave-swarm-network-manager.sh (si veda https://github.com/crs4/docker-hadoop/
tree/develop#setup-a-swarm-cluster-over-a-weave-network [4]).
Digitando il comando ‘weave status’ è possibile verificare che la connettività fra
i nodi della rete weave sia stata effettivamente stabilita (come in figura 5). Il comando
‘docker info’, invece, eseguito sullo swarm manager produce informazioni sullo stato
del cluster, secondo un output del tipo di quello mostrato in figura 4.
4.3
Esecuzione dockerized Hadoop su cluster Swarm
Utilizzare lo script start-multi-host-services.sh per avviare i servizi Hadoop dockerizzati, secondo quanto descritto in [4]. Dopo aver aggiornato il proprio /etc/hosts
come descritto nella guida https://github.com/crs4/docker-hadoop/tree/develop#
update-your-etchosts, è possibile verificare, attraverso il proprio browser, lo stato di attività dei vari servizi Hadoop attraverso le loro interfacce web di gestione, raggiungibili
ai seguenti indirizzi:
– ResourceManager: http://resourcemanager.hadoop.docker.local:8088;
– History Server: http://historyserver.hadoop.docker.local:19888;
– NameNode: http://namenode.hadoop.docker.local:50070.
Riferimenti bibliografici
[1] Amazon. Amazon web services. https://aws.amazon.com/it/, Ottobre 2015.
[2] Amazon.
Docker basics.
http://docs.aws.amazon.com/AmazonECS/latest/
developerguide/docker-basics.html, Ottobre 2015.
[3] Amazon. Getting started with amazon ec2 linux instances. http://docs.aws.
amazon.com/AWSEC2/latest/UserGuide/EC2_GetStarted.html, Ottobre 2015.
25
[4] CRS4. Setup a swarm cluster over a weave network. https://github.com/crs4/
docker-hadoop, Ottobre 2015.
[5] Apache Software Foundation.
apache.org, Ottobre 2015.
Welcome to apache hadoop®.
https://hadoop.
[6] Docker Inc. Create a swarm for development. https://docs.docker.com/swarm/
install-manual/, Ottobre 2015.
[7] Docker Inc. Deploying a registry server. https://docs.docker.com/registry/
deploying/, Ottobre 2015.
[8] Docker Inc. docker-compose.yml reference. https://docs.docker.com/compose/
yml/, Ottobre 2015.
[9] Docker Inc. Docker run reference.
Ottobre 2015.
https://docs.docker.com/reference/run,
[10] Docker Inc.
Docker: Supported installation.
installation/, Ottobre 2015.
https://docs.docker.com/
[11] Docker Inc. Docker swarm. https://docs.docker.com/swarm/, Ottobre 2015.
[12] Docker Inc. Docker swarm scheduler strategies. https://docs.docker.com/swarm/
scheduler/strategy/, Ottobre 2015.
[13] Docker Inc. Dockerfile. https://www.docker.com, Ottobre 2015.
[14] Docker Inc. Dockerfile build command. https://docs.docker.com/reference/
commandline/build/, Ottobre 2015.
[15] Docker Inc. Dockerfile reference. https://docs.docker.com/reference/builder/,
Ottobre 2015.
[16] Docker Inc. Filters. https://docs.docker.com/swarm/scheduler/filter/, Ottobre
2015.
[17] Docker Inc. Install docker compose. https://docs.docker.com/compose/install/,
Ottobre 2015.
[18] Docker Inc. Overview of docker compose. https://docs.docker.com/compose/,
Ottobre 2015.
26
[19] Docker Inc. Welcome to docker trusted registry.
docker-trusted-registry/, Ottobre 2015.
[20] Docker Inc. Working with containers.
usingdocker/, Ottobre 2015.
https://docs.docker.com/
https://docs.docker.com/userguide/
[21] Weaveworks. Github repository. https://github.com/weaveworks/weave#readme,
Ottobre 2015.
[22] Weaveworks. Weave features. http://docs.weave.works/weave/latest_release/
features.html, Ottobre 2015.
27