본문 바로가기
IT 지식/빅데이터 & 분석

JAVA-HIVE/HBASE 간 통신_Hadoop/HIVE/HBase 설치

by 이민우 2023. 1. 21.
728x90
반응형

프로젝트를 진행하던 중, 빅데이터 플랫폼인 하둡의 대표적인 RDB인 Hive와, NoSQL DB인 HBase에 데이러틀 적재해야 하는 프로그램을 짜야할 일이 생겼다.

 

Hadoop 기반 개발은 처음이기에 꽤 많이 헤멨었고, 언젠가 또 Hadoop 기반 개발을 해야할 지 모르는 상황이 발생하면 이번처럼 헤매지 않기 위해 간단한 Java를 통한 HIVE/HBASE 연동 방법을 코드로 구현하는 방법을 대략적으로 적어놓고자 한다.

 

우선 Java Application과 연동되기 위한 Hadoop 인프라를 먼저 설치한다.

Hadoop이 설치될 서버는 다음과 같이 구성했다.

  • OS : CentOS 7.9
  • ROM : 32GB
  • RAM : 8GB

사실 RAM이 중요한데, 로컬 컴퓨터에 램의 용량이 크지 않아 8GB로 설정했다. 가능하다면 크게 줄 수록 테스트 시 스트레스를 받지 않을 수 있고, 여러 테스트 결과 8GB정도는 되어야 RAM 부족으로 에러가 발생하는 일이 없었다.

 


1. 서버 설정

먼저 하둡이 설치되기 위한 몇 가지 설정을 수행한다.

 

가장 먼저 수행할 작업은 hostname변경이다.

다음 명령어를 입력해 hostname을 변경한다.

hostnamectl set-hostname hadoopsv

그리고 /etc/hosts 파일에 다음 문구를 추가한다.

192.168.x.x hadoopsv

 

다음으로 방화벽을 설정한다.

원래대로라면 몇몇 포트만을 열어줘야겠지만, 테스트용으로 할 뿐 상용으로 올리는 게 아니니 방화벽을 꺼버리는 것으로 대체한다.

systemctl stop firewalld
systemctl disable firewalld

 

이제 몇 가지 필요한 인프라를 설치한다.

가장 먼저 필요한 인프라는 자바이다. 다음 명령어로 설치 가능한 openjdk들을 검색하고, 1.8.0 버전의 devel openjdk를 설치한다.

yum list | grep openjdk
yum install -y java-1.8.0-openjdk-devel.x86_64

설치가 완료되었다면 JAVA_HOME을 설정한다. readlink 명령어로 나온 결과물 중 /bin/javac 전까지를 복사한 후 /etc/profile 파일에 복사한 디렉터리와 PATH를 추가한다.

readlink -f `which javac`

vi /etc/profile

# 다음 내용 추가 후 저장
export JAVA_HOME={복사한 디렉터리}
export PATH=$PATH:$JAVA_HOME/bin

 

다음은 DB이다. Hadoop의 RDB인 Hive는 메타데이터를 저장하기 위한 RDB를 필요로 하고, 현 포스팅에서는 해당 RDB로 Postgresql을 선택했다.

Postgresql은 쉬운 설치를 위해 Docker 기반으로 설치했다. 다음 명령어를 순차적으로 실행하여 도커를 설치하고 실행한다.

yum install -y yum-utils device-mapper-persistent-data lvm2
yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
yum install -y docker-ce
systemctl enable docker
systemctl start docker

 

도커 실행까지 완료되었다면 다음 명령어로 postgis를 설치한다.

docker run \
-p 5432:5432 \
--restart always \
--name postgres \
-e TZ=Asia/Seoul \
-e POSTGRES_PASSWORD=password \
-d \
postgis/postgis

 

Image를 pull받아 컨테이너 실행까지 완료되었다면 이제 컨테이너에 진입해 hive 데이터베이스를 생성한다.

docker exec -it postgres bash

su postgres
psql

create database hive;
\q

 

*create database 이후 정상 생성되었는지 확인하고 싶다면 \l 명령어로 확인이 가능하다.

 

 

여기까지 완료되었다면 추가로 몇 가지 인프라를 설치한다.

yum install -y wget net-tools vim

 


2. Hadoop 계정 생성 및 키 생성

 

