요즘 하둡을 이용하여 대량의 로그 분석을 수행하는 작업을 하고 있다. 최종 목표는 20대 이상의 서버에 발생하는 로그를 실시간으로 수집하여 분석하는 것인데 이를 위해 하둡과 하둡 생태계 내의 다양한 기술 요소들을 검토하고 사용하고 있다.

그 중 Oozie는 여러 단계에 걸쳐 처리되는 분석 작업의 흐름(workflow)을 관리하고, 주기/비주기 적으로 분석 작업을 스케쥴링하기 위한 작업을 위해 사용하고 있다. 처음에는 Spring Data를 사용할까 했는데 여러 가지 측면(reference, documentation, user base 등등…)에서 현재까지는 Oozie가 더 나은 것으로 판단 되어 최종적으로 Oozie를 선택했다.

프로젝트는 메이븐으로 구성했는데 최상위 메이븐 프로젝트를 두고 우지의 workflow/coordinator 단위로 하위에 메이븐 모듈을 구성했다.

따라서, 위의 그림에서 rp-da-link-count-process는 메이븐 모듈이면서 하나의 workflow을 처리하기 위한 단위가 된다. Oozie의 워크플로우는 여러 개의 action으로 구성되는데 각 action은 하둡 명령어를 실행하기 위한 스크립트가 될 수도 있고, MapReduce를 프로그램, hive, pig, sqoop등과 연계하기 위한 스크립트가 될 수도 있다.

위의 그림은 하나의 워크플로우를 구성하는 다양한 요소들을 하나의 메이븐 모듈로 만든 모습이다. 이 workflow을 구성하는 프로젝트의 경우 하나의 M/R과 HIVE 스크립트로 구성된 비교적 간단한 메이븐 모듈 프로젝트이다. 다른 모듈들도 거의 비슷한 모습으로 구성됐다고 보면 되겠다. 참고로 M/R의 단위 테스트를 위해 MrUnit을 사용했다.

프로젝트 구성을 마친 후 몇 가지 간단한 유틸을 작성하였는데 이를 통해 workflow및 관련 파일을 개발 서버로 자동 업로드하고 실행할 수 있는 테스트 환경을 구축할 수 있었다. 이를 통해 매번 관련 파일을 ftp등을 사용해 개발서버로 업로드하고 명령 스크립트를 통해 oozie를 실행하는 번거로움에서 벗어날 수 있었다.

이제 전체 프로젝트를 자동 배포하기 위한 환경을 만드는 일만 남았는데 목표는 최상위 프로젝트에서 메이븐 install/deploy 명령을 실행하면 전체 프로젝트에 대한 oozie 배포 구조가 만들어지는 것이다.

배포 구조에 대해 간략히 설명하면 oozie는 workflow별로 디렉토리를 만들도록 권한다. 따라서 Workflow당 하나의 디렉토리가 생기고 그 하위에 workflow(혹은 coordinator)의 세부사항을 정의하는 xml파일 및 관련 리소스 파일이 위치하게 된다. 또, 워크플로우의 액션을 실행하기 위해 jar파일이 필요하다면 lib 폴더 밑에 jar파일들을 위치 시키면 된다. 그림으로 표현하면 다음과 같다.

/Rp-da-link-process 
   - workflow.xml 
   - coordinator.xml 
   - lib    
       - rp-da-link-count-process.jar 
       - aaa.jar 
       - bbb.jar 
       - 기타등등.jar…

메이븐에서 기본으로 제공하는 플러그인으로는 위와 같은 구조를 만들어 낼 수가 없었기 때문에 위와 같은 배포 구조를 만들기 위해서 maven-assembly 플러그인을 사용했다. Maven-assmbly-plugin은 사용자가 프로젝트의 결과물을 원하는 배포 단위로 만들게 해주는 플러그인이라고 보면되겠다.

처음에는 각 모듈 별로 oozie 배포 아카이브를 만들어 내도록 했는데 각 모듈별로 출력 아카이브가 생성되어 전체를 한번에 배포하기가 힘든데다가 각 모듈에서 공통적으로 사용하는 jar파일 또한 중복돼서 lib폴더에 들어가는 문제가 있어 배포용 모듈을 따로 만들기로 했다.

위의 그림1에서 rp-da-backend-deploy 모듈이 배포용 모듈이 되겠다. 이즈음에서 모듈 이름에 컨벤션을 적용했는데 oozie workflow에 해당하는 모듈은 process라는 postfix를 갖도록 했고, workflow에서 공통으로 사용하는 utility 기능을 제공하는 모듈은 utility라는 postfix를 갖도록 했다. 마지막으로 배포용 모듈의 경우에는 deploy라는 postfix를 붙였다.

이를 통해서 process라는 이름을 갖는 모듈만 oozie 배포구조가 만들어지도록 할 수 있었다. 또, 각 workflow에서 공통으로 사용하는 jar파일은 share 디렉토리에 생성되도록 함으로써 lib가 중복되어 배포되는 걸 막았다.  Deploy명령어를 통해 생성된 최종 아카이브의 모습은 다음 그림과 같다.


