Hadoop 완전 분산 모드 구축 (AWS EC2)

suran choi·2022년 10월 28일
2

Hadoop

목록 보기
1/6
post-thumbnail

멀티캠퍼스 수료할 당시 항상 하둡을 단일 노드로 구축한 점이 아쉬워서
분산 모드로 새로 구축한 내용 및 겪었던 오류를 정리하고자 포스팅합니다


아래와 같이 구성하였습니다.

  • AWS EC2: 총 4대
  • Hadoop - 3.2.4
  • Java - OpenJDK 11

우선 VM으로 컴퓨터 4대로 나누어 하둡을 구축할 수도 있었지만,
실제로 서버간 통신할 때 어려움을 겪고 싶어서 EC2 4대로 환경을 구축하였습니다.

  • Namenode -> namenode01
  • Secondary Namenode -> namenode02
  • Datanode1 -> datanode01
  • Datanode2 -> datanode02

위와 같이 네 대로 나누었고 앞으로 각각의 인스턴스들을 노드 이름으로 부를 예정이니 참고하세요!

또한, 모든 노드에서 설정해야 하는 사안 // 특정 노드에서 설정해야 하는 사안이 따로 있으니 제가 연노랑색으로 소제목마다 공시를 하겠습니다.

1. EC2

AWS로 EC2는 구축하였다는 가정하에 말씀드리겠습니다.

우선 하둡을 설정할 때 ip를 지정하는 일이 많은데, EC2 인스턴스의 경우 정지 후 재시작 할 때마다 ip가 달라지므로 고정적인 ip 할당을 위해서는 다음과 같은 작업을 해줘야 합니다.

1-1. 고정적인 ip 할당

[모든 노드에서 설정]

  1. aws에 들어가 왼쪽 메뉴바에서 탄력적 IP 선택

  2. 탄력적 IP를 할당 받은 적이 없으면 화면에 아무것도 안뜰텐데 빨간 네모표 친 탄력적 IP 주소 할당을 클릭합니다.

  3. 아무것도 변경하지 않고 제일 하단의 할당 클릭

  4. 탄력적 IP 주소 할당 -> 탄력적 IP 주소 연결 한 다음 자기가 원하는 인스턴스에 IP를 연결해주면 된다.


1-2. 인바운드 포트 설정

[모든 노드에서 설정]

하둡 노드들끼리 통신을 하기 위해서는 인바운드 포트를 열어줘야 하기 때문에 다음과 같이 포트를 열어주시면 됩니다.

이름Port
Datanode Web UI9864
Datanode port9866
Datanode ipc port9867
Namenode port9000
Namenode Web UI9870
SecondaryNN port9868

  1. 해당 인스턴스 클릭 - 보안 그룹 클릭

  2. 하단의 인바운드 규칙 편집 클릭

  3. 규칙 추가 - [사용자 지정 TCP] - [Port] - [0.0.0.0]




2. Java

[모든 노드에서 설정]
Hadoop은 자바 언어로 구현되었기 때문에 하둡 설치 전에 자바를 먼저 설치해주어야 합니다.

$ sudo apt install openjdk-11-jdk

$ sudo vim ~/.bashrc

=====
# bashrc 파일 안에 아래 내용을 작성
export JAVA_HOME=/usr/lib/jvm/java-11-openjdk-amd64
export PATH=$PATH:$JAVA_HOME/bin
=====

$ sourve ~/.bashrc

# 자바가 잘 설치되었는지 자바 버전 확인
$ java --version




3. Hadoop

3-1. Hadoop 설치

[모든 노드에서 설정]

# hadoop 다운로드
$ wget https://archive.apache.org/dist/hadoop/common/hadoop-3.2.4/hadoop-3.2.4.tar.gz

# 압축파일 풀기
$ tar xvzf hadoop-3.2.4.tar.gz

# 이름 변경
$ mv hadoop-3.2.4 hadoop

# 설치 파일 삭제
$ rm hadoop-3.2.4.tar.gz

$ sudo vim ~/.bashrc

=====
# bashrc 파일에 아래 내용을 작성

