MJay

Scale-up 서버에서의 도커 컨테이너를 이용한 아파치 스파크 시스템 확장성 개선 본문

Cloud Computing/Paper

Scale-up 서버에서의 도커 컨테이너를 이용한 아파치 스파크 시스템 확장성 개선

MJSon 2017. 6. 5. 00:16
요 약

기존의 빅데이터(BigData) 플랫폼에서는 분산 처리 환경(scale-out)을 기반으로 한 하둡(Hadoop)과 스파크(Spark)와 같은 분산 처리 프레임워크가 많이 사용되어 왔다. 

하지만 최근 기술이 발달하여 매니코어(Many-core) 기술과 같은 고성능 컴퓨팅 서버가 보편화됨에 따라 여러 대의 서버로 구성된 분산 처리 환경 대신 한 대의 고성능 컴퓨터 환경(scale-up)에서 분산 처리 프레임워크를 구축하여 빅데이터를 처리하는 시도가 가능해졌다. 

따라서 이러한 방법이 현실화되기 위해서는 코어 수 증가에 따른 성능 확장 (scalability)이 확보되어야 한다.


 본 논문에서는 하둡 파일 시스템(HDFS)과 아파치 스파크(Apache Spark) 시스템을 120 코어로 구성된 단일 scale-up 서버에 구성하고, 스파크 성능을 측정하는 벤치마크의 워크로드 4가지로 코어수를 바꿔가며 성능을 측정하였다. 

코어 수가 늘어남에 따라 성능이 더 잘나오는 것을 기대했지만, 일정 코어수가 늘어나자 성능이 점점 떨어지는 확장성 문제를 발견하였다.

 확장성 문제의 원인으로는 스파크가 사용하는 자바 가상 머신의 GC(Garbage Collection)에 의한 오버헤드, scale-up 서버의 NUMA(Non Un
-iform Memory Access) 메모리 구조에 따른 메모리 접근 지연(Memory Access Latency) 시간 문제, 공유 메모리 시스템(Shared Memory System)의 환경 때문에 발생하는 확장성 저해 요소가 있음을 분석하였다. 

이러한 확장성 문제를 해결하기 위해 리눅스의 도커 컨테이너를 이용하여 scale-up 서버를 파티셔닝(partitioning)하여 하나의 서버를 분산 시스템(Distributed System)처럼 구성하는 방법을 제안하였다.


 본 논문에서는 시스템의 효율적인 파티셔닝을 결정해주는 도커(Docker) 컨테이너(Container) 기반 프레임워크(Decision Engine)의 디자인을 제안하며, 파티셔닝 기법의 가능성을 확인하기 위해 15코어 또는 30코어 단위로 여러 개의 컨테이너를 설정하여 파티셔닝을 수동으로 수행했을 때의 성능을 측정하였다. 


그 결과 4개의 스파크 벤치마크 워크로드에 대해 파티셔닝을 하기 전보다 확장성이 개선된 것을 확인하였다. 






서론


오늘날 컴퓨터 기술과 인터넷 통신의 발달로 인해 자연스럽게 데이터량이 방대해졌다


이러한 데이터는 얼마나 큰지, 얼마나 빨리 생성되는지, 구조화/비구조화 데이터인지 등을 고려해 빅데이터라고 한다


현대에서는 빅데이터를 이용해 새로운 가치를 만들 있기 때문에 중요해지고 있다.


 빅데이터를 관리하고 처리하는 대표적 오픈소스는 하둡이다. 하둡은 많은 양의 데이터를 비교적 쉽게 처리할 있는 자바 소프트웨어 프레임워크로 분산 파일 시스템인 하둡 파일 시스템[11] 분산 처리 시스템인 맵리듀스(MapReduce)[1] 구성되어 있다


그러나 맵리듀스는 데이터 처리를 디스크를 사용하여 느리다는 단점이 있다


단점을 보완하기 위해 아파치 스파크가 제안되었다


스파크는 맵리듀스와 같은 분산 처리 시스템으로 데이터 처리를 디스크가 아닌 메모리를 사용하기 때문에 맵리듀스보다 빠르다는 장점 있다


또한 하나의 플랫폼에서 맵리듀스, 실시간 데이터(Streaming), SQL 기반의 데이터 쿼리, 머신 러닝(Machine Learning) 다양한 라이브러리를 지원한다.


 스파크가 사용되는 환경은 하둡과 마찬가지로 많은 컴퓨터가 네트워크로 연결되어 있는 분산 처리 환경인 scale-out 환경에서 많이 쓰이고 있다


