Skip to content

필사 모드: Hadoop 에코시스템 실전 가이드: HDFS, MapReduce, YARN 핵심 정리

한국어
0%
정확도 0%
💡 왼쪽 원문을 읽으면서 오른쪽에 따라 써보세요. Tab 키로 힌트를 받을 수 있습니다.
원문 렌더가 준비되기 전까지 텍스트 가이드로 표시합니다.

들어가며

Hadoop은 2006년 등장한 이래 빅데이터 처리의 표준으로 자리잡았습니다. Spark, Flink 등 차세대 프레임워크가 등장했지만, HDFS와 YARN은 여전히 데이터 인프라의 핵심 기반입니다. 2026년 현재에도 많은 기업이 Hadoop 기반 데이터 레이크를 운영하고 있으며, 클라우드 환경에서도 HDFS 호환 스토리지(S3, ADLS)를 활용합니다.

이 글에서는 Hadoop의 핵심 구성 요소를 아키텍처 수준에서 이해하고, 실전 운영에 필요한 설정과 튜닝 포인트를 정리합니다.

1. Hadoop 에코시스템 개요

핵심 구성 요소

┌─────────────────────────────────────────────────────────────┐

│ Hadoop Ecosystem │

├─────────────────────────────────────────────────────────────┤

│ [Hive] [Pig] [Spark] [HBase] [Presto] [Flink] │

│ Application / Processing Layer │

├─────────────────────────────────────────────────────────────┤

│ YARN │

│ Resource Management Layer │

├─────────────────────────────────────────────────────────────┤

│ HDFS │

│ Distributed Storage Layer │

└─────────────────────────────────────────────────────────────┘

| 구성 요소 | 역할 | 버전 (2026 기준) |

| ------------- | ----------------------- | ----------------- |

| **HDFS** | 분산 파일 시스템 | Hadoop 3.4.x |

| **YARN** | 리소스 관리 및 스케줄링 | Hadoop 3.4.x |

| **MapReduce** | 배치 처리 프레임워크 | Hadoop 3.4.x |

| **Hive** | SQL-on-Hadoop | Hive 4.x |

| **HBase** | NoSQL 데이터베이스 | HBase 2.6.x |

| **Spark** | 통합 분석 엔진 | Spark 3.5.x / 4.x |

| **ZooKeeper** | 분산 코디네이션 | ZooKeeper 3.9.x |

2026년 Hadoop의 위상

- **HDFS**: 여전히 대규모 데이터 레이크의 핵심 저장소. S3/ADLS와 공존

- **YARN**: Spark, Flink 등 다양한 프레임워크의 리소스 관리자로 활용

- **MapReduce**: 신규 개발에는 사용 빈도가 줄었지만, 레거시 시스템 유지보수에 여전히 필요

- **트렌드**: Hadoop on Kubernetes, Ozone(차세대 스토리지), Iceberg/Delta Lake와의 통합

2. HDFS 아키텍처

핵심 구성 요소

┌──────────────┐

│ NameNode │

│ (Master) │

│ - 메타데이터 │

│ - 블록 위치 │

└──────┬───────┘

┌────────────┼────────────┐

│ │ │

┌───────▼──────┐ ┌──▼──────────┐ ┌▼─────────────┐

│ DataNode 1 │ │ DataNode 2 │ │ DataNode 3 │

│ Block A │ │ Block A │ │ Block B │

│ Block C │ │ Block B │ │ Block A │

└──────────────┘ └─────────────┘ └──────────────┘

Replication Factor = 3

NameNode

NameNode는 HDFS의 메타데이터를 관리하는 마스터 노드입니다.

NameNode가 관리하는 정보

1. 파일/디렉토리 트리 구조 (Namespace)

2. 각 파일의 블록 목록

3. 각 블록이 어느 DataNode에 있는지 (Block Mapping)

4. 파일 권한, 수정 시간 등

NameNode 메모리 사용량 추정

파일 1개 ≈ 150 bytes

블록 1개 ≈ 150 bytes

1억 개 파일 → 약 30GB 힙 메모리 필요

DataNode

DataNode 핵심 동작

1. 블록 저장 (기본 128MB)

2. 클라이언트에게 블록 읽기/쓰기 서비스

3. NameNode에 하트비트 전송 (3초 간격)

4. 블록 리포트 전송 (6시간 간격)

HDFS HA (High Availability)

<!-- hdfs-site.xml - HA 설정 -->

