Boaz/Data Engineering

Hadoop/Spark 이론 정리 및 예제

남디윤 2025. 2. 4. 17:31

안녕하세요

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의 정의

(2) Hadoop 핵심 구성 요소

(3) Hadoop의 특징, 한계

2. Spark

3. Hadoop & Spark 실습 과제

(1) Hadoop + Spark 클러스터 구성

(2) Hadoop MapReduce로 Word Count 실습

(3) Spark로 Word Count 실습

 

 

1. Hadoop

 

(1) Hadoop의 정의

  • High Availability Distributed Object Oriented Platform
  • 대규모 데이터 처리를 위한 오픈 소스 프레임워크
  • 분산 저장(Distributed Storage)분산 처리(Distributed Processing)를 통해 방대한 데이터를 효율적으로 처리하는 것이 특징
  • 아파치(Apache) 소프트웨어 재단에서 개발 및 관리

Image

 

(2) Hadoop 핵심 구성 요소

자체 프레임워크의 핵심 구성 요소(Core Components)

  1. HDFS - Hadoop Distributed File System: 저장 계층
  2. YARN - Yet Another Resource Negotiator: 자원 관리 계층
  3. MapReduce: 데이터 처리 계층

Image

 

1️⃣ HDFS (Hadoop Distributed File System)

  • 대규모 데이터를 분산 저장하는 파일 시스템
  • 데이터를 블록 단위(기본 128MB)로 나눠 슬레이브 노드에 저장
  • 마스터-슬레이브 구조
    • NameNode (마스터): 메타데이터 관리 (파일명, 블록 위치, 권한 등)
    • DataNode (슬레이브): 실제 데이터 블록 저장 및 클라이언트 요청 처리

ImageImage

  • 작동 방식 📖 데이터 읽기 (Read Process)  
    1. 클라이언트 요청
      • 클라이언트가 파일 저장 요청 → NameNode에 파일 생성 요청을 전송
    2. 블록 분할
      • NameNode는 파일을 기본적으로 128MB 크기의 블록으로 분할하도록 설정
    3. 블록 복제 (Replication)
      • 각 블록은 기본적으로 3개의 복제본으로 저장되어 데이터 손실 대비
      • NameNode가 어떤 DataNode에 저장할지 결정
    4. DataNode에 저장
      • 클라이언트는 지정된 DataNode로 데이터를 전송
      • 첫 번째 DataNode에 저장 후, 이 데이터가 두 번째, 세 번째 DataNode로 순차적으로 복제
    5. 저장 완료 확인
      • 모든 복제본이 성공적으로 저장되면, DataNode → NameNode로 상태 보고
      • NameNode가 클라이언트에 저장 완료 응답 전송
  • 작동 방식 ✏️ 데이터 저장 (Write Process)
    1. 클라이언트 요청
      • 클라이언트가 파일 읽기 요청 → NameNode에 파일 위치 정보 요청
    2. 메타데이터 조회
      • NameNode가 파일의 블록 정보와 해당 블록이 저장된 DataNode 목록을 반환
      • 가장 가까운 DataNode를 우선 추천 (데이터 지역성 최적화)
    3. DataNode로 데이터 요청
      • 클라이언트는 추천받은 DataNode로 직접 접속해 데이터 요청
    4. 데이터 전송
      • DataNode는 요청된 블록 데이터를 클라이언트로 전송
    5. 데이터 병합
      • 클라이언트는 전송받은 블록들을 순서대로 병합하여 파일 복원

 

2️⃣ MapReduce (데이터 처리 프레임워크)

  • 대규모 데이터를 병렬로 처리
  • <Key, Value> 쌍으로 데이터를 처리하는 구조
  • 2단계 처리 과정
    • Map 단계: 데이터 로드, 파싱, 필터링, 변환 수행 → 중간 결과 생성
    • Reduce 단계: 중간 결과를 그룹화하고 집계하여 최종 결과 도출
    • Map → Shuffle → Reduce 단계로 나누어 설명하는 것도 가능

Image

  • 작동 방식
    • 목표: 데이터에서 “각 지역(Location)별 점수(Score) 평균” 구하기
  • 예시)

Image

- **Map** 단계
    - 각 데이터가 key:value 쌍으로 묶임
    - 지역(Location):점수(Score) 형태로 표현

Image

- **Shuffle** 단계: 같은 Key를 가진 요소들끼리 그룹짓기

Image

- **Reduce** 단계: 원하는 평균 값 도출

Image

 

 

3️⃣ YARN (Yet Another Resource Negotiator)

  • 클러스터 내 자원(메모리, CPU 등) 관리 및 작업 스케줄링
  • 여러 애플리케이션이 동시에 실행될 수 있도록 지원
  • 구성 요소:
    • (1) ResourceManager (마스터): 전체 클러스터 자원 관리 및 스케줄링
      • Scheduler: 작업(Task) 간 자원 분배, 우선순위 관리
        • 스케줄링 알고리즘:
          • FIFO (First In, First Out): 요청 순서대로 작업 처리
          • Capacity Scheduler: 여러 사용자 간 자원을 공정하게 배분
          • Fair Scheduler: 모든 작업이 비슷한 자원 점유율을 유지하도록 조정
      • ApplicationManager: Client의 작업 요청을 검토, 애플리케이션의 실행을 위해 ApplicationMaster 컨테이너를 NodeManager에 요청, 작업 상태 추적
    • (2) NodeManager (슬레이브):* 클러스터의 각 노드에서 자원(CPU, 메모리 등) 관리 및 작업 실행 환경(Container) 관리
    • (3) ApplicationMaster:* 각 애플리케이션의 자원 요청 및 작업 관리 담당

Image

  • 작동 방식
    • 작업 제출 (Client → ResourceManager)
      • 클라이언트가 YARN에 작업(Job) 제출
    • ApplicationMaster 실행 요청
      • ResourceManager의 ApplicationManager가 요청 수락
      • NodeManager에 ApplicationMaster 컨테이너 생성 요청
    • 자원 요청 및 할당 (AM → Scheduler)
      • ApplicationMaster가 필요한 자원 요청
      • Scheduler가 자원 상태를 확인한 후 할당 결정
    • 작업 실행 (NodeManager → Container)
      • NodeManager가 컨테이너를 생성하고 작업 실행
      • ApplicationMaster가 작업 상태 모니터링 및 제어
    • 작업 완료 및 보고
      • 작업 완료 후 ApplicationMaster가 ResourceManager에 완료 보고

 

 

4️⃣ 하둡 에코시스템

  • Hadoop Core:
    • HDFS, MapReduce, YARN이 핵심 구성 요소
    • 하둡의 기본적인 저장, 처리, 관리 기능 담당
  • Hadoop 에코시스템:
    • Hadoop Core 위에서 동작하는 다양한 도구들 (확장 도구 모음)
    • 예: Hive (SQL 쿼리 처리), Pig (데이터 흐름 처리), Spark (실시간 처리) 등

Image

 

 

 

(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

 

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

https://techvidvan.com/tutorials/hadoop-architecture/

https://pyromaniac.me/entry/Hadoop의-3요소-HDFS-MapReduce-Yarn