SET-UP
1 도식화 – 클러스터 전체 구조 & 데이터 흐름
요소 설명
분류 | 구성요소 | 컨테이너? | 주 역할 |
HDFS | NN | 메타데이터(블록 목록·파일 권한) 관리 | |
DN | 실제 HDFS 블록을 로컬 SSD( /data/hdfs-data )에 저장 | ||
YARN | RM | 클러스터 자원 총괄·스케줄링, ApplicationMaster 컨테이너 생성 | |
NM | 개별 노드의 컨테이너 실행·모니터링 | ||
Spark (YARN-client/cluster) | AM | YARN이 띄우는 컨테이너 | 드라이버 기능, executor 요청 |
Executor | YARN이 NM에 띄움 | 태스크 수행, RDD 캐시 / HDFS I/O |
2 데이터 흐름 (NFS → Spark → NFS)
1.
원본 데이터 : /cl_data/... 또는 /lab-exaone/...
─ 모든 노드에서 동일 NFS 경로로 “읽기 전용” 접근.
2.
(선택) 사전 적재
•
대용량이면 hdfs dfs -put 으로 단 한 번 NN·DN 블록 공간으로 복사.
•
이후 Spark Job은 DataNode 로컬 SSD에서 병렬 로컬 읽기 → 네트워크 부하 감소.
3.
Spark Job 실행
•
spark-submit --master yarn
•
RM → AM → Executor 컨테이너.
•
Executor 는 필요한 블록을 DN에서 가져와 메모리/디스크에 캐시하며 계산.
4.
결과 저장
•
DataFrame.write.parquet("hdfs:///result/...") 또는 file:///cl_data/...
•
HDFS쓰기 시 DN 블록 → NN 메타 업데이트.
•
작업 종료 뒤 결과를 hdfs dfs -get 하여 다시 NFS로 복사하거나, Spark에서 직접 NFS 경로로 저장 가능(소규모 I/O인 경우).
3 마운트 설계 – NFS vs 로컬 SSD
경로 | 호스트 위치 | 컨테이너 mount 지점 | 이유 |
공유 설정 | /cl_data/.../shared/config/hadoop | /opt/hadoop/etc/hadoop (RO) | 모든 컨테이너가 동일 Hadoop 설정 사용 |
NameNode 메타 | /data/hdfs-name (마스터 로컬 SSD) | /hadoop/dfs/name | NN 저널은 로컬 IOPS 필요, NFS 사용 |
DataNode 블록 | /data/hdfs-data (각 워커 SSD) | /hadoop/dfs/data | 블록 I/O 병렬화·성능 보장 |
YARN scratch | /data/yarn-local (워커 SSD) | /var/yarn/local | 셔플·임시 파일, NFS 느림 |
Logs | /data/hadoop-logs (각 노드) | /opt/hadoop/logs | 데몬 로그 보존 및 디스크 경합 차단 |
NFS 원본/결과 | /cl_data/... | file:///... 직접 또는 hdfs dfs -put | 데이터 교환·백업 용도 |
4 스크립트 핵심 변수 & 보안 옵션 설명
4-1 스크립트 변수
변수 | 내용 |
JOB_ID | 클러스터 인스턴스 식별용 태그 |
IMAGE | spark-yarn:latest – 수정된 Docker 이미지 |
DOCKER_COMMON | AppArmor label disable + 기본 프로필 유지 |
MASTER_EXTRA | CHOWN,FOWNER cap → NN/RM 가 로그·PID 파일 소유권 변경 가능 |
NM_EXTRA | SYS_ADMIN cap + /sys/fs/cgroup RW mount → Container CGroup 제어 |
NAME_DIR … | 앞 표 참고 |
4-2 보안 (flag) 상세
옵션 | 커널 Cap / Seccomp | 사용 목적 |
--security-opt label=disable | SELinux/AppArmor 라벨링 해제 | NFS mounted volume 권한 충돌 방지 |
--security-opt apparmor=unconfined | AppArmor 프로필 해제 | 하둡 데몬이 mmap, ptrace 등 제한될 위험 해소 |
--cap-add=SYS_ADMIN (NM만) | CGroup 마운트/제어, mount() 시 필요 | YARN NodeManager가 컨테이너 리소스 격리 |
--cap-add=CHOWN --cap-add=FOWNER (Master) | 파일 owner 변경·소유 파일 override | NN/RM가 로그·PID 디렉토리 퍼미션 수정 |
5 Trial & Error 요약 (설정 변경 일지)
단계 | 문제 & 증상 | 조치 |
① 로그 디렉토리 write Error | Unable to write in /opt/hadoop/logs | Dockerfile USER root 수정 + /data/hadoop-logs 퍼미션 777 |
② 컨테이너 재시작 루프 | Queue configuration missing child queue names for root | capacity-scheduler.xml 추가 – root.default 큐 정의 |
③ RM UI 접속 안 됨 | 방화벽/내부망 | SSH 포트포워딩 -L 9870,8088 활용 |
④ DN 컨테이너 exit (퍼미션) | /data/hdfs-data root only | 각 워커에서 sudo chmod 777 /data/hdfs-data |
6 실전 운영 체크리스트
1.
정지/정리 : Ctrl-C → trap cleanup() → 모든 컨테이너 종료
2.
로그 보존 : 필요 시 DEBUG=1 환경으로 실행
3.
스케일-아웃 : WORKERS=(cluster-data-{01..16}) 배열만 수정
4.
큐 분리 : capacity-scheduler.xml root.queues = analytics,etl 등 확장
5.
보안강화 :
•
AppArmor 프로필 작성 후 -security-opt apparmor=<profile>
•
cap-drop=ALL + 필요한 cap만 cap-add
•
컨테이너‐전용 UID (useradd -s /bin/false spark) 사용
NFS > HDFS
############################ 7. 상태 체크 ####################################
echo "=== Cluster Status ==="
docker exec "namenode_${JOB_ID}" hdfs dfsadmin -report | grep 'Live datanodes' || true
docker exec "resourcemanager_${JOB_ID}" yarn node -list || true
echo "NameNode UI → http://cluster-data-master01:9870"
echo "RM UI → http://cluster-data-master01:8088"
if [ "$DEBUG" -eq 1 ]; then
echo "[DEBUG] 컨테이너·로그 보존. 수동 종료 후 정리 필요."
else
echo "Ctrl-C 로 중단 시 자동 cleanup"
fi
############################ 8. HDFS 데이터 업로드 ############################
echo "[HDFS] /cl_data/joonwon.jang/data/*.jsonl → /input/ 으로 업로드"
docker exec "resourcemanager_${JOB_ID}" bash -c "
hdfs dfs -mkdir -p /input
hdfs dfs -put -f /cl_data/joonwon.jang/data/*.jsonl /input/
"
echo "[HDFS] 업로드 완료 → hdfs dfs -ls /input"
docker exec "resourcemanager_${JOB_ID}" hdfs dfs -ls /input
############################ 9. 유지 루프 ####################################
while true; do
sleep 300
echo \"\$(date): Cluster $JOB_ID alive …\"
done
Python
복사
HDFS 구조 이해
구성요소 | 설명 | 현재 컨테이너 |
NameNode (NN) | HDFS 메타데이터 (파일 이름, 블록 위치 등) 관리 | namenode_<job_id> (마스터 노드) |
DataNode (DN) | 실제 블록 데이터를 저장 (파일 내용을 나눠 저장) | datanode_<job_id>_<hostname> (워커 노드 각각) |
ResourceManager (RM) | Spark/YARN Job 스케줄링 담당 | resourcemanager_<job_id> (마스터 노드) |
NodeManager (NM) | Executor/Container 실행 및 자원 할당 | 워커 노드 컨테이너 |
왜 hdfs dfs -put 명령은 마스터 노드(RM 컨테이너)에서 실행하는가?
•
hdfs dfs 명령은 "클라이언트" 입장입니다.
•
클라이언트는 HDFS 클러스터에게 요청: "이 파일을 HDFS에 저장해줘!"
•
실제 파일을 저장하는 건 DataNode 컨테이너들입니다.
•
hdfs dfs -put은 클라이언트가 파일을 NameNode에게 알려주고 → NameNode가 “이 블록은 DN1, DN2에 분산 저장하라”고 지시합니다.
RM 컨테이너에서 put 해도, 실제 파일은 워커 노드 컨테이너들에 분산 저장됩니다.
구성 요소 | 포트 | 역할 | 현재 스크립트에서 사용 여부 |
HDFS – NameNode Web UI | 9870 | 웹 대시보드 (http://NN:9870) | |
HDFS – NameNode RPC | 8020 | 클라이언트 / DN RPC | |
HDFS – DataNode Web UI | 9864 | DN 웹 UI | |
YARN – ResourceManager Web UI | 8088 | 웹 대시보드 (http://RM:8088) | |
YARN – RM scheduler IPC | 8030 | AM → RM 등록 | |
YARN – RM AM resource-tracker | 8031 | AM → RM status | |
YARN – RM client | 8032 | yarn node -list 실행 시 사용 | |
YARN – NodeManager Web UI | 8042 | executor 상태 확인 | |
Spark Driver (optional) | 4040 | Spark UI | |
Shuffle / History Server | 18080 등 | 필요 시 추가 |