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만 남겨두고 있다.
하지만 이미 모든 시스템을 설치한 후 각 시스템들을 어떻게 연동하여 데이터를 다룰 것인지에 대해 고민을 하다보니
이후가 더 어려울 것 같다는 생각이 든다.


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






한동안 회사 업무 및 앱 개발에 신경을 쓰느라 Hadoop 학습을 좀 등한시 했었다.

그래도 오며 가며 출퇴근 길에 새롭게 HBase (HBase 완벽 가이드) 서적을 읽기 시작했고.

책을 다 읽지는 않았지만 우선 HBase나 설치를 좀 해보자 하고 한동안 잠자고 있던 Hadoop을 깨웠다.


그런데...

이게 웬일인가...

start-all.sh를 통해 dfs와 mapred를 모두 실행을 시켰는데

namenode쪽에서는 모든 서비스가 다 기동이 되었는데 datanode쪽에서는 tasktracker만 올라오고

datanode가 안올라오는 것이다. 이거야말로


고, 고갱님. 다, 당황하셨어요~


아~물론 당황하고 말고...

가장 마지막에 실행시켰을 때만해도 이상없이 잘 작동하던 놈이었으니...


일단 데이터노드가 올라오지 않으니 데이터노드쪽 로그부터 살폈다.

대략 다음과 같은 로그가 찍혀있었다.


2013-10-15 12:56:22,538 INFO org.apache.hadoop.ipc.Client: Retrying connect to server: NAMENODE.local/192.168.10.15:9000. Already tried 0 time(s).

2013-10-15 12:56:23,541 INFO org.apache.hadoop.ipc.Client: Retrying connect to server: NAMENODE.local/192.168.10.15:9000. Already tried 1 time(s).

2013-10-15 12:56:24,544 INFO org.apache.hadoop.ipc.Client: Retrying connect to server: NAMENODE.local/192.168.10.15:9000. Already tried 2 time(s).

2013-10-15 12:56:25,546 INFO org.apache.hadoop.ipc.Client: Retrying connect to server: NAMENODE.local/192.168.10.15:9000. Already tried 3 time(s).

2013-10-15 12:56:26,549 INFO org.apache.hadoop.ipc.Client: Retrying connect to server: NAMENODE.local/192.168.10.15:9000. Already tried 4 time(s).

2013-10-15 12:56:27,552 INFO org.apache.hadoop.ipc.Client: Retrying connect to server: NAMENODE.local/192.168.10.15:9000. Already tried 5 time(s).

2013-10-15 12:56:28,555 INFO org.apache.hadoop.ipc.Client: Retrying connect to server: NAMENODE.local/192.168.10.15:9000. Already tried 6 time(s).

2013-10-15 12:56:29,558 INFO org.apache.hadoop.ipc.Client: Retrying connect to server: NAMENODE.local/192.168.10.15:9000. Already tried 7 time(s).

2013-10-15 12:56:30,561 INFO org.apache.hadoop.ipc.Client: Retrying connect to server: NAMENODE.local/192.168.10.15:9000. Already tried 8 time(s).

2013-10-15 12:56:31,564 INFO org.apache.hadoop.ipc.Client: Retrying connect to server: NAMENODE.local/192.168.10.15:9000. Already tried 9 time(s).

2013-10-15 12:56:31,566 WARN org.apache.hadoop.hdfs.server.datanode.DataNode: java.net.ConnectException: Call to NAMENODE.local/192.168.10.15:9000 failed on connection exception: java.net.ConnectException: Connection refused

at org.apache.hadoop.ipc.Client.wrapException(Client.java:1099)

at org.apache.hadoop.ipc.Client.call(Client.java:1075)

at org.apache.hadoop.ipc.RPC$Invoker.invoke(RPC.java:225)

at com.sun.proxy.$Proxy5.sendHeartbeat(Unknown Source)

at org.apache.hadoop.hdfs.server.datanode.DataNode.offerService(DataNode.java:904)

at org.apache.hadoop.hdfs.server.datanode.DataNode.run(DataNode.java:1458)

at java.lang.Thread.run(Thread.java:724)

Caused by: java.net.ConnectException: Connection refused

at sun.nio.ch.SocketChannelImpl.checkConnect(Native Method)

at sun.nio.ch.SocketChannelImpl.finishConnect(SocketChannelImpl.java:708)

at org.apache.hadoop.net.SocketIOWithTimeout.connect(SocketIOWithTimeout.java:206)

at org.apache.hadoop.net.NetUtils.connect(NetUtils.java:489)

at org.apache.hadoop.ipc.Client$Connection.setupConnection(Client.java:434)

at org.apache.hadoop.ipc.Client$Connection.setupIOstreams(Client.java:560)

at org.apache.hadoop.ipc.Client$Connection.access$2000(Client.java:184)

at org.apache.hadoop.ipc.Client.getConnection(Client.java:1206)

at org.apache.hadoop.ipc.Client.call(Client.java:1050)

... 5 more

얼핏 보니 네트워크상에 9000포트가 안열렸나 싶다...

