Skip to content
Published on

하둡 생태계 실전 가이드: HDFS·YARN·MapReduce 운영 기준

Authors

하둡 생태계 실전 가이드: HDFS·YARN·MapReduce 운영 기준

들어가며

하둡 클러스터를 구축하는 것과 안정적으로 운영하는 것은 완전히 다른 차원의 문제다. 설치 매뉴얼은 넘쳐나지만, HDFS가 90% 차면 어떻게 해야 하는지, YARN 큐가 포화됐을 때 프리엠션 정책을 어떻게 잡아야 하는지, MapReduce 잡이 데이터 스큐로 4시간째 돌고 있을 때 어디를 봐야 하는지 같은 운영 실무 기준을 정리한 문서는 드물다.

이 글은 하둡 생태계(HDFS, YARN, MapReduce)를 프로덕션 환경에서 운영하는 관점에서 용량 계획, 큐 설계, 잡 튜닝, 모니터링, 장애 대응까지 실전 기준을 정리한다. Hadoop 3.x 기준으로 작성했으며, 각 섹션에 실제 설정 예시와 커맨드를 포함한다.


1. HDFS 운영 기준

1.1 블록 크기 설정

HDFS의 기본 블록 크기는 128MB이며, 대용량 파일을 다루는 환경에서는 256MB로 설정하는 것이 일반적이다.

<!-- hdfs-site.xml -->
<property>
  <name>dfs.blocksize</name>
  <value>268435456</value> <!-- 256MB -->
  <description>대용량 ETL 파일 기준 256MB 권장. 소형 파일이 많으면 128MB 유지.</description>
</property>

블록 크기 선택 기준:

기준128MB256MB
평균 파일 크기수백 MB 이하수 GB 이상
MapReduce 매퍼 수많음 (세분화)적음 (대형 태스크)
NameNode 메모리 부담높음낮음
네트워크 활용보통효율적

운영 규칙: NameNode 힙에서 블록 하나가 약 150바이트의 메모리를 소비한다. 1억 개 블록이면 약 15GB의 NameNode 힙이 필요하다. 블록 수를 줄이는 것이 NameNode 안정성에 직결된다.

1.2 복제 팩터 관리

기본 복제 팩터는 3이다. 이 값을 낮추면 저장 공간을 절약할 수 있지만 장애 내성이 줄어든다.

# 클러스터 전체 복제 팩터 확인
hdfs dfsadmin -report | grep "Default Replication"

# 특정 디렉토리의 복제 팩터 변경 (콜드 데이터 아카이빙 시)
hdfs dfs -setrep -w 2 /data/archive/2024/

# 복제 부족 블록 확인
hdfs fsck / -files -blocks -replicaDetails | grep "Under-replicated"

복제 팩터 운영 정책 예시:

  • /data/raw/ (원본 데이터): 복제 팩터 3
  • /data/processed/ (가공 데이터): 복제 팩터 2
  • /data/tmp/ (임시 데이터): 복제 팩터 1
  • Erasure Coding 적용 디렉토리: 복제 팩터 해당 없음 (별도 정책)

1.3 NameNode 관리

NameNode는 HDFS의 단일 장애점(SPOF)이다. HA(High Availability) 구성은 필수이며, 다음 항목을 정기적으로 점검해야 한다.

<!-- hdfs-site.xml: NameNode HA 설정 -->
<property>
  <name>dfs.nameservices</name>
  <value>mycluster</value>
</property>
<property>
  <name>dfs.ha.namenodes.mycluster</name>
  <value>nn1,nn2</value>
</property>
<property>
  <name>dfs.namenode.rpc-address.mycluster.nn1</name>
  <value>namenode1.example.com:8020</value>
</property>
<property>
  <name>dfs.namenode.rpc-address.mycluster.nn2</name>
  <value>namenode2.example.com:8020</value>
</property>
<property>
  <name>dfs.namenode.handler.count</name>
  <value>128</value>
  <description>클라이언트 RPC 요청 처리 스레드 수. 노드 100대 이상이면 128~256 권장.</description>
</property>
# NameNode 상태 확인
hdfs haadmin -getServiceState nn1
hdfs haadmin -getServiceState nn2

# NameNode 힙 사용량 확인
jstat -gcutil $(jps | grep NameNode | awk '{print $1}') 5000

# EditLog 크기 확인 (트랜잭션 로그가 과도하게 쌓이면 문제)
hdfs dfsadmin -fetchImage /tmp/fsimage_check
ls -lh /tmp/fsimage_check

1.4 세이프모드 관리

NameNode가 세이프모드에 있으면 쓰기 작업이 차단된다. 블록 리포트를 충분히 받을 때까지 자동으로 활성화된다.