다음으로 Hadoop과 Hive/HBase가 사용할 계정인 hadoop 계정을 생성한다.

아래 명령어를 따라 계정을 생성하고 비밀번호를 설정한다. 참고로 비밀번호도 hadoop으로 설정했다.

adduser hadoop
passwd hadoop

계정 생성이 완료되었다면 hadoop에 sudo 권한을 부여한다. 반드시 해줘야 할 필요는 없지만, 앞으로의 설치를 모두 hadoop 계정으로 수행하기 위해 부여해주었다.

visudo -f /etc/sudoers

#다음 문구 추가
hadoop ALL=(ALL) ALL

 

이제 hadoop 계정으로 넘어가 자유롭게 서버를 오고갈 수 있도록 key를 생성하고 비밀번호 없이 ssh가 가능하도록 설정해준다.

su hadoop

ssh-keygen -t rsa -P '' -f ~/.ssh/id_rsa;\
cat ~/.ssh/id_rsa.pub >> ~/.ssh/authorized_keys;\
chmod 0600 ~/.ssh/authorized_keys

ssh-copy-id -i ~/.ssh/id_rsa.pub hadoop@hadoopsv

 


3. Hadoop 설치

 

이제 준비는 끝이났고 본격적으로 Hadoop을 설치한다.

Hadoop 폴더는 일단 hadoop 계정의 홈 디렉터리인 /home/hadoop으로 정했다.

홈 디렉터리에서 wget을 통해 hadoop을 설치하고 압축을 해제한다.

cd ~
wget https://downloads.apache.org/hadoop/common/hadoop-3.2.3/hadoop-3.2.3.tar.gz
tar -xvzf hadoop-3.2.3.tar.gz

 

설치가 완료됐으면 /home/hadoop/hadoop-{version} 폴더가 생성된다.

초기 설정 파일은 해당 폴더 내 etc/hadoop 안에 존재한다. 이 폴더 안의 다음 파일들을 수정하도록 한다.

  • workers
  • core-site.xml : hdfs, 맵리듀스 공통 설정 파일
  • hdfs-site.xml : hdfs 설정 파일
  • mapred-site.xml : 맵리듀스 설정파일
  • yarn-site.xml : yarn 설정 파일
  • hadoop-env.sh
  • httpfs-site.xml : httpfs 설정 파일

 

그리고 각 파일을 다음과 같이 설정해준다.

workers

# 기존애 있던 localhost는 삭제
hadoopsv

 

core-site.xml

<configuration>
           <property>
                     <name>fs.defaultFS</name>
                     <value>hdfs://hadoopsv:8020</value>
           </property>
           <property>
                     <name>hadoop.proxyuser.hadoop.hosts</name>
                     <value>*</value>
           </property>
           <property>
                     <name>hadoop.proxyuser.hadoop.groups</name>
                     <value>*</value>
           </property>
</configuration>

 

hdfs-site.xml

<configuration>
           <property>
                     <name>dfs.namenode.name.dir</name>
                     <value>/home/hadoop/hadoopdata/hdfs/namenode</value>
           </property>
           <property>
                     <name>dfs.datanode.data.dir</name>
                     <value>/home/hadoop/hadoopdata/hdfs/datanode</value>
           </property>
           <property>
                     <name>dfs.journalnode.edits.dir</name>
                     <value>/home/hadoop/hadoopdata/hdfs/journalnode</value>
           </property>
           <property>
                     <name>dfs.nameservice</name>
                     <value>hadoop-cluster</value>
           </property>
           <property>
                     <name>dfs.namenode.rpc-address.hadoop-cluster</name>
                     <value>hadoopsv:8020</value>
           </property>
           <property>
                     <name>dfs.namenode.http-address.hadoop-cluster</name>
                     <value>hadoopsv:50070</value>
           </property>
</configuration>

 

mapred-site.xml

<configuration>
           <property>
                     <name>mapreduce.framework.name</name>
                     <value>yarn</value>
           </property>
           <property>
                     <name>mapreduce.map.memory.mb</name>
                     <value>4096</value>
           </property>
           <property>
                     <name>mapreduce.reduce.memory.mb</name>
                     <value>4096</value>
           </property>
           <property>
                     <name>mapreduce.map.java.opts</name>
                     <value>-Xmx4096m</value>
           </property>
           <property>
                     <name>mapreduce.reduce.java.opts</name>
                     <value>-Xmx4096m</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>