얼른 공유기를 살폈더니 9000포트가 이상없이 설정되어있었다.

한동안 이 데이터노드 로그만 가지고 씨름을 하였다.

더 헷갈리게 다음과 같은 오류도 있었다.


2013-10-15 12:56:18,533 WARN org.apache.hadoop.hdfs.server.datanode.DataNode: java.io.IOException: Call to NAMENODE.local/192.168.10.15:9000 failed on local exception: java.io.EOFException

at org.apache.hadoop.ipc.Client.wrapException(Client.java:1107)

at org.apache.hadoop.ipc.Client.call(Client.java:1075)

at org.apache.hadoop.ipc.RPC$Invoker.invoke(RPC.java:225)

at com.sun.proxy.$Proxy5.sendHeartbeat(Unknown Source)

at org.apache.hadoop.hdfs.server.datanode.DataNode.offerService(DataNode.java:904)

at org.apache.hadoop.hdfs.server.datanode.DataNode.run(DataNode.java:1458)

at java.lang.Thread.run(Thread.java:724)

Caused by: java.io.EOFException

at java.io.DataInputStream.readInt(DataInputStream.java:392)

at org.apache.hadoop.ipc.Client$Connection.receiveResponse(Client.java:804)

at org.apache.hadoop.ipc.Client$Connection.run(Client.java:749)

자세히 보면 역시 네트워크상의 스트림을 읽다가 오류가 난것이니 모두 네트워크 문제인 것 같은데...


미련하게 데이터노드만 쳐다보다가 한참만에 '네임노드에서 커넥션 리퓨즈가 났으니 네임노드도 봐야겠구나!' 하는 생각이

들었다...-.-


어쨌든 네임노드의 로그를 살피니 다음과 같은 로그가 찍혀있다.


2013-10-15 12:42:54,406 ERROR org.apache.hadoop.security.UserGroupInformation: PriviledgedActionException as:mazdah cause:org.apache.hadoop.hdfs.server.namenode.SafeModeException: Cannot delete /hadoop-data/mapred/system. Name node is in safe mode.

The ratio of reported blocks 1.0000 has reached the threshold 0.9990. Safe mode will be turned off automatically in 26 seconds.

2013-10-15 12:42:54,408 INFO org.apache.hadoop.ipc.Server: IPC Server handler 3 on 9000, call delete(/hadoop-data/mapred/system, true) from 192.168.10.15:50942: error: org.apache.hadoop.hdfs.server.namenode.SafeModeException: Cannot delete /hadoop-data/mapred/system. Name node is in safe mode.

The ratio of reported blocks 1.0000 has reached the threshold 0.9990. Safe mode will be turned off automatically in 26 seconds.

org.apache.hadoop.hdfs.server.namenode.SafeModeException: Cannot delete /hadoop-data/mapred/system. Name node is in safe mode.

The ratio of reported blocks 1.0000 has reached the threshold 0.9990. Safe mode will be turned off automatically in 26 seconds.

at org.apache.hadoop.hdfs.server.namenode.FSNamesystem.deleteInternal(FSNamesystem.java:1994)

at org.apache.hadoop.hdfs.server.namenode.FSNamesystem.delete(FSNamesystem.java:1974)

at org.apache.hadoop.hdfs.server.namenode.NameNode.delete(NameNode.java:792)

at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)

at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)

at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)

at java.lang.reflect.Method.invoke(Method.java:606)

at org.apache.hadoop.ipc.RPC$Server.call(RPC.java:563)

at org.apache.hadoop.ipc.Server$Handler$1.run(Server.java:1388)

at org.apache.hadoop.ipc.Server$Handler$1.run(Server.java:1384)

at java.security.AccessController.doPrivileged(Native Method)

at javax.security.auth.Subject.doAs(Subject.java:415)

at org.apache.hadoop.security.UserGroupInformation.doAs(UserGroupInformation.java:1121)

at org.apache.hadoop.ipc.Server$Handler.run(Server.java:1382)

일단 SafeModeException이란다. 구글링을 했다. 

네임노드가 처음 시작할 때 혹은 Hadoop이 비정상 종료된 후 실행시키면 Safe mode에서 돌아간단다.

여기서 빠져나오려면 다음과 같이 해야 한단다. 


mazdah$ hadoop dfsadmin -safemode leave


그런데 암만 이 명령을 실행해도 동일한 오류가 계속 발생을 한다.


이 시점에서 '네임노드를 다시 포맷을 하고 재실행 해보자' 하는 생각이 들었다.

그리고 어처구니없고 매우 당황스러운 상황을 겪게된다.


mazdah$ ./hadoop namenode -format

11/08/22 18:08:58 INFO namenode.NameNode: STARTUP_MSG:

/************************************************************

STARTUP_MSG: Starting NameNode

STARTUP_MSG:   host = nhn-PC/10.64.49.213

STARTUP_MSG:   args = [-format]

STARTUP_MSG:   version = 0.20.203.0

STARTUP_MSG:   build = http://svn.apache.org/repos/asf/hadoop/common/branches/br

anch-0.20-security-203 -r 1099333; compiled by 'oom' on Wed May  4 07:57:50 PDT

2011

************************************************************/

