첫번째 포스트를 보고 많은 분들이 개인적인 문의를 주셨다. 그리고, 많은 반박글도 보내주셨다. 주로 Yarn모드를 쓰시는 분들의 반박 내용이 많았는데... 그 분들과 대화를 나누어 보면, 사용하고 있는 옵션이나 세팅은 큰 차이가 없었다. 하지만, 데이타의 저장 방식이나 성격, 수행하고 있는 Batch 의 성격과 주기 그리고, HW 구성이 저마다 달라 충분히 다른 결과가 나올 수 있음을 서로 공감할 수 있었다.
나 역시 Yarn 모드 수행 초반에는 Yarn모드의 성능에 대하여 Over Estimate 한 적도 있었다. 그래서 한동안 TO-BE 아키텍처가 상당 부분 Yarn 모드였던 적이 있었다. 뒤에서도 설명하겠지만, TO-BE 아키텍처 부터 DevOps 구성을 도입 한지라, TO-BE 라고는 하지만, 상단 기간 Production 배치를 리얼 모드 테스트가 가능하였다. 그로부터(DevOps 환경으로부터) 설정을 다양하게 바꾸어 가며 충분한 태스트 해 볼 수 있었고, Job의 성격도 달리 해가며, 다양한 리얼데이타 태스트를 해본 결과 아키텍처를 좀더 우리 환경에 맞는 걸로 변경 적용 할 수 있는 경험치를 얻게 되었다.
지난번 글이 다소 Mesos 에 치우친 글이 었을 수 있을 것이다. 하지만, 모든 면에서 Mesos가 유리한것은 아니다. Yarn 모드가 유리한 부분도 분명 존재하며, 오늘 두번째 고찰에서는 그런쪽도 함께 언급 하도록 하겠다.
두 가지 모드 모두 장단점을 가지고 있는데, 취사 선택은 자신의 몫일 것이다. 자신이 보유한 HW 구성의 특성이나, 비지니스 로직의 성격, 데이타 소스의 성격에 따라, 그리고 무엇보다 중요한 Priority 에 따라 어떤 구성을 할지 선정해야 하며... 그것이 바로 AA(어플리케이션 아키텍처의)의 역할이기도 할것이다.
시작하기에 앞서
서두에 언급한 것 처럼, 여기에 언급 된 내용은 다분히 일부 기능, 혹은 일부 요소에만 국한되어, 성급한 일반화로 보여 질 수 있을 것이다. 본 내용은 논문이나 구글링을 하며 학습한 내용을 적은것이 아니라, 개인적인 경험에서 느낌점을 나열한 것일 뿐이기 때문이다. 돈을 받고 컨설팅 리포팅을 하는 입장이 아니므로, 나에게 혹은 우리 조직에 있어 중요한 요소를 실험 및 경험으로 채득하고, 그 부분에 특화하여 언급하였을 뿐이다.
MECE(Mutually Exclusive and Collectively Exhaustive) 하게 모든 고려 요소를 훓터 주고 있는 건 아니므로, 이 글을 참고하여 아키텍처를 수립하려고 하시는 분들은 꼭 자신의 데이타와 자신의 요건을 가지고 실험을 직접 해보면서 아키텍처 검증 과정을 거치시라 첨언하는 바이다.
[1] 안정성 측면
안정성은 약간 양날의 검인 부분이 존재한다. 지난번 포스트에서도 언급한 바 있지만, Yarn 모드에서는 excutor 갯수, core 갯수(물론 driver-memory 와 excutor-memory 설정도 각각 해줘야 하고...)를 수동 지정해야 하고, Mesos 모드에서는 그 할당을 Mesos 가 추상화 해 주어서, 정교한 세팅을 하지 않아도 되는... 그래서 Mesos 에 활용성 측면에서 더 많은 점수를 주었던 바 있었다. ..( Yarn 도 이런 설정이 불가능 한것은 아니다.. Yarn Dynamic Resource Allocation 으로 검색 해 보시길.. 메커니즘은 약간 다른것 같다. 특히, excutor가 remove 될때 RDD 가 같이 사라지는 문제가 있어, 이 문제를 해결하기 위해 RDD 를 전달 하는 external shuffle 메커니즘이 Mesos 의 그것과 좀 다르다. 아키텍처 특성상.. Mesos 는 해당 Tier 자체가 공유 Memory 를 고려한 프레임워크 인지라 이런 공유 RDD 처리가 좀더 메크러운 것 같다.)
활용성이라고 표현을 하긴 했지만, Production 용 배치로 Job을 돌려 보면, 약 3배 정도 Yarn 모드가 더 빈번한 Java Heap Memory 에러를 접하게 된다.(좀 빡세게 리소스를 Fully 활용하는 경우에 한하여..)
여기까지만 보면 Mesos 모드가 3배 더 안정적이다 라고 결론을 내릴 수도 있다.
하지만, 내가 내리는 결론은 약 52 : 48 정도로 안정성 측면에서는 Yarn 모드에 점수를 더 주고 싶다. 그 이유는 다양한 Job 이 경합을 벌이는 상황에서, Yarn 은 각 Job 의 성격 별로 Queue 나 User 별 그룹을 주고, 그룹 별 Resource 제한이나, 정교한 Priority 설정이 가능하다는 성격 때문이다. (DW 에서도 이런기능이 약한 DW가 있고, 강한 DW가 있다. 물론 필드에서는 기능이 있긴 하지만, 활용하지 않고 사용하는 경우도 태반이긴 하지만...)
위 처럼 복수개의 Queue 를 만들고, 수행하는 Job 별로 Priority 나 동시에 수행가능한 App의 갯수, max Resource 등을 제한하면, Production 환경에서 꼭 수행되어야 하는 Job 과 월배치 처럼 에러가 나면, 다시 돌려도 되는 Job , 그리고, adhoc 배치 처럼 에러가 나도 무방한 Job , 혹은 Backup 용 부수적인 Job 들을 분리하여, 안정성이 높아야 할 Job 들은 에러가 덜 나고, 혹여나 에러가 나더라도, 안정성이 중요치 않은 Job 들이 에러가 나도록 세팅이 가능하다.
위의 파일을 세팅하기 위해서는 사실 위 파일만 가지고는 안된다. 우선 yarn-site.xml 에 요런식의 별도 설정 추가가 필요하다.
위처럼 파일경로를 세팅하지 않으면, Yarn 은 Default 로 Capacity Scheduler 를 사용한다. 병렬 수행을 하면서, 그 Queue 별 그룹핑을 하기 위해 앞에서 언급한 Scheduler 세팅은 Fair Scheduler 를 사용한 예이다. (default 로는 존재하지 않아 새로 생성해 주고 내용을 체워줘야 한다.)
하지만 불행히도, Hadoop Config 상의 위 2개 파일만 세팅하면, 일반적인 MR Job과 Hive 나 Cascading 처럼 외부 Layer 가 수행한 MR성 Job 그리고 Spark Job 간의 관리만 가능하다. 복수 Spark Job 들 내부에서도 정교하게 그루핑을 하고, Fair 모드를 사용하기 위해서는 별도의 추가 세팅이 필요하다.
해당 내용(세번째 세팅)은 아래 메뉴얼에 잘 나와 있다. (1.5.1 세팅의 예임...)
http://spark.apache.org/docs/latest/job-scheduling.html#fair-scheduler-pools
위 까지 모두 세팅을 마무리하고 나면, Spark Job 도 병렬 수행도 되고, 리소스 할당에 제한을 줄수도 있으며, Priority 를 주어 Resource 경합 시 어떤 Job 에 리소스를 몰아 줄지 보다 더 정교한 세팅이 가능하다. 아래처럼 Job 이 동시에 도는 세팅만 하고 싶어도 위 3가지 설정 중 3번째 세팅은 필수로 필요하다. (물론 그것을 구현하기 위한 다른 방법도 존재하긴 하지만..)
위와 같은 세팅은 Mesos 에는 매우 약한 부분이다. 그래서, Heap Memory 에러가 훨신 덜 나는 Mesos 라 할지라도, Yarn 에 더 많은 점수를 주었다. (Mesos 의 경우 동시 수행 세팅은 약 10배 설정이 편하고(거의 할게 없다.), Priority 및 리소스 제약 세팅은 약 30배 세팅이 복잡하다.(편법을 동원하지 않고는 거의 잘 안된다.))
[2] DevOps 측면
위처럼 Yarn 은 정교한 수동 세팅을 할 수 있는 반면, 정교한 수동 세팅은 달리 말하면, 관리 포인트가 많거나 높다 라는 의미로 해석 될 수 있다.
실제, 정교하게 튜닝해서 꽤 안정적이 된 내부 시스템들이, 새롭게 신규 개발된 job 들이 배포되거나, 혹은 한두개 Heavy 배치가 추가 되었거나, 혹은 사이트가 이벤트를 해서 갑자기 트래픽이 폭주했거나.... 혹은 앞의 상황이 하나도 없어도...데이타는 자꾸 적재되면서 크기가 커지니까... 결국에는 최적화가 깨지고 에러를 유발하는 상황을 자주 접하게 된다.
그래서 신경쓸게 너무 많고... 코딩하는게 어려운게 아니라 config 맞추는게 더 어렵다. 그것때문에 내가봤을 때는 반 애자일 적이었다. (이 부분에서는 다분히 주관적인 해석이 많이 들어갔을 수 있다...)
어찌 되었던, 자사의 시스템이 Enterprise 시스템의 한 부분으로서, 애자일 보다는 안정성 및 예측 가능성이 훨씬 더 중요하고, 안정성을 유지하기 위한 수많은 번거로움은 감수 가능한 내부 아키텍처 철학을 가지고 있다면, Yarn 이 더 적합해 보인다.
마치 Spring 을 도입하는 많은 기업들이 그런 측면에서 안정성에 더 Priority 를 높게 주고 있는 것과 같은 맥락일 것이다. (Spring 프로젝트에서 제일 쉬운건 코딩이요..제일 어려운건 Config 였던 경험이 많이 있다.. 그럼에도 불구하고, Spring 프로젝트를 하게 되면, 개발자에 따른 코딩 스타일의 기복이 없고, 모든 코드가 획일화 된 코드와 성능과 예측 가능성을 가지게 된다.)
그 경우(안정성에 더 가중치를 둔 경우) 전통적인 엔터프라이즈 시스템의 구성처럼 Production Zone 과 QA 및 Staging Zone 그리고, Dev Zone 을 물리적으로 구분시키고, 개발 및 배포도 그에 맞추어 branch 와 workflow 관리를 하는게 일반적이다. (아래 처럼..)
git 이나 maven 이나 jenkins 같은 것들이 이를 위한 훌륭한 도구 일 수 있으며, 우리도 초반 1년 반 정도는 BigData 시스템을 그 철학으로 운영했던 경험이 있다. (초반에는 예측가능성과 안정성에 더 초첨을 뒀었기 때문이다...)
DevOps 측면에서 보자면, Yarn 보다는 Mesos 가 좀더 적합한것 같다. 우리의 현 AS-IS 시스템과 TO-BE 시스템이 이쪽에 더 비중을 두고 있는 이유이기도 한데....바로, 정교한 시스템 세팅 그리고 탄탄한 시스템 보다는, 유연하게 아키텍처가 바뀔 수 있고, 아키텍처의 버전업이 수시로 있으면서도, 운영중 Rolling Upgrade가 가능하며, 수시로 실험적인 세팅이 도입되었다가 롤백 되었다가 반복적일 수 있는 아키텍처를 지향하기 때문이다.
DevOps 측면에 더 무게를 둔 시스템은 애자일(agile), 지속적 통합(Continuos integration), 적응형(adaptive style) 개발방법론, 롤링업그레이드 등에 더 Priority 를 준 시스템일 것이다. 그러한 환경에서는 Production Zone 과 Dev Zone 이 방화벽을 사이에 두고 물리적으로 확고한 경계가 있으면 안된다. Dev Zone 이 2개일수도 있고, 3개 일수도 있으며, 지난주에는 Dev Zone 이 10개 Node 였었는데, 이번주는 Dev Zone 이 50개 Node 일수도 있다. 그리고 다음주에는 Dev Zone 이 갑자기 그대로, Production 배치가 도는 Production Zone 으로 탈 바꿈 되어 있을 수도 있으며, 때로는 Dev 프로그램들과 Production 프로그램이 공존해서 돌 수도 있는 것이다. 모든 Production 이 동일 버전으로 수행되진 않아도 되며, 안정성을 필요로하는 Job 들은 가장 안정버전의 버전으로 구동이 되고, adhoc 배치처럼 안정성이 덜 중요한 Job 들은 Production 배치임에도 불구하고, 최신 버전의 환경 구성에 수행되면서, 그 자체가 Dev이면서, 그 자체가 Staging Test 이며, 그 자체가 리얼 운영 QA 단계를 포함한 운영 배포이기도 한 상태가 될 수 있다. 각 단계를 배포 과정을 거치면서 water fall 형태로 하나하나 수행해야 할 필요가 없으며, 한번의 배포가 Dev,QA,Staging,Production 배포를 모두 끝내 줄수도 있다.(마치 아래 처럼..) 그리고 무엇보다... 나선형 개발 방법론 처럼, 하다가 아키텍처나 호환성이 좋지 않으면, 특정 시점의 구성으로 돌아가 언제든 아키텍처나 버전을 달리하며 테스트가 가능하다. 특정 시스템이나 특정 버전으로 돌아가는데 10분이 넘게걸리면 이미 애자일이나 DevOps 를 거론하기에는 자격 미달이다.
이 측면(DevOps 측면)에서 보면, 프로세스 가상화 개념의 Mesos 모드가 90:10 정도로 훨씬 더 유리하다. Hadoop 은 stable 하게 한곳에 있을 수 있고, 분리된 Layer 로서의 Mesos Layer 는 Hadoop Node 를 모두 쓸수도 부분만 쓸수도 있으며, 안쓰는 NoSQL 노드도 다이나믹하게 끌어 들일 수도 있다. Mesos 위에 Docker 를 올려서 다시한번 추상화된 다른 Layer 를 올릴수도 있다. 그리고 무엇보다 Public Cloud 까지 동원할 수 있다. 순수하게 계산 노드 이므로... 이 모든게 가능한 이유는 Mesos 모드는 정교한 컨피그가 없어도 되기 때문이다.
이 경우는 Yarn 이 하나의 시스템안에 Queue 로 Zone 을 나누는것과 달리 mesos 의 경우는 구동 zone 자체를 복수개를 운영하는 시나리오를 취할 수 있다. 복수 Zone 은 각각 Dev, QA, Staging, Production 일 수 있으며, Node 의 갯수가 다이나믹할 수 있고, 리소스를 극명하게 분리할 수도 있으며, 경우에 따라 하나의 머신에 복수 Zone을 띄울 수도 있다.
이 경우 이러한 구성을 자동화 함에 있어, 좀 무겁게는 Open Stack 이 사용될 수도 있고, 좀 가볍게는 Vagrant 가 사용될 수도 있으며, 갑자기 노드가 부족하면, Mesos 노드만 Azure 나 AWS 등 Public Cloud 로 원하는 만큼 무한정 늘려 사용할 수도 있다. 월배치나 분기 배치가 너무나 헤비하다..그러면, 종량제로 다이나믹하게 하루 정도만 수백대를 더 붙여서 돌리고 파기 할 수도 있다. 물론 개발환경을 개발자에게 다이나믹하게 할당해 줄수도.... 수십 테라를 실험한다고 해도....자유롭게 독립적인 테스트 환경을 구비 해줄 수도 있다.
그러면서도 내부 HDFS 는 Fix 된 체로 내부 IDC에 존재하고, dev 존이 Public Cloud 라 할지라도 VPN등 보안 프로토콜을 경유 하여, 내부 데이타를 가지고 리얼 데이타 테스트가 가능한 것이다.
Spark 1.4.1 을 쓰다가 Spark 1.5.1 로 롤링 업그레이드를 하는 시나리오를 가정해보자.
- 초반.
- 1.4.1과 1.5.1의 노드 비율이 초반에는 9:1 일수 있다.
- 10% 의 TO-BE 노드에서는 안정성이 필요하지 않는... adhoc 배치들만 돌리면서 일정 기간 테스트 수행을 할 수 있다.
- 중반.
- adhoc 배치들이 어느정도 잘 도는 시점이 되면, 비율을 6:4 정도로 To-be 에 초반보다 좀 더 할당해주고 as-is 에서 돌던 Heavy 월 배치 중 완료 시간이 민감하지 않은 일부 배치들을 몽땅 to-be 에서 구동 되도록 바꾸고 1~2주 진행상황을 살펴 볼 수 있다. 빌드하지 않아도 쉡 옵션 레벨에서 변경 가능한것이 많은 도움이 된다.
- 이 경우는 Dev 가 real-data 로 QA 및 Staging 역할 까지 하는 경우이며, 아직 까지는 Test 베드 이지만, Production 역할 도 하는 시점이다...
- 중 후반.
- 중반정도까지 수행해도 안정적인 경우 일배치 중 장애시 민감도가 덜한 부분 부터 점진적으로 TO-BE 로 이관하는 단계이다.
- 그러면서 점진적으로 AS-IS 의 노드를 줄이면서, TO-BE 노드로 다이나믹하게 이관되는 시점이다.
- 후반
- 충분한 시간 TO-BE 로 Production 배치들에 대한 안정성 검증이 어느정도 마무리 되었기 때문에, 최적화 튜닝 및 시스템 리소스 상황을 모니터링을 하면서, 전체 노드 이관이 완료 적용되는 시점이다.
- 이 단계를 포함 여기까지의 모든 과정이 Rolling Upgrade 단계였다.
- 물론 요 시점 부터는 튜닝 옵션들을 바꾸어 가며, 조금더 최적화를 진행해야 하는 단계이기도 하다.
위를 진행함에 있어, Mesos 의 장점은 바로 프로세스 가상화라는 점이다. Spark 가 각 노드에 안깔려 있어도 무방하다. Spark gz 압축 파일이 HDFS 같은 공유 리파지토리에 버전별로 저장되어 있으면, Job 을 수행할때, 어떤 버전을 써서 돌릴지 Job 별로 다이나믹하게 분배가 가능하다. 즉, 위의 Zone 에서는 그런 시나리오가 없었지만, 동일한 Zone 에서 복수의 버전을 돌리는 것도 가능하다는 의미이다. 버전을 바꾸어가면 테스트하는게 1분도 안걸리고, 동시에 N개의 버전을 동시 테스트 하는 것도 가능하다.
예를 들어 보겠다. Spark-submit 스크립트에서 master 의 주소를 바꾸어 가며 수행하는 경우, 버전이 서로 다른 서로 다른 Zone 을 다르게 구동할 수 있으며, 버전이 같은데 서로 다른 Zone 으로 구동도 가능하다. 그리고 동일 Zone 에서 버전을 달리 주는 것도 가능한데..바로 아래처럼 spark.executor.uri 옵션에 수행할 spark 버전을 다르게 주어 가능한 것이다. Spark 가 버전별로 복수 노드에 다 설치될 필요가 없고, 위처럼 옵션만 달리하여, Mesos 만 깔린 여러 Node 에 복수개의 Zone 이나 복수개의 버전을 다이나믹하게 조합하여 테스트 할 수가 있다.
부가적으로... Spark-Streaming 의 경우 Yarn 환경에서는 분리된 Yarn 클러스터를 두거나, 정교한 Fair 스케줄러 세팅을 해야 하는 반면, Mesos 환경에서는 Zone 을 분리하는 방식이 Mesos 의 Fair 스케쥴러에 Fine Graind 세팅을 해서 구동하는 것보다 훨씬 더 안정적이며, 훨씬 더 성능이 좋게 나왔다.
[3] 결론.
잡설이 좀 길어 졌는데, 어찌되었든, 결론은 Yarn 모드가 장점이 있고, Mesos 모드가 장점이 있는 것 같다. 각각의 장점 중 어느 부분을 취할지는 AA의 몫일 것이며, 현 상황 이 시스템을 도입하려는 조직의 Dev 스타일의 철학적인 부분에 달려 있으리라 본다.
내가 주장하는 결론은 애자일을 위해선 Mesos를... Enterprise 수준의 안정성을 위해서는 Yarn 이 조금 더 낳은 것 같다 이다.