Cluster : The Beginning - HBase 1.2.6 설치


직전에 포스팅한 Hadoop 설치를 기점으로 복잡한 과정은 거의 끝이 난 듯싶다.
사실 하둡에서 바로 MapReduce를 사용하거나 Spark와 같은 분석 툴을 설치하는 것으로 마무리해도 좋겠으나
그래도 구색을 갖춰보려고 굳이 NoSQL을 하나 설치해보기로 했다.


HBase는 예전에 설치해보기도 하였고 Cassandra가 더 좋은 성능을 보인다는 말도 있고 또 진입 장벽도 비교적
낮다고 하여 Cassandra를 설치해볼까 고민을 하다가 그래도 Hadoop을 설치해놓은 터라 아무래도 HBase를
설치하는 것이 낫다고 판단되어 결국은 HBase로 결정을 하였다.


하지만 개인적으로 학습하는 수준이라는 것이 뻔한 것이다보니 과한 짓을 하는 것은 아닌가 하는 생각도 든다.
(그렇게 따지자면 지금껏 해온 모든 작업이 다 우도살계인 격이지만…-.-)


설치


앞서 포스팅한 다른 시스템들과 마찬가지로 바이너리 패키지를 다운로드 받아 적절한 위치에 압축을 풀면 설치
끝이다. 나는 1.2.6 버전을 다운로드 받아 /opt 아래 압축을 풀었다. 다른 시스템들과 마찬가지로 버전 번호는
과감히 삭제하고 HBase 홈 디렉토리를 /opt/hbase로 만들었다.




사전 준비


HBase를 설치하기 꺼려졌던 가장 큰 이유는 HBase도 클러스터 관리를 위해 zookeeper를 사용한다는 점이었다.
그리고 예전에 처음 설치할 때부터 의문이었지만 zookeeper가 필요한 시스템들 각각을 위해 별도의 zookeeper
앙상블을 만들어야 하는 것인지 아니면 하나의 zookeeper 앙상블로 다수의 클러스터 시스템을 관리할 수 있는 것인지
하는 부분도 잘 알지 못했다. 잘 알지 못하다보니 가급적이면 zookeeper와 엮이지 않는 시스템을 찾고 싶기도 했다.


그러던 차에 구글 그룹과 호튼웤스 커뮤니티에서 도움이 될만한 글타래들을 찾아 어느정도 답을 얻을 수 있었다.
사실 zookeeper에 대해 조금만 공부를 했더래도 알 수 있는 내용이었지만…


결론부터 말하자면 하나의 zookeeper 앙상블로 다수의 클러스터(나의 경우 Kafka, HA Hadoop, HBase)를
관리할 수 있으며 웬만큼 큰 규모가 아니면 3노드 정도의 앙상블로 충분하다는 것이다(처음 Kafka와 HBase를
설치했을 때는 zookeeper 앙상블을 5대의 노드에 구성했더랬다…-.-).


관련 글타래를 아래에 링크한다.


https://groups.google.com/forum/#!topic/storm-user/cYSZE8RDHJ0

https://community.hortonworks.com/questions/35287/how-to-decide-how-many-zookeepers-should-i-have.html 



설정



Hadoop에 비한다면 크게 설정할 것은 없다.

backup-master

# HA 클러스터를 구성할 경우 백업 마스터로 사용할 호스트명을 기록한다.
SECONDARY-NAMENODE.local


base-site.xml

<!-- 
HBase가 지속적으로 실행되면서 regionserver들과 정보를 공유하는 경로
Hadoop의 core-site.xml에 있는 fs.defaultFS 설정과 동일하게 한다
--> 
<property>
	<name>hbase.rootdir</name>
	<value>hdfs://NAMENODE.local:8020/hbase</value>
</property>
<!--
마스터가 될 노드의 URI
-->
<property>
	 <name>hbase.master</name>
	<value>NAMENODE.local:6000</value>
</property>
<!--
zookeeper 앙상블을 구성하는 노드들의 호스트명
나의 경우 Kafka 설치시 설치했던 라즈베리파이의 호스트명을 적었다.
-->
 <property>
	 <name>hbase.zookeeper.quorum</name>
	<value>rpi1,rpi2,rpi3</value>
</property>
<!--
zookeeper 클라리언트가 사용할 포트. 기본 포트인 2181을 사용한다.
-->
<property>
	<name>hbase.zookeeper.property.clientPort</name>
	<value>2181</value> 
</property> 
<!--
데이터 복제 계수를 3으로 지정하였다.
-->
<property>
	<name>dfs.replication</name>
	<value>3</value>
</property>
<!--
HBase를 완전 분산모드로 사용하기로 하였다.
-->
<property>
	<name>hbase.cluster.distributed</name>
	<value>true</value>
</property>
<!--
하나의 Datanode에서 동시에 서비스 가능한 block 개수 제한.
-->
<property>
	<name>dfs.datanode.max.xcievers</name>
	<value>4096</value>
</property>


regionservers

# regionserver로 사용될 노드들의 호스트명을 적는다.
DATANODE1.local
DATANODE2.local
DATANODE3.local


이렇게 간단하게 설정을 마쳤다.
그런데 각 설정에 대한 설명을 찾다보니 내가 한 설정 항목의 일부는 최근 버전에서는 name이 바뀐 것들이
조금 있었다. 아무래도 공식 사이트를 참조하지 않고 여기 저기 블로그를 기웃거리며 정리하다보니 이런 문제가
생겨버렸다.


게다가 HBase 홒메이지의 설정 관련 항목에 하둡 버전과 그 버전에서 지원하는 HBase 버전을 표로 정리한
내용이 있는데 이상하게도 하둡 3.0.0은 목록에 있는데 내가 설치한 2.9.0은 목록에 없다… 과연 내가 설치한
하둡 2.9.0 + HBase 1.2.6은 올바른 조합인지도 잘 모르겠다…ㅠ.ㅠ 아직도 갈길이 멀다…