Re-format filesystem in \tmp\hadoop-nhn\dfs\name ? (Y or N)


hadoop namenode -format을 입력하고 엔터를 치면 위 내용이 나온다.

그리고 이미 이전에 파일 시스템이 구축되어 포맷을 한 적이 있기에 마지막줄처럼 다시 포맷할 것인가 묻는 내용이

나오는데...


아무리 y를 쳐도 계속 format aborted가 나오면서 포맷이 안되는 것이다...ㅠㅠ

나중에 안 사실이지만 이놈이 대소문자를 가리는 놈이었다...ㅠㅠ

즉, Y를 쳤어야 하는 것이다.


어쨌든 결국 포맷에 성공을 하고 데이터노드의 hadoop-data/node01, node02, node03 모두 삭제해주고

다시 한 번 차근차근 해보기로했다.


- 우선 start-all.sh로 모두 실행을 시켜주고

- hadoop dfsadmin -safemode leave로 safe mode에서 나오고(사실 이부분은 이 시점에서는 필요 없는 부분이었다)

- 데이터노드에서 jps로 프로세스를 확인 - 여전히 datanode는 안올라왔다.

- 데이터노드에서 hadoop datanode를 수행하여 개별적으로 데이터노드를 시작시킨다.


여기서 다시 한 번 오류로그를 확인할 수 있었다.

이번엔 비교적 명확한 오류...

데이터 저장소인 hadoop-data/node01(이 경로는 사용자마다 다르다)의 권한이 755(rwxr-xr-x)여야 하는데

777(rwxrwxrwx)로 되어있었던 것이다.


이렇게 해서 최종적으로 디렉토리의 권한을 수정한 후 다시 네임노드에서 재시작을 했더니 드디어 프로세스들이 모두

정상적으로 올라왔다.

연이어 start-hbase.sh를 통해 HBase를 시작하니 역시 정상적으로 프로세스가 시작되었다.


아무래도 나같은 일반 개발자들은 분산 환경을 경험하기가 쉽지 않아 실제 분산환경에서 발생하는 오류를 만나게 되니

문제의 시작점이 어디이고 또 어떤 문제가 원인이고 어떤 문제가 파생된 것인지를 찾기가 쉽지가 않다.

문제를 처음 만났을 때도 그저 프로세스가 올라오지 않은 데이터노드에서만 문제를 확인하려고만 했지 네임노드에 대한

생각은 까맣게 잊고 있었다.


사실 이 문제도 그저 단순하게

네임노드에서 start-all.sh로 시작하고 

hadoop dfsadmin -safemode leave로 세이프모드 나간다음

데이터노드에서 hadoop datanode를 실행해보기만 했어도 쉽게 해결할 수있었을지 모른다.


앞으로는 당황하지 말고 차근차근 노드간의 관계를 염두에 두면서 해결책을 찾아봐야겠다.


최초 작성일 : 2013/06/10 13:13 


역시 PPT 정리는 어렵군요...ㅠ.ㅠ

아래 이미지들은 한빛미디어의 Hadoop 완벽 가이드에 실린 내용을 재정리 한 것입니다.
=======================================================












최초 작성일 : 2013/06/05 13:02 


HDFS (하둡 분산 파일 시스템)은 다음의 사항을 고려하여 설계되었다.


1. 대용량의 파일 : 수백 Mb에서 수백 Tb 혹은 Pb급 이상을 대상으로 함

2. WORM (Write Once Read Many) : 커다란 원본으로부터 데이터 셋을 만들어 그
              데이터 셋을 분석한다. 그러기 위해서는 전체 파일을 읽어야 한다.

3. 범용 하드웨어 : 고성능의 신뢰도 높은 서버가 아닌 다수의 범용 머신으로 구성된
              클러스터에서의 실행을 고려하였다.


========================================================
위 내용에 대해서는 여러 번 반복되었기에 간단하게 적고 넘어간다.

그러나 간혹 'Big'이라는 용어의 함정에 빠져 잊기 쉬운 부분들이 있다.
나 역시 BigData 관련 공부를 시작하면서 문서는 물론이거니와 이미지나 음악 및 동여상 등
개인이 소유하게되는 파일 역시 수적으로나 양적으로 점점 더 커지고 있는 상황에서
이러한 분산 파일 시스템을 개인용으로 만들어보면 어떨까 하는 생각을 해봤다.
기존의 RAID 시스템에 비해 오히려 하드웨어적으로 더 저렴하게 구현을 할 수 있을 것
같았다.

그러나 다음의 내용을 확인하고서는 조용히 생각을 접었다.
(하지만 아직 가능성은 모색 중이다.)
========================================================

HDFS가 적당하지 않은 분야

1. 빠른 데이터 액세스 / 빠른 응답 시간이 필요한 경우
 - 앞서도 나왔지만 HDFS는 대용량의 파일을 처리하기 위한 시스템이고 대체로 배치성
   작업에 적합하다.

