1. 개요
Docker를 이용하여 컨테이너 3개(master, slave1, slave2)를 이용한 fully-distributed 방식으로 Hadoop
분산파일 시스템을 구축한다. 컨테이너 하나를 추가로 더 설치하고 ngnix를 reverse proxy로 사용하고 nodejs
프로그램 서버와 연동해 본다. nodejs에서 webHDFS를 이용하여 하둡 파일시스템에 파일을 업로드/읽기/파일리스트
연산을 하여본다. 이 시스템은 실용성은 없으나 학습하는데에는 도움이 될것이다.
2. Hadoop 설치
Docker를 이용한 Hadoop를 설치한다. docker 우분투 이미지를 다운받고 컨테이너에 hadoop를 설치한다.
우분투 이미지를 다운로드 받고 윈도우즈 파워셀에서 다음과 같이 실행한다.
ps> docker pull ubuntu
ps > docker images
ps> docker run --name hadoop-container -it -d ubuntu:latest <== 컨테이너 시작
ps> docker ps -a
ps> docker exec -it hadoop-container bash
# uname -a <== 컨테이너 안에서 실행
# apt-get update
# apt-get install openjdk-8-jdk <== 자바설치
# java --version
# apt-get install vim <= 편집 프로그램 설치
# apt-get install wget <== wget 설치
# cd /home
# pwd
hadoop 프로그램 다운로드 (공식홈페이지에서 최신버전으로 설치)
# wget https://archive.apache.org/dist/hadoop/common/hadoop-3.2.4/hadoop-3.2.4.tar.gz
# ls
# tar xvzf hadoop-3.2.4.tar.gz <== 압축해제
# vi ~/.bashrc <= 파일편집 아래 환경설정을 입력한다. (자신의 환경에 맞게 설정)
export JAVA_HOME=/usr/lib/jvm/java-8-openjdk-amd64
export HADOOP_HOME=/home/hadoop-3.2.4
export HADOOP_CONFIG_HOME=$HADOOP_HOME/etc/hadoop
export PATH=$PATH:$HADOOP_HOME/bin
export PATH=$PATH:$HADOOP_HOME/sbin
# cat ~/.bashrc
# source ~/.bashrc
# echo $PATH <== 환경설정 확인
# cd $HADOOP_HOME
# mkdir tmp <== 폴더를 생성
# mkdir namenode
# mkdir datanode
# cd $HADOOP_CONFIG_HOME
# ls
hadoop-env.sh 파일에 다음을 추가한다.( cd $HADOOP_HOME/etc/hadoop)
# vi hadoop-env.sh
export JAVA_HOME=/usr/lib/jvm/java-8-openjdk-amd64
export HADOOP_HOME="/home/hadoop-3.2.4"
export PATH=$PATH:$HADOOP_HOME/bin
export PATH=$PATH:$HADOOP_HOME/sbin
export HADOOP_MAPRED_HOME=$HADOOP_HOME
export HADOOP_COMMON_HOME=$HADOOP_HOME
export HADOOP_HDFS_HOME=$HADOOP_HOME
export YARN_HOME=$HADOOP_HOME
export HDFS_NAMENODE_USER=root
export HDFS_DATANODE_USER=root
export HDFS_SECONDARYNAMENODE_USER=root
export YARN_RESOURCEMANAGER_USER=root
export YARN_NODEMANAGER_USER=root
core-site.xml 파일에 다음을 추가한다.( cd $HADOOP_HOME/etc/hadoop )
# vi core-site.xml
<configuration>
<property>
<name>hadoop.tmp.dir</name>
<value>/home/hadoop-3.2.4/tmp</value>
<description>A base for other temporary directories.</description>
</property>
<property>
<name>fs.default.name</name>
<value>hdfs://master:9000</value>
<final>true</final>
<description>The name of the default file system.</description>
</property>
</configuration>
hdfs-site.xml 파일에 다음을 추가한다.(cd $HADOOP_HOME/etc/hadoop)
# vi hdfs-site.xml
<configuration>
<property>
<name>dfs.replication</name>
<value>3</value>
<final>true</final>
<description>Default block replication.</description>
</property>
<property>
<name>dfs.namenode.name.dir</name>
<value>/home/hadoop-3.2.4/namenode</value>
<final>true</final>
</property>
<property>
<name>dfs.datanode.data.dir</name>
<value>/home/hadoop-3.2.4/datanode</value>
<final>true</final>
</property>
<property>
<name>dfs.webhdfs.enabled</name>
<value>true</value>
</property>
<property>
<name>dfs.http.address</name>
<value>0.0.0.0:50070</value>
</property>
</configuration>
mapred-site.xml 파일에 다음을 추가한다.
# vi mapred-site.xml
<configuration>
<property>
<name>mapreduce.framework.name</name>
<value>yarn</value>
</property>
<property>
<name>yarn.app.mapreduce.am.env</name>
<value>HADOOP_MAPRED_HOME=$HADOOP_HOME</value>
</property>
<property>
<name>mapreduce.map.env</name>
<value>HADOOP_MAPRED_HOME=$HADOOP_HOME</value>
</property>
<property>
<name>mapreduce.reduce.env</name>
<value>HADOOP_MAPRED_HOME=$HADOOP_HOME</value>
</property>
<property>
<name>mapred.job.tracker</name>
<value>master:9001</value>
<description>The host and port that the MapReduce job tracker runs
at. If "local", then jobs are run in-process as a single map
and reduce task.
</description>
</property>
</configuration>
yarn-site.xml 파일에 다음을 추가한다.
# vi yarn-site.xml
<configuration>
<!-- Site specific YARN configuration properties -->
<property>
<name>yarn.nodemanager.aux-services</name>
<value>mapreduce_shuffle</value>
</property>
<property>
<name>yarn.resourcemanager.address</name>
<value>master:8032</value>
</property>
<property>
<name>yarn.resourcemanager.scheduler.address</name>
<value>master:8030</value>
</property>
<property>
<name>yarn.resourcemanager.resource-tracker.address</name>
<value>master:8031</value>
</property>
<property>
<name>yarn.resourcemanager.admin.address</name>
<value>master:8033</value>
</property>
<property>
<name>yarn.resourcemanager.webapp.adress</name>
<value>master:8088</value>
</property>
</configuration>
3. 다음과 같은 작업을 수행한다.
# hadoop namenode -format
# apt-get install ssh <== ssh 프로그램 설치
# /usr/sbin/sshd <== ssh 디몬 실행
# rm ~/.ssh/id* <== 기존 키가 있다면 삭제한다.
# cd ~/ <== ssh 키 생성하기 위해 아래 단계를 수행한다.
# ssh-keygen -t rsa -P '' -f ~/.ssh/id_dsa
# cd .ssh
# cat id_dsa.pub >> authorized_keys
4. 작업내용을 컨테이너 이미지로 저장하기 (backup)
현재까지 작업한 내용을 이미지로 저장한다.
ps> docker commit -m "hadoop installed in ubunu" <컨테이너 id> ubuntu:hadoop
ps> docker images <== ubuntu:hadoop 생성된 이미지를 확인
그동안 설정작업하던 컨테이너에서 빠져 나온다.
# exit
5. hadoop master slave 생성하기(4개의 powershell 필요하다.)
ps> docker run -i -t -h master --name master -p 50070:50070 -p 8088:8088 ubuntu:hadoop
ps> docker run -i -t -h slave1 --name slave1 --link master:master ubuntu:hadoop
ps> docker run -i -t -h slave2 --name slave2 --link master:master ubuntu:hadoop
ps>. docker inspect slave1 <== IP를 확인해보자 172.17.0.4 IP는 상황에 따라 바뀔 수 있다.
ps>. docker inspect slave2 <== IP를 확인해보자 172.17.0.5
ps>. docker inspect master <== IP를 확인해보자 172.17.0.3
ps> docker attach master <== master 컨테이너에 접속(또는 이미 접속된 poweshell사용)
root@master:/# vi /etc/hosts
root@master:/# vi $HADOOP_CONFIG_HOME/slaves <== 아래와 같이 입력한다,
slave1
slave2
master
root@master:/# cat $HADOOP_CONFIG_HOME/slaves
root@master:/# start-all.sh <== 실행한다.
6. 이제 실행하여보자.
root@master:/# start-all.sh <==> stop-all.sh /usr/sbin/sshd restart
root@master:/# rm -r $HADOOP_HOME/ tmp/* <== 조심하여 사용한다
root@master:/# rm -r $HADOOP_HOME/ datanode/* <== 조심하여 사용한다
root@master:/# jps <== Java Virtual Machine Process Status
유명한 WordCount 프로그램(Map/Reduce)을 실행하여 보자.
이 프로그램을 실행하여 정상적인 시스템 구축인지 여부를 확인하고자 한다.
root@master:/# cd $HADOOP_HOME
root@master:/# hadoop fs -mkdir /input <==hadoop filesystem에 input 폴더를 생성한다.
root@master:/# hadoop fs -put LICENSE.txt /input
root@master:/# hadoop hdfs -ls /input <== hdfs dfs -ls /input
root@master:/# hadoop jar share/hadoop/mapreduce/hadoop-mapreduce-examples-3.2.4.jar wordcount /input /output
root@master:/# hadoop fs -ls /output <== wordcount 프로그램 출력 결과 파일 리스트 보기
root@master:/# hdfs dfs -cat /output/part-r-00000 <== 파일 출력
root@master:/# hdfs dfs -rm -R /output <== 폴더 삭제
자주 사용하는 hadoop 명령어 정리
# hadoop version
# hdfs dfs -ls / <== hadoop fs -ls /
# hdfs dfs -ls -R /
# hdfs dfs -cat /output/part-r-00000
# hdfs dfs -mkdir <hdfs path>
# hdfs dfs -put <source path> <destination path> <==source location can be a local file system path.
# hdfs dfs -copyFromLocal /home/harsha/empnew.txt/user/harsha/example
# hdfs dfs -get <source hdfs> <destination local file system>
# hdfs dfs -mv <hdfs path> <hdfs path>
# hdfs dfs -mv <hdfs path> <hdfs path>
# hdfs dfs -rm <hdfs path>
7. 사용자 (webuser) 추가
root@master:/# cd $HADOOP_HOME
root@master:# cut -d: -f1 /etc/passwd <== 현재 등록된 사용자 보기
root@master:# groupadd supergroup
root@master: # getent group <== 현재 등록된 그룹 리스트 보기
root@master: # useradd -m webuser -g supergroup <== 사용자 등록하기 (기존 그룹에 추가 /home에 디렉토리 생성)
root@master:# ls -l /home
root@master:# chmod -R 777 tmp <= tmp 폴더 퍼미션 허용
root@master:# hdfs dfs -chmod -R 777 /tmp
root@master:# hdfs dfs -mkdir /user
root@master:# hdfs dfs -mkdir /user/webuser
root@master:# hdfs dfs -chown -R webuser /user/webuser
root@master:# hdfs dfs -ls /user <== check created directory
설정을 변경하고 다시 시작을 원하는 경우
root@master:# stop-all.sh
root@master:# /etc/init.d/ssh restart
root@master:# start-all.sh
root@master:# jps
추가적인 패키지를 설치하여보자(option)
root@master:# apt-get update
root@master:# apt-get install iputils-ping
root@master:# apt-get install net-tools
root@master:# ifconfig <== network 상태확인하기
root@master:# netstat -nap <== 열린 포트확인하기
[참고] 컨테이너를 이미지로 저장하기(backup)
# docker commit -m "hadoop installed in ubuntu" <container id> ubunto:hadoop-master <== image로 저장
8. nodejs에서 하둡파일에 접근하여보자. 새로운 컨테이너를 추가하고 이곳에 nodejs 프로그램을
설치하고 프로그램을 통하여 HDFS에 접근해 본다.
[참고] https://hadoop.apache.org/docs/r1.0.4/webhdfs.html
hdfs-site.xml 파일에 dfs.webhdfs.enabled 설정이 true로 되어 있어야 한다.
파일은 (cd $HADOOP_HOME/etc/hadoop) 폴더에 있다. 확인하여 보자.
<property>
<name>dfs.webhdfs.enabled</name><value>true</value>
</property>
Docker DeskTop에서 새로운 컨테이너 추가 하기 (nginx 설치) -이미지 다운로드 후에 컨테이너 실행한다.
ps> docker run --name nginx-container -d -p 80:80 -p 22:22 nginx:latest <== 컨테이너 시작
ps> docker exec -it nginx-container bash <== 터미널 연결
root@nginx:# nginx -version
root@nginx# service nginx start
root@nginx# service nginx status
PC의 웹브라우저에서 접속을 하여 보자. 80포트에서 웹서버가 실행되고 있다.
root@nginx # cd /etc/nginx/conf.d
root@nginx # cat default.conf <== nginx 기본 설정을 확인한다. 기본 홈페이지 위치를 확인할 수 있다.
root@nginx# cat /usr/share/nginx/html/index.html <== 기본 홈페이지 확인해 본다.
root@nginx# cd /home <== 홈 디렉토리에서 작업한다.
root@nginx# apt-get update
root@nginx# apt-get install -y curl
root@nginx# apt-get install nodejs
root@nginx# node -v
root@nginx# apt-get install npm
root@nginx# npm install -g npm@latest
root@nginx# npm -v
root@nginx# npm install -g express
root@nginx# npm install -g express-generator
root@nginx# apt-get install vim
root@nginx# vi server-test.js <==아래 코드를 입력한다. 또는 아래의 방법으로 PC에서 작업하고 ftp로 업로드한다.
var express = require('express');
var http = require('http');
var app = express();
var server = http.createServer(app);
app.get('/', function (req, res) {
res.send('Hello');
});
app.get('/world.html', function (req, res) {
res.send('Hello World, from world.html file');
});
server.listen(8080, function() {
console.log('Express server listening on port ' + server.address().port);
});
ftp 설정하고 파일을 전송하여 보자. PC에서 작업하는 것이 익숙하고 편리할 수 있다.
root@nginx# apt-get install ssh
root@nginx # cd ~/
root@nginx# ssh-keygen -t rsa -P '' -f ~/.ssh/id_dsa <== 키설치
root@nginx# vi /etc/ssh/sshd_config
#Subsystem sftp /usr/lib/openssh/sftp-server <== 컴맨트처리하고
Subsystem sftp internal-sftp <== 추가
root@nginx# adduser [user name] <== 사용자 추가 (예) ngnix-user
root@nginx# usermod -aG sudo [user name] <== sudo 권한 부여
root@nginx# /etc/init.d/ssh restart <== Secure Shell server: sshd 시작
PC에서 FTP를 이용하여 업로드가 가능하다.
localhost port:22 위에서 추가한 유저 이름과 비번을 이용한다.
root@nginx# cd /home/ngnix-user <== ftp 에서 이 폴더에 파일을 업로드 하였다.
root@nginx# ls
이 디렉토리에서 실행하려면 이 위치에서 패키지를 설치한다.
root@nginx# npm install -g express
root@nginx# npm install -g express-generator
root@nginx# node server-test.js <== 프로그램 시작하기
root@nginx# cd /etc/nginx/conf.d
root@nginx# vi default.conf <== reverse proxy 설정을 하였다. port:80 --> port:8080 으로 보낸다.
root@nginx# service nginx restart
ps> docker start <container_id> <== 재시작 (poewrshell)
ps> docker exec -it nginx-container bash <== 터미널로 연결
root@nginx# cd /home/ngnix-user
root@nginx# node server-test.js <== 8080 포트 서버 프로그램 시작
윈도우즈 브라우저에서 80포트로 접속하면 내부적으로 8080 포트로 redirect 연결된다.
9. nodejs에서 webhdfs 을 이용하여 하둡 파일을 읽고 써보는 프로그램을 작성해 본다.
root@nginx# vi /etc/hosts
172.17.0.2 master <=추가한다
다음 명령어를 입력하여 본다. 정상동작을 확인해 본다.
root@nginx# curl -i "http://172.17.0.2:50070/webhdfs/v1/input?op=LISTSTATUS"
root@nginx# curl -i "http://172.17.0.2:50070/webhdfs/v1/?op=GETHOMEDIRECTORY"
==> {"Path":"/user/dr.who"}
root@nginx# curl -i -L "http://172.17.0.2:50070/webhdfs/v1/input/LICENSE.txt?user.name=root&op=OPEN"
==> 파일 읽기 ( LICENSE.txt 파일을 읽어온다. )
PC 웹브라우저 주소창에서 http://localhost:8088 입력한다. 다음과 같은 정보를 볼 수 있다.
root@nginx# npm install webhdfs <== 모듈을 설치한다.
(1) 다음과 같이 test.js 파일을 만들고 read 하는 프로그램을 실행하여 보자.
//curl -i "http://172.17.0.2:50070/webhdfs/v1/input?op=LISTSTATUS"
async function getListFiles(url,callback) {
console.log('getListFiles...');
보내오는 데이터를 JSON Validator로 확인해 보면 아래와 같이 파일 정보를 보내온다.

(4) 폴더를 생성하는 프로그램을 실행하여 보자.