<!-- JournalNode 설정 (최소 3개) -->

<!-- 자동 failover -->

블록 복제 전략

기본 Rack-Aware 복제 전략 (Replication Factor = 3)

#

1번째 복제본: 클라이언트와 같은 노드 (또는 같은 랙)

2번째 복제본: 다른 랙의 노드

3번째 복제본: 2번째와 같은 랙의 다른 노드

#

┌──────── Rack 1 ────────┐ ┌──────── Rack 2 ────────┐

│ [DataNode1: Block A] │ │ [DataNode3: Block A] │

│ [DataNode2] │ │ [DataNode4: Block A] │

└────────────────────────┘ └────────────────────────┘

3. MapReduce 원리와 실행 흐름

MapReduce 프로그래밍 모델

Input → Split → Map → Shuffle & Sort → Reduce → Output

[파일 분할]

Split 1 → Mapper 1 → (key, value) pairs ─┐

Split 2 → Mapper 2 → (key, value) pairs ──┤── Shuffle & Sort

Split 3 → Mapper 3 → (key, value) pairs ─┘ │

├→ Reducer 1 → Output Part 1

└→ Reducer 2 → Output Part 2

WordCount 예제 (Java)

public class WordCount {

// Mapper: 각 라인을 단어로 분리하여 (단어, 1) 출력

public static class TokenizerMapper

extends Mapper<Object, Text, Text, IntWritable> {

private final static IntWritable one = new IntWritable(1);

private Text word = new Text();

public void map(Object key, Text value, Context context)

throws IOException, InterruptedException {

StringTokenizer itr = new StringTokenizer(value.toString());

while (itr.hasMoreTokens()) {

word.set(itr.nextToken().toLowerCase());

context.write(word, one);

}

}

}

// Reducer: 같은 키의 값들을 합산

public static class IntSumReducer

extends Reducer<Text, IntWritable, Text, IntWritable> {

private IntWritable result = new IntWritable();

public void reduce(Text key, Iterable<IntWritable> values, Context context)

throws IOException, InterruptedException {

int sum = 0;

for (IntWritable val : values) {

sum += val.get();

}

result.set(sum);

context.write(key, result);

}

}

public static void main(String[] args) throws Exception {

Configuration conf = new Configuration();

Job job = Job.getInstance(conf, "word count");

job.setJarByClass(WordCount.class);

job.setMapperClass(TokenizerMapper.class);

job.setCombinerClass(IntSumReducer.class); // 로컬 집계로 네트워크 트래픽 감소

job.setReducerClass(IntSumReducer.class);

job.setOutputKeyClass(Text.class);

job.setOutputValueClass(IntWritable.class);

FileInputFormat.addInputPath(job, new Path(args[0]));

FileOutputFormat.setOutputPath(job, new Path(args[1]));

System.exit(job.waitForCompletion(true) ? 0 : 1);

}

}

Job 실행 흐름

1. 클라이언트가 Job 제출

└→ JAR, 설정, InputSplit 정보를 HDFS에 업로드

2. ResourceManager가 ApplicationMaster 컨테이너 할당

└→ NodeManager에서 AM 시작

3. ApplicationMaster가 InputSplit 수에 따라 Map 태스크 요청

└→ ResourceManager가 컨테이너 할당

4. Map 태스크 실행

└→ InputSplit 읽기 → map() 호출 → 중간 결과를 로컬 디스크에 저장

5. Shuffle & Sort

└→ Map 출력을 파티셔닝 → Reducer로 전송 → 키별 정렬

6. Reduce 태스크 실행

└→ reduce() 호출 → 최종 결과를 HDFS에 저장

7. ApplicationMaster가 Job 완료를 ResourceManager에 알림

4. YARN 리소스 관리

YARN 아키텍처

┌─────────────────────────────────────────────────────┐

│ ResourceManager │

│ ┌──────────────┐ ┌────────────────────────┐ │

│ │ Scheduler │ │ ApplicationManager │ │

│ │ (자원 할당) │ │ (앱 관리) │ │

│ └──────────────┘ └────────────────────────┘ │

└──────────────────────┬──────────────────────────────┘

┌──────────────┼──────────────┐

│ │ │

┌───────▼──────┐ ┌─────▼────────┐ ┌──▼────────────┐

│ NodeManager 1│ │ NodeManager 2│ │ NodeManager 3 │

│ ┌──────────┐ │ │ ┌──────────┐ │ │ ┌──────────┐ │