2. 많은 수의 작은 파일들에 대한 처리
 - 네임노드는 파일들의 메타 데이터를 관리하며 이를 디스크가 아닌 메모리에 저장하여 처리한다.
   따라서 파일의 수가 많아질수록 메모리에 대한 부하가 가중되며 아직도 디스크에 비해
   가격이 비싼 메모리 관리에 문제가 발생할 수 있으며 파일의 수가 비약적으로 많아질
   경우 하드웨어에서 지원 가능한 메모리 용량을 넘어설 수도 있는 문제이다.

3. 다중 writer나 임의의 파일 수정
 - 역시 앞서 나왔듯이 HDFS는 WORM 상태를 고려하여 설계되었다.
   예를 들어 HDFS는 파일을 블럭으로 나눈 후 서로 다른 노드에 저장을 한다.
   뿐만 아니라 필요한 수 만큼의 복제본을 생성한다. 만일 이 파일에 대한 수정을
   허용한다면 파일의 수정이 생길 때마다 각 노드이 해당 블럭을 찾고 수정된 위치에
   변경 사항을 반영해야 하며 이러한 작업을 복제본에까지 적용해야 한다(혹은 변경된
   블럭들을 다시 복제해야 한다).
   얼마나 비효울적인가...

***
즉, 수십Gb에 달하는 대용량의 파일의 존재할지라도 아직도 개인의 디스크에는
많은 수의 작은 파일들이 대부분의 저장공간을 차지하고 있을 것이다.
또한 파일 성격에 따라 수시로 변경되는 파일도 많을뿐더러 이러한 파일들을
빨리 읽혀야 한다.

하지만 동영상을 중심으로하는 대용량 파일들만을 고래해보았을 때는HDFS의
기본 설계에 얼추 들어맞는 것 같다. 대용량이면서 디스크에 저장된 이후 수정이 일어날
일도 없다. 다만 빠른 접근만이 문제가 될 것이다.

최초 작성일 : 2013/05/21 13:01 


이 글에 적는 내용은 2013년 1월 3일 길벗사에서 간행한

'대용량 데이터 분석 및 처리를 위한 hadoop nosql' (서상원김재홍박윤성이준섭명재석 저)의
전자책 버전에서 발췌한 내용입니다.
중요한 내용이 있을 때마다 이러한 정보들을 정리해 올리도록 하겠습니다.

==========================================================

1. 하둡은 크게 HDFS와 MapReduce의 두 부분으로 구성되어있으며
   HDFS는 네임노드, 세컨더리 네임노드, 데이터노드를 동작시키고
   MapReduce는 잡 트래커와 태스크 트래커를 동작시킨다.

   네임노드와 잡 트래커는 마스터 노드(네임노드)에서, 데이터노드와 태스크 트래커는
   슬레이브 노드(데이터노드)에서 동작한다.

   동작하는 프로세스는 jps 명령으로 확인할 수 있다.

2. 하둡 분산 파일 시스템(HDFS)는 다수의 작은 파일보다는 소수의 대용량 파일을 다루는데
   적합하도록 설계된 파일 시스템이다.

3. 하둡에서 각 노드들의 프로세스를 기동하기 위해 SSH를 사용한다. 수 백, 수 천대로
   구성된 클러스터의 경우 일일히 각각의 서버에서 프로세스를 기동할 수 없기 때문에
   네임노드에서 기동을 시키면 클러스터 내의 모든 슬레이브 노드에서 프로세스가 기동이
   되는 데, 이 때 SSH를 사용하여 명령을 전달하게 된다.

4. 하둡이 파일을 블록으로 나누어 저장하는 이유
   - 파일 시스템에 따라 한 개의 파일이 가질 수 있는 최대 크기에는 제약이 있다.
      블록으로 나누어 저장하면 이러한 제약을 피해서 대용량 파일을 저장할 수 있다.
   - 대용량 파일을 하나로 저장할 경우 파일을 읽기 위해 메모리로 로드하는데 부하가
      걸린다. (Gb급 로그 파일을 편집기로 열지 못하는 경우를 생각해보자) 블록으로
      나루면 이러한 문제가 해소된다.

최초 작성일 : 2013/05/20 13:15 


일단 설치와 설정을 끝마쳤다고 생각하고 샘플 job을 수행해보기로 했다.
하지만 아래의 명령을 실행시켜도 map:0% reduce:0%에서 더이상 진행이 없었다.

예제 실행 코드

./hadoop jar ../hadoop-examples-1.0.4.jar wordcount input output

input : 원본 문서가 있는 곳
output : 결과 문서가 저장될 곳

아직도 분산이라는 환경에 익숙하지 않은 탓에 계속 네임노드쪽 로그만 뒤적거리면서 원인을 찾으려고 했다.
하지만 네임노드쪽 로그에는 딱히 이렇다할 에러도 기록된 것이 없어 원인을 찾은데 시간만 잡아먹고 있었다.

그러다가 데이터노드 쪽으로 관심을 돌려 데이터노드의 로그를 살피기 시작했고 여기서 문제의 실마리가
잡히기 시작했다.