# hadoop
export HADOOP_HOME=/home/ubuntu/hadoop
export HADOOP_CONF_DIR=$HADOOP_HOME/etc/hadoop
export PATH=$PATH:$HADOOP_HOME/bin:$HADOOP_HOME/sbin:$HADOOP_HOME/etc/hadoop

# hadoop user
export HDFS_NAMENODE_USER=ubuntu
export HDFS_DATANODE_USER=ubuntu
export HDFS_SECONDARYNAMENODE_USER=ubuntu
export YARN_RESOURCEMANAGER_USER=ubuntu
export YARN_NODEMANAGER_USER=ubuntu
=====

$ source ~/.bashrc

3-2. host / hostname 설정

[모든 노드에서 설정]

EC2 인스턴스를 처음 만들면 hostname이 ip-nn-nnn 이런식으로 기본 설정이 되어 있을 텐데, 그러면 다른 노드를 지정할 때 귀찮기 때문에 (뒤에 나오는 설정 파일 쓸 때도 힘듭니다..) hostname을 바꿔주도록 하겠습니다.

이름hostname
네임노드namenode01
세컨더리 네임노드namenode02
데이터노드1datanode01
데이터노드2datanode02
  1. hostname 설정
  • 본인의 hostname 설정을 위함
$ sudo vim /etc/hostname

=====
# 기존에 적혀 있던 내용 지우고, 각 인스턴스에 맞는 hostname으로 설정
namenode01
=====

# 리부팅
# 리부팅 하고 다시 켜질 때까지 좀 기다리셔야 합니다. ssh 접속이 안되더라도 당황치 마세요
$ sudo reboot

  1. hosts 설정
  • 노드 간 통신을 할 때 해당 hostname, ip로 노드를 찾기 위함

  • 제 ip 들을 공개하지 않기 위해, public ip, private ip 등으로 적겠습니다. 실제 적용하실 때는 aws 인스턴스 홈페이지에서 각자 본인의 public ip, private ip로 설정하시면 됩니다.

    [namenode01에서 설정]

    $ sudo vim /etc/hosts
    
    ---
    private_ip namenode01
    public_ip namenode02
    public_ip datanode01
    public_ip datanode02

    [namenode02에서 설정]

    $ sudo vim /etc/hosts
    
    ---
    public_ip namenode01
    private_ip namenode02
    public_ip datanode01
    public_ip datanode02

    [datanode에서 설정]

    $ sudo vim /etc/hosts
    
    ---
    public_ip namenode01
    public_ip namenode02
    public_ip datanode01
    public_ip datanode02

3-3. SSH 설정

ssh란? 컴퓨터 간의 통신을 할 때 안전하게 통신하기 위해서 사용하는 프로토콜입니다.

기본적으로 내 컴퓨터에서 EC2 인스턴스에 접속할 때도 ssh를 사용하는데요.
네임노드에서 데이터노드로 접근해서 명령을 내려야 하기 때문에, 네임 노드에서 세컨더리 네임노드, 데이터 노드들에 접근가능하도록 공개키를 전달하는 작업이 필요합니다.

저는 노드들마다 pem 키가 달라 Local 컴퓨터에서 pem키를 네임노드에 보내는 작업을 먼저해주었는데, EC2 인스턴스의 pem 키가 전부 동일하신 분은 1번 작업을 한 번만 진행하셔도 됩니다.

[로컬 컴퓨터에서 설정]
1. 인스턴스의 pem키를 네임노드로 전달

# namenode02 pem key(=achacha-sr.pem)-> namenode01에 보내기
$ scp -i achacha.pem -r /Users/user/Downloads/AWS_KEYS/achacha-sr.pem ubuntu@[public_ip]:~/.ssh

# datanode01 pem key(=achacha.pem) -> namenode01에 보내기
$ scp -i achacha.pem -r /Users/user/Downloads/AWS_KEYS/achacha.pem ubuntu@[public_ip]:~/.ssh

# datanode02 pem key(=achacha-jh.pem) -> namenode01에 보내기
$ scp -i achacha.pem -r /Users/user/Downloads/AWS_KEYS/achacha-jh.pem ubuntu@[public_ip]:~/.ssh

-> $ scp -i ~~.pem -r [보낼 파일] ubuntu@[해당 public ip]:[인스턴스 경로]
와 같은 명령어로 로컬 컴퓨터의 파일을 인스턴스로 보낼 수가 있습니다.