│ │Container │ │ │ │Container │ │ │ │Container │ │

│ │(AM) │ │ │ │(Map Task)│ │ │ │(Reduce) │ │

│ └──────────┘ │ │ └──────────┘ │ │ └──────────┘ │

│ ┌──────────┐ │ │ ┌──────────┐ │ │ │

│ │Container │ │ │ │Container │ │ │ │

│ │(Map Task)│ │ │ │(Map Task)│ │ │ │

│ └──────────┘ │ │ └──────────┘ │ │ │

└──────────────┘ └──────────────┘ └───────────────┘

YARN 스케줄러 설정

<!-- yarn-site.xml -->

<!-- 스케줄러 종류: Capacity, Fair, FIFO -->

<!-- NodeManager 리소스 설정 -->

<!-- 컨테이너 최소/최대 메모리 -->

<!-- 컨테이너 최소/최대 vCores -->

Capacity Scheduler 큐 설정

<!-- capacity-scheduler.xml -->

<!-- 큐별 용량 (합계 100%) -->

<!-- 최대 용량 (elasticity) -->

<!-- 큐별 사용자 제한 -->

5. 클러스터 설치

Pseudo-Distributed 모드 (개발/테스트용)

1. Java 설치

sudo apt install -y openjdk-11-jdk

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

2. Hadoop 다운로드

wget https://dlcdn.apache.org/hadoop/common/hadoop-3.4.1/hadoop-3.4.1.tar.gz

tar -xzf hadoop-3.4.1.tar.gz

sudo mv hadoop-3.4.1 /opt/hadoop

export HADOOP_HOME=/opt/hadoop

export PATH=$PATH:$HADOOP_HOME/bin:$HADOOP_HOME/sbin

3. SSH 키 설정 (localhost)

ssh-keygen -t rsa -P '' -f ~/.ssh/id_rsa

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

chmod 600 ~/.ssh/authorized_keys

<!-- core-site.xml -->

<!-- hdfs-site.xml -->

4. NameNode 포맷 및 시작

hdfs namenode -format

start-dfs.sh

start-yarn.sh

5. 확인

hdfs dfs -mkdir /user

hdfs dfs -mkdir /user/$USER

jps # NameNode, DataNode, ResourceManager, NodeManager 확인

Fully Distributed 모드 (프로덕션)

workers 파일 설정 (/opt/hadoop/etc/hadoop/workers)

datanode1

datanode2

datanode3

datanode4

datanode5

<!-- core-site.xml (HA 모드) -->

6. HDFS 핵심 명령어

파일 시스템 조작

파일/디렉토리 목록

hdfs dfs -ls /user/hadoop/

hdfs dfs -ls -R /user/hadoop/ # 재귀적 목록

파일 업로드

hdfs dfs -put localfile.txt /user/hadoop/

hdfs dfs -copyFromLocal data.csv /user/hadoop/input/

hdfs dfs -moveFromLocal temp.log /user/hadoop/logs/

파일 다운로드

hdfs dfs -get /user/hadoop/output/part-r-00000 ./result.txt

hdfs dfs -copyToLocal /user/hadoop/data.csv ./

파일 내용 확인

hdfs dfs -cat /user/hadoop/input/data.csv

hdfs dfs -head /user/hadoop/input/data.csv # 첫 1KB

hdfs dfs -tail /user/hadoop/input/data.csv # 마지막 1KB

hdfs dfs -text /user/hadoop/output/part-r-00000 # 압축 파일도 읽기

디렉토리 생성/삭제

hdfs dfs -mkdir -p /user/hadoop/input/2026/03

hdfs dfs -rm /user/hadoop/temp.txt

hdfs dfs -rm -r /user/hadoop/output/ # 디렉토리 삭제

hdfs dfs -rm -skipTrash /user/hadoop/old/ # 휴지통 건너뛰기

권한 관리

hdfs dfs -chmod 755 /user/hadoop/scripts/

hdfs dfs -chown hadoop:hadoop /user/hadoop/

hdfs dfs -chgrp analytics /data/shared/

디스크 사용량

hdfs dfs -du -h /user/hadoop/ # 디렉토리별 사용량

hdfs dfs -df -h # 전체 용량

hdfs dfs -count -h /user/hadoop/ # 파일/디렉토리 수

관리 명령어

클러스터 상태

hdfs dfsadmin -report # 전체 클러스터 리포트