https://hbase.apache.org/book.html



일단 이렇게 설정을 하고 배포본을 압축하여 sap 명령으로 backup master와 regionserver들엑 복사를
해준다.


실행


실행은 간단하다. 마스터 노드에서 아래와 같이 실행하면 regionserver들도 함께 실행된다.

hadoop@NAMENODE.local $ /opt/hbase/bin/start-hbase.sh


마지막으로 backup master에서 아래와 같이 실행한다.

hadoop@SECONDARY-NAMENODE.local $ /opt/hbase/bin/master-backup.sh



확인


모든 노드에서 HBase가 정상적으로 실행되면 NAMENODE.local:16010과 SECONDARY-NAMENODE.local:16011에서 아래와 같은 화면을 볼 수 있다.




정리


설정 부분에서도 말한 바와 같이 사실 제대로 설치를 하고 설정을 하기 위해서는 공식 홈페이지만한 참고 자료가
없으나 영어의 압박으로 아무래도 한글로 정리해놓은 블로그를 주로 찾게 된다. 그러다보니 설치하는 버전도
제각각이고 설정의 내용도 제각각이어서 간혹 내가 제대로 하고 있는지 의심이 든다. 추후 공식 자료를 통해 한 번 더 
정리하는 작업을 거쳐야 제대로 된 정보의 공유라고 할 수 있을 것 같다.


이제 계획했던 작업은 Apache Spark 하나가 남았다. Spark에 대한 정리가 끝나면 본격적으로 데이터를 수집하고
저장하고 분석하는 단계를 진행해야 할텐데 이 과정에는 프로그래밍도 필요하기에 더 어려운 작업이 될 것 같다.
하지만 한편으로는 매번 시스템 설치만 해놓고 마치 장식장 안의 인형을 보듯이 지켜보기만 했는데 이제 뭔가 실질적인
작업을 해본다는 측면에서 기대가 되기도 한다.


얼른 달려보자~






main










Cluster : The Beginning - Hadoop 2.9.0 설치


이제 라즈베리파이의 구성은 모두 정리가 되었고 맥미니에 클러스터를 구성할 차례이다.
이 글을 쓰는 시점에는 이미 모든 클러스터 구성이 완료 되었으나 여전히 많은 작업이 남아있다.


하지만 모든 클러스터를 구성하는 것 까지는 초보 수준에서 가장 기초적인 설정만으로 진행하고 있으니
같은 맥락에서 진행을 하도록 하겠다.


맥미니에 설치할 Hadoop ecosystem은 3가지로 Hadoop과 HBase 그리고 Spark이다.
HBase는 Cassandra와 고민을 좀 했는데 아무래도 하둡과의 궁합을 생각해서 HBase를 설치하기로 했다.
Spark의 경우 Spark MLlib 때문에 설치해보기로 했는데 메모리를 이용한 시스템이다보니 가정용 PC의 뻔한
메모리 용량으로 제대로 써먹기나 할지 모르겠다(다른 시스템들도 마찬가지지만…).


하둡 배포판 선정


사실 예전에 하둡 1.4와 HBase를 설치했을 때 여러가지 설정과 배포본을 노드에 카피하는 등 많은 작업들이
매우 번거롭게 느껴져서 이번에는 아주 좋은 툴인 Apache Ambari를 사용하여 설치해볼까하고 시도를 해봤다.
그런데 시작부터 막힌 것이 Mac을 지원하지 않아 WMWare에 설치된 Ubuntu에 Ambari를 설치하게 되었다.



일단 설치는 간단하게 되었는데…정작 웹 콘솔을 시작하고 클러스터를 만드는 과정에서 각 노드에 연결을
하지 못하는 문제가 발생을 하였다. 아무래도 Mac에서 진행을 하다보니 지원이 안되는 부분이 있나보다 하고
과감하게 포기를 하고 다시 맨땅에 헤딩하면서 진행을 할 수밖에 없었다.


우선 설치할 시점에서의 최신 버전인 2.9.0 버전을 다운로드 받아 설치하기로 하였다. 그런데 오늘 가서 보니 그새
3.0.0이 새로 릴리즈가 되어있고 2.6.X, 2.7.X, 2.8.X, 2.9.X, 3.0.X가 각각 업데이트가 진행되는 것 같은데
어떤 기준으로 버전이 나누어지고 또 업데이트가 되는지 잘 모르겠다.


배포버전 참조 링크 : http://hadoop.apache.org/releases.html#Download


어쨌든 나는 2.9.0 버전을 선택하여 설치하였다.


설치 환경 및 모드


일단 앞선 몇 번의 포스팅에서 언급한 것과 같이 현재 내가 보유하고 있는 장비는 총 5대의 Mac mini이다.
즉 5대의 PC에 완전 분산모드로 설치를 진행하게 될 것이다. 5대의 host 이름은 각각 다음과 같다.
괄호 안은 떠있게 될 기본 프로세스다. 


  • NAMENODE.local (Active NameNode, JournalNode, ResourceManager, DFSZKFailoverController)
  • SECONDARY-NAMENODE.local (Standby NameNode, JournalNode, DFSZKFailoverController)
    (과거 1.4 설치 때 secondary namenode였음…)
  • DATANODE1.local (DataNode, JournalNode, NodeManager)
  • DATANODE2.local (DataNode , NodeManager)
  • DATANODE3.local (DataNode , NodeManager)


JournalNode 구성 때문에 1대를 더 영입하려다가 참았다…-.-
이후 작성하는 모든 글에서 각 노드는 위에 적은 호스트명을 사용하도록 하겠다.


설치