전체 디렉토리 구조


rp-da-link-count-process 모듈의 구성


share 폴더의 구성

"Process" postfix를 갖는 모듈들만 workflow용 디렉토리가 생성되고 각 디렉토리 하위에는 lib폴더가 생성된 것을 볼 수 있다. share디렉토리 밑에는 각 workflow에서 사용하는 공통 jar파일이 위치한다.

이제 assembly 플러그인을 이용하여 아카이브를 만들어 내는 구체적으로 보겠다. 먼저, Assembly 플러그인을 사용하려 pom.xml에 assembly-plugin을 선언해야 한다. 우리는 deploy용 모듈을 따로 만들었기 때문에 deploy 모듈(rp-da-backend-deploy)의 pom.xml에만 assembly-plugin을 선언했다.

빌드-플러그인 절에 maven-assembly-plugin을 설정하고 실행단계를 정한다. 또, assembly 수행 시 실행할 스크립트 파일명을 지정한다. 우리는 oozie.xml을 스크립트 명으로 정하고 pom.xml과 같은 레벨에 위치하도록 했다. 여기까지 설정한 후 install이나 package명령을 수행하면 oozie.xml을 찾을 수 없다는 에러와 함께 빌드가 실패하는 것을 볼 수 있다. 이제 oozie.xml의 구성을 살표 보도록 하자.

<id>는 assesmbly의 id를 부여하기 위해 사용하며, 해당 아이디가 bundle의 이름에 postfix로 사용된다. <format>은 output archive가 만들어지는 형식을 지정하며, dir로 할 경우 디렉토리 형식으로 아카이브가 만들어진다. 이 외에 tar, jar,zip,war..등을 지원한다. <incldueBaseDirectory>는 아카이브 생성시 모듈명 디렉토리 하위에 아카이브를 생성할 것인지를 나타내는데 우리는 필요하지 않아서 false로 설정했다.

<molduleSets>은 메이븐 프로젝트에 속해있는 모든 모듈을 순환하며 처리하고 싶을 경우 사용한다. 이때, <include>를 사용해서 처리를 원하는 모듈만 골라 낼 수 있다. 우리는 “com.xxx..analysis:process:*”을 필터링 조건으로 사용하여 artifact이름에 process가 들어간 모듈만 골라서 처리하도록 했다. 또, <useAllReactorProjectes>에 true 값을 줌으로써 각 모듈별로 디렉토리를 만들도록 했다.

<sources>절에서는 xml 파일 및 properties파일의 처리를 지시하는 구문들이 있는데, 두 번째<fileSet>에서는 /src/main/resource 디렉토리 하위에 있는 property파일들에 메이븐 프로파일 변수들을 적용하기 위해 <filtered>을 true로 설정했다. 미자막 <filSet>에서는 모듈 디렉토리 하위에 /lib 디렉토리를 만든 후 각 모듈 아카이브를 복사하는 일을 수행한다.

여기까지 하면, rp-da-backend-deploy 프로젝트의 target디렉토리 아래 출력 아카이브가 생성되고 하위 디렉토리에는 “process” postfix를 갖는 모듈들의 디렉토리가 생성되며 다시 그 하위에는 workflow을 구성하는 xml, property파일 및 lib디렉토리가 생성된다. Lib 디렉토리에는 각 모듈의 jar파일이 생성된다.

마지막으로 <dependencySet>을 사용하여 각 모듈들이 사용하는 라이브러리를 모아 /share디렉토리에 넣는 작업을 수행한다. 이 때, <useProjectArtifact>를 false로 함으로써 rp-da-backend-deploy 모듈에서 생성된 jar파일이 share디렉토리 밑으로 들어가는 것을 막을 수 있으며, <exclude>를 사용함으로써 process 모듈에서 생성된 jar파일들도 share 디렉토리에 들어가지 않도록 할 수 있다. 참고로, <dependencySet>에서 찾아지는 jar파일은 rp-da-backend-deploy 모듈의 pom.xml에 <dependencies>에 설정된 jar파일이다.

여기까지 완성한 후 maven install/deploy/package등의 명령을 수행하면 전체 모듈이 oozie배포 구조에 맞춰서 생성되는 것을 볼 수 있다.  이제 hudson에서 maven deploy를 실행한 후 결과물을 서버에 자동 배포하도록 하면 된다..

namoosori
안녕하세요. 나무소리 입니다. 나무소리는 넥스트리(주)의 교육 브랜드 입니다.넥스트리가 지난 20년 동안 쌓아온 개발 및 교육 경험들을 나무소리를 통해 많은 분들과 공유 하려고 합니다.앞으로 저희 나무소리를 통해 보다 나은 교육을 경험 하실 수 있도록 구성원 모두 최선을 다하겠습니다.