</configuration>

 

yarn-site.xml

<configuration>
           <property>
                     <name>yarn.nodemanager.aux-services</name>
                     <value>mapreduce_shuffle</value>
           </property>
           <property>
                     <name>yarn.nodemanager.aux-services.mapreduce_shuffle.class</name>
                     <value>org.apache.hadoop.mapred.ShuffleHandler</value>
           </property>

           <!-- 생략가능 -->
           <property>
                     <name>yarn.nodemanager.local-dirs</name>
                     <value>/yarn/nm-local-dir</value>
           </property>
           <property>
                     <name>yarn.resourcemanager.fs.state-store.uri</name>
                     <value>/yarn/system/rmstore</value>
           </property>
           <!-- 여기까지 -->

           <property>
                     <name>yarn.resourcemanager.hostname</name>
                     <value>hadoopsv</value>
           </property>
           <property>
                     <name>yarn.web-proxy.address</name>
                     <value>0.0.0.0:8089</value>
           </property>
           <property>
                     <name>yarn.resourcemanager.cluster-id</name>
                     <value>cluster1</value>
           </property>
           <property>
                     <name>yarn.resourcemanager.hostname</name>
                     <value>hadoopsv</value>
           </property>
           <property>
                     <name>yarn.resourcemanager.webapp.address</name>
                     <value>hadoopsv:8088</value>
           </property>
</configuration>

 

hadoop-env.sh

#아래 내용을 추가한다.

export JAVA_HOME=/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.352.b08-2.el7_9.x86_64
export HADOOP_PID_DIR=/home/hadoop/pids

추가로 아래 명령어로 방금 설정한 pids 폴더를 만들어준다.

mkdir ~/pids

 

httpfs-site.xml

<configuration>
           <property>
                     <name>httpfs.hadoop.config.dir</name>
                     <value>/home/hadoop/hadoop-3.2.3/etc/hadoop</value>
           </property>
</configuration>

 

모든 파일 설정이 완료되었다면 이제 /etc/profile에 다음 환경변수를 추가한다.

export HADOOP_HOME=/home/hadoop/hadoop-3.2.3
export PATH=$PATH:$HADOOP_HOME/bin
export HADOOP_INSTALL=$HADOOP_HOME
export HADOOP_MAPRED_HOME=$HADOOP_HOME
export HADOOP_COMMON_HOME=$HADOOP_HOME
export HADOOP_HDFS_HOME=$HADOOP_HOME
export HADOOP_YARN_HOME=$HADOOP_HOME
export HADOOP_COMMON_LIB_NATIVE_DIR=$HADOOP_HOME/lib/native
export HADOOP_OPTS="$HADOOP_OPTS -Djava.library.path=$HADOOP_HOME/lib/native"

 

마지막으로 namenode를 포맷한다. 이 떄 이상이 발생하지 않으면 설치가 정상 완료된 것으로 봐도 무방하다.

hdfs namenode -format

포맷 결과

 

이상없이 포맷이 완료됐다면 이제 각 서비스를 켜준다.

hdfs --daemon start journalnode
hdfs --daemon start namenode
hdfs --workers --daemon start datanode
cd $HADOOP_HOME/sbin
./start-yarn.sh
cd $HADOOP_HOME/bin
./mapred --daemon start historyserver
hdfs --daemon start httpfs

*최초 실행 이후로는 start-all.sh / stop-all.sh 명령어를 사용해서 껐다키면 된다.

*최초 실행도 start-all.sh로 해도 되는지는 잘 모르겠다.

 

이후 다음 명령어를 통해 에코시스템들이 잘 켜졌는지 확인해준다.

jps

 


 

4. Hive 설치

 

다음으로 Hadoop의 RDB인 Hive를 설치한다.

다음 명령어를 순차적으로 실행한다.

cd ~
wget https://downloads.apache.org/hive/hive-3.1.2/apache-hive-3.1.2-bin.tar.gz
tar -xvzf apache-hive-3.1.2-bin.tar.gz

 

설치가 완료됐다면 /etc/profile 파일을 수정한다.

sudo vim /etc/profile