앞서 설치한 다른 시스템들과 마찬가지로 다운로드 받은 압축 패키지를 적당한 위치에 풀면 설치 끝이다…-.-
나는 현재 모든 시스템들을 /opt 아래에 설치 중이다. 따라서 hadoop의 경로는 /opt/hadoop이고 
버전 정보는 과감하게 빼버렸다.




사전 준비


하둡을 설치하기 전에 한 가지 준비할 것이 있는데 하둡은 마스터(NameNode)와 슬레이브(Datanode)간에
통신을 하는데 SSH를 이용하게 된다. 이 때 SSH 접근 시 비밀번호 인증을 거치게 되면 정상적으로 통신을 할 수
없기 때문에 먼저 비밀번호 인증 없이 접속을 하기 위해 다음과 같은 절차로 준비를 해야 한다.


일반적으로 사용자 계정의 홈 디렉토리에 있는 .ssh라는 디렉토리에 SSH 관련 인증키들이 들어있다. 만일 기존에
사용 중인 인증 키(보통 id_rsa, id_rsa.pub이라는 이름) 파일들이 보이면 그 파일들을 이용하면 될 것이고 파일이
없거나 .ssh 디렉토리 자체가 없다면 다음과 같이 SSH 키를 생성해준다. 이 작업은 Active NameNode 서버와
Standby NameNode 서버에서 각각 진행한다. 아래는 Active NameNode 기준으로 기록하였다.


'hadoop@NAMENODE.local$ ssh-keygen -t rasa -f  ~/.ssh/id_rsa

당연한 이야기이겠지만 Standby NameNode에서 할 때는 nn2_id_rsa와 같이 키 파일 이름을 다르게 해야
나중에 DataNode로 복사를 할 때 파일을 덮어쓰는 문제를 피할 수 있다.


이렇게 하면 인증키 파일이 생성이 된다. 이제 이 인증키 파일 중 공개키에 해당하는 id_rsa.pub 파일을 각 
DataNode들로 복사를 해준다.


'hadoop@NAMENODE.local$ scp ~/.ssh/id_rsa.pub hadoop@DATANODE1.local:/Users/hadoop/.ssh/id_rsa.pub 
'hadoop@NAMENODE.local$ scp ~/.ssh/id_rsa.pub hadoop@DATANODE2.local:/Users/hadoop/.ssh/id_rsa.pub 
'hadoop@NAMENODE.local$ scp ~/.ssh/id_rsa.pub hadoop@DATANODE3.local:/Users/hadoop/.ssh/id_rsa.pub 


다음 각각의 DataNode의 ~/.ssh 디렉토리로 이동하여 아래와 같이 인증 키 목록에 NameNode에서 받은
인증키의 내용을 추가해준다.


hadoop@DATANODE1.local$ cat  ~/.ssh/id_rsa.pub >> authorized_keys
hadoop@DATANODE2.local$ cat  ~/.ssh/id_rsa.pub >> authorized_keys
hadoop@DATANODE3.local$ cat  ~/.ssh/id_rsa.pub >> authorized_keys


이렇게 만들어진 authorized_keys 파일을 열어보면 대략 이렇게 생겼다.




마지막으로 ssh-agent를 실행하고 ssh-add를 해준다(예전에도 이런 것을 해줬는지 가물가물한데 해야 한다는
것을 보니 아무래도 예전에 내가 뭘 잘못했던게지…-.-)


hadoop@NAMENODE.local$ eval "$(ssh-agent -s)"  
Agent pid 59566  
hadoop@NAMENODE.local$ ssh-add ~/.ssh/id_rsa


가운데 줄은 첫 줄 실행의 결과다. 주의할 것은 콘솔창에서 이렇게만 실행하면 그 콘솔창의 세션 내에서만 반영이
된다. 즉, 콘솔창을 죽였다가 새로 실행하면 이 작업을 다시 해줘야 비밀번호 인증 없이 ssh 접속이 가능하게 된다.
또한 이 세션은 실행한 계정 내에서만 유효하다.


하둡 1.X vs 2.X


간단하게 예전에 설치했던 하둡 1.4와 비교를 하고 넘어가겠다. 생각외로 변경된 사항 때문에 설정해야 할 것들이
많아져서 가볍게라도 언급을 해두어야 할 것 같다. 우선 아래 그림을 먼저 보자.




중요한 변화를 2가지만 짚어보면


HA(High Availability) Cluster 구성

하둡 1.X에서는 NameNode는 1대만 설치가 가능하였으나 하둡 2.X에서는 2대 이상의 
NameNode를 설치할 수 있는데 이 모든 NameNode가 동시에 작동하는 것이 아니라
이 중 1대만이 Active NameNode로 활성화 되고 다른 NameNode들은 Standby
NameNode로, 말 그대로 대기를 하고 있다가 Active NameNode가 다운되었을 경우 
Active 상태가 되어 NameNode로서의 임무를 수행하게 된다. 

이런 운영이 가능하려면 NameNode들 간에 항상 데이터가 공유되어야 하며 그 방법에는
NFS(NAS와 같은 공유 저장소)를 이용하는 방법과 zookeeper와 JournalNode를 이용하는
방법이 있는데 보통 zookeeper와 JournalNode를 이용하는 방법을 많이 쓴다고 한다.
JournalNode는 3개 이상 홀수로 구성을 해야 한다.


YARN의 등장

기존에 MapReduce의 작동이 JobTracker와 TaskTracker를 통해 이루어지던 것이
YARN의 ResourceManager와 NodeManager를 통해 자원 관리 및 모니터링이
이루어지도록 바뀌었다.


하둡 1.X에서는 Secondary NameNode라는 개념이 있었는데 2.X에서도 여전히 사용 가능하며
다만 HA 클러스터를 구성하는 경우에는 Secondary NameNode를 사용할 수 없다.