그러나 최근 코어수가 증가됨에 따라 컴퓨터 자원이 풍부한 고성능 컴퓨터 환경인 scale-up 환경에서도 스파크 시스템의 성능에 대한 연구가 필요해지고 있다


이유는 코어 수가 많은 고성능의 컴퓨터가 보편화되기 시작한다면 코어 수가 적은 서버를 여러 대를 구성해서 데이터를 처리하는 것보다 고성능 컴퓨터 대를 두고 처리하는 [6] 효율적일 있다


하지만 아직까지는 스파크가 scale-up 환경을 고려하지 않기 때문에 성능에 대한 확장성에 문제가 있다.


 scale-up 서버에서 스파크 확장성에 가장 많은 영향을 미치는 요소는 자바 가상 머신의 GC NUMA 메모리 구조[15] 의한 메모리 접근 시간이다

이러한 문제를 해결하기 위해 리눅스의 도커[16] 컨테이너를 이용해 하나의 scale-up 서버를 파티셔닝하는 방법을 제안한다

방법은 코어와 메모리를 여러 개의 컨테이너로 나누어 데이터 처리를 하여 확장성 문제를 해결 있다.


  논문은 도커 컨테이너를 이용해 서버를 파티셔닝 시스템 환경에 따라 효율적인 코어 수를 결정하는 프레임워크 디자인을 제안하며, 파티셔닝 했을 때의 성능을 측정하기 위해 120코어의 scale-up 서버를 15코어씩 8 컨테이너, 30코어씩 4 컨테이너 설정하여 측정하였다.


  결과 공유 메모리 시스템을 분산 시스템처럼 구성하였고, 스파크 벤치마크인 4개의 워크로드(WordCount, Grep, Naive Bayes, K-means)에서 적용한 결과, 파티셔닝 하지 않았을 때보다 120코어에서 확장성을 가지며 처리량이 각각 최대 1.6, 1.5, 1.7, 1.1 향상되었다






관련 연구


 제 2장에서는 scale-out과 scale-up 용어에 대해 설명하고, scale-up 서버에서의 분산 처리 시스템에 관한 기존의 관련 연구에 대해 설명한다.




 그림 1.은 scale-out과 scale-up의 차이점을 표현한 것이다. scale-out 서버는 서버 자체의 성능을 높이기보다 서버의 수를 증가시켜 처리능력을 향상시키는 방식이다. 


scale-up 서버는 반대로 CPU, 메모리, 디스크 등의 하드웨어 성능을 높여 처리능력을 향상시키는 방식이다. s

cale-out과 scale-up 상황에 따라 적합한 경우가 다른데, scale-out은 각각의 처리는 비교적 단순하고 병렬처리를 해야 하는 경우에 적합하고 scale-up은 높은 처리 능력을 요구하는 작업이나 복잡한 처리를 할 때 적합하다고 볼 수 있다.


 scale-up 서버에서 하둡 또는 스파크를 구성했을 때 기존의 관련 연구들이 있다. 


scale-up 서버의 하둡 시스템이 scale-out의 분산 처리 환경보다 좋은 경우가 있다는 것을 주장하는 연구[6]가 있고, scale-up 서버의 스파크 시스템 성능에 대한 연구[7]와 scale-up 서버의 스파크 시스템 성능이 자바 가상 머신의 GC 종류에 따라 차이가 있음을 발견하고 성능이 제일 잘 나오는 GC를 찾아 성능을 개선하는 연구[3]도 있다. 


또한 scale-up 서버에 대한 스파크 시스템 확장성을 파일시스템 관점으로 한 연구[4]도 있다. 

이처럼 scale-up 서버에서의 분산 처리 시스템에 대한 연구가 많아지고 있다. 그러나 기존의 연구들은 scale-up 환경에 분산 시스템 개념을 적용한 확장성 개선은 고려하고 있지 않다. 


 공유 메모리 시스템에 분산 시스템의 개념을 적용한 연구는 몇몇 연구가 있었다[13]


[14]. 본 논문은 도커 컨테이너를 이용해 scale-up 서버를 파티셔닝하여 분산 시스템처럼 구성했다. 

그 결과 NUMA 메모리 구조에 의한 메모리 접근 지연 시간을 최소화 하고 동시에 공유 메모리 시스템에 의한 메모리 접근 충돌을 최소화 하였다. 

그리고 스파크가 사용하는 자바 가상 머신의 GC의 오버헤드를 줄여 scale-up 서버의 스파크 시스템 확장성을 개선하였다. 

또한 도커 컨테이너를 이용한 파티셔닝 방법은 컨테이너 관리 도구인 Google Borg[10] 혹은 Kubernets[9]과도 쉽게 결합할 수 있다. 






배 경