# 추가
export HIVE_HOME=/home/hadoop/apache-hive-3.1.2-bin
export PATH=$PATH:$HIVE_HOME/bin

 

 

설정 완료 후 source /etc/profile 명령어로 수정한 환경변수를 적용하고, Hive가 사용할 디렉터리를 만들어준다.

source /etc/profile

hdfs dfs -mkdir /tmp
hdfs dfs -chmod g+w /tmp
hdfs dfs -mkdir -p /user/hive/warehouse
hdfs dfs -chmod g+w /user/hive/warehouse

 

이제 다음 명령어로 정상적으로 폴더가 생성됐는지 확인한다.

hdfs dfs -ls /
hdfs dfs -ls /user/hive

 

환경설정을 수행한다. 설정 파일은 conf 폴더에 있는 hive-site.xml인데, 설치 직후에는 파일이 존재하지 않으니 hive-default.xml.template을 복사해서 만들어준다.

cd $HIVE_HOME/conf
cp hive-default.xml.template hive-site.xml

 

hive-site.xml를 열어 가장 상단에 다음 설정을 추가한다.

<property>
           <name>system:java.io.tmpdir</name>
           <value>/tmp/hive/java</value>
</property>
<property>
           <name>system:user.name</name>
           <value>${user.name}</value>
</property>

 

그리고 DB 연결을 위해 다음 설정들을 수정한다. 참고로 아래 설정들은 한 군데 붙어있지 않고 떨어져 있으니, "jdo.option" 검색을 통해 일일히 수정한다.

<property>
           <name>javax.jdo.option.ConnectionDriverName</name>
           <value>org.postgresql.Driver</value>
           <description>Driver class name for a JDBC metastore</description>
</property>
<property>
           <name>javax.jdo.option.ConnectionUserName</name>
           <value>postgres</value>
           <description>Username to use against metastore database</description>
</property>
<property>
           <name>javax.jdo.option.ConnectionPassword</name>
           <value>password</value>
           <description>password to use against metastore database</description>
</property>
<property>
           <name>javax.jdo.option.ConnectionURL</name>
           <value>jdbc:postgresql://hadoopsv:5432/hive</value>
           <description>
            JDBC connect string for a JDBC metastore.
            To use SSL to encrypt/authenticate the connection, provide database-specific SSL flag in the connection URL.
            For example, jdbc:postgresql://myhost/db?ssl=true for postgres database.
           </description>
</property>

 

Hive의 Transaction을 허용하기 위한 설정들도 수정한다. 마찬가지로 일일히 찾아 아래와 같이 value를 변경한다.

<property>
           <name>hive.support.concurrency</name>
           <value>true</value>
</property>
<property>
           <name>hive.exec.dynamic.partition.mode</name>
           <value>nonstrict</value>
</property>
<property>
           <name>hive.txn.manager</name>
           <value>org.apache.hadoop.hive.ql.lockmgr.DbTxnManager</value>
</property>
<property>
           <name>hive.compactor.initiator.on</name>
           <value>true</value>
</property>
<property>
           <name>hive.compactor.worker.threads</name>
           <value>3</value>
</property>

 

마지막으로 &#8;을 검색해서 에러를 유발하는 특수기호를 삭제한다.

 

설정이 완료됐다면 hive가 postgresql에 접속할 수 있도록 postgresql jdbc driver을 설치한다.

cd $HIVE_HOME/lib
wget https://jdbc.postgresql.org/download/postgresql-42.5.1.jar --no-check-certificate

 

이제 메타데이터를 생성한다.

cd $HIVE_HOME/bin
./schematool -dbType postgres -initSchema

 

이 때 종종 Exception in thread "main" java.lang.NoSuchMethodError: com.google.common.base.Preconditions.checkArgument(ZLjava/lang/String;Ljava/lang/Object;)V 에러가 발생하곤 하는데, 이 경우 $HADOOP_HOME/share/hadoop/hdfs/lib/guava-{version}.jar을 $HIVE_HOME/lib에 옮기고 기존의 guava-{version}.jar을 삭제하고 재시도하면 된다.

 

마지막으로 hiveserver2를 실행한다.

nohup ./hive --service hiveserver2 &

 

잠시 기다린 후 netstat -tnlp | grep 1000 명령어를 통해 10000포트에 hiveserver2가 정상 실행되었는지 확인한다. 조금 시간이 걸리니, 여유를 갖고 기다린다.