hdfs dfsadmin -printTopology # 랙 구성 확인

Safe Mode

hdfs dfsadmin -safemode get # Safe Mode 상태 확인

hdfs dfsadmin -safemode leave # Safe Mode 해제

블록 관리

hdfs fsck / -files -blocks -locations # 파일 시스템 무결성 검사

hdfs fsck /user/hadoop/ -files # 특정 경로 검사

스냅샷

hdfs dfsadmin -allowSnapshot /user/hadoop/important

hdfs dfs -createSnapshot /user/hadoop/important snap_20260308

hdfs dfs -deleteSnapshot /user/hadoop/important snap_20260308

쿼터 관리

hdfs dfsadmin -setSpaceQuota 100G /user/hadoop/project

hdfs dfsadmin -clrSpaceQuota /user/hadoop/project

7. 성능 튜닝

HDFS 튜닝

<!-- hdfs-site.xml -->

<!-- 블록 크기 (대용량 파일이 많으면 256MB로 증가) -->

<!-- DataNode 동시 전송 스레드 (기본 4096) -->

<!-- NameNode 핸들러 스레드 (기본 10) -->

<!-- Short-circuit 로컬 읽기 -->

MapReduce 튜닝

<!-- mapred-site.xml -->

<!-- Map 태스크 메모리 -->

<!-- Reduce 태스크 메모리 -->

<!-- Shuffle 버퍼 -->

<!-- 압축 -->

튜닝 요약표

| 항목 | 기본값 | 권장값 | 영향 |

| ------------------------------------- | ------ | ----------------- | -------------------- |

| `dfs.blocksize` | 128MB | 128~256MB | 대용량 파일 → 256MB |

| `dfs.replication` | 3 | 2~3 | 저장 공간 vs 안정성 |

| `dfs.namenode.handler.count` | 10 | 20~200 | NameNode RPC 처리량 |

| `mapreduce.map.memory.mb` | 1024 | 1024~4096 | Map 태스크 메모리 |

| `mapreduce.reduce.memory.mb` | 1024 | 2048~8192 | Reduce 태스크 메모리 |

| `mapreduce.task.io.sort.mb` | 100 | 256~512 | Map 정렬 성능 |

| `yarn.nodemanager.resource.memory-mb` | 8192 | 물리 메모리의 80% | 노드 총 할당 메모리 |

8. Spark vs MapReduce 비교

| 항목 | MapReduce | Spark |

| ------------------- | ------------------- | ---------------------------------- |

| **처리 방식** | 디스크 기반 배치 | 인메모리 배치/스트리밍 |

| **속도** | 기준 (1x) | 10~100x 빠름 |

| **반복 처리** | 매번 디스크 I/O | 메모리에 캐싱 |

| **프로그래밍 모델** | Map → Reduce | RDD, DataFrame, SQL |

| **언어** | Java | Scala, Python, Java, R, SQL |

| **실시간 처리** | 불가 | Structured Streaming |

| **메모리 요구** | 낮음 | 높음 |

| **장애 복구** | 디스크에서 재계산 | Lineage로 재계산 |

| **적합한 워크로드** | 단순 ETL, 로그 처리 | ML, 그래프, 반복 처리, 대화형 분석 |

Spark WordCount (비교용)

from pyspark.sql import SparkSession

spark = SparkSession.builder.appName("WordCount").getOrCreate()

text_file = spark.sparkContext.textFile("hdfs:///user/hadoop/input/")

counts = text_file.flatMap(lambda line: line.split(" ")) \

.map(lambda word: (word, 1)) \

.reduceByKey(lambda a, b: a + b)

counts.saveAsTextFile("hdfs:///user/hadoop/output/spark-wordcount")

9. 모니터링

핵심 모니터링 메트릭

| 메트릭 | 설명 | 경고 기준 |

| ----------------------- | ----------------- | ------------ |

| NameNode Heap 사용률 | NN 메모리 사용량 | > 80% |

| Under-Replicated Blocks | 복제 부족 블록 수 | > 0 (지속) |

| Dead DataNodes | 장애 DN 수 | > 0 |

| HDFS Capacity Used | 디스크 사용률 | > 80% |

| YARN Memory Used | 메모리 사용률 | > 85% |

| Pending Containers | 대기 중 컨테이너 | > 100 (지속) |

웹 UI 포트

NameNode UI: http://namenode:9870

ResourceManager UI: http://resourcemanager:8088

