[HDFS란 무엇인가]
HDFS는 하둡 분산 파일 시스템으로, 클러스터 환경에서의 작동을 전제로 설계되었다. NameNode라고 하는 마스터 노드와 DataNode라고 하는 복수의 워커 노드로 구성된다.
NameNode: HDFS의 마스터 노드에 해당한다. HDFS상에 보존되는 파일의 메타데이터와 보존된 파일의 분할된 조각(블록)이 어떤 DataNode에서 관리되는지 등의 정보를 관리한다.
DataNode: HDFS의 워커 노드를 말한다. HDFS상에 보존된 파일의 블록을 관리한다.
HDFS는 슬레이브 노드인 DataNode를 추가함으로써 I/O처리량과 저장 용량을 스케일아웃할 수 있다. 또 블록을 기본 3개의 DataNode에 replica하여 보존함으로써, 일부 슬레이브 노드가 고장을 일으키더라도 데이터 손실이 없도록 설계되었다.
[YARN이란 무엇인가]
YARN은 하둡의 클러스터 관리 시스템으로, 스파크를 비롯한 각종 분산처리 프레임워크로 개발한 애플리케이션이 작동하는 환경을 제공/관리하는 기반이다. YARN은 Resource Manager라고 불리는 마스터 노드와 NodeManager라고 하는 여러 개의 워커 노드로 구성된다.
ResourceManager: 클러스터 전체의 계산 리소스를 관리하고, 클라이언트가 요구한 리소스를 NodeManager로부터 확보하도록 스케줄링한다. 스파크에서의 ResourceManager는 요청된 executor 갯수와 CPU 코어의 수, 메모리 양에 따라 executor를 하나 이상의 NodeManager로부터 확보하는 역할을 담당한다.
NodeManager: 클러스터 전체의 계산 리소스를 관리하는 ResourceManager와는 달리, 자신이 설치된 머신(노드)의 계산 리소스만을 관리한다. ResourceManager로부터 받은 요청에 따라, 필요한 계산 리소스를 확보한 '컨테이너'라는 애플리케이션의 실행 환경을 제공한다. 요청된 컨테이너의 개수에 따라서 복수의 NodeManager로부터 컨테이너를 확보해 분산 처리한다. 스파크의 경우 executor가 NodeManager로부터 확보된 컨테이너 상에서 작동하는 것이다.
[HDFS와 YARN의 환경 설정과 동작 확인]
/etc/hadoop/conf에 있는 core-site.xml, hdfs-site.xml, yarn-site.xml을 각각 root 권한으로 다음과 같이 편집한다.
core-site.xml
fs.defaultFS: 이용할 분산 파일시스템을 지정한다. HDFS라면 hdfs://<NameNode의 URL>:<포트>와 같은 형식으로 값을 지정한다.
hadoop.tmp.dir: HDFS와 YARN에서 이용하는 임시 디렉터리를 지정한다.
hdfs-site.xml
dfs.namenode.name.dir: NameNode가 HDFS상 파일의 메타데이터를 보존하는 데렉터리를 지정한다.
dfs.datanode.data.dir: DataNode가 블록을 보존하는 디렉터리를 지정한다. 모든 DataNode의 이 디렉터리 용량의 합을 3으로 나눈 값이 HDFS에 저장 가능한 데이터의 용량이 된다(블록의 레플리카를 3으로 했을 경우)
yarn-site.xml
yarn.resourcemanger.hostname: ResourceManager가 동작하는 머신의 호스트명을 설정한다.
yarn.nodemanager.log-dirs: 컨테이너가 출력하는 로그의 디렉터리를 지정한다. 스파크에서는 executor와 드라이버의 로그가 출력된다.
yarn.nodemanager.local-dirs: NodeManager가 이용하는 로컬디스크이 경로를 지정한다.
스파크 애플리케이션은 jar 파일로 패키징해야한다. 스파크 애플리케이션 디렉터리 일반적인 구조는 아래와 같다.
src/main/scala : 스칼라로 만든 프로그램(소스코드) 보관
src/test/scala: 스칼라로 만든 테스트 프로그램(소스코드) 보관
다음은 샘플 애플리케이션이다. 주어진 텍스트 파일에 포함되는 yyyyMMdd 형식의 날짜로부터 무슨 요일인지를 판단하고, 그중 일요일이 몇번 등장하는지 세는 애플리케이션(SundayCount)이다. 이때 텍스트 파일에는 복수의 줄이 존재하고, 각 줄에는 날짜가 하나씩 기록되어 있다고 하자.
package com.example.chapter4 import org.joda.time.{DateTime, DateTimeConstants} import org.joda.time.format.DateTimeFormat import org.apache.spark.{Sparkconf, SparkContext} object SundayCount { def main(args: Array[String]) { if (args.length < 1) { throw new IllegalArgumentException("명령 인수에 날짜가 기록된 파일의 경로를 지정해주세요.") } val filePath = args(0) val conf = new SparkConf val sc = new Sparkcontext(conf) try { // 텍스트 파일을 로드한다. val textRDD = sc.textFile(filePath) // 문자열로 표현된 날짜로부터 DateTime형 인스턴스를 생성한다. val dateTimeRDD = textRDD.map { date => val pattern = DateTimeFormat.forPattern("yyyyMMdd") DateTime.parse(dateStr, pattern) } // 일요일만 추출한다. val sundayRDD = dateTimeRDD.filter { dateTime => dateTime.getDayOfWeek == DateTimeConstants.SUNDAY } // sundayRDD에 들어있는 일요일 갯수를 센다. val numOfSunday = sundayRDD.count println(s"주어진 데이터에는 일요일이 ${numOfSunday}개가 들어 있습니다.") } finally { sc.stop() } } }
[스파크 애플리케이션 실행하기]
스파크 애플리케이션을 실행할 때는 spark-submit 명령을 이용하는데, 그 형식은 다음과 같다.
$ ${SPARK_HOME}/bin/spark-submit \
--master <동작 모드> \
--class <main 메서드가 구현된 애플리케이션의 클래스> \
--name <애플리케이션 이름> \
<spark-submit 명령의 옵션> \
애플리케이션의 클래스가 포함된 JAR 파일 \
<애플리케이션에 넘기는 옵션>
스파크 애플리케이션을 실행할 때 동작 모드라는 옵션을 선택할 수 있다.
1. local 모드
local 모드란 spark-submit 명령을 실행한 클라이언트상에서 프로세스를 구동하고, 해당 프로세스 안에서 executor를 구동하여 애플리케이션을 실행하는 동작 모드를 말한다. 단일 머신 환경을 구축할 경우는 local모드로 스파크 애플리케이션을 실행한다.
local 모드로 스파크 애플리케이션을 실행할 경우 spark-submit 명령의 --master 옵션에 다음중 하나를 선택하여 지정한다. 차이점은 클라이언트의 프로세스에서 구동되는 executor에 할당하는 스레드 수가 다르다는 점이다.
local: executor에 한 개의 스레드만을 할당한다.
local[*]: 클라이언트 머신에 탑재된 CPU의 코어 수만큼 executor에 스레드를 할당한다.
local[<스레드개수>]: executor에 지정된 수만큼의 스레드를 할당한다.
${SPARK_HOME}/bin/spark-submit \
--master local \
--class com.example.chapter4.SundayCount \
--name Sundaycount \
~/spark-simple-app/target/scala-2.10/spark-simple-app.assembly-0.1.jar \
/path/to/data.txt
2. yarn-client 모드 / yarn-cluster 모드
yarn-client 모드와 yarn-cluster 모드는 YARN이 관리하는 클러스터상에서 애플리케이션을 실행하는 모드를 말한다. 클러스터의 노드 매니저상에서 executor가 동작하고, 각 executor가 분산처리를 시행한다.
yarn-cluster 모드는 드라이버 프로그램이 클러스터의 NodeManager상에서 동작하므로 클러스터 전체의 계산 리소스를 이용할 수 있고 오류 처리도 YARN에 위임할 수 있다.
클러스터 환경을 구축한 경우, 간단한 동작 확인을 위해 매번 클러스터상에서 애플리케이션을 실행하기 번거로울 수 있다. 클러스터 환경을 구축했더라도 HDFS를 이용하지 않고 local 모드로 애플리케이션을 실행할 수 있다. ${SPARK_HOME}/conf/spark-env.sh에 정의된 변수 HADOOP_CONF_DIR의 선두에 #을 추가하여 코멘트아웃한다. 이 수정으로 데이터소스의 파일시스템으로 HDFS가 아닌 로컬 파일시스템을 이용하게 된다. 이 상태에서 spark-submit 명령의 --master 옵션에 local을 지정하면, 단일 머신 환경과 마찬가지로 클라이언트상에서 애플리케이션을 움직일 수 있다.
'프로그래밍(TA, AA) > JVM 언어' 카테고리의 다른 글
[SPARK] 스파크 실행 구조 (1) | 2018.10.19 |
---|---|
[SPARK] 스파크의 직렬화 (0) | 2018.10.19 |
[SPARK] 스파크의 처리 모델 RDD (0) | 2018.10.09 |
[SPARK] 아파치 스파크란? (0) | 2018.10.08 |
[SPARK] 스파크 주요 키워드 (1) | 2018.10.06 |