카테고리 없음

Docker Hadoop ngnix nodejs 시스템 구성하기

Wood Pecker 2022. 7. 29. 20:47

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 하는 프로그램을  실행하여 보자. 

// test.js 파일 ( HDFS에 있는 파일을  read 읽는다. )
const WebHDFS = require("webhdfs"); //npm install wehbhdfs
var hdfs = WebHDFS.createClient({
  user: 'root',
  host: '172.17.0.2',
  port: 50070,
  path: '/webhdfs/v1'
});
var fileLocationURL = '/input/LICENSE.txt';

readHDFSFile(fileLocationURL);

function readHDFSFile(locationOfHDFSFile){
   var remoteFileStream = hdfs.createReadStream(locationOfHDFSFile);
    remoteFileStream.on('error', function onError (err) {
        console.log(err);
    });
    remoteFileStream.on('data', function onChunk (chunk) {
        console.log(chunk.toString());
     });
      remoteFileStream.on('finish', function onFinish () {
        console.log('finish...');
      });
}
root@nginx#  node test.js   <==프로그램을 실행하고 테스트 하여 보자.
 
(2)  다음은 로컬에 있는 파일(nginx 컨테이너)을 HDFS에 업로드를 하여 본다.
// test.js 파일 ( upload)

const fs = require("fs"); // npm install fs
const WebHDFS = require("webhdfs"); //npm install wehbhdfs
var hdfs = WebHDFS.createClient({
  user: 'root',
  host: '172.17.0.2',
  port: 50070,
  path: '/webhdfs/v1'
});

var data = new Buffer.from('Hey!');
var localFileStream = fs.createReadStream('./test.js');
var remoteFileStream = hdfs.createWriteStream('/input/test.js');
// Pipe data to HDFS
localFileStream.pipe(remoteFileStream);

// Handle errors
remoteFileStream.on('error', function onError (err) {
  console.log('on error=',err);
});

remoteFileStream.on('data', function onChunk (chunk) {
  data = Buffer.concat([ data, chunk ]);
  console.log('data=',data);
});

// Handle finish event
remoteFileStream.on('finish', function onFinish () {
  console.log('finished anyway (fail or sucess??)');
  console.log('finished data=',data.toString());
});
root@nginx#  node test.js   <==프로그램을 실행하고 테스트 하여 보자.
 
(3). 다음은  HDFS에 있는 파일리스트 보기를 하여보자. 

//curl -i "http://172.17.0.2:50070/webhdfs/v1/input?op=LISTSTATUS"

async function getListFiles(url,callback) {

  console.log('getListFiles...');

  await axios.get(url)
  .then((response) => {
     console.log("Response >>", response.data);
     callback(response.data);
    })
  .catch((error) => {
      console.log("error>>", error)
      callback(error);
   })
}
 var url='http://172.17.0.2:50070/webhdfs/v1/input?op=LISTSTATUS';
 getListFiles(url, (result)=>{
        console.log('call back!! result=',result);
    
  })

보내오는 데이터를 JSON Validator로 확인해 보면 아래와 같이 파일 정보를 보내온다. 

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

var   url= "http://172.17.0.2:50070/webhdfs/v1/test_folder?op=MKDIRS&user.name=root";

sendCreateFolderWebHdfdCommand(url,(result)=>{
     console.log('callback  result=',result);
  });

async function sendCreateFolderWebHdfdCommand(url,callback) {
  // curl -i -X PUT "http://172.17.0.2:50070/webhdfs/v1/test_folder?op=MKDIRS&user.name=root"
  console.log('url=',url);
  await axios.put(url)
  .then((response) => {
     console.log("Response >>", response.data);
     callback(response.data);
    })
  .catch((error) => {
      //console.log("error>>", error)
      callback(error);
   })
}
 

 

 

 

반응형