우선 데이터노드에서 jps 명령을 통해 TaskTracker가 로드되지 않았다는 사실을 확인했다.
그리고 바로 hadoop-mazdah-tasktracker-macmini-server.com.log 파일에서 다음과 같은 로그를
발견했다

이 로그의 ERROR 항목 바로 직전에 나오는 WARN 내용으로부터 디렉토리 설정에 뭔가 문제가 있다는 것을
짐작하고 처음 글에서 잠시 언급한 것 처럼 이 디렉토리도 모든 노드들 간에 경로를 일치시키기로 했다.


처음 디렉토리 설정이 맞지 않았을 때의 오류 로그

************************************************************/
2013-05-20 11:27:20,495 INFO org.apache.hadoop.mapred.TaskTracker: STARTUP_MSG:
/************************************************************
STARTUP_MSG: Starting TaskTracker
STARTUP_MSG:   host = macmini-server.com/134.102.35.58
STARTUP_MSG:   args = []
STARTUP_MSG:   version = 1.0.4
STARTUP_MSG:   build = https://svn.apache.org/repos/asf/hadoop/common/branches/branch-1.0 -r 1393290; compiled by 'hortonfo' on Wed Oct  3 05:13:58 UTC 2012
************************************************************/
2013-05-20 11:27:20,657 INFO org.apache.hadoop.metrics2.impl.MetricsConfig: loaded properties from hadoop-metrics2.properties
2013-05-20 11:27:20,710 INFO org.apache.hadoop.metrics2.impl.MetricsSourceAdapter: MBean for source MetricsSystem,sub=Stats registered.
2013-05-20 11:27:20,711 INFO org.apache.hadoop.metrics2.impl.MetricsSystemImpl: Scheduled snapshot period at 10 second(s).
2013-05-20 11:27:20,711 INFO org.apache.hadoop.metrics2.impl.MetricsSystemImpl: TaskTracker metrics system started
2013-05-20 11:27:20,979 INFO org.apache.hadoop.metrics2.impl.MetricsSourceAdapter: MBean for source ugi registered.
2013-05-20 11:27:25,144 INFO org.mortbay.log: Logging to org.slf4j.impl.Log4jLoggerAdapter(org.mortbay.log) via org.mortbay.log.Slf4jLog
2013-05-20 11:27:25,190 INFO org.apache.hadoop.http.HttpServer: Added global filtersafety (class=org.apache.hadoop.http.HttpServer$QuotingInputFilter)
2013-05-20 11:27:25,220 WARN org.apache.hadoop.mapred.TaskTracker: TaskTracker local dir /Volumes/Data2/hadoop-data/mapred/local error can not create directory: /Volumes/Data2/hadoop-data/mapred/local, removing from local dirs
2013-05-20 11:27:25,221 ERROR org.apache.hadoop.mapred.TaskTracker: Can not start task tracker because java.util.ConcurrentModificationException
at java.util.AbstractList$Itr.checkForComodification(AbstractList.java:372)
at java.util.AbstractList$Itr.next(AbstractList.java:343)
at org.apache.hadoop.mapred.TaskTracker$LocalStorage.checkDirs(TaskTracker.java:211)
at org.apache.hadoop.mapred.TaskTracker.<init>(TaskTracker.java:1449)
at org.apache.hadoop.mapred.TaskTracker.main(TaskTracker.java:3742)

2013-05-20 11:27:25,222 INFO org.apache.hadoop.mapred.TaskTracker: SHUTDOWN_MSG:


각각의 설정 파일에서 다음과 같이 value를 통일시켰다.
몰론 네임노드와 데이터노드의 실제 물리적 공간도 /hadoop-data로 맞추었다.

core-site.xml

<property>
        <name>hadoop.tmp.dir</name>
        <value>/hadoop-data/tmp</value>
    </property>
   
hdfs-site.xml

<property>
     <name>dfs.name.dir</name>
        <value>/hadoop-data</value>
    </property>

    <property>
        <name>dfs.data.dir</name>
        <value>/hadoop-data</value>
    </property>
   
mapred-site.xml

<property>
         <name>mapred.system.dir</name>
         <value>/hadoop-data/mapred/system</value>
    </property>
    <property>
     <name>mapred.local.dir</name>
        <value>/hadoop-data/mapred/local</value>
    </property>
   

그리고 각 노드간 변경된 설정들을 sync 시킨 후 다시 start-all.sh를 실행시켰다.
그러나 여전히 문제가 발생을 하였다. 이번엔 jps 명령어를 통해 확인하니 데이터노드쪽에서 DataNode 프로세스가
로드되지 않았고 hadoop-mazdah-datanode-macmini-server.com.log 파일을 확인하니 다음고 같은 로그가
찍혔다.

