맵리듀스(Map-Reduce) 데이터 흐름

하둡 맵리듀스는 클러스터 환경에서 대량의 데이터를 병렬로 처리하는 응용 프로그램을 쉽게 작성할 수 있는 소프트웨어 프레임워크입니다. 맵리듀스 작업은 일반적으로 입력 데이터를 독립적

sparkdia.tistory.com

  이전 포스팅에서 맵리듀스의 데이터 흐름을 간략하게 살펴보았습니다. 

  일반적으로 Mapper와 Reducer 인터페이스의 map과 reduce 메소드를 구현하는 것만으로도 간단하게 맵리듀스 프레임워크를 사용할 수 있습니다.

  만약, 입/출력 대상으로 텍스트 파일 외 다른 형식의 파일이나 데이터베이스를 사용하는 경우나 맵리듀스 내부의 상세 작업을 컨트롤하기 위해서는 추가적인 개발 작업이 필요합니다.

  이를 위해 맵리듀스의 작동 방법을 좀 더 상세하게 살펴보도록 하겠습니다.

[Ref.]  Hadoop, The Definitive Guide

 

  맵리듀스 Job은 클라이언트가 수행하는 작업의 기본 단위로, 맵 태스크(Map task)와 리듀스 태스크(Reduce task)로 나눠서 실행합니다.

 

1. Map task 단계

  Map task 단계에서는 입력 데이터를 읽어 <key, value> 구조의 입력 레코드를 구성한 뒤 중간 단계의 레코드로 변환하는 작업을 합니다.

   맵리듀스 프레임워크의 입력으로 다양한 형식의 입력 데이터가 사용 될 수 있습니다. 물론, 하둡에서 제공되는 기본 파일 형식외에는 입력 파일의 형식이 무엇이고 어떻게 레코드 형태로 변환할 수 있는지 정의하는 작업은 필요합니다. 이러한 작업은 InputFormat과 RecordReader라는 인터페이스를 확장 구현하여 정의 가능합니다.

 

InputFormat

  InputFormat은 맵리듀스 Job의 입력 명세서라고 표현할 수 있습니다.

  맵리듀스 프레임워크에서는 Job의 InputFormat을 이용해 아래와 같은 작업을 수행합니다.

  1) 작업의 입력 명세서를 검증
  2) 입력 파일을 분할하여 InputSplit을 생성한 뒤, 각 개별 Mapper에 할당
  3) Mapper가 처리할 입력 레코드를 InputSplit에서 어떻게 추출해야 할 지 명시하는 RecordReader를 구현

  InputFormat을 구현한 기본 클래스는 FileInputFormat이며, 이를 확장한 다수의 하위 클래스가 존재합니다. 대표적으로 기본 InputFormat인 TextInputFormat 클래스도 FileInputFormat의 하위 클래스입니다. FileInputFormat의 하위 클래스의 기본 동작은 입력 파일의 총 크기(Byte)을 기준으로 입력을 논리적 InputSplit 인스턴스로 분할하는 것입니다.

 

InputSplit 

  InputSplit은 Job의 입력을 고정 크기로 분리한 데이터 조각입니다. 입력 데이터를 다수의 Mapper가 병렬로 분산 처리할 수 있도록 다수의 논리적인 InputSplit으로 분리한 것입니다.

  하나의 InputSplit마다 맵 태스크를 생성하게 되며, InputSplit의 각 레코드는 RecordReader에 의해 <key, value> 형태인 입력 레코드로 변환되어 map 함수로 전달됩니다.

 

RecordReader

  RecordReader는 입력 데이터가 크기 기준(byte-oriented view)으로 분리된 InputSplit을 Mapper에서 <key, value> 쌍 형태로 처리할 수 있도록 레코드 기반의 형태(record-oriented view)로 변환하는 작업을 수행합니다.

  LineRecordReader는 TextInputFormat이 제공하는 기본 레코드 입력기입니다. LineRecordReader는 정의된 레코드  delimiter(기본 값은 개행 문자)에 의해 입력 데이터를 분리합니다. 이 때, 분리된 각 문자열이 레코드의 value가 되며, key는 파일에서 해당 문자열의 위치(Byte offset)입니다. 

 

Map

  맵에서는 입력 데이터를 읽어 map 함수에서 사용자가 정의한 연산을 수행합니다.

  맵 함수의 처리 결과는 우선 메모리 버퍼에 저장되며 버퍼의 내용이 한계치에 도달하면 일괄로 디스크에 저장(Spill)됩니다. 이 때, 맵의 출력 데이터는 키 값에 의해 정렬되고 리듀서 수에 맞게 파티션별로 나눠서 저장됩니다. 파티션 별로 출력 데이터를 나눠서 저장하는 이유는 리듀서별로 전송할 출력 데이터를 미리 구분하기 위해서입니다. 

  만약, 컴바이너 함수가 정의되어 있다면 맵의 출력 값이 컴바이너 함수의 입력 값이 되고, 컴바이너 함수의 결과 데이터에 대해 정렬과 파티셔닝 작업이 발생하게 됩니다. 컴바이너 함수를 사용하는 이유는 맵 결과 데이터의 크기를 감소시켜 리듀서로 전송할 데이터 양(네트워크 부하)을 줄이기 위함입니다.

 

 

2. Reduce task 단계

Reduce

  리듀스 태스크는 각 맵 태스크가 완료되는 즉시 맵의 출력 데이터를 리듀스가 실행되는 노드에 복사하기 시작합니다(Shuffle).

  맵의 출력 데이터가 복사될 때 리듀서는 다수의 맵 출력 데이터를 정렬 순서를 유지하면서 병합합니다.
  리듀스에서는 병합된 데이터를 읽어 reduce 함수에서 사용자가 정의한 연산을 수행합니다.

 