제 3장에서는 본 논문에서 나오는 개념인 하둡의 하둡 파일 시스템과 아파치 스파크의 특징 및 구조 및 개념에 대해 설명한다. 

그리고 논문에서 제안하는 도커에 대한 배경 지식을 설명한다.

3.1 하둡(Hadoop)


 하둡은 대량의 데이터를 처리하기 위한 병렬 분산 처리 소프트웨어로써, 구글 파일 시스템(GFS)에서 비롯되어 YAHOO의 개발자 더그 커팅이 만들어낸 빅데이터 처리 기술이다. 

하둡 파일 시스템[11]과 데이터를 분산 시켜 처리한 뒤 하나로 합치는 기술인 맵리듀스[1]를 구현한 오픈 소스 프레임워크이다. 

간단히 말해 병렬처리를 가능하게 해주는 단순한 데이터 모델이라 할 수 있다. 


본 논문에서는 실험을 위해 하둡의 분산 파일 시스템인 하둡 파일 시스템을 사용하였기 때문에 하둡 파일 시스템의 구조와 특징에 대해 설명한다.


하둡은 마스터/슬레이브 구조로서, 하둡 파일 시스템은 마스터인 네임노드(NameNode)와 슬레이브의 데이터노드(DataNode)로 구성된다.


 네임노드는 하둡 파일 시스템에 저장되는 각종 파일과 디렉토리들의 메타정보를 관리하고 실제 데이터는 다수의 데이터노드에 분산 저장하는 역할을 한다. 


메타정보에는 하나의 파일에 대해 이름, 속한 디렉토리 정보, 복제본 개수의 수, 해당 파일을 구성하는 데이터 블록들의 ID 리스트, 각 블록별 저장 데이터노드의 이름이 있으며, 네임노드는 이런 메타정보를 메모리에 유지한다. 


네임노드에는 회복(Recovery)을 위한 보조의 네임노드가 하나 더 구성되는데 이를 2차 네임노드(Secondary NameNode)라 부른다. 


2차 네임노드는 주기적으로 네임노드에게 체크포인트를 요청하고, 네임노드는 메모리에 존재하는 파일시스템 메타정보를 디스크 파일로 써버린다. 


이를 체크포인트라 부르며 이 파일을 2차 네임노드가 복사해간다


또한 체크포인트 사이에 혹시 발생할지 모르는 문제를 대비해 체크포인트 사이의 모든 하둡 파일 시스템 트랜잭션은 모두 Edit Log라는 파일에 수록하며, 체크포인트를 수행할 때마다 Edit Log의 내용은 리셋하는 방식으로 구성된다.



3.1.2 하둡 파일 시스템(HDFS)의 특징


 하둡 파일 시스템은 하나의 파일을 여러 개의 블록으로 나누어 가능한 한 여러 데이터노드에 저장한다. 

블록의 크기는 기본이 64MB이며, 파일 하나는 적어도 하나의 블록을 가져야 하고 한 블록의 크기가 작지 않다. 


또한 하둡 파일 시스템은 하부 운영체제의 파일 시스템을 사용하는데, 데이터노드들이 동작하는 서버 운영체제의 파일 시스템을 그대로 사용하여 구현된 분산 환경의 파일 시스템이다. 


디스크상의 특정 디렉토리를 데이터노드가 블록을 저장할 장소로만 지정하고 하둡 파일 시스템 상의 파일과 디렉토리, 블록 저장 정보들은 네임노드가 관리한다.


 하둡 파일 시스템은 하드웨어가 고장 났을 때도 대비하여 문제를 해결할 수 있다. 

데이터블록을 보통 3군데에 저장하는데, 저장 시 같은 랙(Rack)에 있는 서버들 두 개에 저장하고 다른 하나는 다른 랙에 있는 서버에 저장하는 방식을 택한다

복제본 개수(Replication Factor)라 하여 시스템 상황에 맞게 다른 값으로 설정해줄 수 있으며, 네임노드가 특정 데이터노드에 문제가 발생한 것을 알면 바로 그 데이터노드에 있던 데이터 블록들을 다른 데이터노드들로 복제하는 방식으로 문제를 해결한다.


3.2 아파치 스파크(Apache Spark)


 아파치 스파크는 분산된 여러 대의 노드에서 연산을 할 수 있게 해주는 범용적 목적의 클러스터링 플랫폼이라고 정의할 수 있다. 

스파크는 scala로 구현되어 있어 자바 가상 머신 위에서 동작하며 하나의 플랫폼에서 여러 가지가 가능하고, 디스크 I/O 기반이 아닌 메모리를 사용하기 때문에 속도가 빠르다.


 또한 다양한 언어 파이썬, 자바, 스칼라 등을 제공해 연동성이 좋다는 장점이 있다. 이 절에서는 스파크에 대한 개념과 스파크 구조에 대해 설명한다.


