# Configuração do Hadoop, HBase e Kafka na Máquina Local com Docker > Publicado em 16 de Setembro em 2015 ###### tags: `Hadoop` `HBase` `Kafka` `Docker` `Tutorial` Esse tutorial é sobre a criação de uma imagem do Docker com a configuração local do Hadoop, HBase e Kafka. Nesse procedimento, o Hadoop é configurado no modo pseudo-distribuído com cada serviço rodando em uma instância própria da JVM, mas todas na mesma máquina. O HBase e o Kafka também rodam em modo 'distribuído' compartilhando uma instância separada do ZooKeeper. Esse procedimento é muito útil para testar funcionalidades desses serviços e aprendizado, mas não é uma solução completa para uso em produção. ## Pré-requisito Nesse procedimento, é necessário que o Docker esteja instalado e funcionando; também é necessário acesso à Internet. Originalmente, esse procedimento foi testado no ArchLinux atualizado até final de Agosto/2015. https://wiki.archlinux.org/index.php/Docker ```sh sudo docker version > Client: > Version: 1.8.1 > API version: 1.20 > Go version: go1.4.2 > Git commit: d12ea79 > Built: Sat Aug 15 17:29:10 UTC 2015 > OS/Arch: linux/amd64 > > Server: > Version: 1.8.1 > API version: 1.20 > Go version: go1.4.2 > Git commit: d12ea79 > Built: Sat Aug 15 17:29:10 UTC 2015 > OS/Arch: linux/amd64 ``` ## Configuração Hadoop, ZooKeeper, HBase e Kafka. ### Container Começamos com a criação de um conainer do Docker com a imagem do CentOS6. > Importante: para os endereços com `grandesdados-hadoop` funcionarem fora do container, direto na máquina host, é necessário colocar no `/etc/hosts` da máquina host o endereço IP do container do Docker para esse nome. Ao executar o comando `run`, o Docker automaticamente fará o download da imagem e a shell será inicializada dentro de um novo container. ```sh sudo docker run -i -t --name=grandesdados-hadoop --hostname=grandesdados-hadoop centos:6 /bin/bash > Unable to find image 'centos:6' locally > 6: Pulling from library/centos > > f1b10cd84249: Pull complete > fb9cc58bde0c: Pull complete > a005304e4e74: Already exists > library/centos:6: The image you are pulling has been verified. Important: image verification is a tech preview feature and should not be relied on to provide security. > > Digest: sha256:25d94c55b37cb7a33ad706d5f440e36376fec20f59e57d16fe02c64698b531c1 > Status: Downloaded newer image for centos:6 > [root@grandesdados-hadoop /]# ``` Já dentro do container criamos um usuário e local que serão usados para a instalação e execução dos processos. ```sh adduser -m -d /hadoop hadoop cd hadoop ``` A versão usada nesse procedimento é o Java 8, atual versão estável da Oracle. ```sh curl -k -L -H "Cookie: oraclelicense=accept-securebackup-cookie" -O http://download.oracle.com/otn-pub/java/jdk/8u60-b27/jdk-8u60-linux-x64.rpm rpm -i jdk-8u60-linux-x64.rpm echo 'export JAVA_HOME="/usr/java/jdk1.8.0_60"' > /etc/profile.d/java.sh source /etc/profile.d/java.sh echo $JAVA_HOME > /usr/java/jdk1.8.0_60 java -version > java version "1.8.0_60" > Java(TM) SE Runtime Environment (build 1.8.0_60-b27) > Java HotSpot(TM) 64-Bit Server VM (build 25.60-b23, mixed mode) ``` Para completar o ambiente de execução, instalamos os serviços e bibliotecas necessárias. ```sh yum install -y tar openssh-clients openssh-server rsync gzip zlib openssl fuse bzip2 snappy > (...) ``` (configuração do SSH para acesso sem senha) ```sh service sshd start chkconfig sshd on su - hadoop ssh-keygen -C hadoop -P '' -f ~/.ssh/id_rsa cp ~/.ssh/{id_rsa.pub,authorized_keys} ssh-keyscan grandesdados-hadoop >> ~/.ssh/known_hosts ssh-keyscan localhost >> ~/.ssh/known_hosts ssh-keyscan 127.0.0.1 >> ~/.ssh/known_hosts ssh-keyscan 0.0.0.0 >> ~/.ssh/known_hosts ssh grandesdados-hadoop > Warning: Permanently added the RSA host key for IP address '172.17.0.12' to the list of known hosts. > (nova shell, sem login nem confirmação) # (sair do shell do ssh) exit # (sair do shell do su) exit whoami > root ``` ### Hadoop Procedimento para configuração local do Hadoop em modo pseudo-distribuído com uma JVM por serviço. Esse procedimento é baseado na [documentação do Hadoop](http://hadoop.apache.org/docs/r2.7.1/hadoop-project-dist/hadoop-common/SingleCluster.html). Serviços: * HDFS: NameNode, SecondaryNameNode, DataNode * YARN: ResouceManager, NodeManager * MR: HistoryServer ... **Instalação** O pacote usado nesse procedimento é o Hadoop 2.7.1 para CentOS6 descrito outro [artigo](https://hackmd.io/@CiroCavani/compilacao-do-hadoop-para-centos6-rhel6-usando-docker). Primeiramente, colocamos o pacote dentro do container. ```sh # (shell fora do container) sudo docker cp hadoop-2.7.1.tar.gz grandesdados-hadoop:/hadoop ``` De volta ao container como usuário root. ```sh tar zxf hadoop-2.7.1.tar.gz -C /opt chown hadoop:hadoop -R /opt/hadoop-2.7.1 echo 'export PATH=$PATH:/opt/hadoop-2.7.1/bin:/opt/hadoop-2.7.1/sbin' > /etc/profile.d/hadoop.sh source /etc/profile.d/hadoop.sh hadoop version > Hadoop 2.7.1 > Subversion Unknown -r Unknown > Compiled by hadoop on 2015-09-01T00:30Z > Compiled with protoc 2.5.0 > From source with checksum fc0a1a23fc1868e4d5ee7fa2b28a58a > This command was run using /opt/hadoop-2.7.1/share/hadoop/common/hadoop-common-2.7.1.jar mkdir -p /data/hadoop chown hadoop:hadoop /data/hadoop ``` **Configuração** (para a configuração, deve ser usado o usuário hadoop: `su - hadoop`) Editar `/opt/hadoop-2.7.1/etc/hadoop/core-site.xml`: ```xml <configuration> <property> <name>hadoop.tmp.dir</name> <value>/data/hadoop</value> </property> <property> <name>fs.defaultFS</name> <value>hdfs://grandesdados-hadoop</value> </property> </configuration> ``` Editar `/opt/hadoop-2.7.1/etc/hadoop/hdfs-site.xml`: ```xml <configuration> <property> <name>dfs.replication</name> <value>1</value> </property> <property> <name>dfs.blocksize</name> <value>8M</value> </property> </configuration> ``` Editar `/opt/hadoop-2.7.1/etc/hadoop/yarn-site.xml`: ```xml <configuration> <property> <name>yarn.nodemanager.aux-services</name> <value>mapreduce_shuffle</value> </property> </configuration> ``` Editar `/opt/hadoop-2.7.1/etc/hadoop/mapred-site.xml`: ```xml <configuration> <property> <name>mapreduce.framework.name</name> <value>yarn</value> </property> <property> <name>mapreduce.jobtracker.staging.root.dir</name> <value>/user</value> </property> </configuration> ``` Setup Inicial (antes da primeira inicialização). ```sh hdfs namenode -format > 15/09/16 02:12:03 INFO namenode.NameNode: STARTUP_MSG: > /************************************************************ > STARTUP_MSG: Starting NameNode > STARTUP_MSG: host = grandesdados-hadoop/172.17.0.12 > STARTUP_MSG: args = [-format] > STARTUP_MSG: version = 2.7.1 > (...) > INFO namenode.NameNode: createNameNode [-format] > Formatting using clusterid: CID-5daa32a0-3ab6-405e-bfd2-05c0a6e1e7e6 > (...) > INFO common.Storage: Storage directory /data/hadoop/dfs/name has been successfully formatted. > (...) ``` **HDFS** (como usuário hadoop `su - hadoop`) ```sh start-dfs.sh > Starting namenodes on [grandesdados-hadoop] > grandesdados-hadoop: starting namenode, logging to /opt/hadoop-2.7.1/logs/hadoop-hadoop-namenode-grandesdados-hadoop.out > localhost: starting datanode, logging to /opt/hadoop-2.7.1/logs/hadoop-hadoop-datanode-grandesdados-hadoop.out > Starting secondary namenodes [0.0.0.0] > 0.0.0.0: starting secondarynamenode, logging to /opt/hadoop-2.7.1/logs/hadoop-hadoop-secondarynamenode-grandesdados-hadoop.out # criação do diretório do usuário hadoop hdfs dfs -mkdir -p /user/hadoop ``` Interface Web do Name Node: http://grandesdados-hadoop:50070/ Interface Web do Data Node (vazia): http://grandesdados-hadoop:50075/ Interface Web do Secondary Name Node: http://grandesdados-hadoop:50090/ Para parar o serviço: ```sh stop-dfs.sh ``` **YARN** (como usuário hadoop `su - hadoop`) ```sh start-yarn.sh > starting yarn daemons > starting resourcemanager, logging to /opt/hadoop-2.7.1/logs/yarn-hadoop-resourcemanager-grandesdados-hadoop.out > localhost: starting nodemanager, logging to /opt/hadoop-2.7.1/logs/yarn-hadoop-nodemanager-grandesdados-hadoop.out ``` Interface Web do Resource Manager: http://grandesdados-hadoop:8088/ Interface Web do Node Manager: http://grandesdados-hadoop:8042/ Para parar o serviço: ```sh stop-yarn.sh ``` **History Server** (como usuário hadoop `su - hadoop`) ```sh mr-jobhistory-daemon.sh start historyserver > starting historyserver, logging to /opt/hadoop-2.7.1/logs/mapred-hadoop-historyserver-grandesdados-hadoop.out ``` Interface Web do History Server: http://grandesdados-hadoop:19888/ Para parar o serviço: ```sh mr-jobhistory-daemon.sh stop historyserver ``` **Teste** (para os testes, deve ser usado o usuário hadoop: `su - hadoop`) Processos: ```sh ps x > PID TTY STAT TIME COMMAND > 5162 ? S 0:00 -bash > 5327 ? Sl 0:08 /usr/java/jdk1.8.0_60/bin/java -Dproc_namenode (...) > 5423 ? Sl 0:07 /usr/java/jdk1.8.0_60/bin/java -Dproc_datanode (...) > 5612 ? Sl 0:06 /usr/java/jdk1.8.0_60/bin/java -Dproc_secondarynamenode (...) > 5772 ? Sl 0:08 /usr/java/jdk1.8.0_60/bin/java -Dproc_resourcemanager (...) > 5870 ? Sl 0:07 /usr/java/jdk1.8.0_60/bin/java -Dproc_nodemanager (...) > 6189 ? Sl 0:08 /usr/java/jdk1.8.0_60/bin/java -Dproc_historyserver (...) > 6273 ? R+ 0:00 ps x ``` Exemplos de MapReduce: ```sh yarn jar /opt/hadoop-2.7.1/share/hadoop/mapreduce/hadoop-mapreduce-examples-2.7.1.jar > An example program must be given as the first argument. > Valid program names are: > aggregatewordcount: An Aggregate based map/reduce program that counts the words in the input files. > aggregatewordhist: An Aggregate based map/reduce program that computes the histogram of the words in the input files. > bbp: A map/reduce program that uses Bailey-Borwein-Plouffe to compute exact digits of Pi. > dbcount: An example job that count the pageview counts from a database. > distbbp: A map/reduce program that uses a BBP-type formula to compute exact bits of Pi. > grep: A map/reduce program that counts the matches of a regex in the input. > join: A job that effects a join over sorted, equally partitioned datasets > multifilewc: A job that counts words from several files. > pentomino: A map/reduce tile laying program to find solutions to pentomino problems. > pi: A map/reduce program that estimates Pi using a quasi-Monte Carlo method. > randomtextwriter: A map/reduce program that writes 10GB of random textual data per node. > randomwriter: A map/reduce program that writes 10GB of random data per node. > secondarysort: An example defining a secondary sort to the reduce. > sort: A map/reduce program that sorts the data written by the random writer. > sudoku: A sudoku solver. > teragen: Generate data for the terasort > terasort: Run the terasort > teravalidate: Checking results of terasort > wordcount: A map/reduce program that counts the words in the input files. > wordmean: A map/reduce program that counts the average length of the words in the input files. > wordmedian: A map/reduce program that counts the median length of the words in the input files. > wordstandarddeviation: A map/reduce program that counts the standard deviation of the length of the words in the input files. ``` Rodando o Cálculo do Pi com MapReduce: ```sh yarn jar /opt/hadoop-2.7.1/share/hadoop/mapreduce/hadoop-mapreduce-examples-2.7.1.jar pi 16 100000 > Number of Maps = 16 > Samples per Map = 100000 > (...) > INFO impl.YarnClientImpl: Submitted application application_1442439610364_0001 > INFO mapreduce.Job: The url to track the job: http://grandesdados-hadoop:8088/proxy/application_1442439610364_0001/ > INFO mapreduce.Job: Running job: job_1442439610364_0001 > (...) > Job Finished in 48.333 seconds > Estimated value of Pi is 3.14157500000000000000 ``` ### ZooKeeper Esse procedimento é baseado na [documentação do ZooKeeper](https://zookeeper.apache.org/doc/r3.4.6/zookeeperStarted.html). Dentro do container como usuário root: ```sh curl -L -O http://archive.apache.org/dist/zookeeper/zookeeper-3.4.6/zookeeper-3.4.6.tar.gz tar zxf zookeeper-3.4.6.tar.gz -C /opt chown hadoop:hadoop -R /opt/zookeeper-3.4.6 echo 'export PATH=$PATH:/opt/zookeeper-3.4.6/bin' > /etc/profile.d/zookeeper.sh source /etc/profile.d/zookeeper.sh mkdir -p /data/zookeeper chown hadoop:hadoop /data/zookeeper ``` Editar `/opt/zookeeper-3.4.6/conf/zoo.cfg`: ```ini tickTime=6000 dataDir=/data/zookeeper clientPort=2181 ``` Inicializando o serviço: ```sh su - hadoop zkServer.sh start > JMX enabled by default > Using config: /opt/zookeeper-3.4.6/bin/../conf/zoo.cfg > Starting zookeeper ... STARTED ``` Para parar o serviço: ```sh zkServer.sh stop ``` **Teste** (para os testes, deve ser usado o usuário hadoop: `su - hadoop`) Processo: ```sh ps x | grep zoo > 8246 ? Sl 0:00 /usr/java/jdk1.8.0_60/bin/java (...) org.apache.zookeeper.server.quorum.QuorumPeerMain (...) > 8291 ? S+ 0:00 grep zoo ``` Telnet: ```sh echo 'ruok' | curl telnet://grandesdados-hadoop:2181 > imok ``` Cliente: ```sh zkCli.sh -server grandesdados-hadoop:2181 > Connecting to grandesdados-hadoop:2181 > ... > [zk: grandesdados-hadoop:2181(CONNECTED) 0] ls / > [zookeeper] > [zk: grandesdados-hadoop:2181(CONNECTED) 1] help > ZooKeeper -server host:port cmd args > stat path [watch] > set path data [version] > ls path [watch] > delquota [-n|-b] path > ls2 path [watch] > setAcl path acl > setquota -n|-b val path > history > redo cmdno > printwatches on|off > delete path [version] > sync path > listquota path > rmr path > get path [watch] > create [-s] [-e] path data acl > addauth scheme auth > quit > getAcl path > close > connect host:port > [zk: grandesdados-hadoop:2181(CONNECTED) 3] quit ``` ### HBase Esse procedimento é baseado na [documentação do HBase](http://hbase.apache.org/book.html#quickstart). Dentro do container como usuário root: ```sh curl -L -O http://archive.apache.org/dist/hbase/1.1.2/hbase-1.1.2-bin.tar.gz tar zxf hbase-1.1.2-bin.tar.gz -C /opt chown hadoop:hadoop -R /opt/hbase-1.1.2 echo 'export PATH=$PATH:/opt/hbase-1.1.2/bin' > /etc/profile.d/hbase.sh source /etc/profile.d/hbase.sh mkdir -p /data/hbase/tmp chown hadoop:hadoop -R /data/hbase ``` Editar `/opt/hbase-1.1.2/conf/hbase-site.xml`: ```xml <configuration> <property> <name>hbase.cluster.distributed</name> <value>true</value> </property> <property> <name>hbase.rootdir</name> <value>hdfs:///hbase</value> </property> <property> <name>hbase.tmp.dir</name> <value>/data/hbase/tmp</value> </property> <property> <name>hbase.zookeeper.quorum</name> <value>grandesdados-hadoop</value> </property> </configuration> ``` Editar `/opt/hbase-1.1.2/conf/hbase-env.sh`: <br/>(manter conteúdo original, só alterar os valores abaixo) ```sh export HBASE_OPTS="-XX:+UseConcMarkSweepGC -Djava.net.preferIPv4Stack=true" export HBASE_MANAGES_ZK=false ``` Inicializando o serviço: ```sh su - hadoop start-hbase.sh > starting master, logging to /opt/hbase-1.1.2/bin/../logs/hbase-hadoop-master-grandesdados-hadoop.out > Java HotSpot(TM) 64-Bit Server VM warning: ignoring option PermSize=128m; support was removed in 8.0 > Java HotSpot(TM) 64-Bit Server VM warning: ignoring option MaxPermSize=128m; support was removed in 8.0 > starting regionserver, logging to /opt/hbase-1.1.2/bin/../logs/hbase-hadoop-1-regionserver-grandesdados-hadoop.out ``` Interface Web do Master: http://grandesdados-hadoop:16010/ Interface Web do Region Server: http://grandesdados-hadoop:16301/ Para parar o serviço: ```sh stop-hbase.sh ``` **Teste** (para os testes, deve ser usado o usuário hadoop: `su - hadoop`) Processo: ```sh ps x | grep hbase > 8790 ? S 0:00 bash /opt/hbase-1.1.2/bin/hbase-daemon.sh --config /opt/hbase-1.1.2/bin/../conf foreground_start master > 8804 ? Sl 0:14 /usr/java/jdk1.8.0_60/bin/java -Dproc_master (...) > 8915 ? S 0:00 bash /opt/hbase-1.1.2/bin/hbase-daemon.sh --config /opt/hbase-1.1.2/bin/../conf foreground_start regionserver -D hbase.regionserver.port=16201 -D hbase.regionserver.info.port=16301 > 8929 ? Sl 0:14 /usr/java/jdk1.8.0_60/bin/java -Dproc_regionserver (...) > 9329 ? S+ 0:00 grep hbase ``` Cliente: ```sh hbase shell > HBase Shell; enter 'help<RETURN>' for list of supported commands. > Type "exit<RETURN>" to leave the HBase Shell > Version 1.1.2, rcc2b70cf03e3378800661ec5cab11eb43fafe0fc, Wed Aug 26 20:11:27 PDT 2015 > > hbase(main):001:0> status > 1 servers, 0 dead, 2.0000 average load > > hbase(main):002:0> help > HBase Shell, version 1.1.2, rcc2b70cf03e3378800661ec5cab11eb43fafe0fc, Wed Aug 26 20:11:27 PDT 2015 > Type 'help "COMMAND"', (e.g. 'help "get"' -- the quotes are necessary) for help on a specific command. > Commands are grouped. Type 'help "COMMAND_GROUP"', (e.g. 'help "general"') for help on a command group. > (...) > hbase(main):004:0> exit ``` ### Kafka Esse procedimento é baseado na [documentação do Kafka](http://kafka.apache.org/documentation.html#quickstart). Dentro do container como usuário root: ```sh curl -L -O http://archive.apache.org/dist/kafka/0.8.2.1/kafka_2.10-0.8.2.1.tgz tar zxf kafka_2.10-0.8.2.1.tgz -C /opt chown hadoop:hadoop -R /opt/kafka_2.10-0.8.2.1 echo 'export PATH=$PATH:/opt/kafka_2.10-0.8.2.1/bin' > /etc/profile.d/kafka.sh source /etc/profile.d/kafka.sh mkdir -p /data/kafka chown hadoop:hadoop /data/kafka ``` Editar `/opt/kafka_2.10-0.8.2.1/config/server.properties`: <br/>(manter conteúdo original, só alterar os valores abaixo) ```ini log.dirs=/data/kafka zookeeper.connect=grandesdados-hadoop:2181 ``` Inicializando o serviço: ```sh su - hadoop kafka-server-start.sh /opt/kafka_2.10-0.8.2.1/config/server.properties &> kafka.out & ``` Para parar o serviço: ```sh kafka-server-stop.sh /opt/kafka_2.10-0.8.2.1/config/server.properties ``` **Teste** (para os testes, deve ser usado o usuário hadoop: `su - hadoop`) Processo: ```sh ps x | grep kafka > 9818 ? Sl 0:03 /usr/java/jdk1.8.0_60/bin/java (...) kafka.Kafka /opt/kafka_2.10-0.8.2.1/config/server.properties > 9928 ? S+ 0:00 grep kafka ``` Enviando e recebendo mensagens: ```sh kafka-topics.sh \ --create \ --zookeeper grandesdados-hadoop:2181 \ --replication-factor 1 \ --partitions 1 \ --topic test > Created topic "test". echo 'Primeira mensagem de teste' | kafka-console-producer.sh --broker-list grandesdados-hadoop:9092 --topic test > (...) kafka-console-consumer.sh --zookeeper grandesdados-hadoop:2181 --topic test --from-beginning > Primeira mensagem de teste > ^CConsumed 1 messages ``` ## Conclusão A revolução em BigData é um fenômeno da tecnologia desenvolvida ao longo dos últimos anos focada na manipulação de um grande volume de dados em máquinas de baixo custo. Essa é a tecnologia que torna possível combinar uma solução de dados escalável com processos para geração de resultados relevantes, tanto no desenvolvimento de produtos quanto na evolução do conhecimento. O importante é entender como essa tecnologia pode ser usada para agregar valor ao negócio e permitir imaginar soluções inovadoras. Esse artigo documenta o passo-a-passo de uma configuração local do Hadoop, ZooKeeper, HBase e Kafka. Esses são os serviços essenciais em uma plataforma de BigData que, juntamente com o Spark, possibilitam o desenvolvimento de soluções tanto para processamento batch quanto para tempo real. Em artigos futuros, entrarei usando essa solução para desenvolver e testar algumas aplicações de BigData usando Spark.