OutputFormat

  OutputFormat은 맵리듀스 Job의 출력 명세서라고 표현할 수 있습니다.

  맵리듀스 프레임워크에서는 Job의 OutputFormat을 이용해 아래와 같은 작업을 수행합니다.

    1) 작업의 출력 명세서를 검증 (예: 출력 디렉토리 존재 여부)
    2) 작업의 출력 파일을 작성하는 데 사용되는 RecordWriter 구현

 

RecordWriter

  RecordWriter는 출력 <key, value> 쌍을 출력 파일에 씁니다.

  RecordWriter을 구현한 기본 클래스는 LineRecordWriter입니다. LineRecordWriter은 key와 value를 tab 문자로 구분하며, 각 레코드는 개행 문자로 구분하여 데이터를 저장합니다.

 

 

  이상으로 맵리듀스의 작동 방법에 대해 알아봤습니다.
  맵리듀스의 작동 원리를 이해하게 되면, 맵리듀스 구현이 용이해지고 디버깅 작업이 좀 더 수월해질 수 있을것입니다. 또한,  Hive 등 하둡 에코 시스템에서의 데이터를 저장하고 관리하는 방법에 대한 이해도도 높아질 수 있으실 것입니다.

만약, 위 내용에 대해서 오류를 발견하시거나 궁금한 사항이 있으시면 적극적인 의견 부탁드립니다.

 

[Ref.] Hadoop, The Definitive Guide
       
https://hadoop.apache.org/docs/r1.2.1/mapred_tutorial.html

 

  하둡 맵리듀스는 클러스터 환경에서 대량의 데이터를 병렬로 처리하는 응용 프로그램을 쉽게 작성할 수 있는 소프트웨어 프레임워크입니다.

  맵리듀스 작업은 일반적으로 입력 데이터를 독립적인 청크로 분할(Split)하여 다수의 노드에서 병렬로 맵 작업을 수행합니다. 맵 작업의 결과물은 Shuffling 되어 리듀스 작업의 입력으로 전달되며, 리듀스 작업의 결과물이 최종 결과 데이터 셋이 됩니다.
  이러한 맵 리듀스 과정에서의 입/출력 데이터는 <key, value> 쌍의 집합 형태로 표현합니다.

  대표적인 맵리듀스의 예제인 단어세기 프로그램을 기준으로 맵리듀스의 논리적 데이터 흐름을 살펴보겠습니다.

  단어세기 프로그램은 입력 데이터에서 각 단어의 건수를 계산하여 출력하는 프로그램입니다.

  해당 프로그램은 먼저 입력 경로 내 존재하는 텍스트 파일을 읽어 문자열 데이터를 분할(Split)하여 각 맵에 분배하여 줍니다. 데이터를 분할하는 기준은 InputFormat으로 정의할 수 있습니다. InputFormat의 기본은 TextInputFormat이며, 이 경우 개행을 기준으로 데이터를 분할하므로 맵은 한 번에 한 줄의 문자열을 처리하게 됩니다.

  맵은 입력받은 문자열을 공백 기준으로 분리(Splitting)하여 <단어,1> 형태의 <key, value> 쌍을 생성합니다. 아래 목록은 맵 연산의 결과 예시입니다.
  <Hadoop, 1>
  <MapRecdce, 1>
  <software, 1> ...
  <MapRecdce, 1> ...

  맵의 출력은 키를 기준으로 정렬된 후 리듀스에 전달됩니다. 

  만약 프로그램 내 컴바이너(Combiner)가 정의되어 있다면 리듀스 연산에 앞서 컴바이너 연산이 선행됩니다. 이때 정렬된 맵의 출력 값은 컴바이너의 입력값이 되며, 컴바이너의 출력 값이 리듀스에 전달되게 됩니다.

  컴바이너는 네트워크 사용량을 줄이기 위한 목적으로 리듀스에 전달하는 데이터의 크기를 최소화하기 위해 사용됩니다. 일반적으로 연산 내용이 리듀스와 동일하며 로컬 내 맵 결과 데이터만을 대상으로 리듀스 작업을 미리 진행하는 단계라고 이해하시면 됩니다.

  아래는 컴바이너 연산까지 적용된 맵 연산 결과 예시입니다.
  <Hadoop, 1>
  <MapRecdce, 2>
  <software, 1> ...

  위에서 언급했듯이 맵 연산 결과 데이터는 리듀스의 입력 데이터로 전달됩니다. 이때 키 값이 같은 맵의 출력 결과물은 하나의 리듀스가 키 값의 건수를 계산할 수 있도록 동일한 리듀스로 전달됩니다(Shuffling). 

  리듀스에서는 입력 값으로 전달받은 맵 연산 결과 데이터를 읽어 단어별로 건수를 계산하게 됩니다. <key, value> 구조인 입력 값을 읽어 key가 동일한 데이터의 value를 합한 결과를 <key, value> 쌍 구조로 출력하게 됩니다.

  아래는 리듀스 연산 후 출력되는 최종 결과 데이터의 예입니다.
  <Hadoop, 10>
  <MapRecdce, 18>
  <job, 23> ...

 

  지금까지 살펴본 맵 리듀스 연산을 Java로 구현한 소스 코드는 아래와 같습니다.

package org.myorg;

import java.io.IOException;
import java.util.*;