************************************************************/
2013-05-20 12:28:44,171 INFO org.apache.hadoop.hdfs.server.datanode.DataNode: STARTUP_MSG:
/************************************************************
STARTUP_MSG: Starting DataNode
STARTUP_MSG:   host = macmini-server.com/134.102.35.58
STARTUP_MSG:   args = []
STARTUP_MSG:   version = 1.0.4
STARTUP_MSG:   build = https://svn.apache.org/repos/asf/hadoop/common/branches/branch-1.0 -r 1393290; compiled by 'hortonfo' on Wed Oct  3 05:13:58 UTC 2012
************************************************************/
2013-05-20 12:28:44,307 INFO org.apache.hadoop.metrics2.impl.MetricsConfig: loaded properties from hadoop-metrics2.properties
2013-05-20 12:28:44,317 INFO org.apache.hadoop.metrics2.impl.MetricsSourceAdapter: MBean for source MetricsSystem,sub=Stats registered.
2013-05-20 12:28:44,317 INFO org.apache.hadoop.metrics2.impl.MetricsSystemImpl: Scheduled snapshot period at 10 second(s).
2013-05-20 12:28:44,317 INFO org.apache.hadoop.metrics2.impl.MetricsSystemImpl: DataNode metrics system started
2013-05-20 12:28:44,403 INFO org.apache.hadoop.metrics2.impl.MetricsSourceAdapter: MBean for source ugi registered.
2013-05-20 12:28:52,800 ERROR org.apache.hadoop.hdfs.server.datanode.DataNode: java.io.IOException: Incompatible namespaceIDs in /hadoop-data: namenode namespaceID = 1440344326; datanode namespaceID = 1690373933
at org.apache.hadoop.hdfs.server.datanode.DataStorage.doTransition(DataStorage.java:232)
at org.apache.hadoop.hdfs.server.datanode.DataStorage.recoverTransitionRead(DataStorage.java:147)
at org.apache.hadoop.hdfs.server.datanode.DataNode.startDataNode(DataNode.java:385)
at org.apache.hadoop.hdfs.server.datanode.DataNode.<init>(DataNode.java:299)
at org.apache.hadoop.hdfs.server.datanode.DataNode.makeInstance(DataNode.java:1582)
at org.apache.hadoop.hdfs.server.datanode.DataNode.instantiateDataNode(DataNode.java:1521)
at org.apache.hadoop.hdfs.server.datanode.DataNode.createDataNode(DataNode.java:1539)
at org.apache.hadoop.hdfs.server.datanode.DataNode.secureMain(DataNode.java:1665)
at org.apache.hadoop.hdfs.server.datanode.DataNode.main(DataNode.java:1682)

2013-05-20 12:28:52,802 INFO org.apache.hadoop.hdfs.server.datanode.DataNode: SHUTDOWN_MSG:


이 내용은 구글링을 통해 쉽게 해결하였다.
위에서 디렉토리 경로를 바꾸면서 기존 생성했던 디렉토리를 새 위치로 그냥 카피를 했던 것이다.
즉 /hadoop-data라는 디렉토리 안에 기존에 생성된 설정들이 그대 담겨있었다. 이로 인해 문제가 발생을 한 것이었고
/hadoop-data를 싹 비우고 새로 실행하니 드디어 wordcount 예제가 실행이 되었다.

역시 아직은 분산이라는 환경에 익숙하지 않은 탓에 사소하면서도 쉽게 해결하지 못하는
문제들이 많이 발생을 한다. 이 부분은 이론적인 학습을 통해 보충을 하는 수 밖에 없을 것 같다.

그리고 이번 글에 같이 적으려던 놀고먹게된 맥미니에 대한 이야기는 별도로
작성하려 한다.

최초 작성일 : 2013/05/16 13:37


미리 말씀드리지만 이 글은 설치 안내가 아니라 설치 중에 실수할 수 있을만한 부분에 대해

적은 글입니다. 설치 전반에 대해 참고한 글은 본문 중에 링크를 하였으니 참고하세요...^^


=========================================================


원래는 교재와 함께 천천히 실습을 진행할 계획이었는데…

지난 한 달 간 되지도 않는 영어실력으로 문서 번역한다고 삽질을 해놨더니 조급증이 생겨서

우선 하둡부터 설치를 하고 봤다.


애초 예정대로 대상 머신들은 모두 애플의 맥 기종으로 맥북 프로1대 맥미니 서버 1대 맥미니 1대이며

이 중 맥북프로와 맥미니 서버는 같은 네트워크 대역에 있으나 맥미니 1대는 다른 네트워크 대역에 있다.

다음 글에 언급하겠지만 역시나…맥미니는 클러스터로 묶일 수가 없다…ㅠ.ㅠ

(이거 해볼라구 따로 구입한 놈인데…제 역할을 못하게 됐다…ㅠ.ㅠ)


우선 설치는 무진장 쉽다.

개나 소나 할 수 있다.

개나 소가 컴퓨터를 이용할 수 있다는 가정하에…-.-


암튼 다운로드 받고 압축 풀고 java home 잡아주고 설정 xml파일 3개정도 만져주면 끝이다.

우선 도움을 받은 사이트를 링크한다.

많지도 않다.

요기만 잘 보고 진행하면 만사 땡이다.


http://blrunner.com/29

http://develop.sunshiny.co.kr/868

http://develop.sunshiny.co.kr/893


하지만…

중요한 함정이 도사리고 있었다.