이런 변화로 인해 하둡 2.X에서는 zookeeper에 대한 설정을 해야 하며 JournalNode 프로세스를
띄워야 하고 YARN을 구동시켜야 하는 등 1.X에 비해 해야 할 일이 늘었다. 


참고로 zookeeper는 이전에 Kafka 설치 시 라즈베리파이에 함께 설치한 zookeeper를 함께 사용한다. 


아래 이미지는 2.X의 구조를 나타낸 그림이다.




설정


설치는 언급할 것도 없이 매우 간단하였고…이제는 설정이다. 역시나 설정도 필수적인 몇몇 항목만 제대로 
설정을 하면 나머지는 기본값으로 그냥 사용하면 된다. 그리고 경로도 좀 독특해서 아래와 같은 경로에 설정 파일들이 
존재한다.


/opt/hadoop/etc/hadoop


그런데!
다른 시스템들과는 달리 하둡은 설정 파일에 기본 값들이 들어있지 않다! 즉, 파일에 최상위 엘리먼트 태그만
덩그러니 있고 내용은 비어있다. 따라서 일단 잘 설명되어있는 블로그나 사이트로 가서 기본적인 내용을 
복사해와야 한다…ㅠ.ㅠ 내가 설정한 내용은 다음과 같다.


  • core-site.xml
<!-- 필수 설정 -->
<property>
      <name>fs.defaultFS</name>
      <value>hdfs://NAMENODE.local:9090</value>
</property>
<!-- 아래 2개의 설정은 옵션~
<property> 
      <name>io.file.buffer.size</name>
      <value>131072</value>
</property>
<property> 
      <name>hadoop.tmp.dir</name>
      <value>/opt/hadoop/temp</value>
</property>
-->
<!--
HA Cluster를 구성할 때 JournalNode를 관리하기 위한 zookeeper 서버를 설정 
이 서버들은 이전에 포스팅한 Kafka 설치 관련 내용에서 이미 설치해둔 라즈베리파이들이다. 
-->
<property> 
      <name>ha.zookeeper.quorum</name>
      <value>rpi1,rpi2,rpi3</value>
</property>



  • hdfs-site.xml
<!-- 
아래 내용 중 데이터 복제 계수를 의미하는 dfs.replication가 설정되지 않았는데 기본값으로
3이 적용 된다.
-->
<!-- NameNode가 namespace와 transaction 로그를 저장하기 위한 경로 -->
<property>
          <name>dfs.namenode.name.dir</name>
          <value>/Users/hadoop/data/dfs/namenode</value>
</property>
<!-- DataNode 자체 및 클러스터와의 관계에 대한 메타데이터를 저장하기 위한 경로 -->
<property>
          <name>dfs.datanode.data.dir</name>
          <value>/Users/hadoop/data/dfs/datanode</value>
</property>
<!-- JournalNode의 메타데이터를 저장하기 위한 경로 -->
<property>
          <name>dfs.journalnode.edits.dir</name>
          <value>/Users/hadoop/data/dfs/journalnode</value>
</property>
<!-- 이하는 HA Cluster 구성을 위해 필요한 내용 -->
<!-- 클러스터 내의 nameservice를 대표하는 논리적인 이름 -->
<property>
	<name>dfs.nameservices</name>
         <value>mazberrycluster</value>
</property>
<!-- 위에서 설정한 nameservice 내에서 사용될 NameNode들의 논리적 이름 -->
<property>
	<name>dfs.ha.namenodes.mazberrycluster</name>
	<value>nn1,nn2</value>
</property>
<!-- 첫 번째 NameNode(nn1)에서 사용할 RPC 호스트:포트 -->
<property>
	<name>dfs.namenode.rpc-address.mazberrycluster.nn1</name>
	<value>NAMENODE.local:8020</value>
</property>
<!-- 두 번째 NameNode(nn2)에서 사용할 RPC 호스트:포트 -->
<property>
	<name>dfs.namenode.rpc-address.mazberrycluster.nn2</name>
	<value>SECONDARY-NAMENODE.local:8020</value>
</property>
<!-- 첫 번째 NameNode(nn1)에서 사용할 Web UI 호스트:포트 -->
<property>
	<name>dfs.namenode.http-address.mazberrycluster.nn1</name>
	<value>NAMENODE.local:50070</value>
</property>
<!-- 두 번째 NameNode(nn2)에서 사용할 Web UI 호스트:포트 -->
<property>
	<name>dfs.namenode.http-address.mazberrycluster.nn2</name>
	<value>SECONDARY-NAMENODE.local:50070</value>
</property>
<!-- 각 JournalNode에서 공유할 데이터를 저장할 URI -->
<property>
	<name>dfs.namenode.shared.edits.dir</name>
	<value>qjournal://NAMENODE.local:8485;SECONDARY-NAMENODE.local:8485;DATANODE1.local:8485/mazberrycluster</value>
</property>
<!-- 클라이언트가 Active NameNode에 접근할 때 사용할 JAVA 클래스 -->
<property>
	<name>dfs.client.failover.proxy.provider.mazberrycluster</name>
	<value>org.apache.hadoop.hdfs.server.namenode.ha.ConfiguredFailoverProxyProvider</value>
</property>
<!-- Failover가 발생했을 때 Active NameNode로의 접근을 차단할 방법 -->
<property>
        <name>dfs.ha.fencing.methods</name>
        <value>sshfence</value>
</property>
<!-- 위에서 ssh를 사용하기로 했기 때문에 ssh 인증키 경로를 설정해준다. -->
<property>
        <name>dfs.ha.fencing.ssh.private-key-files</name>
        <value>/Users/hadoop/.ssh/id_rsa</value>