3.2.1 스파크의 개념

 스파크는 RDD(Resilient Distributed Datasets)[2]라는 여러 분산 노드에 걸쳐서 저장되는 변경이 불가능한 데이터(객체)를 정의한다.


 RDD를 디스크가 아닌 메모리에 올려놓고 사용하기 때문에 디스크를 사용하는 하둡의 맵리듀스보다 빠르고, 다양한 연산을 할 수 있다는 장점이 있다.


 RDD의 특성은 한번 생성이 되면 변경이 불가능하다는 특성이 있다. 


RDD가 어떻게 만들어졌는지 기록을 해두는데 이것을 계보(lineage)라 한다. 계보는 DAG(Directed Acyclic Graph)로 디자인이 되어 있어, 데이터 문제가 발생했을 때 만들어둔 계보를 보고 복구(fault-tolerant)를 할 수 있다. 


 데이터를 변경하기 위해선 새로운 RDD를 만들어야 하는데 이를 위해 RDD에서는 2가지의 기능을 지원한다. 


첫 번째 기능은 Transformation으로, 기존의 RDD를 변경하여 새로운 RDD를 생성해낸다. 흔한 케이스는 filter와 같이 특정 데이터만 뽑아내거나 map 함수처럼 데이터를 분산 배치하는 것 등이 있다. 


두 번째 기능은 Action인데, RDD 값을 기반으로 무엇인가를 계산해서 결과를 생성해 내는 것이다. 가장 쉬운 예로는 count()와 같은 기능을 들 수 있다.

 RDD의 Transformation, Action의 과정을 lazy-execution이라고 하는데 실제 Transformation 단계에서는 RDD가 생성되지 않고 계보, 즉 DAG만을 생성한다.


 DAG를 생성하다가 Action을 수행할 때 한 번에 연산을 처리하여 시스템이 얼마나 자원을 사용할 것인지 대한 자원을 배치하고 효율적으로 Action을 수행한다. 


이러한 방법을 사용하는 이유는 Transformation을 수행할 때부터 RDD를 생성해 메모리에 올려놓게 되면 데이터가 클 경우, 전체가 메모리에 올라가면 비효율적이기 때문에 Action 수행 시에 데이터를 메모리에 불러온다.




그림 3.은 스파크의 계층으로 인프라, 스파크 코어, 스파크 코어 위의 라이브러리로 나눌 수 있다. 


스파크가 기동하기 위한 인프라 계층은 스파크가 독립적으로 기동할 수 있는 Standalone Scheduler가 실행이 된다. 

기본적인 스케줄러 외에도 하둡의 리소스 매니저인 YARN이나 일반적인 클러스터 관리자 Mesos 위에서도 기동될 수 있도록 구현되어 있다. 

그 위로 메모리 기반의 분산 클러스터 컴퓨팅 환경의 스파크 코어가 실행이 되고, 스파크 코어 위에서 다양한 라이브러리가 실행된다. 

스파크 코어를 이용하여 특정한 기능에 목적이 맞추어진 각각의 라이브러리를 실행한다. 


빅데이터를 SQL로 핸들링할 수 있게 해주는 Spark SQL, 실시간으로 들어오는 데이터에 대한 처리를 해주는 Spark Streaming, 머신러닝을 위한 MLib, 그래프 데이터 프로세싱이 가능한 GraphX이 그 대상이다.





그림 4.는 스파크의 클러스터 구조로서, 하둡과 마찬가지로 마스터/슬레이브 구조로 이루어진다. 


스파크 프로그램은 일반적으로 드라이버 프로그램(Driver Program)이라고 한다. 


드라이버 프로그램은 메인 함수를 갖고 있는 프로세스를 말하며, 보통 spark-submit을 통해 사용자가 구현한 코드를 제출하면 구현한 코드에서는 SparkContext라는 객체를 생성하고 데이터 처리를 위한 준비를 한다.



 SparkContext가 클러스터 매니저에 접속하여 이를 통해 가용한 Executor를 할당 받는다. 할당을 받으면 드라이버 프로그램은 여러 개의 병렬적인 task로 나뉘어져서 스파크의 Worker Node에 있는 Executor에서 작업의 프로그램 로직이 수행된다. 


3.3 도커(Docker)
 도커[16]는 오픈소스 기반 리눅스 컨테이너 관리 도구이다. 