앞서 구글의 논문을 번역하는 가운데 구글 애들이 매우 자주 강조한 내용이 있었다.

'MapReduce 라이브러리는 병렬이나 분산 시스템에 대한 경험이 없는 개발자들도

쉽게 접근할 수 있다'는 것이다.


그러나 이 쉽게 접근할 수 있다는 의미는 좀 더 구체적으로 말하면

'(얼마간의 혹은 꽤 오랜 시간 삽질을 거치게 되면) 쉽게 접근할 수 있다'라는 것이다.


대체로 분산 시스템이라는 것이 물리적으로 다른 공간에 위치한 머신들 사이에 동일한 프로세스를

마치 동일하 머신상에서 수행하는 것 처럼 처리할 수 있다는 의미일 것이다.

하지만 이러한 분산 시스템을 위해 먼저 알아 두어야 할 것이 바로 '물리적으로 분리된 공간'이라는 점이다.

이 것은 시스템의 환경을 설정할 때 뜻하지 않은 실수를 하게 만든다.

바로 호스트명 또는 서버 주소를 설정하는 부분에서 발생을 하게 되는 것이다.


오늘의 실수를 통해 이야기 해보자.


우선 Hadoop은 Standalone모드와 Pseudo-distributed모드 그리고 Fully-distributed모드로

실행할 수 있다. 각각의 모드는 특별이 데몬을 띄울 때 옵션이 있거나 한 것이 아니라 위 링크에

설명되어있는 설정파일을 어떻게 설정을 하느냐에 따라 달라진다.


Standalone : 모든 설정파일을 초기 상태로 비워둔채로 하둡을 실행한다. map/reduce 프로그램을

                       신속하게 개발/디버깅하기 위해 사용된다.

Pseudo-distributed : 모든 설정 파일에 각 노드의 주소를 모두 localhost로 입력한다. 단일한

                       머신 내에서 가상으로 분산 환경을 만들 때 사용된다.

Fully-distributed : 모든 설정 파일에서 각 노드의 주소는 실제 부여된 IP나 도메인 또는 hosts 파일에

                       등록된 이름을 사용해야 하며 각각의 머신들은 실제로 분산되어있어야 한다.


내가 처음 참조한 설치 방법에 대한 블로그는 http://blrunner.com/29였다.

그런데 이 블로거는 Pseudo-distributed로 실행할 것을 전제로 하여 설명을 하고 있다.

그런데 나는 Fully-distributed를 목표로 진행을 하고 있었다. (그래서 피같은 돈 들여 맥미니까지 추가

구매를 하였다. 근데 그놈은 현재 놀고있다…ㅠ.ㅠ)


아무 생각 없이 따라하다보니 하둡 설정이 모두 Pseudo-distributed에 맞춰진 것이다.

여기서 첫 번째 실수가 있었다.


다음으로는 원래 분산 시스템이란 것이 그런가 모르겠는데

각 머신들간의 동기화를 위해서인지 하둡 자체가 동일한 경로에 설치가 되어야한다는 것을

나중에 알았다.(혹은 위치가 달라도 설정만 별도로 해주면 되는지도 모르겠다. 아직 모르는게

더 많아서…^^;;;)


즉 A 머신의 하둡 설치 경로가 /home/mazdah/hadoop-1.0.4였다면

B 머신의 하둡 설치 경로도 /home/mazdah/hadoop-1.0.4여야 한다는 것이다.


꼭 이렇게 하지 않아도 될지 모르지만 개인적인 생각에 시스템을 아예 처음 설치하는 것이라면

디스크 볼륨 등을 통일해서 이렇게 같은 경로에 설치하는 것이 관리적인 차원에서 좋을 것 같다.


이미 다른 시스템들이  잔뜩 설치된 곳에서는 디스크 볼륨명을 함부로 바꾸기도 쉽지 않고

여러모로 헷갈릴 듯싶다.


아래는 머신간에 하둡 설치 위치가 달랐을 때와 설치 위치가 같았을 때 start-all.sh를 실행한

콘솔 메시지 내용이다.


xxx와 yyy 머신은 데이터 노드이고 localhost는 네임노드이다.

현재 /Volumes/Data2/hadoop-1.0.4로 표시되는 것은 처음 설치한 네임노드에서의 하둡 설치

위치(HADOOP_HOME)이다.


이 중 xxx 시스템의 설치 위치를 네임노드와 일치시켰더니 이후 실행 시 xxx 머신에서는

No such file or directory 메시지가 나오지 않게 되었다.


하지만 yyy노드이 경우 이미 다른 웹 시스템 및 SVN과 CI용으로 젠킨스 등이 설치된 상태라 함부로

디스크 볼륨명을 수정하기가 어려웠다. 그래서 3대의 시스템 모두 설치 위치를 /hadoop-1.0.4로

옮겨버렸다. 참으로 심플한 결정이었다…-.-


네임노드와 데이터 노드의 하둡 설치 위치가 달랐을 때


Mazdah-ui-MacBook-Pro:bin mazdah$ ./start-all.sh