# 세이프모드 상태 확인
hdfs dfsadmin -safemode get

# 세이프모드 강제 해제 (주의: 블록 무결성 확인 후에만 실행)
hdfs dfsadmin -safemode leave

# 세이프모드 진입 조건 확인
hdfs dfsadmin -report | grep -E "Safe mode|Missing blocks"
<!-- hdfs-site.xml: 세이프모드 임계값 조정 -->
<property>
  <name>dfs.namenode.safemode.threshold-pct</name>
  <value>0.999</value>
  <description>전체 블록 중 99.9%가 리포트되면 세이프모드 해제</description>
</property>
<property>
  <name>dfs.namenode.safemode.extension</name>
  <value>30000</value>
  <description>세이프모드 해제 후 추가 대기 시간 (30초)</description>
</property>

1.5 HDFS Balancer 운영

DataNode 간 디스크 사용률 편차가 커지면 특정 노드에 핫스팟이 발생한다. Balancer를 정기적으로 실행해야 한다.

# Balancer 실행 (기본 임계값 10%)
hdfs balancer -threshold 5

# 대역폭 제한 설정 (운영 시간에는 제한 필요)
hdfs dfsadmin -setBalancerBandwidth 52428800  # 50MB/s

# Balancer 백그라운드 실행 (cron 등록 권장)
nohup hdfs balancer -threshold 5 -idleiterations 5 > /var/log/hadoop/balancer.log 2>&1 &

Balancer 운영 규칙:

  • 야간(00:00~06:00)에 cron으로 실행
  • 운영 시간에는 대역폭을 20MB/s 이하로 제한
  • threshold는 5~10% 범위로 설정
  • DataNode 추가 직후에는 반드시 실행

2. HDFS 용량 계획과 데이터 수명주기

2.1 HDFS Quota 관리

디스크 사용량 폭주를 방지하려면 디렉토리별 quota를 반드시 설정한다.

# 네임 쿼터 설정 (파일/디렉토리 수 제한)
hdfs dfsadmin -setQuota 1000000 /data/team-a/

# 스페이스 쿼터 설정 (용량 제한, 복제 팩터 포함)
hdfs dfsadmin -setSpaceQuota 10T /data/team-a/

# 쿼터 현황 확인
hdfs dfs -count -q -h /data/team-a/
# 출력: QUOTA  REM_QUOTA  SPACE_QUOTA  REM_SPACE_QUOTA  DIR_COUNT  FILE_COUNT  CONTENT_SIZE  PATHNAME

# 쿼터 해제
hdfs dfsadmin -clrSpaceQuota /data/team-a/

팀별 쿼터 설계 예시:

경로스페이스 쿼터네임 쿼터비고
데이터 엔지니어링/data/de/50TB5,000,000ETL 파이프라인
ML 팀/data/ml/30TB2,000,000학습 데이터
분석 팀/data/analytics/20TB1,000,000집계 결과
임시 영역/data/tmp/5TB500,0007일 TTL

2.2 데이터 압축 전략

HDFS에서 압축을 적용하면 저장 공간과 네트워크 I/O를 모두 절약할 수 있다.

압축 코덱압축률속도분할 가능용도
Snappy보통매우 빠름아니오 (컨테이너 포맷 사용 시 가능)중간 데이터, 셔플
LZ4보통매우 빠름아니오실시간 처리
Gzip높음느림아니오아카이브, 콜드 데이터
Zstandard높음빠름아니오Gzip 대체, 아카이브
Bzip2매우 높음매우 느림장기 보관
<!-- core-site.xml: 압축 코덱 등록 -->
<property>
  <name>io.compression.codecs</name>
  <value>
    org.apache.hadoop.io.compress.GzipCodec,
    org.apache.hadoop.io.compress.SnappyCodec,
    org.apache.hadoop.io.compress.ZStandardCodec,
    org.apache.hadoop.io.compress.Lz4Codec
  </value>
</property>
<!-- mapred-site.xml: MapReduce 중간 출력 압축 -->
<property>
  <name>mapreduce.map.output.compress</name>
  <value>true</value>
</property>
<property>
  <name>mapreduce.map.output.compress.codec</name>
  <value>org.apache.hadoop.io.compress.SnappyCodec</value>
</property>

2.3 Erasure Coding (EC)

Hadoop 3.x에서 도입된 Erasure Coding은 복제 팩터 3 대비 약 50%의 저장 공간을 절약하면서도 동일한 내결함성을 제공한다.

# 사용 가능한 EC 정책 확인
hdfs ec -listPolicies

# RS-6-3 정책 활성화 (6 데이터 블록 + 3 패리티 블록)
hdfs ec -enablePolicy -policy RS-6-3-1024k