</property>
<!-- 자동으로 Failover 처리를 할 것인지 -->
<property>
        <name>dfs.ha.automatic-failover.enabled</name>
        <value>true</value>
</property>



  • slaves
## Slave. 즉, DataNode로 사용할 서버의 호스트명을 적어준다.
DATANODE1.local
DATANODE2.local
DATANODE3.local



  • mapred-site.xml
<!-- Map-Reduce 실행 시 관리 프레임워크로 YARN을 지정 -->
<property>
      <name>mapreduce.framework.name</name>
      <value>yarn</value>
</property>



  • yarn-site.xml
<!-- Map-Reduce 실행시 사용할 셔플 서비스 설정 -->
<property>
      <name>yarn.nodemanager.aux-services</name>
      <value>mapreduce_shuffle</value>
</property>
<!-- 위에 설정한 셔플 수행을 위한 JAVA 클래스 -->
<property>
      <name>yarn.nodemanager.auxservices.mapreduce.shuffle.class</name>
      <value>org.apache.hadoop.mapred.ShuffleHandler</value>
</property>
<!-- 위에 설정한 셔플 수행을 위한 JAVA 클래스 -->
<property>
          <name>yarn.nodemanager.local-dirs</name>
          <value>/opt/hadoop/data/yarn/nm-local-dir</value>
</property>
<!-- ResourceManager 상태가 저장될 경로 -->
<property>
          <name>yarn.resourcemanager.fs.state-store.uri</name>
          <value>/opt/hadoop/data/yarn/system/rmstore</value>
</property>
<!-- ResourceManager가 수행될 노드의 호스트명 -->
<property>
          <name>yarn.resourcemanager.hostname</name>
          <value>NAMENODE.local</value>
</property>
<!-- YARN의 web proxy 주소:포트 -->
<property>
          <name>yarn.web-proxy.address</name>
          <value>0.0.0.0:8089</value>
</property>


휴…이제 설정이 끝난 것 같다.
이렇게 설정이 끝났으면 설치한 하둡 배포판을 모든 노드의 같은 경로에 복사해준다.



마지막으로 데몬 실행 파일들에 보면 실제로 데몬을 실행하는 코드가 모두 nohup으로 시작하는데 Mac에서는
nohup 명령어가 없다. 따라서 파일을 열어 nohup으로 시작하는 명령 코드에서 nohup을 모두 제거해주어야 한다.


실행


상당히 많은 분량의 설정이 있었던 만큼 실행 역시 순탄치 않다.
일단 기본적으로 위에 언급된 것만 해도 NameNode, DataNode, JournalNode, YARN 등이 있다.
게다가 Active와 Standby NameNode를 지정해주기 위한 단계와 Failover 처리를 위한 프로세스도
띄워주어야 한다.


이제부터 차근차근 순서를 밟아 실행을 해보자. 우선 $HADOOP_HOME으로 이동하자.


$ cd /opt/hadoop



  • Failover 컨트롤러 실행을 위해 먼저 zookeeper를 초기화 해주어야 한다.
hadoop@NAMENODE.local$ bin/hdfs zkfc -formatZK



  • JournalNode로 사용할 서버에서 각각 JournalNode 프로세스를 실행한다.
    나의 경우 NAMENODE.local, SECONDARY-NAMENODE.local, DATANODE1.loca의 3대이다.
hadoop@NAMENODE.local$ sbin/hadoop-daemon.sh start journalnode
hadoop@SECONDARY-NAMENODE.local$ sbin/hadoop-daemon.sh start journalnode
hadoop@DATANODE1.local$ sbin/hadoop-daemon.sh start journalnode



  • NameNode를 포맷한다.
hadoop@NAMENODE.local$ bin/hdfs namenode -format



  • Active NameNode를 실행한다.
hadoop@NAMENODE.local$ sbin/hadoop-daemon.sh start namenode



  • zookeeper Failover 컨트롤러를 실행한다.
hadoop@NAMENODE.local$ sbin/hadoop-daemon.sh start zkfc



  • 전체 DataNode를 실행한다 (각각의 DataNode에서 hadoop-daemon.sh로 실행해도 된다.)
hadoop@NAMENODE.local$ sbin/hadoop-daemons.sh start datanode



  • Standby NameNode로 이동하여 Active NameNode의 메타 데이터를 Standby NameNode로 
    복사한다.
hadoop@SECONDARY-NAMENODE.local$ bin/hdfs namenode -bootstrapStandby



  • Standby NameNode를 실행한다.
hadoop@SECONDARY-NAMENODE.local$ sbin/hadoop-daemon.sh start namenode



  • Standby NameNode용 zookeeper Failover 컨트롤러를 실행한다.
hadoop@SECONDARY-NAMENODE.local$ sbin/hadoop-daemon.sh start zkfc



  • 다시 Active NameNode로 돌아와 YARN을 실행한다.
hadoop@NAMENODE.local$ sbin/start-yarn.sh



  • 마지막으로 Map-Reduce를 위한 history 서버를 실행한다.
hadoop@NAMENODE.local$ sbin/mr-jobhistory-daemon.sh start historyserver


이렇게 해서 하둡으로의 긴 여정이 끝이났다…ㅠ.ㅠ


모니터링


하둡을 설치하고 나면 아래와 같이 Active NameNode와 Standby NameNode에서 각각 관리 사이트로
접속을 할 수 있다. 기본 포트는 50070이다.




정리


전체적으로 상당히 긴 과정이었다. 이 것이 그저 꼴랑 5대의 노드로 구성된 클러스터이니 망정이지 수 백, 수 천 대의
노드로 구성된 클러스터라면 정말 관리 시스템의 도움이 없이는 제대로 운영할 수 없을 것이다.


