Hadoop/Spark 이론 정리 및 예제
안녕하세요
BOAZ 방학 Adv 세션 발표를 하며 준비했던 자료를 포스팅해보려고 합니다
제가 담당한 부분은 Hadoop/Spark여서 이 자료를 업로드합니다 ㅎㅎ
Spark의 경우 학기 Base 세션 발표 때 했던 내용이랑 유사해서 생략합니다.
Spark 포스팅:https://uni-datastudy.tistory.com/87
Apache Spark RDD/Dataframe 정리
안녕하세요BOAZ 학기 Base 세션 발표를 하며 준비했던 자료를 포스팅해보려고 합니다제가 담당한 부분은 Spark RDD/DataFrame 이여서 이 자료를 업로드합니다 ㅎㅎ 목차1. Apache Spark의 개념과 등장
uni-datastudy.tistory.com
목차
1. Hadoop
(1) Hadoop의 정의
- High Availability Distributed Object Oriented Platform
- 대규모 데이터 처리를 위한 오픈 소스 프레임워크
- 분산 저장(Distributed Storage)과 분산 처리(Distributed Processing)를 통해 방대한 데이터를 효율적으로 처리하는 것이 특징
- 아파치(Apache) 소프트웨어 재단에서 개발 및 관리
(2) Hadoop 핵심 구성 요소
자체 프레임워크의 핵심 구성 요소(Core Components)
- HDFS - Hadoop Distributed File System: 저장 계층
- YARN - Yet Another Resource Negotiator: 자원 관리 계층
- MapReduce: 데이터 처리 계층
1️⃣ HDFS (Hadoop Distributed File System)
- 대규모 데이터를 분산 저장하는 파일 시스템
- 데이터를 블록 단위(기본 128MB)로 나눠 슬레이브 노드에 저장
- 마스터-슬레이브 구조
- NameNode (마스터): 메타데이터 관리 (파일명, 블록 위치, 권한 등)
- DataNode (슬레이브): 실제 데이터 블록 저장 및 클라이언트 요청 처리
- 작동 방식 📖 데이터 읽기 (Read Process)
- 클라이언트 요청
- 클라이언트가 파일 저장 요청 → NameNode에 파일 생성 요청을 전송
- 블록 분할
- NameNode는 파일을 기본적으로 128MB 크기의 블록으로 분할하도록 설정
- 블록 복제 (Replication)
- 각 블록은 기본적으로 3개의 복제본으로 저장되어 데이터 손실 대비
- NameNode가 어떤 DataNode에 저장할지 결정
- DataNode에 저장
- 클라이언트는 지정된 DataNode로 데이터를 전송
- 첫 번째 DataNode에 저장 후, 이 데이터가 두 번째, 세 번째 DataNode로 순차적으로 복제
- 저장 완료 확인
- 모든 복제본이 성공적으로 저장되면, DataNode → NameNode로 상태 보고
- NameNode가 클라이언트에 저장 완료 응답 전송
- 클라이언트 요청
- 작동 방식 ✏️ 데이터 저장 (Write Process)
- 클라이언트 요청
- 클라이언트가 파일 읽기 요청 → NameNode에 파일 위치 정보 요청
- 메타데이터 조회
- NameNode가 파일의 블록 정보와 해당 블록이 저장된 DataNode 목록을 반환
- 가장 가까운 DataNode를 우선 추천 (데이터 지역성 최적화)
- DataNode로 데이터 요청
- 클라이언트는 추천받은 DataNode로 직접 접속해 데이터 요청
- 데이터 전송
- DataNode는 요청된 블록 데이터를 클라이언트로 전송
- 데이터 병합
- 클라이언트는 전송받은 블록들을 순서대로 병합하여 파일 복원
- 클라이언트 요청
2️⃣ MapReduce (데이터 처리 프레임워크)
- 대규모 데이터를 병렬로 처리
- <Key, Value> 쌍으로 데이터를 처리하는 구조
- 2단계 처리 과정
- Map 단계: 데이터 로드, 파싱, 필터링, 변환 수행 → 중간 결과 생성
- Reduce 단계: 중간 결과를 그룹화하고 집계하여 최종 결과 도출
- Map → Shuffle → Reduce 단계로 나누어 설명하는 것도 가능
- 작동 방식
- 목표: 데이터에서 “각 지역(Location)별 점수(Score) 평균” 구하기
- 예시)
- **Map** 단계
- 각 데이터가 key:value 쌍으로 묶임
- 지역(Location):점수(Score) 형태로 표현
- **Shuffle** 단계: 같은 Key를 가진 요소들끼리 그룹짓기
- **Reduce** 단계: 원하는 평균 값 도출
3️⃣ YARN (Yet Another Resource Negotiator)
- 클러스터 내 자원(메모리, CPU 등) 관리 및 작업 스케줄링
- 여러 애플리케이션이 동시에 실행될 수 있도록 지원
- 구성 요소:
- (1) ResourceManager (마스터): 전체 클러스터 자원 관리 및 스케줄링
- Scheduler: 작업(Task) 간 자원 분배, 우선순위 관리
- 스케줄링 알고리즘:
- FIFO (First In, First Out): 요청 순서대로 작업 처리
- Capacity Scheduler: 여러 사용자 간 자원을 공정하게 배분
- Fair Scheduler: 모든 작업이 비슷한 자원 점유율을 유지하도록 조정
- 스케줄링 알고리즘:
- ApplicationManager: Client의 작업 요청을 검토, 애플리케이션의 실행을 위해 ApplicationMaster 컨테이너를 NodeManager에 요청, 작업 상태 추적
- Scheduler: 작업(Task) 간 자원 분배, 우선순위 관리
- (2) NodeManager (슬레이브):* 클러스터의 각 노드에서 자원(CPU, 메모리 등) 관리 및 작업 실행 환경(Container) 관리
- (3) ApplicationMaster:* 각 애플리케이션의 자원 요청 및 작업 관리 담당
- (1) ResourceManager (마스터): 전체 클러스터 자원 관리 및 스케줄링
- 작동 방식
- 작업 제출 (Client → ResourceManager)
- 클라이언트가 YARN에 작업(Job) 제출
- ApplicationMaster 실행 요청
- ResourceManager의 ApplicationManager가 요청 수락
- NodeManager에 ApplicationMaster 컨테이너 생성 요청
- 자원 요청 및 할당 (AM → Scheduler)
- ApplicationMaster가 필요한 자원 요청
- Scheduler가 자원 상태를 확인한 후 할당 결정
- 작업 실행 (NodeManager → Container)
- NodeManager가 컨테이너를 생성하고 작업 실행
- ApplicationMaster가 작업 상태 모니터링 및 제어
- 작업 완료 및 보고
- 작업 완료 후 ApplicationMaster가 ResourceManager에 완료 보고
- 작업 제출 (Client → ResourceManager)
4️⃣ 하둡 에코시스템
- Hadoop Core:
- HDFS, MapReduce, YARN이 핵심 구성 요소
- 하둡의 기본적인 저장, 처리, 관리 기능 담당
- Hadoop 에코시스템:
- Hadoop Core 위에서 동작하는 다양한 도구들 (확장 도구 모음)
- 예: Hive (SQL 쿼리 처리), Pig (데이터 흐름 처리), Spark (실시간 처리) 등
(3) Hadoop의 특징, 한계
- 특징
- 확장성 (Scalability): 수천 대의 서버로 확장 가능
- 내결함성 (Fault Tolerance): 노드가 고장 나도 데이터 손실 최소화 (복제본 유지)
- 대규모 데이터 처리: 페타바이트(PB)급 데이터 처리 가능
- 오픈 소스: 자유롭게 사용 및 수정 가능
- 한계점
- 실시간 처리 한계: 배치 처리 중심으로, 실시간 분석은 어려움 (Spark로 보완 가능)
- 복잡한 설정: 초기 설정 및 관리가 복잡
- 자원 집약적: 클러스터 유지에 많은 하드웨어 자원 필요
2. Spark
spark는 위에 첨부한 글로 이동해주세용~
3. Hadoop & Spark 실습 과제
(1) Hadoop + Spark 클러스터 구성
⚠️ docker가 먼저 설치되어 있어야 합니다.
저는 wsl ubuntu 환경에서 진행했습니다.
jy@DESKTOP-O18BVMG:/mnt/c/Users/82105/Desktop/boaz$ docker --version
Docker version 27.2.0, build 3ab4256
(1) docker-compose.yml
파일 작성
yml 파일에 아래 내용 붙혀넣기 이후
컨트롤 x → y → 엔터
mkdir hadoop-spark-cluster
cd hadoop-spark-cluster
nano docker-compose.yml
version: "3"
services:
namenode:
image: bde2020/hadoop-namenode:2.0.0-hadoop3.2.1-java8
container_name: namenode
environment:
- CLUSTER_NAME=HadoopCluster
- CORE_CONF_fs_defaultFS=hdfs://namenode:9000 # 추가: HDFS 기본 파일 시스템 설정
ports:
- "9870:9870" # NameNode UI
- "9000:9000" # HDFS RPC 포트
volumes:
- namenode_data:/hadoop/dfs/name
networks:
- hadoop-spark
datanode:
image: bde2020/hadoop-datanode:2.0.0-hadoop3.2.1-java8
container_name: datanode
environment:
- CLUSTER_NAME=HadoopCluster
- CORE_CONF_fs_defaultFS=hdfs://namenode:9000
- HDFS_CONF_dfs_namenode_rpc-address=namenode:9000 # 추가: NameNode의 RPC 주소 명시
ports:
- "9864:9864" # DataNode UI
volumes:
- datanode_data:/hadoop/dfs/data
depends_on:
- namenode
networks:
- hadoop-spark
resourcemanager:
image: bde2020/hadoop-resourcemanager:2.0.0-hadoop3.2.1-java8
container_name: resourcemanager
environment:
- YARN_CONF_yarn_resourcemanager_hostname=resourcemanager
- CORE_CONF_fs_defaultFS=hdfs://namenode:9000 # 추가: YARN도 HDFS를 인식하도록 설정
ports:
- "8088:8088" # YARN ResourceManager UI
depends_on:
- namenode
networks:
- hadoop-spark
nodemanager:
image: bde2020/hadoop-nodemanager:2.0.0-hadoop3.2.1-java8
container_name: nodemanager
environment:
- YARN_CONF_yarn_resourcemanager_hostname=resourcemanager
- CORE_CONF_fs_defaultFS=hdfs://namenode:9000 # 추가
depends_on:
- resourcemanager
networks:
- hadoop-spark
spark-master:
image: bitnami/spark:latest
container_name: spark-master
environment:
- SPARK_MODE=master
- SPARK_MASTER_HOST=spark-master
- CORE_CONF_fs_defaultFS=hdfs://namenode:9000 # Spark도 HDFS 인식하도록 추가
ports:
- "7077:7077" # Spark Master Port
- "8080:8080" # Spark Master UI
networks:
- hadoop-spark
spark-worker:
image: bitnami/spark:latest
container_name: spark-worker
environment:
- SPARK_MODE=worker
- SPARK_MASTER_URL=spark://spark-master:7077
- CORE_CONF_fs_defaultFS=hdfs://namenode:9000 # 추가
ports:
- "8081:8081" # Spark Worker UI
depends_on:
- spark-master
networks:
- hadoop-spark
networks:
hadoop-spark:
driver: bridge # 명시적으로 bridge 네트워크 사용
volumes:
namenode_data:
datanode_data:
(2) 클러스터 시작
조금 기다리셔야 합니다.
docker-compose up -d
컨테이너 상태 확인
docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
893e2cd94a5b bde2020/hadoop-nodemanager:2.0.0-hadoop3.2.1-java8 "/entrypoint.sh /run…" About a minute ago Up About a minute (healthy) 8042/tcp nodemanager
c04c18f3928c bitnami/spark:latest "/opt/bitnami/script…" About a minute ago Up About a minute 0.0.0.0:8081->8081/tcp spark-worker
95185149e430 bde2020/hadoop-datanode:2.0.0-hadoop3.2.1-java8 "/entrypoint.sh /run…" About a minute ago Up About a minute (healthy) 0.0.0.0:9864->9864/tcp datanode
8b57eaf37c0f bde2020/hadoop-resourcemanager:2.0.0-hadoop3.2.1-java8 "/entrypoint.sh /run…" About a minute ago Up About a minute (healthy) 0.0.0.0:8088->8088/tcp resourcemanager
1cf5bde35991 bitnami/spark:latest "/opt/bitnami/script…" About a minute ago Up About a minute 0.0.0.0:7077->7077/tcp, 0.0.0.0:8080->8080/tcp spark-master
187b57286f65 bde2020/hadoop-namenode:2.0.0-hadoop3.2.1-java8 "/entrypoint.sh /run…" About a minute ago Up About a minute (healthy) 0.0.0.0:9000->9000/tcp, 0.0.0.0:9870->9870/tcp namenode
웹 UI
- Hadoop NameNode UI: http://localhost:9870
- Hadoop ResourceManager UI: http://localhost:8088
- Spark Master UI: http://localhost:8080
- Spark Worker UI: http://localhost:8081
DataNode 컨테이너 상태 확인
아래 두 명령어를 넣었을 때 아래처럼 다 0이 나오면 데이터 노드가 연결이 안된것
docker exec -it namenode bash
hdfs dfsadmin -report
# 비정상
root@d1af4741fc23:/# hdfs dfsadmin -report
Configured Capacity: 0 (0 B)
Present Capacity: 0 (0 B)
DFS Remaining: 0 (0 B)
DFS Used: 0 (0 B)
DFS Used%: 0.00%
Replicated Blocks:
Under replicated blocks: 0
Blocks with corrupt replicas: 0
Missing blocks: 0
Missing blocks (with replication factor 1): 0
Low redundancy blocks with highest priority to recover: 0
Pending deletion blocks: 0
Erasure Coded Block Groups:
Low redundancy block groups: 0
Block groups with corrupt internal blocks: 0
Missing block groups: 0
Low redundancy blocks with highest priority to recover: 0
Pending deletion blocks: 0
-------------------------------------------------
# 정상
root@187b57286f65:/# hdfs dfsadmin -report
Configured Capacity: 1081101176832 (1006.85 GB)
Present Capacity: 1020640931840 (950.55 GB)
DFS Remaining: 1020640907264 (950.55 GB)
DFS Used: 24576 (24 KB)
DFS Used%: 0.00%
Replicated Blocks:
Under replicated blocks: 0
Blocks with corrupt replicas: 0
Missing blocks: 0
Missing blocks (with replication factor 1): 0
Low redundancy blocks with highest priority to recover: 0
Pending deletion blocks: 0
Erasure Coded Block Groups:
Low redundancy block groups: 0
Block groups with corrupt internal blocks: 0
Missing block groups: 0
Low redundancy blocks with highest priority to recover: 0
Pending deletion blocks: 0
-------------------------------------------------
Live datanodes (1):
Name: 172.18.0.4:9866 (datanode.hadoop-spark-cluster_hadoop-spark)
Hostname: 95185149e430
Decommission Status : Normal
Configured Capacity: 1081101176832 (1006.85 GB)
DFS Used: 24576 (24 KB)
Non DFS Used: 5467922432 (5.09 GB)
DFS Remaining: 1020640874496 (950.55 GB)
DFS Used%: 0.00%
DFS Remaining%: 94.41%
Configured Cache Capacity: 0 (0 B)
Cache Used: 0 (0 B)
Cache Remaining: 0 (0 B)
Cache Used%: 100.00%
Cache Remaining%: 0.00%
Xceivers: 1
Last contact: Tue Feb 04 07:13:28 UTC 2025
Last Block Report: Tue Feb 04 07:12:43 UTC 2025
Num of Blocks: 0
(2) Hadoop MapReduce로 Word Count 실습
NameNode 컨테이너에 접속
docker exec -it namenode bash
샘플 데이터 생성하고 하둡 파일시스템에 업로드
echo -e "Hello Hadoop and Spark\nBig Data Big Value\nHello World" > sample.txt
hdfs dfs -mkdir -p /user/test
hdfs dfs -put sample.txt /user/test
업로드 확인
hdfs dfs -ls /user/test
root@187b57286f65:/# hdfs dfs -ls /user/test
Found 1 items
-rw-r--r-- 3 root supergroup 54 2025-02-04 07:20 /user/test/sample.txt
WordCount MapReduce 실행
아래 코드를 실행하면 뭐가 좌라라락 실행이 되면서 출력이 됩니다.
hadoop jar /opt/hadoop-3.2.1/share/hadoop/mapreduce/hadoop-mapreduce-examples-3.2.1.jar wordcount /user/test/sample.txt /user/test/output_mr
출력 파일 목록 확인
hdfs dfs -ls /user/test/output_mr
root@187b57286f65:/# hdfs dfs -ls /user/test/output_mr
Found 2 items
-rw-r--r-- 3 root supergroup 0 2025-02-04 07:25 /user/test/output_mr/_SUCCESS
-rw-r--r-- 3 root supergroup 60 2025-02-04 07:25 /user/test/output_mr/part-r-00000
결과 데이터 확인
hdfs dfs -cat /user/test/output_mr/part-r-00000
root@187b57286f65:/# hdfs dfs -cat /user/test/output_mr/part-r-00000
2025-02-04 07:25:49,163 INFO sasl.SaslDataTransferClient: SASL encryption trust check: localHostTrusted = false, remoteHostTrusted = false
Big 2
Data 1
Hadoop 1
Hello 2
Spark 1
Value 1
World 1
and 1
Spark 애플리케이션 HDFS에 쓰기 권한 설정
hdfs dfs -chmod -R 777 /user/test
네임노드 나가기 : exit
(3) Spark로 Word Count 실습
Spark 컨테이너에 접속
docker exec -it spark-master bash
wordcount.py 작성
nano 또는 vi 명령어 설치 후 진행하셔도 됩니다. 저는 없어서 그냥 echo 씀
echo "from pyspark import SparkContext
sc = SparkContext('spark://spark-master:7077', 'WordCount')
text_file = sc.textFile('hdfs://namenode:9000/user/test/sample.txt')
counts = text_file.flatMap(lambda line: line.split(' ')) \
.map(lambda word: (word, 1)) \
.reduceByKey(lambda a, b: a + b)
counts.saveAsTextFile('hdfs://namenode:9000/user/test/output_spark')" > wordcount.py
Spark 애플리케이션 실행
spark-submit --master spark://spark-master:7077 wordcount.py
결과 확인
두 개의 part 파일로 나눠서 저장된 모습
exit
docker exec -it namenode bash
hdfs dfs -ls /user/test/output_spark
hdfs dfs -cat /user/test/output_spark/part-00000
jy@DESKTOP-O18BVMG:/mnt/c/Users/82105/Desktop/boaz/hadoop-spark-cluster$ docker exec -it namenode bash
root@187b57286f65:/# hdfs dfs -ls /user/test/output_spark
Found 3 items
-rw-r--r-- 3 spark supergroup 0 2025-02-04 07:38 /user/test/output_spark/_SUCCESS
-rw-r--r-- 3 spark supergroup 49 2025-02-04 07:38 /user/test/output_spark/part-00000
-rw-r--r-- 3 spark supergroup 51 2025-02-04 07:38 /user/test/output_spark/part-00001
root@187b57286f65:/# hdfs dfs -cat /user/test/output_spark/part-00001
2025-02-04 07:39:25,087 INFO sasl.SaslDataTransferClient: SASL encryption trust check: localHostTrusted = false, remoteHostTrusted = false
('Hello', 2)
('Spark', 1)
('Data', 1)
('World', 1)
root@187b57286f65:/# hdfs dfs -cat /user/test/output_spark/part-00000
2025-02-04 07:39:40,368 INFO sasl.SaslDataTransferClient: SASL encryption trust check: localHostTrusted = false, remoteHostTrusted = false
('Hadoop', 1)
('and', 1)
('Big', 2)
('Value', 1)
References