# 디렉토리에 EC 정책 적용
hdfs ec -setPolicy -path /data/archive -policy RS-6-3-1024k

# EC 정책 확인
hdfs ec -getPolicy -path /data/archive

EC 적용 시 주의사항:

  • 최소 9개 DataNode 필요 (RS-6-3 기준)
  • 랜덤 읽기 성능이 복제 방식보다 낮음 (인코딩/디코딩 오버헤드)
  • 핫 데이터보다는 콜드/웜 데이터에 적합
  • 기존 파일에는 적용 불가 (새로 쓰거나 distcp로 이동)

2.4 Tiered Storage

HDFS의 스토리지 정책을 활용하면 SSD, HDD, 아카이브 스토리지를 계층적으로 관리할 수 있다.

# 스토리지 정책 확인
hdfs storagepolicies -listPolicies

# 핫 데이터 → SSD
hdfs storagepolicies -setStoragePolicy -path /data/hot -policy HOT

# 웜 데이터 → 1 SSD + N HDD
hdfs storagepolicies -setStoragePolicy -path /data/warm -policy WARM

# 콜드 데이터 → 아카이브
hdfs storagepolicies -setStoragePolicy -path /data/cold -policy COLD

# 정책에 따라 데이터 이동 실행
hdfs mover -p /data/
<!-- hdfs-site.xml: DataNode 스토리지 타입 지정 -->
<property>
  <name>dfs.datanode.data.dir</name>
  <value>[SSD]/ssd/hdfs/data,[DISK]/hdd1/hdfs/data,[DISK]/hdd2/hdfs/data,[ARCHIVE]/archive/hdfs/data</value>
</property>

2.5 데이터 수명주기 자동화

#!/bin/bash
# data_lifecycle.sh - 데이터 수명주기 자동화 스크립트

DATE=$(date +%Y-%m-%d)
LOG="/var/log/hadoop/lifecycle_${DATE}.log"

echo "[${DATE}] 데이터 수명주기 관리 시작" >> ${LOG}

# 1. 90일 이상 된 임시 데이터 삭제
echo "=== 임시 데이터 정리 ===" >> ${LOG}
hdfs dfs -find /data/tmp -name "*" -atime +90 -print >> ${LOG}
hdfs dfs -rm -r -skipTrash $(hdfs dfs -find /data/tmp -name "*" -atime +90) 2>> ${LOG}

# 2. 30일 이상 된 처리 데이터 → 복제 팩터 2로 변경
echo "=== 복제 팩터 조정 ===" >> ${LOG}
for dir in $(hdfs dfs -ls /data/processed/ | awk '{print $8}' | tail -n +2); do
    mod_date=$(hdfs dfs -stat "%Y" ${dir})
    age_days=$(( ($(date +%s) - $(date -d "${mod_date}" +%s)) / 86400 ))
    if [ ${age_days} -gt 30 ]; then
        hdfs dfs -setrep 2 ${dir} >> ${LOG} 2>&1
    fi
done

# 3. 180일 이상 된 데이터 → Erasure Coding 디렉토리로 이동
echo "=== 아카이브 이동 ===" >> ${LOG}
hadoop distcp -skipcrccheck /data/processed/old/ /data/archive/ >> ${LOG} 2>&1