starting namenode, logging to /Volumes/Data2/hadoop-1.0.4/libexec/../logs/hadoop-mazdah-namenode-Mazdah-ui-MacBook-Pro.local.out

xxx.xxxxx.xxx: bash: /Volumes/Data2/hadoop/bin/hadoop-daemon.sh: No such file or directory

yyy.yyyy.yyy: bash: line 0: cd: /Volumes/Data2/hadoop-1.0.4/libexec/..: No such file or directory

yyy.yyyy.yyy: bash: /Volumes/Data2/hadoop/bin/hadoop-daemon.sh: No such file or directory

localhost: starting secondarynamenode, logging to /Volumes/Data2/hadoop-1.0.4/libexec/../logs/hadoop-mazdah-secondarynamenode-Mazdah-ui-MacBook-Pro.local.out

starting jobtracker, logging to /Volumes/Data2/hadoop-1.0.4/libexec/../logs/hadoop-mazdah-jobtracker-Mazdah-ui-MacBook-Pro.local.out

xxx.xxxxx.xxx: bash: /Volumes/Data2/hadoop/bin/hadoop-daemon.sh: No such file or directory

yyy.yyyy.yyy: bash: line 0: cd: /Volumes/Data2/hadoop-1.0.4/libexec/..: No such file or directory

yyy.yyyy.yyy: bash: /Volumes/Data2/hadoop/bin/hadoop-daemon.sh: No such file or directory


Mazdah-ui-MacBook-Pro:bin mazdah$ ./stop-all.sh

stopping jobtracker

yyy.yyyy.yyy: bash: line 0: cd: /Volumes/Data2/hadoop-1.0.4/libexec/..: No such file or directory

yyy.yyyy.yyy: bash: /Volumes/Data2/hadoop/bin/hadoop-daemon.sh: No such file or directory

xxx.xxxx.xxx: bash: /Volumes/Data2/hadoop/bin/hadoop-daemon.sh: No such file or directory

stopping namenode

yyy.yyyy.yyy: bash: line 0: cd: /Volumes/Data2/hadoop-1.0.4/libexec/..: No such file or directory

yyy.yyyy.yyy: bash: /Volumes/Data2/hadoop/bin/hadoop-daemon.sh: No such file or directory

xxx.xxxx.xxx bash: /Volumes/Data2/hadoop/bin/hadoop-daemon.sh: No such file or directory

localhost: stopping secondarynamenode


네임노드와 데이터 노드의 하둡 설치 위치가 같아진 후


Mazdah-ui-MacBook-Pro:bin mazdah$ ./start-all.sh

starting namenode, logging to /Volumes/Data2/hadoop-1.0.4/libexec/../logs/hadoop-mazdah-namenode-Mazdah-ui-MacBook-Pro.local.out

xxx.xxxx.xxx: starting datanode, logging to /Volumes/Data2/hadoop-1.0.4/libexec/../logs/hadoop-mazdah-datanode-localhost.out

yyy.yyyy.yyy: bash: line 0: cd: /Volumes/Data2/hadoop-1.0.4/libexec/..: No such file or directory

yyy.yyyy.yyy: bash: /Volumes/Data2/hadoop/bin/hadoop-daemon.sh: No such file or directory

localhost: starting secondarynamenode, logging to /Volumes/Data2/hadoop-1.0.4/libexec/../logs/hadoop-mazdah-secondarynamenode-Mazdah-ui-MacBook-Pro.local.out

starting jobtracker, logging to /Volumes/Data2/hadoop-1.0.4/libexec/../logs/hadoop-mazdah-jobtracker-Mazdah-ui-MacBook-Pro.local.out

xxx.xxxx.xxx: starting tasktracker, logging to /Volumes/Data2/hadoop-1.0.4/libexec/../logs/hadoop-mazdah-tasktracker-localhost.out

yyy.yyyy.yyy: bash: line 0: cd: /Volumes/Data2/hadoop-1.0.4/libexec/..: No such file or directory

yyy.yyyy.yyy: bash: /Volumes/Data2/hadoop/bin/hadoop-daemon.sh: No such file or directory


첫 날부터 너무 긴 내용을 적으면 이후 진행에 애로 사항이 꽃피는데…

암튼 처음 설치다보니 삽질이 적지 않았다. 하지만 반나절 정도 삽질하고 네임노드와 데이터 노드가 정상적으로

연결된 것을 볼 수 있었으니 그리 나쁘진 않은 성적인 것 같다.

구글 아자씨들 말대로 쉽긴 쉬운가보다.

(컴퓨터를 할 줄 아는) 개나 소나 할 수 있으니…^^;;;


암튼 오늘인 여기까지

다음에는 아직 못돌려본 샘플 프로그램을 좀 돌려보고 부가적으로다가

혼자 놀게된 맥미니가 왜 혼자 놀게 되었는지(당근 네트워크 대역이 다르니…-.-)

또 거금을 들여 구입한 맥미니를 그냥 놀게 둘 수는 없으니 어떻게 활용할지에 대해 다뤄보자.

+ Recent posts

티스토리 툴바