컨테이너란 리눅스 커널에서 제공하는 기술로, 가상화(Virtualization) 기술과 비슷하지만 가상화보다 훨씬 가벼운 기술이라고 볼 수 있다.



       
그림 5. 하이퍼바이저와 도커의 계층 구조

 호스트 컴퓨터에서 다수의 운영체제를 돌리기 위한 플랫폼을 하이퍼바이저(Hypervisor)라 하며, 하이퍼바이저의 가상화 기술은 VMware, Xen, 리눅스 KVM, Oracle Virtual Box 등 여러 종류가 있다. 


그림 5.의 (a)는 하이퍼바이저의 계층을 나타낸 것이다. 

가상 머신 자체는 완전한 컴퓨터를 생성하는 것이라 볼 수 있기 때문에 게스트 OS(Operating System)가 있어야 하고, 그 위에 프로그램들이 실행된다. 

따라서 호스트 컴퓨터의 자원을 사용할 때 하이퍼바이저를 통해 호스트 OS에게 자원을 요청해야 하므로, 그 시간 동안 오버헤드가 발생해 호스트 컴퓨터에서 프로그램을 수행할 때보다 성능이 느리다는 단점이 있다. 

그러나 도커는 게스트 OS를 설치하지 않고, OS 이미지가 동작하도록 CPU와 메모리 영역만 가상화한다

그림 5. (b)의 도커 계층구조를 보면 도커는 도커 엔진 위에 OS 전체를 설치하는 것이 아닌 실행하고자 하는 OS 이미지의 실행파일과 라이브러리를 컨테이너 이미지로 만들면 된다. 

그 외에 구동하는 데 필요한 OS자원이나 라이브러리는 호스트 컴퓨터의 환경을 공유한다. 따라서 하드웨어를 가상화하는 계층이 없고 호스트 자원을 공유하기 때문에 메모리, 파일시스템, 네트워크 속도 등 가상 머신에 비해 빠르다.


제 4장. Scale-up 서버의 확장성 문제

 이 장에서는 scale-up 서버의 로컬 호스트(local host)에서 단일 노드(single node)로 구성된 아파치 스파크 시스템 확장성 문제에 대해 분석한 내용에 대해 설명한다. 



4.1 실험 환경



 그림 6.은 본 논문에서 사용된 IBM x3950 x6 시스템이다. 

120코어(8소켓x15 코어)의 Intel Xeon E7-8870 시스템을 사용하였으며 본 논문의 실험은 물리적 인 코어의 확장성에 초점을 맞추고 있기 때문에 하이퍼스레딩(Hyper-Threading)은 비활성하고 커널 버전은 4.5-rc6을 사용하였다.


소켓안에 Core가 있고 Core 안에 Cache가 있다.


4.2 벤치마크
 성능 측정을 위한 벤치마크로 빅데이터벤치(BigDataBench)의 Big Data Generator Suite(BDGS)[5]를 사용한다.
 BDGS는 오픈소스 소프트웨어로써, 다양한 워크로드와 데이터 셋을 제공하고 사용자가 원하는 만큼의 데이터 크기를 생성할 수 있다. 본 논문에서는 스파크를 사용하는 워크로드 4가지를 사용해 성능을 측정한다.



각각의 워크로드가 하는 작업은 다음과 같다.




스파크는 워커노드의 Executor가 사용하는 자바 가상 머신의 힙(Heap)메모리 크기를 설정 할 수 있다. 

만약 자바 가상 머신의 힙 메모리가 입력 데이터 크기보다 크다면 자바 가상 머신의 GC 영향을 거의 최소화 할 수 있지만, 일반적으로 빅데이터를 처리하는 환경에서는 데이터 크기가 힙 메모리 크기보다 더 크다


그러므로 힙 메모리 크기를 데이터 크기보다 크게 설정하는 것은 힘들다. 


따라서 이번 실험에서는 데이터 사이즈보다 작은 각각의 워크로드에 자바 가상 머신의 힙 메모리를 4G를 할당하여 실험을 진행하였다. 




4.2.2 소프트웨어 설정


 본 논문에 사용하는 벤치마크인 BDGS[5]가 하둡은 1.2.1 버전, 스파크는 1.3.1 버전으로 지원하므로, 소프트웨어의 버전을 1.x 버전을 사용하였다.


 제 3장의 배경에서 설명했듯이, 하둡과 스파크는 마스터/슬레이브 구조로 마스터 노드와 슬레이브 노드가 각각 따로 정해져서 분산처리를 한다. 

그러나 이 장에서는 scale-up 서버의 확장성을 실험하기 위해 그림 7.과 같이 하둡과 스파크의 모든 데몬(java process)들을 마스터/슬레이브의 분산 노드가 아닌 하나의 로컬 호스트에 단일 노드로 구성한다. 