[namenode01에서 설정]
2. ssh 공개키를 생성한 후, 다른 노드들에게 공개키 전달

# -t : type(rsa), -P : 이전 암호 초기화 -f : 파일 저장 위치
$ ssh-keygen -t rsa -P '' -f ~/.ssh/id_rsa
$ cat ~/.ssh/id_rsa.pub >> ~/.ssh/authorized_keys

# namenode02 copy
$ scp -i achacha-sr.pem ~/.ssh/id_rsa.pub ubuntu@[public_ip]:~/.ssh/

# datanode01 copy
$ scp -i achacha.pem ~/.ssh/id_rsa.pub ubuntu@[public_ip]:~/.ssh/

# datanode02 copy
$ scp -i achacha-jh.pem ~/.ssh/id_rsa.pub ubuntu@[public_ip]:~/.ssh/

[namenode02, datanode01, datanode02에서 설정]
3. 공개키를 authorized_keys에 전달

$ cat ~/.ssh/id_rsa.pub >> ~/.ssh/authorized_keys

[namenode01에서 설정]
4. 네임노드에서 다른 노드로 접속가능 한지 확인

$ ssh namenode02

$ ssh datanode01

$ ssh datanode02

3-4. 방화벽 설정

다른 블로그에서 봤을 때는 방화벽을 아예 다 내려주는 경우도 있던데, 저는 방화벽을 아예 내려주기에는 보안적인 문제가 있을 것이라 생각하여 서로의 노드 ip, 자기 자신의 port 정도만 열어주었습니다.

[namenode01에서 설정]

$ sudo ufw allow from [namenode02_public ip]
$ sudo ufw allow from [datanode01_public ip]
$ sudo ufw allow from [datanode02_public ip]

$ sudo ufw allow 22
$ sudo ufw allow 9000
$ sudo ufw allow 9870

$ sudo ufw enable

[namenode02에서 설정]

$ sudo ufw allow from [namenode01_public ip]
$ sudo ufw allow from [datanode01_public ip]
$ sudo ufw allow from [datanode02_public ip]

$ sudo ufw allow 22
$ sudo ufw allow 9868

$ sudo ufw enable

[datanode01에서 설정]

$ sudo ufw allow from [namenode01_public ip]
$ sudo ufw allow from [namenode02_public ip]
$ sudo ufw allow from [datanode02_public ip]

$ sudo ufw allow 22
$ sudo ufw allow 9864
$ sudo ufw allow 9866
$ sudo ufw allow 9867

$ sudo ufw enable

[datanode02에서 설정]

$ sudo ufw allow from [namenode01_public ip]
$ sudo ufw allow from [namenode02_public ip]
$ sudo ufw allow from [datanode01_public ip]

$ sudo ufw allow 22
$ sudo ufw allow 9864
$ sudo ufw allow 9866
$ sudo ufw allow 9867

$ sudo ufw enable

[모든 노드에서 진행]
각 서버간 통신이 되어야 하둡도 진행이 가능하기 때문에 여기서 꼭 확인하고 넘어가주세요.

# 예. namenode01에서 실행 (다른 노드에서도 각자 telnet으로 통신 되는지 확인 필)
$ telnet [namenode02_public ip] 9868
$ telnet [datanode01_public ip] 9866
$ telnet [datanode02_public ip] 9866

3-5. 설정 파일

파일 이름내용
core-site.xmlHDFS와 맵리듀스에서 공통적으로 사용할 환경설정 정보
yarn-site.xml맵리듀스 프레임워크에서 사용하는 셔플 서비스를 지정
mapred-site.xml맵리듀스에서 사용할 환경정보 설정
hdfs-site.xmlHDFS에서 사용할 환경정보 설정
workers (hadoop 3.x)datanode 지정

