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