스파크는 하나의 노드에 여러 개의 Worker 수를 설정할 수 있다. 

실험하기 전에 미리 scale-up 환경에서 여러 개의 Worker를 설정하여 성능을 측정 해본 결과, 하나의 Worker일 때와 성능차이가 눈에 띄지 않았다. 

따라서 본 논문에서는 하나의 Worker를 설정하고 실험하였다. 

또한 관련 연구에 있었던 자바 가상 머신의 GC 종류에 따른 성능 차이[3]도 확인하기 위해 Parallel GC, G1 GC 두 종류의 GC를 설정하여 실험하였다.

 하둡의 저장소는 디스크 입출력 병목 현상을 줄이고 코어 수에 따른 환경만을 고려하기 위해 메모리를 사용하는 임시 파일 시스템(tmpfs)을 사용하였다.



PS GC가 더 크구먼

그림 8.은 로컬호스트의 단일노드로 구성된 환경에서 스파크를 사용하는 4개의 벤치마크 워크로드에 대한 실험 결과로 확장성을 보여준다. 

Y축은 초당 몇 MB의 데이터 처리를 하는지를 나타내는 처리량을 나타내며 X축은 실험할 때 설정한 CPU 코어의 수를 나타낸다. 

실험은 2, 8, 15, 30, 45, 60, 90, 120코어로 CPU를 껐다 켜면서 실험하였다. 

실험 결과 60코어까지는 확장성을 가지다가 그 이후에는 성능의 확장성의 문제가 있다. 이러한 확장성 문제가 생기는 이유로는 다음과 같은 문제들이 있다.

 자바 가상 머신에서 GC가 호출되면, 자바 가상 머신에서 수행되는 쓰레드들은 멈추고 GC 작업을 완료하고 동작하는데, 자바에선 이를‘stop-the-world’라고 부른다. 

따라서 코어가 많아질수록 직렬화(serialization) 되는 코어들이 늘어나 오버헤드(overhead)가 발생하여 처리량이 떨어진다. 

또 다른 문제는 NUMA 메모리 구조다. 

즉 코어마다 메모리에 접근하는 거리가 다르다. 

그러므로 메모리 접근 지연 시간에 의한 오버헤드도 확장성 문제의 원인중 하나로 볼 수 있다. 

본 논문에서는 확장성의 문제점 중 한 가지로 GC를 지적하고 있기 때문에 하나의 GC가 아닌 두 종류의 GC로 실험을 하였다. 하나는 Parallel GC이고, 다른 하나는 G1 GC로 설정하여 실험하였다. 

실험 결과 GC 종류에 따른 성능차이는 크다. 

Parallel GC는 GC를 처리하는 쓰레드를 여러 개를 생성해 병렬 처리함으로써 분산 처리하는 스파크에서는 G1 GC보다 더 좋은 성능을 보인다. 

하지만 아무리 Parallel GC라도 여전히 확장성 문제를 가지고 있다. 




다음은 각 워크로드의 CPU 사용량으로 그림 9. 와 같다. 

스파크는 하나의 scale-up 서버에서 단일 노드로 프로세서들이 동작하는 환경의 특성을 고려하지 않았기 때문에 코어 수가 많아져도 CPU를 다 사용하지 못하는 확장성 문제가 있다. 


그림 9.와 같이 모든 워크로드에서 코어가 많아질수록 idle 시간이 전체적으로 늘어나는 것을 볼 수 있다.


제 5장. 도커 컨테이너 파티셔닝 기법

 스파크 시스템의 확장성 문제를 해결하는 근본적인 해결 방법은 스파크의 라이브러리와 스파크 드라이버 프로그램을 scale-up 서버를 위해 확장성을 가지게 만드는 것이다. 


그러나 scale-out 시스템에 맞게 작성된 스파크 프로그램을 수정하는 것은 쉽지 않다.


 본 논문에서는 scale-up 서버의 스파크 시스템 확장성 문제를 해결하기 위해 도커 컨테이너를 이용한 파티셔닝 기법을 제안한다. 

파티셔닝을 위해 도커 컨테이너를 이용하는 이유는 버추얼 머신보다 훨씬 가벼운 구조로 되어 있으며, 최근 도커 기반으로 시스템을 관리하는 구조로 변경되고 있기 때문이다. 

따라서 본 연구의 파티셔닝을 위한 방법으로 도커 컨테이너를 사용하였다.

5.1 파티셔닝의 이점

 스파크의 모든 쓰레드들은 모두 자바 가상 머신 위에서 동작하기 때문에 자바 가상 머신에 의존적이다. 