import org.apache.hadoop.fs.Path;
import org.apache.hadoop.conf.*;
import org.apache.hadoop.io.*;
import org.apache.hadoop.mapred.*;
import org.apache.hadoop.util.*;

public class WordCount {

   public static class Map extends MapReduceBase implements Mapper<LongWritable, Text, Text, IntWritable> {
     private final static IntWritable one = new IntWritable(1);
     private Text word = new Text();

     public void map(LongWritable key, Text value, OutputCollector<Text, IntWritable> output, Reporter reporter) throws IOException {
       String line = value.toString();
       StringTokenizer tokenizer = new StringTokenizer(line);
       while (tokenizer.hasMoreTokens()) {
         word.set(tokenizer.nextToken());
         output.collect(word, one);
       }
     }
   }

   public static class Reduce extends MapReduceBase implements Reducer<Text, IntWritable, Text, IntWritable> {
     public void reduce(Text key, Iterator<IntWritable> values, OutputCollector<Text, IntWritable> output, Reporter reporter) throws IOException {
       int sum = 0;
       while (values.hasNext()) {
         sum += values.next().get();
       }
       output.collect(key, new IntWritable(sum));
     }
   }

   public static void main(String[] args) throws Exception {
     JobConf conf = new JobConf(WordCount.class);
     conf.setJobName("wordcount");

     conf.setOutputKeyClass(Text.class);
     conf.setOutputValueClass(IntWritable.class);

     conf.setMapperClass(Map.class);
     conf.setCombinerClass(Reduce.class);
     conf.setReducerClass(Reduce.class);

     conf.setInputFormat(TextInputFormat.class);
     conf.setOutputFormat(TextOutputFormat.class);

     FileInputFormat.setInputPaths(conf, new Path(args[0]));
     FileOutputFormat.setOutputPath(conf, new Path(args[1]));

     JobClient.runJob(conf);
   }
}

[Ref.] https://hadoop.apache.org/docs/r1.2.1/mapred_tutorial.html

  이전 포스트 "HDFS 아키텍처"에서 하둡은 분산 저장과 분산 처리를 하기 위한 프레임워크라고 소개를 했었습니다.

  Hadoop 1.x에서는 맵리듀스가 분산처리를 담당했었습니다.
  그러나 배치 처리를 위한 맵리듀스의 한계를 뛰어넘어 다양한 프레임워크에서 HDFS를 효율적으로 액세스 할 수 있는 환경에 대한 요구사항이 발생하게 되었습니다.

  이러한 요구사항에 대한 결과물이 Hadoop 2.x에서부터 도입된 YARN(Yet Another Resource Negotiator)입니다.
  YARN이 도입되면서 자원 관리와 잡 스케쥴링/모니터링 기능이 분리되어 다양한 프레임워크가 안정적으로 클러스터 내에서 작업을 실행할 수 있는 환경이 마련되었습니다.

 

[출처] hortonworks

 

YARN 아키텍처

  YARN 프레임워크는 데이터 연산을 위한 Resource Manager와 Node Manager로 구성되어 있습니다.

  Resource Manager는 중앙에서 클러스터 내 모든 사용 가능한 자원을 모든 응용프로그램 간에 중재하는 역할을 담당합니다.
  Node Manager는 노드별로 존재하며, 노드의 자원 사용량(CPU, 메모리, 디스크, 네트워크)을 모니터링하고 Resource Manager에 보고합니다.

[출처] https://www.edureka.co/blog/introduction-to-hadoop-2-0-and-advantages-of-hadoop-2-0/

 

  Resource Manager에는 Scheduler와 Application Manager라는 두 개의 메인 컴포넌트가 존재합니다.

  Scheduler는 제약 조건(용량, 큐, etc.)에 의거해 실행중인 여러 응용 프로그램에 자원을 할당하는 작업을 수행합니다. Scheduler는 응용 프로그램의 자원 요구 사항에 따라 스케줄링 기능을 수행할 뿐, 응용 프로그램의 실행 상태에 대해서는 관여하지 않습니다.

  Applications Manager는 클라이언트가 제출한 작업을 승인하고 응용 프로그램별 Application Master를 실행하기 위한 Container를 협상합니다. 응용 프로그램이 종료될 때까지 Application Master의 상태를 관리합니다. 

  Application Master는 애플리케이션 별 라이브러리의 인스턴스입니다. Resource Manager와 자원을 협상하여 Container를 할당받으며, Node Manager와 협력하여 Container와 자원 사용 상태를 모니터링합니다.

  Container는 클러스터에 할당된 자원을 의미합니다. Container 안에서 실제적으로 응용 프로그램의 태스크(Task)가 수행됩니다.

 

 

HADOOP 동작 방식

1) 클라이언트 프로그램이 Resource Mananger에게 응용 프로그램을 제출합니다. 제출된 응용 프로그램에는 응용 프로그램별 Application Master를 자체적으로 시작하는 데 필요한 명세서도 포함되어 있습니다.

2) Resource Manager는 Application Master를 시작하기 위한 Container를 협상한 뒤, Application Master를 시작합니다.

3) Application Master가 가동되면 Resource Manager에 등록됩니다. 등록 후 클라이언트 프로그램은 Resource Manager를 쿼리하여 Application Master와 직접 통신할 수 있게 됩니다.

4)  Application Master는 자원 요청(resource-request) 프로토콜을 통해 적절한 자원 Container를 요청합니다.

5) Container를 할당 받으면 Application Master는 Node Manager에 Container 실행 명세서를 제공하고 Container를 시작합니다. 일반적으로 실행 명세서에는 Container가 Application Master와 자체적으로 통신하는 데 필요한 정보가 포함되어 있습니다.