일단 전체 에코시스템 구성에서 가장 큰 고비를 넘긴 것 같다. 이제 정리할 것은 HBase와 Spark만 남겨두고 있다.
하지만 이미 모든 시스템을 설치한 후 각 시스템들을 어떻게 연동하여 데이터를 다룰 것인지에 대해 고민을 하다보니
이후가 더 어려울 것 같다는 생각이 든다.


그래도 차근차근 끝까지 가봐야겠다.













Cluster : The Beginning - Apache Kafka와 EMQ 연동


HAProxy, EMQ, Kafka 설치를 통해 일단 입구는 마련이 되었다…고 생각했으나 아직 한 가지 남은 것이 있었다.
단순한 메신저 기능이나 M2M 통신만을 위한 것이 아니라 데이터 분석이 목적이라면 EMQ를 통해 들어온 데이터를 
저장해야 할텐데 아직 그 기능이 구현되지 않았다.


EMQ의 토픽을 영구 저장소에 저장하는 다른 방법이 있는지는 모르겠으나 나의 경우 일단 Kafka가 설치되어있고
곧 Hadoop과 HBase를 설치할 예정이기에(2018년 1월 2일 현재 설치 완료됨) 다음과 같은 경로로 저장을 하기로
했다.




그리 어렵지 않은 내용이니 간단하게 소개하고 마치도록 하겠다.


1차시기 실패 : emqttd_plugin_kafka_bridge


우선 처음 검색해서 찾아낸 것이 emqttd_plugin_kafka_bridge란 놈이었다. 이름으로 알 수 있듯이 EMQ와의
연동을 고려하여 만들어진 것 같은데…어쩐 일인지 빌드가 되지 않았다. 우선은 라즈베리파이라서 그런가보다 하고
넘어 가고 다른 대안을 찾기 시작했다. mqttKafkaBridge와 같은 몇몇 도구들도 찾아보았으나 라즈베리파이에서는
잘 실행이 안되었다 (아래 링크는 시도를 해보았거나 검색 결과로 찾은 도구들이다). 



결국 아래 링크된 페이지를 참조하여 kafka에 있는 connect-standalone.sh를 이용하여 연동하는데 성공하였다.


https://howtoprogram.xyz/2016/07/30/apache-kafka-connect-mqtt-source-tutorial/


connect-standalone.sh 이용하기


우선 나의 경우 위에 링크한 페이지를 참고로 하여 mqtt 연동을 위한 설정은 mqtt.properties 파일에 
아래와 같이 하였다. 이 파일은 $KAFKA_HMOE/config에 위치해야 한다.

# 이 커넥터의 이름과 커넥터로 사용할 클래스 그리고 task의 최댓값을 설정한다.
name=mqtt
connector.class=com.evokly.kafka.connect.mqtt.MqttSourceConnector
tasks.max=1

# kafka쪽에서 사용할 토픽 이름이다.
kafka.topic=mqtt-kafka

# mqtt에 연결할 kafka broker의 아이디이다. 나머지 2대의 kafka broker에는 각각
# mqtt-kafka-2, mqtt-kafka-3으로 설정이 되어있다.
mqtt.client_id=mqtt-kafka-1

# 연결 관련 설정으로 위에 링크한 참조 페이지 내용을 그대로 사용하였다.
mqtt.clean_session=true
mqtt.connection_timeout=30
mqtt.keep_alive_interval=60

# MQTT 관련 설정. mqtt.server_uris는 나의 경우 EMQ를 노드 2개의 클러스터로 구성하였고
# 부하 분산을 위해 HAProxy가 설치된 서버 주소로 설정하였다. 그리고 EMQ에서 사용할 토픽은
# /mqtt로 설정하였다.
mqtt.server_uris=tcp://172.30.1.23:1884
mqtt.topic=/mqtt


이와 같이 설정한 후 connect-standalone.sh를 다음과 같이 실행한다(물론 이미 zookeeper와 kafka는 
실행이 된 상태여야 한다).

$ cd $KAFKA_HOME/bin
$ ./connect-standalone.sh config/connect-standalone.properties config/mqtt.properties


connect-distribute.sh도 있는데 standalone과 어떤 차이가 있는지 잘 모르겠다. 추후 다시 확인을 해봐야겠다.


연동 결과


connect-standalone.sh를 실행하고 나면 잠시 후 EMQ의 웹 화면에 아래와 같이 mqtt.properties에 설정한
mqtt.client_id 값들이 메뉴 곳곳에 보이는 것을 확인할 수 있다.


EMQ에 연결된 클라이언트로 mqtt.properties에 설정한 클라이언트 Id가 보인다.

현재 연결된 세션에도 역시 클라이언트 Id가 보인다.


마찬가지로 구독자 목록에도 클라이언트 Id가 보이며 구독하는 토픽은 mqtt.topic에 설정해준 값인 /mqtt
보인다.


마지막으로 Kafka Manager에서 Topic List메뉴를 보면 mqtt.properties의 kafka.topic 항목에 설정한
mqtt-kafka가 보이는 것을 확인할 수 있다.




정리


앞서 정리한 내용과 마찬가지로 세세한 부분까지 확인하지는 못했지만 우선 Kafka와 EMQ를 연동하는 것 까지
작업을 완료 하였다. 이제 EMQ -> Kafka -> Hadoop(HBase)로 이어지는 프로세스에는 아두이노로 만들
온습도계의 데이터를 저장할 것이고 Kafka Producer -> Kafka -> Hadoop(HBase)로 이어지는 프로세스에는
일반 텍스트 데이터를 저장하게 될 것이다.


이렇게 해서 데이터 컬렉션을 담당할 부분은 모두 설치가 완료가 되었다.
다음 시간부터는 데이터 저장 및 분석을 위한 Hadoop과 HBase 설치에 대한 내용을 정리하고 그 이후 데이터의 
실시간 분석 및 머신 러닝을 위한 Apache Spark 설치에 대한 내용으로 마무리를 하도록 하겠다.


