이전 포스팅에서는 Hadoop과 Hadoop의 MapReduce에 대해 알아보았다.
2024.11.08 - [Hadoop] - [Hadoop] Apache Hadoop - MapReduce
이번 포스팅에서는 Hadoop의 주요 기능인 HDFS에 대해 알아보겠다.
1. HDFS(Hadoop Distributed File System) 정의
The Hadoop Distributed File System (HDFS) is a distributed file system designed to run on commodity hardware. It has many similarities with existing distributed file systems. However, the differences from other distributed file systems are significant. HDFS is highly fault-tolerant and is designed to be deployed on low-cost hardware. HDFS provides high throughput access to application data and is suitable for applications that have large data sets. HDFS relaxes a few POSIX requirements to enable streaming access to file system data. HDFS was originally built as infrastructure for the Apache Nutch web search engine project. HDFS is part of the Apache Hadoop Core project.
출처 : https://hadoop.apache.org/docs/stable/hadoop-project-dist/hadoop-hdfs/HdfsDesign.html
정리하면, HDFS는 상용 하드웨어에서 실행되도록 설계된 분산 파일 시스템이다. HDFS는 내결함성이 뛰어나며, 저가형 하드웨어에 배포할 수 있도록 설계되었다. HDFS는 애플리케이션 데이터에 대한 높은 처리량 액세스를 제공하며 대용량 데이터 세트가 있는 애플리케이션에 적합하다고 한다.
2. HDFS 설계 과정과 목표 (Assumptions and Goals)
하드웨어 장애 (Hardware Failure)
HDFS는 수백에서 수천 개의 서버가 파일 시스템의 데이터를 분산 저장하며, 하드웨어가 고장날 가능성이 항상 존재한다. 따라서, HDFS는 오류를 빠르게 감지하고 자동으로 복구하는 기능을 핵심 목표로 삼고 있다. 이는 대규모 분산 시스템에서 매우 중요한 설계 요소이다.
대용량 데이터 세트 지원 (Large Data Sets)
HDFS는 수 기가바이트에서 테라바이트까지 대용량 파일을 지원하도록 설계되어 있다. 따라서, 클러스터 전체에 걸쳐 높은 데이터 대역폭을 제공하고, 하나의 클레스터에서 수백 노드를 확장하며 수천만 개의 파일을 지원할 수 있어야 한다.
요약하자면,
HDFS는 대규모 데이터 처리에 최적화된 분산 파일 시스템으로서, 높은 내결함성, 데이터 처리량, 대규모 확장성, 데이터 접근의 효율성을 위해 설계되었다고 할 수 있다.
그렇다면, Hadoop은 어떤 구조로 이루어져있을까?
3. 네임 노드와 데이터 노드 (NameNode and DataNodes)
HDFS의 마스터/워커 아키텍처
- NameNode는 마스터 서버로서, 파일 시스템의 네임 스페이스(파일 및 디렉토리 구조)를 관리하고 클라이언트가 파일에 접근하는 것을 조정하는 약할을 담당한다
- DataNode는 워커 서버로서, 클러스터 내의 각 노드에 저장된 데이터를 관리한다. 보통 클러스터의 각 노드 하나의 DataNode가 존재하고, 데이터 블록을 저장하고 관리하는 역할을 한다
파일 시스템 네임스페이스와 데이터 저장
- HDFS는 사용자 데이터를 파일 형태로 저장할 수 있는 파일 시스템 네임스페이스를 제공한다
- 내부적으로 파일은 하나 이상의 블록으로 나누어지고, 각각의 블록은 여러 DataNode에 분산 저장된다. 이를 통해 대규모 파일도 여러노드에 걸쳐 분산 저장할 수 있다
NameMode의 역할
- 파일 시스템 네임스페이스 작업을 수행한다. 파일과 디렉토리를 open, close, rename 등의 작업을 NameNode가 관리한다
- 블록의 위치와 매핑을 결정한다. NameNode는 각 파일 블록이 어느 DataNode에 저장되는 지 결정하여 파일에 대한 메타데이터를 관리한다
- 사용자 데이터는 NameNode를 거치지 않고 바로 DataNode를 통해 접근되기 때문에, NameNode의 역할은 주로 메타데이터 관리에 집중된다
DataNode의 역할
- 클라이언트의 읽기 및 쓰기 요청을 처리한다. 클라이언트가 파일을 읽거나 쓸 때, 해당 파일의 블록을 가진 DataNode들이 요청을 처리한다
- 블록 생성, 삭제, 복제 작업을 수행한다. DataNode는 NameNode의 지시에 따라 새로운 블록을 생성하거나, 필요에 따라 삭제, 복제하여 데이터 안정성을 유지한다
HDFS(Hadoop Distributed File System) Architecture
NameNode와 메타데이터 관리
- 메타데이터에는 파일 경로, 각 파일의 복제본 수, 파일이 저장된 DataNode 목록 과 같은 정보가 포함된다
- 클라이언트가 HDFS에 접근할 때, 먼저 NameNode에 메타데이터 요청을 보내 파일 위치 정보와 같은 데이터를 조회한다
DataNode와 데이터 저장
- DataNode는 여러개의 Rack에 분산되어 있다
- 블록은 복제되어 여러 DataNode에 저장되므로 하나의 노드에 장애가 발생해도 데이터 손실 방지 가능
데이터 읽기(Read) 프로세스
- 클라이언트가 데이터를 읽으려 할 때, 먼저 NameNode에 메타데이터 요청을 보내 어떤 DataNode에 해당 데이터가 있는 지 확인
- 이후, 클라이언트는 DataNode에 직접 접근해서 데이털을 읽는다. NameNode를 거치지 않고 데이터를 직접 읽기 때문에 효율적인 데이터 접근 가능
데이터 쓰기(Write) 프로세스
- 클라이언트가 데이터를 저장할 때도, 먼저 NameNode에 파일 이름 및 복제본 수를 포함한 메타데이터 요청을 보낸다
- NameNode는 데이터를 저장할 DataNode 목록을 지정해주고, 클라이언트는 이 목록을 바탕으로 여러 DataNode에 데이터를 분산해 저장
- 데이터가 DataNode에 저장될 때, Replication(복제) 과정을 거쳐 데이터 블록의 본사본이 지정된 다른 DataNode에 저장
랙 간 복제
- HDFS는 복제본을 여러 랙에 걸쳐 저장해서 내구성을 향상 시킨다, 한 렉에 문제가 발생해도 다른 랙에 복제본이 있어 데이터 손실을 방지할 수 있다
- Rack1과 Rack2에 데이터가 복제되어 있는 것을 볼 수 있다, 이는 HDFS가 데이터의 내구성과 고가용성을 유지하는 방법이다
Metadata ops (메타데이터 작업)
- 파일의 위치 정보, 블록의 위치, 파일 상태등을 조회하는 작업이다, 클라이언트가 파일에 접근하기 전에 필요한 정보를 얻기 위해 수행
Block ops (블록 작업)
- 클라이언트가 데이터를 읽거나 쓸 때, 실제 데이터를 다루는 작업이다, 클라이언트는 블록데이터를 직접 DataNode에 가져오거나 저장하며, 복제 과정도 포함된다
Data Replication (데이터 복제)
- NameNode는 각 블록의 복제본 수를 결정하고 유지하며, 이를 위해 DataNode로 부터 주기적인 Hearbeat와 Blockreport를 받음
- Heartbeat - DataNode가 정상적으로 작동 중임을 의미
- Blockreport - 특정 DataNode에 저장된 모든 블록의 목록을 NameNode에 보고한다
HDFS가 어떤 기능을 하는 지 알아봤고, 이제 HDFS를 본격적으로 실행해보자.
4. HDFS 설치
HDFS를 설치하는 방법은 이전 포스팅을 참고하면 좋을 거 같다.
2024.03.13 - [데이터 엔지니어링] - Apache Spark & Hadoop 클러스터 구축 및 설정
5. HDFS 실행
hadoop의 sbin에 있는 실행 파일 목록을 보면, start-all, dfs, yarn 등이 있는데, start-all.sh를 해서 실행하면 된다.
일단 hadoop을 실행하기 전에, jps로 java 프로세스들이 실행된 목록을 확인해보면,
start-all.sh를 실행하면 starting namenode, datanodes, secondary namenode 등이 실행되고 경고도 나오는 것을 확인할 수 있다.
여기에서 경고는 YARN_CONF_DIR는 HADOOP_CONF_DIR에 대체되었다고 나와있다.
마스터 노드와 워커 노드에 jps를 해보겠다
마스터 노드에는 ResourceManager, NameNode, SecondaryNameNode 프로세스가 실행되고 있고,
워커 노드에는 DataNode, NodeManager가 프로세스가 실행되고 있는 것을 확인할 수 있다.
앞서, NameNode와 DataNode의 역할에 대해서는 알아봤지만
SecondaryNameNode와 ResourceManager는 처음 보는 프로세스이다.
그렇다면, SecondaryNameNode와 ResourceManager, NodeManager는 어떤 프로세스인지 알아보자.
SecondaryNameNode
SecondaryNameNode는 Hadoop의 HDFS에서 NameNode를 보조하는 프로세스이다.
NameNode를 백업하는 역할로 오해할 수 있지만, NameNode의 장애를 대비한 백업 역할을 하는 것이 아니라, 다른 역할을 한다.
SecondaryNameNode의 역할 :
- 메타데이터 스냅샷 생성 및 체크포인트 수행을 한다
- NameNode는 변경 사항을 Edit Log에 기록하고 있지만, 시간이 경과하면서 Edit log가 커지면 NameNode의 속도가 느려지고 성능 저하가 발생할 수 있다
- 그래서 SecondaryNameNode는 주기적으로 Edit Log와 NameNode의 파일 시스템 이미지(fsimage)를 가져와 이를 병합해서 최신 상태의 fsimage를 생성하고, 이것을 체크포인트라고 한다
- 병합된 fsimage 파일을 NameNode에 저장하고 Edit Log를 비워줌으로써, NameNode가 다시 시작할 때, 로드할 메타데이터의 크기를 줄여준다
- SecondaryNameNode는 NameNode가 다운 되었을 때, 이를 대체할 수 있는 기능은 없기 때문에, NameNode의 장애에 대비하려면 고가용성(High Availability) 설정이 필요하다
ResourceManager, NodeManager
ResourceManager와 NodeManager는 YARN(Yet Another Resource Negotiator)에 관련된 컴포넌트이기 때문에, 추후 YARN 포스팅에서 다뤄보도록 하겠다.
6. HDFS WEB UI
HDFS WEB UI에 접속하려면, Masternode'ip:9870에 접속하면 된다.
OverView
HDFS Web UI에서 Started, Version, security, Heap Memory Used, DFS Used 등 클러스터의 상태를 확인할 수 있다.
Datanodes
Datanodes 탭에 들어가면, Data node들의 상태를 확인할 수 있다,
DataNodes 탭에서 확인할 수 있는 정보는 데이터 노드들의 ip, 연결 시점, 얼마나 사용했는지 얼만큼의 Capacity가 남아있는지 등을 확인할 수 있다.
나 같은 경우는 Hadoop을 실행하고 DataNode들이 제대로 연결되었는 지 확인하기 위해 DataNodes으로 확인을 많이 한다.
jps를 해봤을 때, datanode가 실행되고 있는데, datanodes 탭에는 연결이 안될 수도 있기 때문에 잘 연결되었는지 쉽게 확인할 수 있다.
Browse Directory
이제 HDFS에 본격적으로 파일을 올리고 확인할 수 있는 Browse Directory를 확인해보자,
HDFS를 사용할 수 있는 다양한 명령어가 있다.
- hdfs dfs -ls: 경로의 파일과 디렉토리 목록 확인
- hdfs dfs -mkdir: 디렉토리 생성
- hdfs dfs -put file /path: HDFS에 파일 업로드
- hdfs dfs -get /path /localpath: HDFS 파일을 다운로드
- hdfs dfs -cat, -df -h 등 리눅스 명령어와 비슷하고 명령어 전에 - 를 추가하면 된다
그렇다면 데이터를 명령어를 통해 HDFS에 올려보자,
-put 명령어를 통해 파일을 HDFS의 /data 디렉토리에 올렸다.
파일이 올라가는 중에는 _COPYING_이라고 표시되고 있다.
자세하게 살펴보면, Replication (복제수) 3와 Block Size 128MB를 확인할 수 있다.
기본 설정으로 되어 있고, hadoop의 conf 에서 변경할 수 있다.
File information을 살펴보면, Download, head, tail 등을 바로 확인할 수 있게 제공하고 있다.
제일 중요한 정보인 Block 개수와, Block ID, Availability을 보면, 3 개의 워커 노드가 배정되어 있는 것을 확인할 수 있다.
마스터 노드가 적절하게 워커노드 3개를 데이터에 접근할 수 있게 관리하는 것이다.
그렇다면 다른 파일은 어떻게 되어 있을까?
크기가 약 7.1GB 정도 하는 2001_2022.csv 파일은 Blcok 개수가 57개이다.
7.1GB 크기의 데이터를 128MB 크기의 블록으로 나누면 56.75가 나오고, 블록을 정수로 처리하기 때문에 57개의 블록이 할당된다.
그렇다면 왜 HDFS에 데이터를 올려야할까?
7. HDFS에 데이터를 올려야하는 이유
다수의 노드가 있는 클러스터에서 동일한 데이터를 처리하는 경우에 HDFS를 사용하지 않으면,
각 노드 마다 동일한 경로에 동일한 파일이 있어야 데이터를 처리할 수 있다.
클러스터의 노드가 얼마 없다면 귀찮아도 가능하겠지만, 수백, 수천 개의 노드가 있다면 불가능할 것이다.
클러스터 전체에서 같은 데이터를 사용하거나 처리하려면,
데이터 분산 저장과 중앙 관리를 하는 HDFS에 저장하여 처리해야한다.
HDFS는 네트워크를 통해 데이터를 읽고 쓰는 방식으로 동작하는 분산 파일 시스템이며, 클러스터 내의 모든 노드는 네트워크를 통해 HDFS에 접근할 수 있고 물리적으로는 분산되어 있어도 논리적으로는 하나의 파일 시스템 처럼 동작하기 때문에 HDFS를 사용해야한다.
그렇다면, 예를 들어서 확인해보겠다.
HDFS를 사용했을 때, 혹은 사용하지 않았을 때 비교
Zeppelin에서 Spark DataFrame을 사용해서 데이터 분석을 했을 때,
HDFS를 사용했을 때와 사용하지 않았을 때를 비교해보자.
1) HDFS를 사용했을 때
HDFS를 사용했을 때는 클러스터에서 csv 파일을 가져와서 DF로 변환하고 집계와 같은 함수도 제대로 수행하는 것을 볼 수 있다.
2) 로컬 파일 시스템을 사용했을 때
로컬 파일 시스템을 사용했을 때도 Spark DataFrame으로 변환하고 show까지 잘 수행한 모습을 확인할 수 있다.
로컬 파일 시스템을 사용하면 모든 노드에 같은 위치에 파일이 있는 거 아닌 이상 에러가 발생해야 하는 거 아닌가?
왜 에러가 발생하지 않을까? 그 이유는
Spark 드라이버 노드가 로컬 파일을 읽고 데이터를 각 노드에 자동으로 분산해서 df.show()를 수행했을 때 에러가 발생하지 않았다.
하지만 df.count()를 했을 때는 에러가 발생했는데, 에러 내용은 이러하다.
org.apache.spark.SparkException: Job aborted due to stage failure: Task 3 in stage 4.0 failed 4 times, most recent failure: Lost task 3.3 in stage 4.0 (TID 21) (192.168.10.10 executor 0): java.io.FileNotFoundException: File file:/home/spark/data/2019_2020.csv does not exist
count()를 했을 때는 csv 파일이 존재하지 않는다고 에러가 발생했다.
앞서 말한 모든 노드에 동일한 위치에 파일이 없으면 에러가 발생한다고 했던 상황이다.
그렇다면 왜 show()는 에러가 발생하지 않았고, count()는 에러가 발생했을까?
- df.show()는 드라이버 노드가 소량의 데이터(20개 행)를 가져와 출력하는 작업으로 드라이버 노드의 로컬 파일에만 접근해도 문제가 없이 실행되지만,
- count()는 모든 데이터를 분산 처리해야 하므로 각 워커 노드가 파일을 읽어야 하는데, 읽는 과정에서 각 노드의 로컬 파일에 데이터가 존재하지 않아서 에러가 발생했다
결론
이번 글을 통해 HDFS의 정의와 구조에 대해 알아보았다.
또한, HDFS를 설치해서 Web UI를 통해 HDFS를 살펴보고 직접 파일도 올려보았으며,
HDFS를 사용했을 때와 사용하지 않았을 때를 비교하여 HDFS를 사용해야하는 이유에 대해 알아보았다.
이렇게 HDFS는 대용량 데이터를 분산 저장 시스템으로 각 노드에 파일이 없어도 접근 가능하며 처리할 수 있었고,
최적화된 분산 파일 시스템으로서, 높은 내결함성, 데이터 접근의 효율성을 확인할 수 있었다.
다음 포스팅에서는 YARN에 대해 알아보도록 하겠다.
'Hadoop' 카테고리의 다른 글
[Hadoop] YARN(Yet Another Resource Negotiator) (0) | 2024.11.19 |
---|---|
[Hadoop] Apache Hadoop - MapReduce (0) | 2024.11.08 |