[모든 노드에서 진행]

  • core-site.xml

    fs.defaultFS - 네임노드의 호스트명과 포트 번호 설정

    $ vim $HADOOP_CONF_DIR/core-site.xml
    
    =====
    <configuration>
        <property>
                <name>fs.defaultFS</name>
                <value>hdfs://namenode01:9000</value>
        </property>
    </configuration>
    =====
  • yarn-site.xml

    yarn.nodemanager.aux-services - 셔플 서비스 이름
    yarn.resourcemanager.hostname - ResourceManager 노드에 설정

    $ vim $HADOOP_CONF_DIR/yarn-site.xml
    
    =====
    <configuration>
       <property>
          <name>yarn.nodemanager.aux-services</name>
          <value>mapreduce_shuffle</value>
       </property>
        <property>
            <name>yarn.resourcemanager.hostname</name>
            <value>namenode01</value>
        </property>
    </configuration>
    =====
  • mapred-site.xml

    • mapreduce.framework.name
      • option - yarn모드라고 설정해줌
    $ vim $HADOOP_CONF_DIR/mapred-site.xml
    =====
    <configuration>
        <property>
            <name>mapreduce.framework.name</name>
            <value>yarn</value>
        </property>
    </configuration>
    =====

[namenode01, namenode02에서 진행]

  • hdfs-site.xml

    dfs.replication - 데이터 복제수, default 3
    dfs.permissions - false
    dfs.namenode.name.dir - fsimage가 저장될 경로, Namenode에 설정
    dfs.namenode.http.address - namenode의 webui 포트지정
    dfs.secondary.http.address - 세컨더리 네임노드 주소와 포트지정

    $ vim $HADOOP_CONF_DIR/hdfs-site.xml
    
    =====
    <configuration>
        <property>
            <name>dfs.replication</name>
            <value>2</value>
        </property>
        <property>
            <name>dfs.permissions</name>
            <value>false</value>
        </property>
        <property>
            <name>dfs.namenode.name.dir</name>
            <value>/home/ubuntu/hadoop/namenode_dir</value>
        </property>
        <property>
            <name>dfs.namenode.http.address</name>
            <value>namenode01:9870</value>
        </property>
        <property>
            <name>dfs.secondary.http.address</name>
            <value>namenode02:9868</value>
        </property>
    </configuration>
    =====
  • hadoop-env.sh

    hadoop_conf 폴더나 자바 경로 등을 지정함

    $ vim $HADOOP_CONF_DIR/hadoop-env.sh
    
    # line 54
    export JAVA_HOME=/usr/lib/jvm/java-11-openjdk-amd64
    
    # line 58
    export HADOOP_HOME=/home/ubuntu/hadoop
    
    # line 68
    export HADOOP_CONF_DIR=${HADOOP_HOME}/etc/hadoop
    
    # line 198
    export HADOOP_PID_DIR=$HADOOP_HOME/pids
  • workers

    datanode의 이름을 지정함
    (slaves - hadoop 2.x , workers - hadoop 3.x)

    # datanode용으로 쓸 노드의 호스트네임을 적어줌
    $ vim $HADOOP_CONF_DIR/workers
    
    =====
    datanode01
    datanode02
    =====

[datanode01, datanode02에서 진행]

  • hdfs-site.xml
$ vim $HADOOP_CONF_DIR/hdfs-site.xml

=====
<configuration>
        <property>
                <name>dfs.replication</name>
                <value>2</value>
        </property>
        <property>
                <name>dfs.permissions</name>
                <value>false</value>
        </property>
        <property>
                <name>dfs.datanode.data.dir</name>
                <value>/home/ubuntu/hadoop/datanode_dir</value>
        </property>
</configuration>
=====
  • hadoop-env.sh
$ vim $HADOOP_CONF_DIR/hadoop-env.sh

# line 54
export JAVA_HOME=/usr/lib/jvm/java-11-openjdk-amd64

# line 58
export HADOOP_HOME=/home/ubuntu/hadoop

# line 68
export HADOOP_CONF_DIR=${HADOOP_HOME}/etc/hadoop

[namenode01에서 진행]

$ hdfs namenode -format

$ start-all.sh

jps를 찍어보았을 때 아래처럼 각 노드에 알맞는 노드들이 올라오면 성공입니다!
혹은 hdfs dfsadmin -report로 데이터 노드가 알맞게 올라왔는지 확인 가능합니다.
+http://[namenode01_public ip]:9870 으로 네임노드의 web ui에 들어가지나 확인해보세요.

0개의 댓글