어느덧 해가 바뀌었고 다행히 설치 자체는 순조롭게 진행이 되고 있다.
부디 늦지 않게 데이터가 수집되고 수집한 데이터를 분석하는 것 까지 정리 할 수 있기를 바란다.


이 글을 보고 계시는 분들께 새해 인사 전하면서 이만 줄인다.


무술년 한 해 모두 행복하시기를 바랍니다.
새해 복 많이 받으세요!!! 






  1. 2018.01.11 01:02

    비밀댓글입니다

    • 2018.01.11 08:47

      비밀댓글입니다








Cluster : The Beginning - Raspberry pi에 Apache Kafka 설치하기


이전 작업으로 일단 기본적인 출발은 마무리가 되었다.
하지만 EMQ를 설치한 내용에서 언급했듯이 MQTT는 경량화 프로토콜로 주로 IoT에 특화되어 있다고 볼 수 있어
(Facebook Messanger에서 MQTT를 사용한다고 하는데 현재형인지 또 어떤 영역에 어떻게 사용하는지는 잘
모르겠다) 아직은 절반의 성공일 뿐이다.


센서 데이터 분석을 위한 환경 뿐만 아니라 일반적인 데이터 분석에 대한 환경을 갖추기 위해서는 MQTT라는 진입점
만으로는 부족한 것이다. 그래서 일반 데이터를 수집하는 부분은 예전에 한 번 시도를 해보았던 Apache Kafka를
이용하기로 했다. Kafka를 이용해 수집할 데이터도 예전과 마찬가지로 트위터의 데이터가 될 것이다. 다만 클라이언트는
예전에는 Node.js를 이용하여 구현했으나 이번에는 다른 방식을 찾아볼 생각이다.


이번 포스팅은 바로 이 Apache Kafka를 라즈베리파이에 설치하고 구동하는 과정을 정리해보겠다.
사실 2016년도에 정리한 내용의 축약 버전이나 다름없어 마지막 정리에 2016년에 포스팅한 내용을 모두
링크하였으니 참고하시길 바란다.


개요 - Kafka는 MQTT와 뭐가 다른가?


일단 Kafka 역시 Message Queue기반의 시스템이다. 용어의 차이는 있지만 대체로 구성이 비슷하다.




아주 심플하고 직관적인(하지만 정확하진 않은…-.-) 비유를 들자면 다른 Message Queue 시스템을 퀵서비스라고
한다면 Kafka는 택배라고 할 수 있을 것이다. 퀵서비스는 작은 물건이나 서류를 송신자로부터 수신자 에게 직접 전달을
해주지만 택배는 큰 덩치의 물건들을 물류창고에 집하했다가 다시 배송을 한다. 하지만 이 것은 어디까지나 간단한 비유고
자세한 차이점은 아래 블로그에 잘 정리가 되어있다.

http://epicdevs.com/17


일단 Kafka는 용량이 큰 데이터 전송에 유리하고 클러스터를 통해 데이터를 ‘복제’해둘 수 있으며, Message Queue가
broker에서 subscriber로 topic을 push해주는 반면 kafka는 consumer가 필요할 때 broker로부터 pull 방식으로
가져다 쓸 수 있다는 차이 정도만 알아두면 될 것 같다.


zookeeper 설치, 설정, 실행


개요에서 설명한 것과 같이 Kafka의 경우 클러스터를 구성하여 분산처리를 할 수 있으며 전송되는 데이터를 여러 노드에
복제해놓을 수도 있다. 하지만 이러한 분산 처리를 하기 위해서는 zookeeper라는 분산 코디네이터의 도움을 받아야
한다. 즉, Kafka를 사용하기 위해서는 zookeeper를 먼저 설치해야 한다는 뜻이다.


라즈베리파이에 zookeeper 설치는 매우 간단해서 그냥 바이너리 배포판을 다운로드 받아 적당한 위치에 압축을
풀고 환경에 맞게 설정한 후 실행을 하면 된다…-.-


나는 일단 3.4.10 버전을 받아서 /opt/zookeeper에 압축을 풀었다.
설정은 딱 3가지만 하면 된다.

#데이터를 저장할 디렉토리를 설정한다.
dataDir=/var/lib/zookeeper

#간단하게 기본 설정 파일에서 주석만 풀어주면 된다. 
#주석 처리되어있으면 서버간 통신 때 connection refused가 발생한다.
maxClientCnxns=60

#zookeeper의 클러스터는 별도로 앙상블이라고 불리우는데 앙상블을 구성할 서버 주소를 적어준다.
server.0=172.30.1.54:2888:3888
server.1=172.30.1.13:2888:3888
server.2=172.30.1.42:2888:3888


zookeeper 앙상블이 정상적으로 실행되기 위해서는 dataDir에 지정된 경로에 myid 파일이 필요하며 이 파일에는
3번째 서버 설정에서 정의된 서버 ID가 적혀있어야 한다. 위 설정을 기준으로 보자면 server.0 서버에는 0이,
server.1 서버에는 1이, server.2 서버에는 2가 적혀 있어야 한다.


앙상블(클러스터)을 구성하는 모든 서버에 동일한 설정을 해주고 나서 각 서버에서 아래와 같이 zookeeper 서버를
실행해준다.

$ $ZOOKEEPER_HOME/bin/zkServer.sh start


한가지 주의할 사항은 클라이언트의 요청을 처리하는데 있어서 leader 역할을 하는 한 대의 노드에서만 읽기와 쓰기가
모두 가능하다. follower에서는 오직 읽기만 처리 가능하며, 만일 쓰기 요청이 오면 각 follower 노드들은 그 요청을
leader 노드에 위임하게 된다.