# 4. 용량 리포트
echo "=== 용량 현황 ===" >> ${LOG}
hdfs dfs -du -s -h /data/* >> ${LOG}

echo "[${DATE}] 데이터 수명주기 관리 완료" >> ${LOG}

3. YARN 큐 설계와 리소스 관리

3.1 Capacity Scheduler vs Fair Scheduler

항목Capacity SchedulerFair Scheduler
기본 제공Apache Hadoop 기본CDH 기본
리소스 보장큐별 최소 용량 보장가중치 기반 균등 분배
프리엠션지원지원
멀티테넌시강함 (계층형 큐)보통
설정 복잡도높음보통

권장: Hadoop 3.x에서는 Capacity Scheduler가 공식 기본값이며, 대규모 멀티테넌트 환경에 적합하다.

3.2 Capacity Scheduler 큐 설계

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

  <!-- 루트 큐 하위 구조 -->
  <property>
    <name>yarn.scheduler.capacity.root.queues</name>
    <value>production,development,system</value>
  </property>

  <!-- production 큐: 전체 리소스의 60% -->
  <property>
    <name>yarn.scheduler.capacity.root.production.capacity</name>
    <value>60</value>
  </property>
  <property>
    <name>yarn.scheduler.capacity.root.production.maximum-capacity</name>
    <value>80</value>
  </property>
  <property>
    <name>yarn.scheduler.capacity.root.production.queues</name>
    <value>etl,realtime</value>
  </property>

  <!-- production > etl 큐 -->
  <property>
    <name>yarn.scheduler.capacity.root.production.etl.capacity</name>
    <value>70</value>
  </property>
  <property>
    <name>yarn.scheduler.capacity.root.production.etl.maximum-capacity</name>
    <value>90</value>
  </property>
  <property>
    <name>yarn.scheduler.capacity.root.production.etl.user-limit-factor</name>
    <value>2</value>
  </property>

  <!-- production > realtime 큐 -->
  <property>
    <name>yarn.scheduler.capacity.root.production.realtime.capacity</name>
    <value>30</value>
  </property>
  <property>
    <name>yarn.scheduler.capacity.root.production.realtime.maximum-capacity</name>
    <value>50</value>
  </property>

  <!-- development 큐: 전체 리소스의 30% -->
  <property>
    <name>yarn.scheduler.capacity.root.development.capacity</name>
    <value>30</value>
  </property>
  <property>
    <name>yarn.scheduler.capacity.root.development.maximum-capacity</name>
    <value>50</value>
  </property>

  <!-- system 큐: 전체 리소스의 10% (모니터링, 유지보수) -->
  <property>
    <name>yarn.scheduler.capacity.root.system.capacity</name>
    <value>10</value>
  </property>
  <property>
    <name>yarn.scheduler.capacity.root.system.maximum-capacity</name>
    <value>20</value>
  </property>

</configuration>

큐 구조 다이어그램:

root (100%)
├── production (60%, max 80%)
│   ├── etl (70% of production, max 90%)
│   └── realtime (30% of production, max 50%)
├── development (30%, max 50%)
└── system (10%, max 20%)

3.3 프리엠션(Preemption) 설정

프리엠션은 큐가 보장된 리소스를 돌려받기 위해 다른 큐의 컨테이너를 강제 종료하는 메커니즘이다.

<!-- yarn-site.xml -->
<property>
  <name>yarn.resourcemanager.scheduler.monitor.enable</name>
  <value>true</value>
</property>
<property>
  <name>yarn.resourcemanager.scheduler.monitor.policies</name>
  <value>org.apache.hadoop.yarn.server.resourcemanager.monitor.capacity.ProportionalCapacityPreemptionPolicy</value>
</property>

<!-- 프리엠션 대기 시간: 15초 후 시작 -->
<property>
  <name>yarn.resourcemanager.monitor.capacity.preemption.monitoring_interval</name>
  <value>3000</value>
</property>
<property>
  <name>yarn.resourcemanager.monitor.capacity.preemption.max_wait_before_kill</name>
  <value>15000</value>
</property>

<!-- 한 번에 프리엠션할 수 있는 최대 비율 -->
<property>
  <name>yarn.resourcemanager.monitor.capacity.preemption.total_preemption_per_round</name>
  <value>0.1</value>
</property>

3.4 YARN 리소스 설정

<!-- yarn-site.xml: NodeManager 리소스 설정 -->
<property>
  <name>yarn.nodemanager.resource.memory-mb</name>
  <value>65536</value> <!-- 64GB (전체 메모리의 80% 정도) -->
</property>
<property>
  <name>yarn.nodemanager.resource.cpu-vcores</name>
  <value>24</value> <!-- 물리 코어 수의 1.5~2배 -->
</property>

<!-- 컨테이너 메모리 범위 -->
<property>
  <name>yarn.scheduler.minimum-allocation-mb</name>
  <value>1024</value>
</property>
<property>
  <name>yarn.scheduler.maximum-allocation-mb</name>
  <value>32768</value>
</property>

<!-- 컨테이너 vcore 범위 -->
<property>
  <name>yarn.scheduler.minimum-allocation-vcores</name>
  <value>1</value>
</property>
<property>
  <name>yarn.scheduler.maximum-allocation-vcores</name>
  <value>12</value>
</property>
# YARN 큐 상태 확인
yarn queue -status production

# 실행 중인 애플리케이션 확인
yarn application -list -appStates RUNNING

# 큐별 리소스 사용량 확인
yarn queue -status production.etl

# YARN 스케줄러 설정 리로드 (재시작 없이)
yarn rmadmin -refreshQueues

4. MapReduce 잡 튜닝

4.1 Mapper/Reducer 수 최적화

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

<!-- 매퍼 메모리: 기본 1GB이지만, 대용량 데이터에서는 2~4GB 권장 -->
<property>
  <name>mapreduce.map.memory.mb</name>
  <value>2048</value>
</property>
<property>
  <name>mapreduce.map.java.opts</name>
  <value>-Xmx1638m</value> <!-- memory.mb의 80% -->
</property>

<!-- 리듀서 메모리: 매퍼보다 크게 설정 (집계 연산이 많으므로) -->
<property>
  <name>mapreduce.reduce.memory.mb</name>
  <value>4096</value>
</property>
<property>
  <name>mapreduce.reduce.java.opts</name>
  <value>-Xmx3276m</value> <!-- memory.mb의 80% -->
</property>

<!-- 리듀서 수 명시 (데이터 크기에 따라 조정) -->
<property>
  <name>mapreduce.job.reduces</name>
  <value>100</value>
</property>

Mapper/Reducer 수 산정 공식:

매퍼 수 ≈ 입력 데이터 크기 / 블록 크기
  : 1TB 입력, 256MB 블록 → 약 4,000개 매퍼

리듀서 수 ≈ 0.95 × (클러스터 내 총 reduce 슬롯 수)
  또는 실측 기반으로 리듀서 하나당 처리량이 256MB~1GB가 되도록 조정

4.2 셔플(Shuffle) 최적화

셔플은 MapReduce에서 가장 비용이 큰 단계다. 네트워크 I/O와 디스크 I/O가 집중된다.

<!-- mapred-site.xml: 맵 측 정렬/스필 설정 -->
<property>
  <name>mapreduce.task.io.sort.mb</name>
  <value>512</value>
  <description>정렬 버퍼 크기. 기본 100MB → 512MB로 증가하면 스필 횟수 감소</description>
</property>
<property>
  <name>mapreduce.task.io.sort.factor</name>
  <value>100</value>
  <description>동시 머지 가능한 스트림 수. 기본 10 → 100으로 증가</description>
</property>
<property>
  <name>mapreduce.map.sort.spill.percent</name>
  <value>0.80</value>
  <description>정렬 버퍼가 80% 차면 스필 시작</description>
</property>

<!-- 리듀스 측 셔플 설정 -->
<property>
  <name>mapreduce.reduce.shuffle.parallelcopies</name>
  <value>20</value>
  <description>리듀서가 매퍼 출력을 가져오는 병렬 스레드 수</description>
</property>
<property>
  <name>mapreduce.reduce.shuffle.input.buffer.percent</name>
  <value>0.70</value>
  <description>셔플 입력에 할당할 힙 비율</description>
</property>
<property>
  <name>mapreduce.reduce.shuffle.merge.percent</name>
  <value>0.66</value>
  <description>인메모리 머지 시작 임계값</description>
</property>

4.3 데이터 스큐 처리

데이터 스큐(skew)는 특정 키에 데이터가 집중되어 일부 리듀서만 과부하가 걸리는 현상이다.

스큐 진단:

# 잡의 카운터에서 리듀서별 입력 레코드 수 편차 확인
yarn logs -applicationId application_1234567890_0001 | grep "Reduce input records"

# 잡 히스토리 서버에서 태스크별 실행 시간 확인
mapred job -history /path/to/job_history_file

스큐 해결 방법:

  1. 솔팅 키(Salting): 키에 랜덤 접두사를 붙여 분산
// 매퍼에서 키에 솔트 추가
int salt = random.nextInt(10);
outputKey.set(salt + "_" + originalKey);

// 첫 번째 MR: 솔트 키로 부분 집계
// 두 번째 MR: 솔트 제거 후 최종 집계
  1. Combiner 적용: 매퍼 출력을 로컬에서 미리 집계
job.setCombinerClass(MyCombiner.class);
  1. 파티셔너 커스터마이징: 데이터 분포를 고려한 파티셔닝
public class SkewAwarePartitioner extends Partitioner<Text, IntWritable> {
    @Override
    public int getPartition(Text key, IntWritable value, int numPartitions) {
        String k = key.toString();
        if (k.equals("HOT_KEY")) {
            // 핫 키는 여러 리듀서에 분산
            return (k.hashCode() + random.nextInt(10)) % numPartitions;
        }
        return (k.hashCode() & Integer.MAX_VALUE) % numPartitions;
    }
}

4.4 투기적 실행(Speculative Execution)

느린 태스크(straggler)를 감지하면 동일 태스크를 다른 노드에서 병렬 실행하여 먼저 완료되는 결과를 채택한다.

<!-- mapred-site.xml -->
<property>
  <name>mapreduce.map.speculative</name>
  <value>true</value>
</property>
<property>
  <name>mapreduce.reduce.speculative</name>
  <value>false</value>
  <description>리듀서는 데이터를 많이 소비하므로 투기적 실행 비활성화 권장</description>
</property>

주의: 외부 시스템에 쓰기를 수행하는 태스크(DB insert, API 호출 등)에서는 반드시 비활성화해야 한다. 중복 쓰기가 발생할 수 있다.

4.5 JVM 재사용

매 태스크마다 JVM을 새로 생성하면 오버헤드가 크다. 소형 태스크가 많을 때 효과적이다.

<!-- mapred-site.xml -->
<property>
  <name>mapreduce.job.jvm.numtasks</name>
  <value>10</value>
  <description>하나의 JVM에서 최대 10개 태스크 실행. -1이면 무제한.</description>
</property>

5. 클러스터 모니터링과 알림

5.1 주요 모니터링 메트릭

HDFS 핵심 메트릭:

메트릭정상 범위경고 임계값위험 임계값
DFS 사용률< 70%80%90%
언더 복제 블록0> 100> 1,000
누락 블록0> 0> 10
NN 힙 사용률< 70%80%90%
Dead DataNode 수0> 0> 2
NN RPC 평균 처리 시간< 10ms> 50ms> 200ms

YARN 핵심 메트릭:

메트릭정상 범위경고 임계값위험 임계값
클러스터 메모리 사용률< 80%85%95%
Pending 컨테이너 수< 50> 200> 1,000
Unhealthy 노드 수0> 0> 3
큐 대기 애플리케이션 수< 10> 50> 200

5.2 JMX를 통한 메트릭 수집

# NameNode JMX 메트릭 조회
curl -s http://namenode:9870/jmx | python3 -m json.tool | grep -A5 "CapacityUsed"

# ResourceManager JMX 메트릭 조회
curl -s http://resourcemanager:8088/jmx | python3 -m json.tool | grep -A5 "AllocatedMB"

# DataNode JMX 메트릭 조회
curl -s http://datanode:9864/jmx?qry=Hadoop:service=DataNode,name=FSDatasetState

5.3 Prometheus + Grafana 연동

# prometheus.yml - 하둡 JMX Exporter 설정
scrape_configs:
  - job_name: 'hadoop-namenode'
    scrape_interval: 30s
    static_configs:
      - targets: ['namenode1:7001', 'namenode2:7001']
        labels:
          cluster: 'production'
          component: 'namenode'

  - job_name: 'hadoop-datanode'
    scrape_interval: 30s
    static_configs:
      - targets: ['datanode1:7002', 'datanode2:7002', 'datanode3:7002']
        labels:
          cluster: 'production'
          component: 'datanode'

  - job_name: 'hadoop-resourcemanager'
    scrape_interval: 30s
    static_configs:
      - targets: ['resourcemanager:7003']
        labels:
          cluster: 'production'
          component: 'resourcemanager'

  - job_name: 'hadoop-nodemanager'
    scrape_interval: 30s
    static_configs:
      - targets: ['datanode1:7004', 'datanode2:7004', 'datanode3:7004']
        labels:
          cluster: 'production'
          component: 'nodemanager'

JMX Exporter 실행 설정 (hadoop-env.sh):

# hadoop-env.sh
export HDFS_NAMENODE_OPTS="$HDFS_NAMENODE_OPTS -javaagent:/opt/jmx_exporter/jmx_prometheus_javaagent.jar=7001:/opt/jmx_exporter/namenode.yml"
export HDFS_DATANODE_OPTS="$HDFS_DATANODE_OPTS -javaagent:/opt/jmx_exporter/jmx_prometheus_javaagent.jar=7002:/opt/jmx_exporter/datanode.yml"
export YARN_RESOURCEMANAGER_OPTS="$YARN_RESOURCEMANAGER_OPTS -javaagent:/opt/jmx_exporter/jmx_prometheus_javaagent.jar=7003:/opt/jmx_exporter/resourcemanager.yml"
export YARN_NODEMANAGER_OPTS="$YARN_NODEMANAGER_OPTS -javaagent:/opt/jmx_exporter/jmx_prometheus_javaagent.jar=7004:/opt/jmx_exporter/nodemanager.yml"

5.4 Grafana 알림 규칙 예시

# Grafana Alert Rules (Alerting YAML)
groups:
  - name: hadoop_alerts
    rules:
      - alert: HDFSCapacityCritical
        expr: hadoop_namenode_capacity_used_gb / hadoop_namenode_capacity_total_gb > 0.9
        for: 10m
        labels:
          severity: critical
        annotations:
          summary: 'HDFS 용량 90% 초과'
          description: 'HDFS 사용률이 {{ $value | humanizePercentage }}입니다. 즉시 데이터 정리 또는 노드 추가 필요.'

      - alert: HDFSMissingBlocks
        expr: hadoop_namenode_missing_blocks > 0
        for: 5m
        labels:
          severity: critical
        annotations:
          summary: 'HDFS 누락 블록 발생'
          description: '{{ $value }}개의 블록이 누락되었습니다.'

      - alert: YARNUnhealthyNodes
        expr: hadoop_resourcemanager_unhealthy_nodes > 0
        for: 5m
        labels:
          severity: warning
        annotations:
          summary: 'YARN Unhealthy 노드 발생'
          description: '{{ $value }}개의 노드가 unhealthy 상태입니다.'

      - alert: YARNMemoryPressure
        expr: hadoop_resourcemanager_allocated_mb / hadoop_resourcemanager_available_mb > 0.95
        for: 15m
        labels:
          severity: warning
        annotations:
          summary: 'YARN 메모리 리소스 부족'
          description: '클러스터 메모리 사용률이 95%를 초과했습니다.'

5.5 Ambari / Cloudera Manager 활용

전용 관리 도구를 사용하면 설정 관리, 모니터링, 알림을 통합적으로 처리할 수 있다.

기능Ambari (Apache)Cloudera Manager
설정 관리UI 기반, 버전 이력UI 기반, 롤백 지원
모니터링내장 대시보드내장 + Grafana 연동
알림SMTP, SNMPSMTP, SNMP, Webhook
서비스 관리개별 서비스 제어롤링 재시작 지원
라이선스Apache (무료)상용 (CDP)

6. 장애 대응 가이드

6.1 DataNode 장애

증상: DataNode 프로세스 다운, 네트워크 단절, 디스크 장애

# 1단계: Dead DataNode 확인
hdfs dfsadmin -report | grep -A3 "Dead datanodes"

# 2단계: 해당 DataNode 로그 확인
tail -500 /var/log/hadoop/hdfs/hadoop-hdfs-datanode-*.log | grep -E "ERROR|WARN|FATAL"

# 3단계: 디스크 상태 확인
df -h  # 디스크 용량
smartctl -a /dev/sda  # 디스크 건강 상태
dmesg | grep -i "error\|fail\|i/o"  # 커널 로그에서 디스크 오류 확인

# 4단계: DataNode 재시작 또는 제거
# 재시작 가능한 경우:
hdfs --daemon start datanode

# 제거해야 하는 경우 (Decommission):
# 1) dfs.hosts.exclude에 노드 추가
# 2) 설정 리프레시
hdfs dfsadmin -refreshNodes
# 3) 데이터 마이그레이션 진행 상황 모니터링
hdfs dfsadmin -report | grep "Decommission Status"

DataNode Decommission 설정:

<!-- hdfs-site.xml -->
<property>
  <name>dfs.hosts.exclude</name>
  <value>/etc/hadoop/conf/dfs.exclude</value>
</property>
# /etc/hadoop/conf/dfs.exclude
datanode-bad-01.example.com
datanode-bad-02.example.com

6.2 NameNode Failover

HA 환경에서 Active NameNode 장애 시 자동 Failover가 동작해야 한다.

# NameNode 상태 확인
hdfs haadmin -getAllServiceState
# 출력 예:
# nn1    active
# nn2    standby

# 수동 Failover (긴급 시)
hdfs haadmin -failover nn1 nn2

# ZKFC 프로세스 확인 (자동 Failover의 핵심)
jps | grep DFSZKFailoverController

# ZooKeeper 세션 상태 확인
echo "stat" | nc zookeeper1 2181

# Failover가 안 될 때: ZKFC 재시작
hdfs --daemon stop zkfc
hdfs --daemon start zkfc

자동 Failover 설정:

<!-- hdfs-site.xml -->
<property>
  <name>dfs.ha.automatic-failover.enabled</name>
  <value>true</value>
</property>

<!-- core-site.xml -->
<property>
  <name>ha.zookeeper.quorum</name>
  <value>zk1.example.com:2181,zk2.example.com:2181,zk3.example.com:2181</value>
</property>

6.3 디스크 장애 대응

DataNode에서 특정 디스크가 장애를 일으켰을 때, 전체 DataNode를 내리지 않고 해당 디스크만 제외할 수 있다.

<!-- hdfs-site.xml: 디스크 장애 허용 설정 -->
<property>
  <name>dfs.datanode.failed.volumes.tolerated</name>
  <value>2</value>
  <description>최대 2개 볼륨 장애까지 DataNode 유지. 전체 볼륨 수의 1/3 이하 권장.</description>
</property>
# 디스크 교체 절차
# 1. 장애 디스크 확인
hdfs dfsadmin -getDatanodeInfo datanode01:9866

# 2. 해당 볼륨을 dfs.datanode.data.dir에서 제거
# 3. DataNode 재시작 (Hadoop 3.x에서는 리컨피그 가능)
hdfs dfsadmin -reconfig datanode datanode01:9866 start

# 4. 리컨피그 상태 확인
hdfs dfsadmin -reconfig datanode datanode01:9866 status

# 5. 새 디스크 마운트 후 data.dir에 추가, 다시 리컨피그

6.4 YARN ResourceManager 장애

# RM HA 상태 확인
yarn rmadmin -getAllServiceState

# RM 수동 전환
yarn rmadmin -transitionToActive rm2

# NodeManager가 RM에 연결 못하는 경우
# NM 로그 확인
tail -200 /var/log/hadoop/yarn/hadoop-yarn-nodemanager-*.log | grep "ERROR"

# NM 재시작
yarn --daemon stop nodemanager
yarn --daemon start nodemanager

7. 운영 체크리스트

7.1 일간 체크리스트

#!/bin/bash
# daily_health_check.sh

echo "========== HDFS 일간 점검 =========="
# HDFS 상태 요약
hdfs dfsadmin -report | head -20

# 누락/복제부족 블록 확인
hdfs fsck / -list-corruptfileblocks

# NameNode 세이프모드 확인
hdfs dfsadmin -safemode get

echo "========== YARN 일간 점검 =========="
# YARN 노드 상태
yarn node -list -all | head -20

# 실패한 애플리케이션 확인 (최근 24시간)
yarn application -list -appStates FAILED

# 큐 사용 현황
yarn queue -status root

echo "========== 시스템 점검 =========="
# 디스크 사용량
df -h | grep -E "/data|/hdfs"

# 메모리/CPU
free -g
uptime

7.2 주간 체크리스트

항목커맨드/행동기준
HDFS fsck 전체 실행hdfs fsck / -files -blocksCorrupt 블록 0
Balancer 실행hdfs balancer -threshold 5노드 간 편차 < 5%
YARN 로그 정리yarn logs -applicationId ... -am30일 이상 로그 삭제
GC 로그 분석NN/RM GC 로그 검토Full GC < 5회/일
디스크 SMART 점검smartctl -a /dev/sd*오류 0

7.3 월간 체크리스트

항목설명
용량 추세 분석월별 HDFS 사용량 증가율 계산, 3개월 후 용량 예측
큐 리소스 재조정팀별 실제 사용량 기반으로 capacity 재설정
성능 베이스라인 갱신주요 ETL 잡 실행 시간 트렌드 확인
보안 감사접근 권한, 서비스 계정 점검
하둡 버전/패치 검토보안 패치, 버그 수정 적용 여부

7.4 용량 계획 스프레드시트

현재 클러스터 상태:
-DataNode: N
- 노드당 디스크: 12 × 4TB HDD = 48TB
- 총 원시 용량: N × 48TB
- HDFS 사용 가능 용량 (복제 팩터 3 기준): N × 48TB / 3 = N × 16TB
- 현재 HDFS 사용량: X TB
- 사용률: X / (N × 16) × 100 = Y%

월별 증가량: Z TB/month

노드 추가 시점 계산:
- 안전 임계값: 80%
- 여유 용량: (N × 16 × 0.8) - X = W TB
- 현재 증가 속도로 W / Z = M개월 후 80% 도달
- 노드 주문 리드타임 고려 → M - 2개월 전에 주문 필요

8. 마무리

하둡 클러스터 운영은 초기 구축보다 지속적인 관리와 튜닝에 더 많은 노력이 필요하다. 이 글에서 다룬 핵심 사항을 정리하면 다음과 같다.

HDFS: 블록 크기와 복제 팩터를 데이터 특성에 맞게 설정하고, NameNode 힙 관리와 Balancer 실행을 정기 루틴으로 확립한다. Erasure Coding과 Tiered Storage를 활용해 스토리지 비용을 최적화한다.

YARN: Capacity Scheduler 기반의 계층형 큐를 설계하고, 프리엠션 정책을 활성화하여 리소스 공정성을 보장한다. 큐 capacity는 실제 사용 패턴에 맞춰 주기적으로 재조정한다.

MapReduce: 셔플 최적화(정렬 버퍼, 스필 임계값)와 데이터 스큐 처리가 잡 성능의 핵심이다. JVM 재사용과 투기적 실행을 상황에 맞게 설정한다.

모니터링: JMX + Prometheus + Grafana 파이프라인을 구축하고, HDFS 용량/블록 상태, YARN 리소스/큐 상태에 대한 알림을 설정한다.

장애 대응: NameNode HA, DataNode Decommission, 디스크 핫스왑 절차를 사전에 문서화하고 훈련한다.

운영 체크리스트를 일간/주간/월간으로 나눠 실행하고, 용량 계획을 데이터 기반으로 수립하면 대부분의 운영 이슈를 선제적으로 방지할 수 있다.