*Hive Session ID = ... 만 계속 출력된다면 껐다 켜보자. 끄는 명령어는 kill -15 {pid}이다.

 

 


5. Zookeeper 설치

 

Java Application이 HBase에 접근할 때는 Zookeeper을 통해 접근하게 된다. 그렇기에 HBase 설치 시 Zookeeper를 먼저 설치해주어야 한다.

psql과 달리 도커로 설치하지 않는 이유는 HBase와 Zookeeper가 특정 디렉터리를 공유해야하는데, 이 부분을 쉽게 공유하게 하기 위함이다. 물론 도커로 설치하고 디렉터리를 컨테이너 내 디렉터리와 연동시켜도 무방할 것 같다.

 

우선 주키퍼를 설치한다.

cd ~
wget https://downloads.apache.org/zookeeper/zookeeper-3.6.4/apache-zookeeper-3.6.4-bin.tar.gz
tar -xvzf apache-zookeeper-3.6.4-bin.tar.gz

 

zookeeper의 환경설정을 다음과 같이 수행한다. 파일은 conf 폴더 내 zoo_sample.cfg 파일을 zoo.cfg 파일로 변경해 사용한다.

cd ~/apache-zookeeper-3.6.4-bin/conf
cp zoo_sample.cfg zoo.cfg
vim zoo.cfg

#수정
dataDir=/home/hadoop/data

#추가
maxClientCnxns=0
maxSessionTimeout=180000

저 dataDir은 HBase에도 들어갈 예정이므로 잘 기억해둔다.

이제 아래 명령어로 방금 설정한 디렉터리를 생성한다.

mkdir ~/data

 

폴더가 생성됐다면 zookeeper 서버를 실행한다.

cd ~/apache-zookeeper-3.6.4-bin/bin
./zkServer.sh start

 

 


6. HBase 설치

 

마지막으로 Hadoop의 NoSQL인 HBase를 설치한다.

cd ~
wget http://archive.apache.org/dist/hbase/2.4.15/hbase-2.4.15-bin.tar.gz
tar xvzf hbase-2.4.15-bin.tar.gz

 

HBase는 기본적으로 실행 시 Zookeeper을 내장해서 실행된다.

하지만 현 포스팅에서는 Zookeeper을 별도로 이미 설치했으므로, 해당 옵션을 꺼줘야 한다.

이 외에도 추가적인 설정을 수행한다. 파일은 conf 폴더 내의 hbase-site.xml, hbase-env.sh, regionservers 파일이다.

 

hbase-site.xml

<configuration>
           <property>
                     <name>hbase.cluster.distributed</name>
                     <value>true</value>
           </property>
           <property>
                     <name>hbase.tmp.dir</name>
                     <value>./tmp</value>
           </property>
           <property>
                     <name>hbase.rootdir</name>
                     <value>hdfs://hadoopsv:8020/hbase</value>
           </property>
           <property>
                     <name>hbase.zookeeper.property.clientport</name>
                     <value>2181</value>
           </property>
           <property>
                     <name>hbase.zookeeper.quorum</name>
                     <value>hadoopsv</value>
           </property>
           <property>
                     <!-- zookeeper 설정과 일치시킨다. -->
                     <name>hbase.zookeeper.property.dataDir</name>
                     <value>home/hadoop/data</value>
           </property>
           <property>
                     <name>hbase.master</name>
                     <value>hadoopsv:16000</value>
           </property>
           <property>
                     <name>zookeeper.session.timeout</name>
                     <value>1200000</value>
           </property>
</configuration>

 

hbase-env.sh

export JAVA_HOME=/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.352.b08-2.el7_9.x86_64
export HBASE_MANAGES_ZK=false

 

regionservers

# 기존 localhost는 삭제
hadoopsv

 

설정 완료 후 hbase를 실행한다.

cd /home/hadoop/hbase-2.4.15/bin
./start-hbase.sh

 

이후 jps로 확인한다. 참고로 설치 과정에서 에러가 있을 경우 잠시 후 jps 재실행 시 HMaster가 꺼질 수 있으므로, jps 명령어 결과에서 HMaster가 잘 켜져있다고 판단하지 말고 시간이 조금 지나 재확인해본다.

728x90
반응형