따라서 본 논문에서는 자바 가상 머신의 파티셔닝에 대한 효과를 분석하기 위해, 자바 가상 머신에서 동작하는 응용프로그램의 성능을 가장 실용적으로 측정 할 수 있는 벤치마크인 SPECjbb2013[8]을 사용하여 사전에 파티셔닝에 대한 효과를 분석하였다.


 파티셔닝된 실험은 SPECjbb2013 벤치마크의 자바 가상 머신의 수를 시스템의 소켓의 개수와 동일하게 설정하였고, 메모리 용량을 시스템 최대 가용 용량으로 설정하여 실험하였다. 


실험은 다음과 같이 코어를 나누어 파티셔닝한 성능과 그렇지 않은 성능을 측정하였다. 실험결과 그림 10.을 보면 하나의 자바 가상 머신에서 프로그램을 실행한 결과보다 각각의 소켓을 나누어 여러 개의 자바 가상 머신에서 실행하면 더 좋은 성능이 나오는 것을 보여준다.



5.2 확장성 개선을 위한 고려 요소


 확장선 개선을 위한 파티셔닝 기법의 고려해야 할 첫 번째는 4장의 실험에서 확인할 수 있듯이 자바 가상 머신의 GC의 영향[3]이다. 


따라서 코어수가 많은 scale-up 서버에서 하나의 단일노드로 시스템을 구성하게 되면 GC가 발생하는 동안 더 큰 오버헤드가 발생할 수 있다. 



두 번째 고려 사항은 메모리 접근 지연 시간[15]이다. 


원격 메모리 접근에 따른 접근 시간이 높아지기 때문에 성능을 저하시킨다.


 리눅스는 이러한 문제를 해결하기 위해 커널 내부에 automatic NUMA balancing[17]이라는 기능이 있으나, 스파크 확장성에는 별다른 영향을 주지 못하였다. 


세 번째 고려 사항은 운영 체제 자체의 저해 요소이다. 


NUMA의 영향 뿐만 아니라, 공유 메모리 시스템의 환경 때문에 발생하는 확장성 저해 요소를 생각 해야한다. 


자바 가상 머신 위에서 동작하는 쓰레드간의 공유하는 single address space 때문에 발생하는 문제로 공유 메모리에 대한 락(lock)이 있다. 


마지막으로 고려해야 할 사항은 분산 처리 환경에서 뒤처진 task에 대한 문제[12]이다. 




그림 11.과 같이 분산 처리 환경에서는 여러 워커 노드에서 하나의 job에 대한 task들을 나눠서 처리하는데, 이 때 모든 워커 노드의 task들이 동일한 시간에 수행이 완료되지 않고 먼저 끝나는 노드와 그렇지 않은 노드가 발생한다. 


그러면 먼저 끝나는 노드는 다른 노드가 task를 완료할 때까지 대기하게 되는데, 이 때 발생하는 오버헤드는 job을 완료하는 시간을 상당히 연장시킨다. 


이러한 문제는 분산 처리 환경에서의 근본적인 문제이다.





본 논문에서는 앞 절에서 설명한 확장선 개선 고려 요소를 생각하여, 그림 12.와 같은 도커 파티셔닝 프레임워크 디자인을 제안한다.


 하나의 scale-up 서버를 도커 컨테이너를 이용해 파티셔닝하여 분산 처리 시스템처럼 구성한다. 

하나의 도커 컨테이너는 분산 처리 시스템의 워커 노드의 역할을 하게 되며, 독립된 CPU와 메모리를 사용하게 된다. 


이렇게 파티셔닝을 통해 가져올 수 있는 효과는 자바 가상 머신의 GC의 영향을 시스템 전체가 받는 것이 아닌 GC가 수행되는 컨테이너의 부분만 영향을 받음으로 전체적인 오버헤드를 줄일 수 있다. 


또 각 컨테이너는 할당된 소켓의 메모리만 접근하기 때문에 메모리 접근 지연 문제를 해결함과 동시에 공유 메모리 시스템에서 발생할 수 있는 락 문제도 해결 할 수 있다. 


하지만 전체적인 확장성 저해 요소 문제점들을 파티셔닝으로 개선했다고 하더라도 시스템을 몇 개의 파티션으로 나눌지, 컨테이너의 코어의 수는 몇 개씩 할당할지 정하는 것은 중요하다. 


이유는 스파크의 워크로드 알고리즘마다 시스템의 어느 자원을 어떻게 사용할지 다 다르고, 서버 환경에 따라 파티셔닝을 크게 적게 나누었을 때 혹은 작게 많이 나누었을 때 성능이 좋을 수도 있기 때문이다. 