6) Container에서 실행되는 응용 프로그램 코드는 응용 프로그램 명세서(application-specific) 프로토콜을 통해 Application Master에 필요한 정보(진행, 상태 등)를 제공합니다.

7) 클라이언트는 응용 프로그램 명세서(application-specific) 프로토콜을 통해 Application Master로부터 상태 및 진행 상황 등의 정보를 전달받습니다.

8) 응용 프로그램과 필요한 모든 작업이 완료되면 Application Master는 Resource Manager에 등록을 해제하고 종료하게 됩니다.

[출처] https://blog.cloudera.com/apache-hadoop-yarn-concepts-and-applications/

 

 

 

[Ref.] : https://hadoop.apache.org/docs/current/hadoop-yarn/hadoop-yarn-site/YARN.html
            https://blog.cloudera.com/apache-hadoop-yarn-concepts-and-applications/

 

  하둡을 간략하게 정의하면 '분산 저장 & 분산 처리'라고 표현할 수 있습니다.
  대량의 데이터를 다수의 데이터 노드에 분산하여 저장을 하고, 다수의 프로세스가 작업을 분배하여 처리하는 방식이기 때문입니다.

  하둡에서의 분산 저장과 분산 처리 기술 중에서 분산 저장을 담당하는 것이 바로 HDFS(Hadoop Distributed File System)입니다.

  HDFS도 다른 파일 시스템처럼 계층적 파일 구조를 지원합니다. 디렉토리나 파일을 생성/삭제/이동할 수 있으며, 디렉토리 안에 하위 디렉토리를 생성할 수 있습니다. 또한, 용량이나 파일 개수 할당 제한도 설정 가능하며, 접근 권한 설정도 가능합니다.

HDFS 브라우저

 

  그럼 다른 파일 시스템과 비교하여 HDFS만의 특징은 무엇이 있을까요?

   - 높은 장애 결함 허용성(내결함성)
   - 저비용의 범용 하드웨어 기반으로도 효율적인 분산 파일 시스템 구성 가능
   - 대용량의 데이터 셋을 액세스 할 수 있는 높은 처리량
   - 파일 시스템 데이터를 스트리밍 액세스 방식으로 처리 가능 

  위와 같은 HDFS만의 특징으로 대용량의 데이터를 안정적으로 관리할 수 있게 됩니다.

  구체적으로 HDFS에서 대용량의 데이터를 관리하는 방법에 대해 알아보도록 하겠습니다.

 

  우선, HDFS의 아키텍처는 마스터/슬래이브 구조입니다.

네임노드(NameNode) 데이터노드(DataNode)

  HDFS 클러스터는 하나의 네임노드(마스터)와 하나 이상의 데이터노드(슬래이브)로 구성됩니다.

  네임노드는 파일 시스템 네임스페이스를 관리하고 클라이언트에 의한 파일 액세스를 조정하는 역할을 담당합니다.
  네임스페이스를 실행하여 파일과 디렉토리를 열거나 닫고, 이름을 변경하는 작업 등을 처리하고 데이터노드와 블럭의 매핑 정보를 관리합니다. 

  데이터노드는 파일 시스템 클라이언트로부터의 파일 읽기/쓰기 요청을 수행합니다. 또한 네임노드의 요청에 따라 블럭 생성/삭제/복제를 수행합니다.

  하둡 클러스터에 저장되는 파일은 하나 이상의 블럭으로 쪼개져 다수의 데이터노드에 분산되어 저장됩니다.

 

 

데이터 복제

  HDFS에서 장애 결함 허용이 가능한 이유는 데이터 복제 기능을 제공하기 때문입니다.

  HDFS는 대규모 클러스터의 여러 시스템(데이터노드)에 걸쳐 매우 큰 파일을 안정적으로 저장하도록 설계되었습니다. 각 파일은 연속된 블록으로 저장되는데, 내결함성을 위해 파일 블록은 복제되어 여러 데이터노드에 분산되어 저장됩니다. 블록 크기 및 복제 계수(replication factor)는 파일 별로 설정할 수 있습니다.

  네임 노드는 주기적으로 클러스터의 각 데이터노드에서 하트 비트 및 블록 보고서를 받습니다. 하트 비트를 수신하면 데이터 노드가 제대로 작동하고 있음을 나타냅니다. 만약, 네임노드가 특정 데이터노드로부터 하트 비트를 수신받지 못했다면, 네임노드는 해당 데이터노드를 사용불능(dead) 상태로 등록하고, 사용불능인 데이터노드에 저장되어 있던 복제본을 다른 데이터노드에 복제하여 블록의 복제본의 수가 복제 계수와 동일하도록 관리하게 됩니다.

  복제본의 배치 전략은 HDFS의 성능, 가용성, 안정성을 좌우하는 중요한 요소입니다.
  복제본은 여러 랙에 걸쳐 저장될 수 있습니다. 일반적으로 동일한 랙 안에 설치된 서버간의 네트워크 대역폭이 다른 랙에 설치된 서버와의 네트워크 대역폭보다 더 큽니다. 네트워크 성능을 고려하면 동일한 랙에 위치한 서버에 복제본을 저정하는 것이 효율적일수도 있겠지만, 하나의 랙안의 모든 서버가 동시에 장애가 발생할 수 있다는 사실을 간과할 수는 없습니다. 네트워크 성능과 안정성이 Trade-off 관계인 것입니다.

  일반적으로 복제 계수가 3인 경우에 로컬 장비(Writer가 위치한 데이터노드)에 하나의 복제본을 저장하고 로컬 장비와 동일한 랙에 위치한 다른 장비와 다른 랙에 위치한 장비에 나눠서 복제본을 저장하게 됩니다.

 

 