어느 서버가 leader고 어느 서버가 follower인지는 zookeeper에서 확인 가능한데 다음 명령어로 확인 가능하다. 
아래는 현재 노드가 follower임을 보여준다.




zookeeper에 대한 기본적인 내용은 이 것이 전부다. 하지만 분산 시스템을 관리한다는 본연의 임무를 생각해본다면
zookeeper에 대해 알아야 할 내용은 상당히 많다. 또한 zookeeper API를 이용하면 zookeeper를 통해 관리되는
분산 시스템을 직접 만들 수도 있다. 한마디로 zookeeper에 대한 것만 공부하자고 해도 상당히 많은 시간이 필요하므로
여기서는 이정도로 마무리 하겠다.


Kafka 설치


지금껏 진행해온 다른 시스템 설치와 마찬가지로 설치 자체는 매우 간단하다. 바이너리 배포본을 다운로드 한 후
압축을 풀고, 설정하고, 실행하면 된다.


나의 경우 일단 Kafka는 2.11-1 버전을 다운로드 받았고 /opt/kafka에 압축을 풀었다.




Kafka 설정


Kafka의 설정 파일 위치는 다음과 같다. 나는 /opt/kafka에 설치를 했으니 /opt/kafka/config 아래에 있는
server.properties를 수정하면 된다.




이전과 마찬가지로 반드시 설정해야 할 내용만 정리해보자.

#앞서 zookeeper 설정에서 설명한 서버 아이디를 적어준다. 여기는 172.30.1.54 서버이므로
#server.0=172.30.1.54:2888:3888 설정을 참고하여 0으로 설정하였다.
broker.id=0

#로그를 기록할 경로를 지정한다.
log.dirs=/var/lib/kafka-logs

#topic을 저장할 파티션을 몇개로 할 지 지정한다. 서버가 3대이니 일단 3으로 지정해보았다.
#이렇게 설정하면 하나의 데이터 파일이 3개로 쪼개져서 저장이 된다.데이터 파일이 Topic으로 들어오는 데이터가       #3영개의 영역으로 나뉘어서 저장이 된다.
#하지만 partition이란 하나의 Topic을 몇 개로 나눌지를 결정하는 것이지 #물리적 서버의 댓수와는 상관이 없다. num.partitions=3 #데이터 파일의 복제본을 몇개나 가지고 있을지 설정한다. 3으로 설정했으니 3개의 복제본이 존재하게 된다. offsets.topic.replication.factor=3 #클러스터 관리를 위한 zookeeper 서버 목록을 적는다. zookeeper 설정에서는 IP 주소로 설정했는데 #여기서는 host 이름으로 설정하여 일관성이 없는 설정이 되긴 했지만...-.- #각 서버는 다음과 같이 매핑되니 참고하시길 바란다. #rpi1=172.30.1.54, rpi2=172.30.1.13, rpi3=172.30.1.42 zookeeper.connect=rpi1:2181,rpi2:2181,rpi3:2181


위 내용만 설정하면 kafka 서버를 실행할 수 있다.


마지막으로 num.partitions과 offsets.topic.replication.factor 설정이 어떻게 반영되는지에 대해 아래와 같이
그림으로 간단하게 표현을 할 수 있다.




위 그림을 설명하자면 다음과 같은 구조의 경우라 볼 수 있다.

  • 3개의 노드 
  • 3개의 파티션(num.partitions=3)
  • 3개의 복제본(offsets.topic.replication.factor=3)


여기서 주의해서 볼 것은 leader와 follower로 항상 leader에만 쓰기가 가능하며 leader에 데이터가 기록되면
기록된 데이터가 follower로 복제된다는 것이다.


보다 상세한 내용은 좀 더 공부를 한 후 다시 정리해보도록 하겠다.


실행


실행은 /opt/kafka/bin경로로 이동하여 다음과 같이 입력하면 된다.

$ ./kafka-server-start.sh ../config/server.properties


만일 JMX를 이용한 모니터링 도구를 이용하고자 한다면 다음과 같이 실행한다.

$ env JMX_PORT=9000 ./kafka-server-start.sh ../config/server.properties


이렇게 실행을 한 후 아래 2개의 모니터링 도구를 사용할 수 있다.

Kafka Offset Monitor : http://quantifind.github.io/KafkaOffsetMonitor/

Kafka Manager : https://github.com/yahoo/kafka-manager


주의 사항


2016년도에 Kafka를 설치할 때는 맥미니에 설치하였지만 이번에는 라즈베리파이에 설치를 하였다.
이 차이는 결코 작은 차이가 아니다. 하드웨어 사양으로 인해 라즈베리파이에서는 사용할 수 있는 자원이
매우 한정적인 것이다. 실제로 라즈베리파이에서 kafka를 실행했을 때 잦은 빈도로 메모리 부족 현상이
발생을 하였다. 따라 일단 라즈베리파이에서 안정적으로 실행을 하기 위해서는 kafka-server-start.sh 파일의
다음 부분을 찾아 Xmx와 Xms를 적절히 수정해주어야 한다. 기본 값은 1G이다.

export KAFKA_HEAP_OPTS="-Xmx512M -Xms512M"



정리


사실 라즈베리파이에서 설치 및 구동을 한 것 외에는 2016년도에 정리했던 내용과 별 다른 점이 없다.
다시 정리한다는 것이 중복된 작업일 수도 있으나 복습한다는 의미로 한 번 더 정리해보았다.
그런 의미에서 가장 중요한 부분은 ‘주의 사항’이 아닐까 싶다.


가장 기초적인 설치,설정,실행 부분만 짚고 넘어갔으니 2016년도의 Kafka 관련 모든 글을 링크하면서
이번 포스팅을 마칠까 한다.











+ Recent posts

티스토리 툴바