따라서 워크로드에 따른 효율적인 파티셔닝을 결정해주는 프레임워크(Decision Engine)가 필요하다.


 그림 12.의 좌측은 스파크 워크로드, 시스템에서 이용한 가능한 코어 수, 데이터 타입 등을 고려하여 어떻게 파티셔닝 된 도커 컨테이너에서 스파크 프로그램을 실행할지 결정한다. 


또한 프레임워크 안에 straggler 모니터를 만들어서 task가 빨리 끝난 도커 컨테이너 워커노드에 대해 CPU 할당을 task가 아직 작업의 수행이 완료되지 않은 다른 도커 컨테이너 워커노드에 할당할 수 있게 만들면 분산 처리 환경에서의 근본적인 문제도 해결 할 수 있다.







앞서 5장에서 말했듯이 scale-up 서버를 파티셔닝 하더라도 워크로드 종류, 시스템에서 이용한 가능한 코어 수, 데이터 타입을 고려하여 어떻게 나누느냐에 따라 효율성이 달라질 수 있다.




그러므로 본 논문에서는 실험에 사용한 scale-up 서버의 메모리 접근 지연 시간을 고려, 6.과 같이 소켓 단위인 15코어씩 나눈 8개의 도커 컨테이너와 좀 더 크게 나누었을 때의 성능 비교를 위해 30코어씩 4개의 도커 컨테이너를 만들어 파티셔닝 하였다.






Evaluation은 제친다.

본 논문에서는 분산 처리 시스템인 아파치 스파크를 하나의 scale-up 서버에서 구성하였을 때, 성능에 대한 확장성 문제를 발견하고 이에 대한 해결책으로 도커 컨테이너를 이용한 파티셔닝을 제안했다. 


그 결과 공유 메모리 시스템을 분산 시스템처럼 구성하였고, 스파크 벤치마크인 4개의 워크로드(WordCount, Grep, Naive Bayes, K-means)에서 적용한 결과, 120코어에서 파티셔닝 하지 않았을 때보다 확장성을 가지며 처리량이 각각 최대 1.6배, 1.5배, 1.7배, 1.1배 향상되었다.



 scale-up 서버에서의 확장성 문제의 원인은 첫째로 자바 가상 머신의 GC이다. 스파크는 기본적으로 자바 가상 머신 위에서 동작하기 때문에 자바 가상 머신의 GC에 의해 영향을 받는다. 


이에 분산 처리 시스템을 성능이 좋은 시스템이라도 하나의 서버로 구성하면 GC의 오버헤드가 더 커질 수 있다. 


두 번째는 scale-up 서버의 NUMA 메모리 구조 때문이다. 이런 메모리 구조에서는 메모리 접근 지연 시간 때문에 오버헤드가 발생한다. 


세 번째는 공유 메모리 시스템의 공유메모리 접근 때문에 락이 발생하여 확장성 저해 요소가 있다.


 이러한 확장성 문제의 원인들을 도커 컨테이너 파티셔닝 기법으로, 하나의 scale-up 서버를 분산 처리 환경의 시스템처럼 구성하여 확장성을 개선할 수 있었다. 

하지만 scale-up 서버의 환경에 따라 파티셔닝 기법을 다르게 적용해야 하는 것을 확인 할 수 있었고, 분산 처리 환경에서의 일반적인 문제인 뒤처진 task에 대한 문제는 파티셔닝 방법을 적용해도 여전히 존재하는 것을 확인 할 수 있었다.


 이러한 이슈들을 해결하기 위해 향후 연구로는 5장에서 제안한 프레임워크를 실제로 구현해 볼 필요성이 있다. 본

 논문의 실험에서는 수동으로 도커 컨테이너를 생성해 일일이 실행해서 성능을 확인했지만, 이것을 어떤 파티셔닝을 사용할지 자동으로 결정해주는 프레임워크가 있다면 더 효율적일 수 있다. 

또한 뒤처진 task에 대한 문제를 본 논문에서는 코어 수를 많게 파티셔닝 함으로써 이 문제를 완화할 수 있었지만, 향후 연구로 근본적인 해결할 방법을 연구해 볼 필요가 있다. 


실제로 분산 처리 환경에서는 이 문제를 해결하기는 어렵지만, scale-up 서버에서는 하나의 공유 메모리 시스템을 분산 처리 시스템처럼 도커를 활용해 파티셔닝 한 것이므로 수행 완료된 task들을 모니터링하고 있다가 아직 수행이 완료되지 못한 컨테이너에게 코어를 할당하는 방법 등으로 해결하는 방법을 연구해 볼 수 있다.


 따라서 이 문제도 도커를 활용해 해결할 수 있는 가능성이 높다.