DataNode UI: http://datanode:9864

NodeManager UI: http://nodemanager:8042

MapReduce History: http://historyserver:19888

Prometheus + Grafana 연동

prometheus.yml

scrape_configs:

- job_name: 'hadoop-namenode'

metrics_path: '/jmx'

params:

format: ['prometheus']

static_configs:

- targets: ['namenode:9870']

- job_name: 'hadoop-datanode'

metrics_path: '/jmx'

params:

format: ['prometheus']

static_configs:

- targets: ['datanode1:9864', 'datanode2:9864', 'datanode3:9864']

- job_name: 'hadoop-resourcemanager'

metrics_path: '/jmx'

params:

format: ['prometheus']

static_configs:

- targets: ['resourcemanager:8088']

10. 트러블슈팅

NameNode 장애

NameNode가 Safe Mode에서 빠져나오지 않을 때

hdfs dfsadmin -safemode get

hdfs dfsadmin -safemode leave

NameNode EditLog 손상 시

hdfs namenode -recover

NameNode OOM

→ hadoop-env.sh에서 힙 사이즈 증가

export HDFS_NAMENODE_OPTS="-Xmx32g -Xms32g"

DataNode 장애

DataNode 상태 확인

hdfs dfsadmin -report | grep -A5 "Dead datanodes"

특정 DataNode 블록 검증

hdfs fsck / -files -blocks -locations | grep "datanode1"

DataNode 디스크 풀

→ dfs.datanode.data.dir에 새 디스크 추가

→ DataNode 재시작

YARN 애플리케이션 장애

실행 중인 애플리케이션 목록

yarn application -list

애플리케이션 로그 확인

yarn logs -applicationId application_1709875200_0001

애플리케이션 강제 종료

yarn application -kill application_1709875200_0001

컨테이너 로그 확인

yarn logs -applicationId application_1709875200_0001 -containerId container_1709875200_0001_01_000001

11. 운영 체크리스트

초기 구축 체크리스트

- [ ] Java 버전 확인 (JDK 11 이상 권장)

- [ ] SSH 키 기반 인증 설정 (전 노드)

- [ ] NTP 동기화 확인 (전 노드)

- [ ] OS 튜닝 (ulimit, swappiness, THP 비활성화)

- [ ] 디스크 JBOD 구성 (RAID 사용 금지)

- [ ] HDFS HA 구성 (JournalNode 3개 이상)

- [ ] YARN HA 구성 (ResourceManager 2개)

- [ ] 네트워크 대역폭 확인 (10Gbps 이상 권장)

일상 운영 체크리스트

- [ ] NameNode 힙 사용률 모니터링

- [ ] Under-replicated 블록 확인

- [ ] Dead DataNode 확인

- [ ] HDFS 용량 사용률 확인

- [ ] YARN 큐 리소스 사용률 확인

- [ ] 로그 디스크 사용량 확인

- [ ] 장기 실행 Job 확인

정기 점검 체크리스트

- [ ] `hdfs fsck /` 실행하여 파일 시스템 무결성 확인

- [ ] NameNode 백업 (fsimage + edits)

- [ ] 보안 패치 적용 계획 수립

- [ ] 디스크 교체 계획 (SMART 확인)

- [ ] 클러스터 밸런싱 (`hdfs balancer`)

- [ ] 로그 로테이션 및 정리

마무리

Hadoop은 빅데이터 생태계의 기반 인프라로서 여전히 중요한 위치를 차지하고 있습니다. HDFS는 대규모 데이터 저장소로, YARN은 다양한 처리 프레임워크의 리소스 관리자로 계속 활용되고 있습니다.

핵심 정리:

1. **HDFS**는 블록 단위 분산 저장 + 복제로 안정성 확보

2. **MapReduce**는 단순하지만 디스크 I/O가 많아 Spark 대비 느림

3. **YARN**은 다양한 프레임워크를 위한 범용 리소스 관리자

4. **성능 튜닝**은 블록 크기, 메모리, 스레드 수 조정이 핵심

5. **모니터링**은 NameNode 힙, Under-replicated 블록, YARN 큐에 집중

현재 단락 (1/296)

Hadoop은 2006년 등장한 이래 빅데이터 처리의 표준으로 자리잡았습니다. Spark, Flink 등 차세대 프레임워크가 등장했지만, HDFS와 YARN은 여전히 데이터 인프라...

작성 글자: 0원문 글자: 11,431작성 단락: 0/296