파일시스템 메타데이터 관리

  HDFS 파일시스템 네임스페이스는 파일에 대한 블록 매핑 및 파일 시스템 프로퍼티 정보를 포함하고 있습니다. 이 파일시스템 네임스페이스는 네임노드의 로컬 OS 파일시스템에 FsImage라는 파일로 저장되어 있습니다.

  HDFS 파일 시스템에 변경(예를 들어 신규 파일 생성)이 발생하면 변경 내역을 즉시 FsImage에 저장하지는 않습니다.
  변경 내역은 EditLog라는 파일(FsImage처럼 네임노드의 로컬 OS 파일 시스템에 저장)에 우선 기록되며, checkpoint가 발생하는 시점(dfs.namenode.checkpoint.period 설정 값에 따라 주기적으로 발생)에 EditLog에 기록된 변경내역이 FsImage에 일괄적으로 반영되게 됩니다.

 

 

 

[Ref.] : https://hadoop.apache.org/docs/current/hadoop-project-dist/hadoop-hdfs/HdfsDesign.html

 

  하둡의 데이터 노드를 생성하고 하둡을 실행하기 위해서는 사전 작업 및 환경 설정이 필요합니다. 관련 내용은 아래 포스팅을 참고하시면 됩니다.

> 하둡(Hadoop) 설치하기[#1] - 설치 준비

> 하둡(Hadoop) 설치하기[#2] - 하둡 환경 설정하기


  당연한 얘기이지만, 하둡 테스트를 위해 가상머신에 하둡을 설치하는 이유는 클러스터를 구성 할 수 있는 서버를 확보 할 수 없기 때문입니다. Single 환경이 아닌 클러스터 환경을 구축하기 위해서는 최소한으로 1개의 관리노드와 3개의 데이터 노드가 필요한데, 일반 가정집에서 이런 환경을 구축한다는 것은 사실상 불가능합니다. 구축이 가능하더라도 시끄러운 서버의 소음과 하루종일 함께 할 인내심은 절대로 가지고 싶지 않겠죠.

  아무튼, 서버 구축은 현실적으로 불가능하므로 우리는 데스크탑에서 가상환경을 구축하여 하둡을 설치하고 테스트 할 수 있습니다. 필자 또한 VirtualBox를 이용해 하둡 설치 작업을 진행하고 있습니다. VirtualBox를 이용하여 하둡을 설치를 하게되면 데이터 노드로 사용할 서버 구성을 쉽게 할 수 있다는 장점도 있습니다.

  이런 장점을 살려, 지금까지 설치한 하둡 마스터 서버를 기반으로 데이터 노드 서버를 구성해보겠습니다.
  참고로, 설치 테스트에 사용된 VirtualBox는 6.0.14 버전입니다.

 

1. 데이터 노드 서버 생성

  VirtualBox의 왼쪽에는 설치된 가상머신의 목록을 보여줍니다. 지금까지 하둡 설치 및 구성이 완료된 가상머신을 종료한 후에, 가상머신 목록에서 오른쪽 버튼을 눌러 팝업 메뉴를 띄워보겠습니다.

  메뉴 중에서 '복제'를 선택하면 아래와 같이 새로 생성 할 가상머신의 이름과 경로를 선택하는 창이 나타납니다. 적절한 '이름'과 '경로'를 입력해주면 됩니다. 'MAC 주소 정책'은 새로운 MAC 주소를 할당받기 위해서 '모든 네트워크 어댑터의 새 MAC 주소 생성'을 선택합니다. 설정이 완료되었으면 '다음' 버튼을 클릭합니다.

  복제 방식에서는 '완전한 복제'를 선택한 후 '복제' 버튼을 클릭합니다.

  복제 작업이 진행되는 동안 progress bar를 통해 복제 작업이 진행되는 상태를 확인할 수 있습니다.

  복제가 완료되면 VirtualBox 왼쪽 목록에 복제한 가상머신 Hadoop_Data1을 볼 수 있을 것입니다.

 

2. 데이터 노드 IP주소 및 hostname 설정

  먼저, Hadoop_Data1 가상머신을 구동해보겠습니다. (IP 주소를 변경하기 전이므로 Hadoop_MST와 동시에 구동하면 IP 주소 충돌이 발생할 수 있습니다.)

  앞서 정의했던 서버 정보에 따라 IP주소를 변경해주면 됩니다.

서버 호스트명 IP 비고
관리 노드 hmng 192.168.0.100 NameNode 및  ResourceManager 등
데이터 노드 1 hdata1 192.168.0.101 DataNode 및 NodeManager등
데이터 노드 2 hdata2 192.168.0.102
데이터 노드 3 hdata3 192.168.0.103

  필자는 IP 주소를 쉽게 변경하고자 윈도우X 환경에서 IP주소를 변경하였습니다.

  이어서, hostname도 변경해보겠습니다. hostname은 /etc/hostname 파일 내용을 변경해주면 됩니다. 물론 CentOS 8 환경인 경우에 해당되는 내용입니다. 각 서버 환경에 따라 변경 작업을 진행해주면 됩니다. 

sudo vi /etc/hostname

  위 파일 내용을 변경하였으면, 적용하기 위해 가상머신을 재부팅해줘야 합니다.

 

3. SSH 설정

  하둡에서는 원격 서버의 데몬을 관리하기 위해 SSH를 사용합니다. 따라서, 클러스터 내 서버간에 비밀번호 입력이 없어도 SSH 접속이 가능하도록 설정이 필요합니다.

  RSA 암호화 방식으로 비밀번호 입력 없이도 원격 서버에 로그인 가능하도록 설정해보겠습니다. 우선 마스터 서버에서 RSA 공개키/개인키를 생성합니다.

> ssh-keygen

  ssh-keygen 명령을 실행하고나면 위와 같이 지정된 경로에 개인키/공개키가 생성된 것을 확인할 수 있습니다.

  이렇게 생성된 공개키를 모든 서버에 복사를 합니다.

> ssh-copy-id hmng
> ssh-copy-id hdata1
> ssh-copy-id hdata2
> ssh-copy-id hdata3

  ssh-copy-id 명령어를 실행한 후 데이터노드 서버를 확인해보면 공개키가 생성된 것을 확인해 볼 수 있을 것입니다.

  마스터서버에서 데이터노드 서버로 ssh 접속을 해보겠습니다. 비밀번호 입력없이 바로 접속이 가능하다면 정상적으로 설정된 것입니다.

  여기서 주의할 점은 위 작업을 모든 서버에서 설정해줘야 한다는 점입니다.
  하둡 클러스터 내 모든 서버간 SSH 통신이 필요하므로, 단방향이 아닌 양방향간에도 비밀번호 없이 접속 가능하도록 모든 서버에서 공개키/개인키를 생성한 후, 공개키를 모든 서버에 복사해줘야 합니다.

  SSH 설정이 마무리 되었다면 .ssh/authorized_keys 내 파일 내용은 아래와 같은 형태일 것입니다.

 

 

4. 데이터 노드 추가

  이제 데이터 노드에 대한 설정이 완료되었습니다.
  Hadoop_Data1 가상머신을 종료한 후, 1. 데이터 노드 서버 생성을 참고하여 Hadoop_Data2와 Hadoop_Data3를 생성해줍니다.

  복제가 완료되면 VirtualBox의 왼쪽 가상머신 목록은 아래와 같은 형상이 될 것입니다.

  이어서, 2. 데이터 노드 IP주소 및 hostname 설정을 참고하여 Hadoop_Data2와 Hadoop_Data3 서버의 IP주소 및 hostname을 변경해줍니다.

 

5. HDFS 포맷

  데스크탑이나 노트북에서 새 디스크를 사용하기 위해서는 먼저 포맷 작업을 수행해야 합니다. 하둡의 파일시스템인 HDFS도 역시 포맷 작업을 한 후에 사용이 가능합니다.

  HADOOP_HOME 디렉토리로 이동한 뒤 아래 명령을 입력하여 HDFS를 포맷합니다.

> bin/hdfs namenode -format

  에러 메세지 없이 마지막에 아래와 같은 로그가 표시되면 정상적으로 포맷이 완료된 것입니다.

 

 

6. 하둡 시작

  이제 하둡 클러스터를 구동하기 위해서는 먼저 HDFS 프로세스를 구동한 후 YARN 프로세스를 구동해줘야 합니다.

  우선 아래 명령을 입력하여 HDFS 프로세스를 실행해봅니다.

> sbin/start-dfs.sh

  HDFS가 정상적으로 시작되었다면 마스터 서버에서는 NameNode와 SecondaryNameNode 자바 프로세스를 데이터 노드에서는 DataNode 자바 프로세스를 확인 할 수 있을 것입니다.

 

  웹브라우저에서 아래 URL로 접속해보자. IP주소는 사용자가 설정한 마스터서버의 IP주소를 입력해주면 됩니다.

http://마스터서버IP:50070

  위와 같이 NameNode 정보 웹페이지가 표시되고 HDFS 정보가 정확하다면 정상적으로 HDFS가 구동된 것입니다.

 

이어서 아래 명령어를 입력하여 YARN 프로세스를 구동해보자.

> sbin/start-yarn.sh

YARN이 정상적으로 실행되었다면 마스터서버에서는 ResourceManager 자바 프로세스가 데이터노드 서버에서는 NodeManager 자바 프로세스를 확인할 수 있을 것이다.

 

다시 웹브라우저에서 아래 URL로 접속해보자. 여기서도 IP주소는 사용자가 설정한 마스터서버의 IP주소를 입력해주면 된다.

http://마스터서버IP:8088

위와 같이 ResourceManager 페이지가 표시된다면 정상적으로 YARN이 구동된 것이다.

 

  참고로, 아래 명령어를 사용하면 한번에 HDFS와 YARN가 순차적으로 구동됩니다.

> sbin/start-all.sh

 

  하둡 클러스터를 종료 시에는 구동 순서와 반대로 YARN 프로세스를 종료 한 후 HDFS 프로세스를 종료해줘야 합니다.

> sbin/stop-yarn.sh

> sbin/stop-dfs.sh

  물론, stop-all.sh 스크립트를 실행하여 한번에 하둡 클러스터를 종료할 수 있습니다.

> sbin/stop-all.sh

 


  이상으로 하둡 설치에 관한 포스팅을 마무리하고자 합니다.
  여기에서 언급하지는 않았지만 hdfs-site.xml 파일 내 오타와 방화벽 문제(어차피 가상환경에서의 테스트라 그냥 방화벽 해제하여 해결)로 프로세스가 제대로 구동되지 않아 삽질을 좀 했었습니다. 이 포스트를 참고하여 하둡 설치를 진행하시는 분들도 필자와 같은 문제들을 직면할 수도 있습니다. 하지만, IT 업무를 수행하면서 항상 느끼는 바는 시도하지 않는 것보다는 삽질을 통해서라도 조금 더 배워 나가는 것이 본인의 캐리어를 쌓을 수 있는 더 나은 방법이라고 생각합니다. 설치 작업 중간에 여러 문제가 발생하더라도 거기서 포기하지 마십시오. 우리에게는 인터넷 검색을 할 수 있는 능력이 있으며, 도움을 요청하면 누군가는 해결의 실마리를 제공해줄 누군가가 반드시 있을 것입니다.

 

 

'BigData > Hadoop' 카테고리의 다른 글

맵리듀스(Map-Reduce) 데이터 흐름  (0) 2020.05.23
Hadoop YARN  (0) 2020.05.11
HDFS 아키텍처  (0) 2020.05.11
하둡(Hadoop) 설치하기[#2] - 하둡 환경 설정  (0) 2020.03.01
하둡(Hadoop) 설치하기[#1] - 설치 준비  (0) 2020.03.01

  하둡 환경 설정을 설정하기 앞서 사전 작업이 필요합니다. 사전 작업은 이전 포스트를 참고하시면 됩니다.

> 하둡(Hadoop) 설치하기[#1] - 설치 준비


1. 하둡 설정 파일

  하둡 데몬을 실행시키기 위해서 기본적으로 설정해야 하는 파일은 아래와 같습니다.

파일명 설명
etc/hadoop/core-site.xml 클러스터 내 네임노드에서 실행되는 하둡 데몬에 관한 설정
etc/hadoop/hdfs-site.xml 하둡 파일시스템에 관한 설정 
etc/hadoop/yarn-site.xml Resource Manager에 관한 설정
etc/hadoop/mapred-site.xml 맵리듀스에 관한 설정

 

2. core-site.xml 설정

  core-site.xml에서는 기본 파일 시스템 이름을 설정해줍니다.
  아래와 같이 fs.defaultFS의 값을 URI 형식으로 입력하면됩니다.

<configuration>
    <property>
        <name>fs.defaultFS</name>
         <value>hdfs://호스트명:9000</value>
    </property>
</configuration>

 

3. hdfs-site.xml 설정

  hdfs-site.xml에서는 namespace와 트랙잭션 로그를 저장 할 네임노드와 데이터 노드의 저장 경로를 지정하고, 데이터 복제 개수를 설정해줍니다.

<configuration>
    <property>
        <name>dfs.namenode.name.dir</name>
         <value>file:///data/namenode</value>
    </property>
    <property>
        <name>dfs.datanode.data.dir</name>
         <value>file:///data/datanode</value>
    </property>
    <property>
         <name>dfs.namenode.checkpoint.dir</name>
         <value>file:///data/namesecondary</value>
    </property>
    <property>
        <name>dfs.replication</name>
         <value>3</value>
    </property>
</configuration>

 

4. yarn-site.xml 설정

  yarn-site.xml에서는 리소스매니저 Web-ui 주소, 노드매니저에서 중간단계 파일 및 로그를 저장할 경로를 정의해줍니다.

<configuration>
    <property>
        <name>yarn.nodemanager.local-dirs</name>
         <value>file:///data/yarn/local</value>
    </property>
    <property>
        <name>yarn.nodemanager.log-dirs</name>
         <value>file:///data/yarn/logs</value>
    </property>
    <property>
        <name>yarn.resourcemanager.hostname</name>
         <value>hmng</value>
    </property>
</configuration>

 

5. mapred-site.xml 설정

  mapred-site.xml에서는 기본 맵리듀스 프레임워크로 yarn을 설정해줍니다.

<configuration>
    <property>
        <name>mapreduce.framework.name</name>
         <value>yarn</value>
    </property>
</configuration>

 

 

6. hosts 및 IP 설정

  하둡 클러스터에서 사용할 서버 구성 정보는 아래와 같이 정의하였습니다. 물론, 필자가 임의로 설정한 호스트명과 IP이므로 각 설정 내용은 사용자 환경에 맞게 변경하여 사용하면 됩니다.

서버 호스트명 IP 비고
관리 노드 hmng 192.168.0.100 NameNode 및  ResourceManager 등
데이터 노드 1 hdata1 192.168.0.101 DataNode 및 NodeManager등
데이터 노드 2 hdata2 192.168.0.102
데이터 노드 3 hdata3 192.168.0.103

  hosts 파일을 열어 각 서버의 IP와 호스트명을 입력해줍니다.

> sudo vi /etc/hosts

  필자가 입력한 hosts 파일 내용은 아래와 같습니다.

192.168.0.100   hmng 
192.168.0.101   hdata1 
192.168.0.102   hdata2 
192.168.0.103   hdata3 

 

7. Slave 설정

  DataNode와 NodeManager가 실행된 서버가 Slave 노드가 됩니다. (참고로, NameNode와 ResourceManager가 실행되는 서버는 Master 노드입니다.) 클러스터내 Slave 서버 목록은 $HADOOP_HOME/etc/hadoop/slaves 파일에서 관리되며, IP 주소나 hostname 목록을 입력하면 됩니다.

  slave 파일을 열어 아래와 같이 입력합니다. 필자는 IP주소 대신에 데이터노드의 호스트명을 입력하였습니다.

hdata1
hdata2
hdata3

 

 

  이것으로 하둡의 기본 환경 설정을 마무리하였습니다.

  이어서, 지금까지 설정된 마스터 노드를 활용하여 데이터 노드를 생성하는 작업을 진행하도록 하겠습니다.

> 하둡(Hadoop) 설치하기[#3] - 데이터 노드 생성 및 하둡 실행

 

 

 

 

  데스크탑이 너무 느려져서 포맷을 했더니, VirtualBox에서 하둡 관리노드가 있던 가상 OS만 복구가 안되는 상황을 맞이하게 되었습니다.;;
  이번 기회에 다시 한번 하둡을 설치하면서 여기에 그 과정을 정리해보고자 합니다.
  설치 할 하둡 관련 정보는 아래와 같습니다.

- Hadoop : 2.10.0
- OS : CentOS 8 (VirtualBox 6에 설치 완료)
- Java : JDK 7 (설치 완료)

 

1. 사전 작업 - 자바 설치

  하둡을 설치하기 위해서는 우선 자바가 설치되어있어야 합니다. 각 하둡 버전에 적합한 자바 버전은 하둡 위키를 참고하면 됩니다.

▶ URL : https://cwiki.apache.org/confluence/display/HADOOP2/HadoopJavaVersions

 

  JDK 7 설치 방법은 아래 블로그 내용을 참고하면 됩니다.

▶ URL : https://sparkdia.tistory.com/6

 

2. OS 그룹/사용자 추가

  하둡관련 디렉토리의 권한 관리를 위해 리눅스 그룹과 사용자를 추가하고 sudo 권한을 부여해보겠습니다.

  먼저, 그룹 hadoop 을 생성합니다.

> sudo groupadd -g 10000 hadoop

  그룹의 생성 결과는 /etc/group 파일 내용을 확인해보면 됩니다.

 

  방금 생성한 hadoop 그룹에 속하는 사용자 hduser를 만들어보겠습니다.

>sudo useradd -g hadoop -u 10000 hduser

  사용자 생성 결과는 /etc/passwd 파일 내용을 확인해보면 됩니다.

  hduser 계정의 비밀번호를 변경하고

> sudo passwd hduser

  Sudo 권한을 부여해주겠습니다. Sudo 권한 부여는 /etc/sudoers 파일에 사용자 계정과 권한 설정 내용을 추가해주면 되는데, 해당 파일은 읽기 권한만 설정되어 있기 때문에 쓰기 권한 부여 후 파일 내용을 수정해줘야 합니다.

  /etc/sudoers 파일 하단에 아래 내용을 추가합니다. 

hduser  ALL=(ALL)       NOPASSWD: ALL

  /etc/sudoers 설정 내용은 탭으로 항목을 구분하며 '사용자 \t 호스트 \t 명령어' 설정 정보를 입력해주면 되는데, 전체 대상으로 모든 권한이 필요하므로 위와 같이 입력하도록 합니다.

 

 

3. 설치파일 다운로드

  하둡 설치 파일을 다운로드 하기 위해 우선 하둡 홈페이지의 다운로드 사이트로 이동합니다.

▶URL : https://hadoop.apache.org/releases.html

Hadoop download 페이지

  하둡 설치 파일을 다운로드 할 때, 하둡 버전 외에도 두 가지 설치 방법에 따라 다운로드 해야 할 대상 파일이 달라집니다.

  1. Source(Java) 파일을 다운로드 받아 컴파일하기.
  2. Binary 파일을 받아 설치하기.

  하둡 개발을 목적으로 설치를 한다면 다운로드 페이지의 'Source download' 항목에서 원하는 버전의 'source'를 클릭하면 됩니다. 필자는 Map-Reduce 테스트를 위한 하둡 환경이 필요하므로, 2.10.0 버전의 Binary download를 클릭하였습니다.

  그러면 위와 같이 설치 파일을 다운로드 받을 수 있는 Mirror site가 list-up된 페이지를 볼 수 있습니다. 이 중에서 원하는 사이트를 선택하여 설치 파일을 다운로드 받으면 됩니다. 만약, 원격 서버나 가상 서버 내에 파일을 저장해야 한다면 해당 URL을 복사한 뒤 설치 대상 서버에서 wget을 이용해 파일을 다운로드 합니다.

> sudo wget http://mirror.apache-kr.org/hadoop/common/hadoop-2.10.0/hadoop-2.10.0.tar.gz

 

4. 설치 파일 압축풀기

  다운로드 된 파일을 확인해보겠습니다.

  위와 같이 다운로드한 파일은 압축된 상태이며, 설치를 위해서 압축을 풀어줘야 합니다. /usr/local 디렉토리에 파일을 압축해제하겠습니다.

>  sudo tar -zxvf ./hadoop-2.10.0.tar.gz -C /usr/local/

  압축 해제된 파일들의 사용자와 그룹은 hduser와 hadoop으로 변경해줍니다.

> sudo chown -R hduser:hadoop /usr/local/hadoop-2.10.0/

 

5. bashrc 설정

~/.bashrc 파일을 열어서 HADOOP_HOME 변수를 추가하고, PATH에 하둡 실행 파일을 위한 경로도 추가해줍니다.

export HADOOP_HOME=/usr/local/hadoop-2.10.0/
export PATH=$PATH:$JAVA_HOME/bin:$HADOOP_HOME/bin/:$HADOOP_HOME/sbin

 

  이것으로 하둡 설치를 위한 사전 작업이 완료되었습니다.
  이어서, 하둡 실행을 위한 설정 변경 작업을 진행해보도록 하겠습니다.

> 하둡(Hadoop) 설치하기[#2] - 하둡 환경 설정하기

 

+ Recent posts