[독후감] 거침없이 하둡 활용해 보기

이 문서는 [거침없이 배우는 하둡(Chuck Lam 지음 / 이현남, 강택현 옮김 / 지앤선 출판사)]을 읽고 쓴 독후감이다.

hadoop_in_action_face

가장 기본적인 내용은 간단히 정리해보고, 지금까지 미처 활용하지 못했던 몇가지 팁을 작성하고자 한다.

하둡이란

하둡(Hadoop)은 빅데이터를 처리할 수 있는 분산 응용 프로그램을 작성하고, 실행하기 위한 오픈 소스 프레임워크다. 분산 컴퓨팅 플랫폼은 하둡 외에도 다양하게 존재하지만, 하둡은 아래와 같은 차이점을 갖는다.

  • 접근성(Accessibility)
    하둡은 다수의 범용 컴퓨터를 이용하여 쉽게 클러스터를 구성할 수 있다. 또는 아마존의 EC2(Elastic Compute Cloud)와 같은 클라우드 인프라를 간단히 활용할 수도 있다.
  • 견고함(Robust)
    하둡은 범용 컴퓨터로 구성된 클러스터상에서 실행되도록 설계되었기 때문에, 하드웨어가 고장이 나더라도 쉽게 복구할 수 있다.
  • 확장가능성(Scalability)
    처리 속도나 저장 용량을 늘리고자 할 때, 단순히 컴퓨터를 더 추가함으로써 선형적으로 확장이 가능하다.
  • 단순함(Simplicity)
    분산된 컴퓨터에서 병렬적으로 처리되는 프로그램을 손쉽게 개발할 수 있다.

<하둡의 설계 철학>

프로그램은 일반적으로 데이터를 프로그램이 있는 컴퓨터에 가져와서 처리하게 된다. 반면 하둡의 경우, 데이터가 있는 컴퓨터에 프로그램을 전송해서 그 곳에서 데이터를 처리한다. 따라서 실제 데이터가 저장되어 있는 컴퓨터에서 데이터가 처리된다. 데이터가 대용량이라는 점을 감안해 볼 때, 데이터를 옮기는 것보다 프로그램을 옮기는 것이 당연하며, 하둡은 이러한 철학을 따라 만들어졌다.

MapReduce 살펴보기

MapReduce 프로그램은 map과 reduce, 2단계로 이루어진다. map 단계에서는 입력 데이터를 필터링하여 reduce 단계에서 처리할 수 있는 형태로 변경한다. reduce는 map의 출력 값을 입력 값으로 받은 후, 데이터를 통합한다.

하둡의 구성 요소

하둡은 아래의 데몬들로 구성된다.

  • NameNode(네임노드)
  • DataNode(데이터노드)
  • Secondary NameNode(세컨데리 네임노드)
  • Job Tracker(잡 트래커)
  • TaskTracker(태스크 트래커)

hadoop_diagram

  •  NameNode
    하둡은 마스터/슬레이브 구조를 가진다. 네임노드는 HDFS에서 마스터 역할을 하며, 슬레이브 역할을 하는 데이터 노드에게 I/O 작업을 할당한다. 네임노드는 현재 이중화 구성을 할 수 없어서, 하둡 클러스터를 운영할 때 단일 장애 지점이 된다.
    * 네임노드 백업 및 이중화에 대해서는 조금 후에 살펴보도록 하겠다.
  •  DataNode
    실제 데이터는 데이터노드에 저장된다. 클라이언트가 HDFS에 파일을 읽거나 쓰기 위해 네임노드에게 요청을 날리면, 네임노드는 어느 데이터노드의 어디 블록에 파일이 있는지(또는 쓸지)를 알려준다. 그러면 클라이언트는 데이터노드와 직접 통신하여, 파일을 읽거나 쓰게된다. 다시 말해, 데이터노드와 블록 위치가 정해지면 클라이언트는 네임노드와는 전혀 통신하지 않고, 해당 데이터 노드와 직접 통신한다.
    클러스터가 처음 시작될 때, 각 데이터 노드에서 자신의 블록 정보를 네임노드에게 알려준다. 그런 후 데이터 노드는 자신의 로컬 디스크에 변경사항이 발생할 때마다 네임노드에게 변경사항을 알려주게된다.
  •  Secondary Name Node
    세컨데리 네임노드는 HDFS의 블록이 변경되더라도 실시간으로 변경정보를 갱신하지 않는다. 세컨데리 네임노드는 네임노드의 블록정보를 병합할 때 사용하기 위한 노드이며, 백업 노드도 아니고 stand by 네임 노드는 더더욱 아니다.
    하지만 네임노드에 장애가 발생할 경우를 대비해서 백업용 노드로 활용할 수 있다. 그리고 네임노드가 장애가 난 경우, 세컨데리 네임노드를 네임노드로 활용할 수도 있다. 이러한 작업은 모두 자동화 되지 않으며, 수작업으로 처리해야 한다.
    * 네임노드 백업 및 이중화에 대해서는 조금 후에 살펴보도록 하겠다.
  •  JobTracker
    클라이언트가 요청한 작업(job)에 대한 실행을 관리한다. 일반적으로 잡트래커는 마스터 노드, 즉 네임노드가 설치된 노드에서 실행한다.
  •  TaskTracker
    작업을 실제로 처리하는 일은 태스크트래커가 맡는다. 슬레이브 노드, 즉 데이터 노드에는 하나의 태스크트래커만이 존재하며, 여러개의 JVM을 생성해서 다수의 map과 reduce를 실행하게 된다.
    mapreduce

Job Chaining

복잡한 문제가 있을 때 하나의 프로그램으로 처리할 수도 있지만, 작은 책임만을 가지도록 프로그램을 나누면 프로그램을 유지보수하기가 쉬워진다. MapReduce에서도 여러개의 작은 Job을 연결하여 복잡한 문제를 처리할 수 있다.

  • Job Pipeline(잡 파이프라인)
    Job A와 Job B가 있고, A 작업이 끝난 후 A 작업의 출력을 B 작업의 입력으로 사용해야 한다고 해보자. 수작업으로 A 작업이 끝난뒤, B 작업을 실행할 수도 있지만, 파이프라인을 이용하면 여러개의 Job을 서로 연결할 수 있다.
    job_A | job_B위와 같이 실행한 경우, job_A의 드라이버가 실행 된 후, job_B의 드라이버가 실행된다. 그리고 job_A의 결과 파일이 job_B의 입력파일로 설정된다.
  • Job Dependency(잡 의존성)
    여러가지 Job이 있고, 각 Job이 모두 순차적으로 실행되지는 않을 경우 단순히 파이프라인만으로는 실행 순서를 결정할 수 없다. 예를 들어 job_A, job_B, job_C가 있고, job_A와 job_B는 job_C보다 먼저 실행되어야 하지만, job_A와 job_B는 어느 순서로 실행되어도 되는(또는 동시에 실행되어도 관계 없는) 경우를 가정해보자. 이 경우 아래와 같이
    job_A | job_B | job_C
    또는
    job_B | job_A | job_C와 같이 실행해도 원하는 결과를 얻을 수 있다. 하지만 처리속도는 최적화되지 않는데, job_A와 job_B는 동시에 실행하는 편이 낫기 때문이다. 이러한 경우 의존성을 직접 설정하여 처리 순서를 결정할 수 있다.예를 들어 job_C에 대해 아래와 같이 설정할 수 있다.
    job_C.addDependingJob(job_A);
    job_C.addDependingJob(job_B);이렇게 설정하면, job_A와 job_B가 종료된 후 job_C가 실행되는 것을 보장한다.
    이처럼 의존성이 결정된 job은 모두 JobControl 객체에 등록해야하며, 이때 addJob() 메서드를 이용한다.
    의존성과 job 등록이 완료되면, JobControl.run() 메서드를 실행하여 job을 실행할 수 있다.
    JobControl에는 allFinished() 메서드와, getFailedJobs() 메서드가 있어 job들의 실행상태를 모니터링할 수 있다.
  • ChainMapper와 ChainReducer
    데이터를 처리할 때 두가지 책임을 갖는 매퍼를 만드는 경우가 있다. 예를 들어 웹로그를 읽어서 사용자 접근 유형을 분석하는 MapReduce를 개발한다고 해보자. 이경우 아래와 같은 처리흐름을 따라 처리할 수 있다.
    – 로그 정규화 및 유효하지 않은 라인 제거 : 입력 파일의 로그 중에서, 정해진 로그 포맷에 맞지 않는 라인을 걸러낸다.
    – 클라이언트 Ip별로 매핑 : 클라이언트 IP를 키로, 상태가 200인 접근 로그를 값으로 매핑한다.
    – 클라이언트 IP별 접근 유형 리듀싱 : 클라이언트 IP별로 접근 로그를 분석하여 결과파일로 리듀싱한다.
    – 리듀싱된 결과 DB에 로드 : 리듀싱된 결과를 DB에 로드한다.하나의 Job으로도 위의 로직을 모두 구현할 수 있으나, 첫번째 유효성 검사 작업과 마지막 DB 로드 작업은 다른 Job에서도 공통적으로 필요한 모듈이므로 별도의 모듈로 관리하면 재사용이 용이하다. 따라서 아래와 같이 Job을 구조화해볼 수도 있다.
    Job_A | Job_B | Job_CJob_A
    – mapper : 웹로그의 입력을 읽어 정규화한다. 키는 라인번호, 값은 로그 라인 전체를 매핑한다.
    – reducer : IdentityReducer를 사용한다.Job_B
    – mapper : 클라이언트 Ip별로 매핑. 키는 클라이언트 IP, 값은 접근 로그
    – reducer : 클라이언트 IP별 접근 유형 리듀싱. 키는 클라이언트 IP, 값은 분석 결과Job_C
    – mapper : 분석 결과를 DB로 로드한다. 출력은 없음
    – reducer : 없음
    이처럼 파이프라인을 활용하면 책임에 따라 Job을 하위 모듈로 구조화할 수 있지만, 각 단계마다 중간 결과를 처리해야 하므로 I/O가 발생하게 된다.이와는 달리 아래와 같이 구조화할 수도 있다.
    Job_A_mapper | job_B | job_C_mapper
    (Job_A_mapper | job_B_mapper | job_B_reducer | job_C_mapper)즉, 전처리 단계는 모두 매퍼에서 실행하고, 후처리 단계는 리듀서 이후에 실행하는 방식이다. 이때 ChainMapper와 ChainReducer를 사용할 수 있다. 위의 로직을 의사 코드로 작성해보면 아래와 같다.

    ChainMapper.addMapper(Job_A_mapper);
    ChainMapper.addMapper(Job_B_mapper);
    ChainReducer.setReducer(Job_B_reducer);
    ChainReducer.addMapper(Job_C_mapper);

IsolationRunner을 활용한 태스크 재실행

TDD를 바탕으로 MapReduce를 개발하더라도, 실행단계에서는 예외가 발생하기 마련이다. 이러한 경우 스택 트레이스를 눈으로 확인해서 디버깅을 하게 되는데, 그 과정이 상당히 번거로울 뿐만 아니라 버그를 찾기도 쉽지 않다. 이를 위해 하둡에서는 ISolationRunner라는 유틸리티를 제공한다. ISolationRunner를 사용하면 실패한 태스크에 대해, 실패할 당시의 데이터를 사용하여 해당 태스크만 독립적으로 실행할 수 있다.

ISolationRunner를 사용하려면 keep.failed.tasks.files 속성을 true로 설정해야 한다. true로 설정한 후 Job을 실행하면, 태스크가 실패한 경우 해당 데이터를 보관하게 된다.

자세한 사용법은 하둡 ISolationRunner튜토리얼을 참고한다.

MapReduce 성능 향상을 위한 팁

컴바이너(Combiner)의 활용

매퍼의 결과값이 큰 경우, 매퍼의 결과를 모두 리듀서로 전달할 때 네트워크 I/O에서 병목이 발생할 수 있다. 이러한 경우에는 컴바이너를 활용하면 성능이 향상될 수 있다. 별도의 컴바이너 프로그램을 구현하기보다는, 리듀서를 매퍼 단계에서 적용하여 매핑의 결과를 줄이는 효과를 내기 위해서 사용한다.

압축하기

컴바이너를 활용하더라도, 매퍼의 결과인 중간 단계의 데이터가 클 수 있다. 이러한 경우 중간 데이터를 압축하면 성능을 개선할 수 있다. 매퍼의 결과를 압축하기 위해서는 아래의 속성을 설정해야 한다.

속성 설명

  • mapred.compress.map.output
    매퍼의 출력을 압축하지 여부
  • mapred.map.output.compression.codec
    매퍼의 출력을 압축할 때 사용할 코덱 클래스

이 두 속성은 설정파일에 전역 속성으로 설정하기보다는, Job의 성격에 따라 JobConf 객체에 설정하는 편이 낫다.

압축할 때 사용할 수 있는 코덱에는 DefaultCodec, GzipCodec, BZip2Codec 등이 있다.

리듀스의 출력 데이터는 중간단계의 데이터가 아닌 최종 결과물인 경우가 많다. 따라서 리듀스의 출력을 압축하는 경우 문제가 된다. 출력값이 하둡의 블록 사이즈(보통 64MB)보다 큰 경우, 압축된 출력 결과가 2개 이상의 블록으로 분할되게 된다. 대다수의 압축형식에서 이처럼 분할된 압축 파일을 개별적으로 압축 해제할 수 없다. 결국 리듀서의 출력 값을 입력 값으로 사용하는 또다른 Job이 있는 경우, 각 블록마다 태스크가 실행되는 대신 하나의 태스크만 실행되므로 병렬 처리라는 장점을 잃게 된다.

이를 위해 하둡에서는 SequenceFile이라는 특별한 형태의 파일을 지원한다.

JVM의 재사용

태스크트래커는 매퍼와 리듀서에 대해, 별도의 JVM을 새로 할당하여 자식 프로세스로 실행한다. 따라서 초기화 작업이 복잡한 경우, JVM을 실행하는데 시간이 오래 걸린다. 이처럼 JVM을 새로 시작하는데 시간이 오래 걸린다면, Job을 실행하는 전체 시간도 오래 걸린다.

하둡 0.19 버전에서는 동일한 Job의 여러 태스크에 대해 JVM을 재사용할 수 있다. JVM을 재사용하면 태스크의 시작 비용을 줄일 수 있다. JVM을 재사용하려면, mapred.job.reuse.jvm.num.tasks 속성을 변경한다. 또는 JobConf 객체의 setNumTasksToExecutePerJvm(int) 메서드를 활용할 수도 있다.

추론적 실행(Speculative Execution)

맵리듀스 프레임워크는 맵 태스크나 리듀스 태스크가 실패한 경우, 자동으로 태스크를 재실행한다. 이처럼 재실행할 수 있는 이유는 동일한 태스크가 여러번 실행되더라도 동일한 결과가 나오도록 보장하기 때문이다. 이는 수학적 용어로 “멱등성이 보장된다”라고 부른다.

태스크가 실패하지 않더라도 동일한 태스크가 여러번 실행될 수 있다. 예를 들어 특정 노드에서만 태스크가 느리게 진행될 수 있다. 이는 자원 상황(CPU, I/O 등)에 따라 해당 시점에만 발생할 수 있는 경우다. 이 경우 하둡은 동일한 태스크를 다른 노드에서도 실행하게 되며, 가장 빨리 완료된 태스크의 결과를 최종 결과로 사용하며 종료되지 않은 나머지 태스크는 종료시킨다. 이러한 기능을 추론적 실행이라고 부른다.

기본적으로 추론적 실행은 true로 설정되어 있으며, 맵과 리듀서에 대해 개별적으로 설정할 수 있다.

  • mapred.map.tasks.speculative.execution : 매퍼에 대한 설정
  • mapred.reduce.tasks.speculative.execution : 리듀서에 대한 설정

태스크가 모두 완료되어야만 Job이 완료되므로, 특정 태스크가 느리게 처리되는 경우 Job의 전체 실행시간 또한 느려지게된다. 따라서 추론적 실행을 사용하면, 특정 상황에 종속되지 않고 Job의 실행시간이 평균적으로 빠르게 처리된다는 점을 보장한다.

하지만 일반적으로는 추론적 실행을 사용하지 않는다. 이는 태스크가 멱등성을 가지지 않는 경우가 많기 때문이다. 예를 들어 분석 결과를 DB에 저장하는 경우, 추론적 실행을 사용하면 동일한 데이터가 DB에 저장되므로 중복 저장되는 결과를 낳게 된다. 따라서 실행하려는 Job의 특성에 따라 추론적 실행을 설정해야 한다.

DB와의 상호작용

맵리듀스 프로그램의 입력 데이터가 DB에 있거나, 맵리듀스의 결과를 DB에 저장해야 하는 경우가 있을 수 있다. 이 중에서 입력 데이터를 DB에서 가져와야 하는 경우에는 매퍼에서 DB 커넥션을 얻어서 처리하는 방식은 지양해야 한다. 입력 데이터가 많은 경우, 매퍼의 개수는 그에 맞게 늘어나게 되며 결국 DB 커넥션의 수도 그만큼 증가하게 된다. 이 경우 DB에 과부하가 걸리며 전체 Job의 실행 속도가 늦어지거나, DB 자체에 장애가 발생할 수도 있다.

따라서 입력 데이터를 DB로부터 읽어야하는 경우에는 드라이버 클래스에서 DB 커넥션을 하나만 얻어와서 입력 데이터를 파일로 만든 후, 각 맵에서는 해당 파일을 사용하도록 구현해야 한다.

반대로 맵 리듀스의 결과를 DB에 저장해야하는 경우에는 각 리듀서에서 DB 커넥션을 얻어와서 처리할 수 있다. 리듀스는 매퍼에 비해 동시에 실행되는 수가 아주 적으므로, DB 커넥션 또한 많이 사용하지 않기 때문이다. 하둡에서는 이를 위해 DBOutputFormat 클래스를 제공한다.

DBOutputFormat

먼저 드라이버에서 출력 포맷을 DBOutputFormat으로 설정한 후, DB 커넥션 정보는 DBConfiguration 클래스의 configureDB() 메서드를 활용해서 설정한다. 그리고 출력할 데이터를 DBOutputFormat 클래스의 setOutput() 메서드를 활용해서 설정한다.


conf.setOutputFormat(DBOutputFormat.class);
DBConfiguration.configureDB(job, drvierClass, dbUrl, userId, userPass);
DBOutputFormat.setOutput(job, tableName, col1, col2, col3, ...);

태스크 개수 할당 규칙

태스크트래커는 동시에 실행할 수 있는 맵과 리듀서의 최대 개수를 설정할 수 있으며, 기본값은 4개다(맵 2개, 리듀서 2개). 일반적으로 코어 하나당 2개의 태스크를 할당한다. 따라서 쿼드 코어라면 총 6개의 태스크를 설정할 수 있다(맵 3개, 태스크 3개). 태스크 트래커와 데이터노드가 각각 하나의 태스크를 사용하므로, 결국 총 8개의 태스크가 실행되게 된다. 이 경우 전제사항은 해당 태스크에서 CPU를 많이 사용하기 보다는 I/O 작업이 많은 경우다. 만약 CPU 사용이 많은 태스크라면, 설정은 조금 낮추어야 한다.

동시에 실행할 맵과 리듀서의 개수는 각 Job별로 설정할 수도 있다. 맵의 경우 입력 데이터의 크기에 따라 자동으로 설정되며, 리듀서의 개수는 직접 설정이 가능하다. 별도로 설정하지 않는 경우 각 Job별로 하나의 reduce 태스크만 할당된다. 일반적으로 클러스터에서 리듀서 태스크트래커 최대 개수에 0.95 또는 1.75를 곱한 값을 사용한다.

fsck

하둡은 파일 시스템의 상태를 검사할 수 있는 fsck 유틸리티를 제공한다.

bin/hadoop fsck /path/to/directory

fsck

over-replicated 블록 또는 under-replicated 블록의 경우, 시간이 지나면 자동으로 정상으로 돌아온다. 하지만 mis-replicated 블록, corrupt 블록, missing replicas의 경우에는 자동으로 복구가 불가능하다. 이 경우 문제가 된 블록을 삭제하려면, fsck 명령어에 -delete 옵션을 사용한다. 또는 -move 옵션을 사용해 일단 /lost-found로 옮긴 후, 이후에 복구작업을 수행할 수도 있다.

권한 관리

하둡은 일반적으로 하둡이 실행된 시스템의 사용자 권한 체계를 그대로 따른다. 주의할 점은 하둡을 실행한 사용자는 하둡 파일 시스템에서 슈퍼유저로 분류된다. 만약 슈퍼유저 권한을 또다른 사용자에게 주고자한다면, dfs.permissions.supergroup 파라미터를 설정한다.

데이터노드 제거 및 추가

특정 데이터노드가 장애가 난 경우, 단순히 노드를 클러스터에서 네트워크 연결을 끊더라도 HDFS은 정상적으로 운영된다. 그리고 장애가 난 데이터노드에 있던 블록을 복제 계수를 맞추기 위해 자동으로 복제작업을 시작한다. 하지만 좀더 안정적으로 제거하고자 한다면 디커미션(decommsion) 기능을 사용해야 한다.

먼저 네임노드가 설치된 노드에서 dfs.hosts.exclude 파일에 제거할 노드를 “호스트명 IP” 형태로 추가한다. 그런후 네임노드에서 아래의 명령어를 실행한다.

bin/hadoop dfsadmin -refreshNodes

그러면 네임노드는 디커미션 작업을 실행하여 해당 노드를 제거하게 된다.

데이터노드 추가 작업 또한 간단하다. 단순히 데이터노드 데몬과 태스크트래커 데몬을 실행하면 된다. 네임노드가 재실행될 경우를 대비해서, 네임노드의 conf/slaves 파일에 추가할 데이터노드를 추가하는 것도 잊지 말자.

이보다 중요한 작업은 데이터를 옮기는 일이다. 추가된 새로운 노드에는 디스크가 비어 있으므로, 기존의 데이터노드에서 블록을 복제하여 새로운 노드에 복사해야 한다. 이를 위해 밸런서를 실행해야 한다.

bin/start-balancer.sh

위의 명령어는 백그라운드에서 실행되며, 데이터 분포가 균형을 이룰때까지 실행된다.

클러스터가 균형을 이룬다는 말은 각 데이터노드의 사용률이 시스템의 평균 사용률의 임계치 내에 들어왔다는 말이다 일반적으로 임계치는 10%이다. 밸런서를 실행할 때, 임계치를 설정할 수 있다. 아래는 임계치를 5%로 설정하여 밸런서를 실행하는 경우다.

bin/start-balancer.sh -threshold 5

네임노드와 세컨데리 네임노드

네임노드는 시스템의 메타데이터와 블록에 대한 위치정보를 메모리에 유지한다. 네임노드는 드라이브 문제로 인한 데이터 손실을 막기 위해서 RAID 드라이브를 사용해야 한다.

네임노드는 HDFS에 저장된 파일의 블록에 대한 매핑정보를 메모리에 유지하므로, 블록이 많아질수록 성능이 느려질 수 있다. 따라서 블록 사이즈를 크게 하면 매핑정보가 그만큼 줄어들게 된다. 반면에 블록 사이즈가 커지면, 맵리듀스에서 병렬적으로 처리할 수 있는 태스크의 개수가 작아지므로, 입력 파일의 사이즈가 작은 경우 Job 프로그램의 실행속도가 느려질 수도 있다.

기본적으로 블록 사이즈는 64MB이며, 경우에 따라 128MB로 설정하기도 한다. 블록 사이즈는 dfs.block.size 속성을 설정하면 된다.

세컨데리 네임노드로 구동할 노드는 반드시 네임노드와 동일한 하드웨어 스펙을 사용해야 한다. 이를 이해하려면 네임노드와 세컨데리 네임노드 사이의 관계에 대해 이해하여야 한다.

secodary-name-node

네임노드는 fsimage와 edlits 로그 파일을 이용하여 파일 시스템의 상태정보를 관리한다. fsimage 파일은 파일 시스템 전체의 특정 시점에 대한 스냅샷이며, edits 로그 파일은 해당 시점 이후의 변경사항을 기록한 로그 파일이다. 따라서 두 개의 파일을 이용하면 파일 시스템의 현재 상태를 정확히 알 수 있다.

네임노드가 구동될 때 네임노드는 두 파일을 병합하여 현재 시점에 대한 스냅샷을 fsimage 파일에 기록한다. 그리고 비어 있는 edits 로그 파일이 만들어진다. 이후의 변경사항은 모두 edits 로그 파일에 기록된다. 네임노드는 파일 시스템의 상태 정보에 대한 복사본(fsimage와 edits 로그 파일이 병합된 정보)을 메모리에 상주시켜, 클라이언트 요청에 빠르게 응답한다.

이때 문제는 edits 로그 파일이 너무 커질 경우, 네임노드를 재기동할 때 병합하는 시간이 오래 걸리므로 재기동하는 시간 또한 오래 걸리게 된다. 이를 위해 fsimage 파일과 edits 로그 파일을 병합하는 작업을 주기적으로 실행하게 된다. 네임노드의 경우 파일 시스템 전체에 대한 마스터 역할을 수행하므로, 병합 작업과 같이 자원을 많이 차지하는 작업은 별도의 노드에서 수행하게 되는데, 바로 이 서버가 세컨데리 네임 노드다. 즉 세컨데리 네임노드는 네임 노드로부터 fsimage 파일과 edits 로그 파일을 fs.checkpoint.dir 디렉토리로 주기적으로 가져와서 병합하여, 해당 시점의 스냅샷을 기록한다. 그리고 병합된 fsimage 파일은 다시 네임노드로 복사하며, 네임노드는 병합된 fsimage 파일을 저장하게 된다.

따라서 세컨데리 네임노드는 백업용 노드가 아닌, 현재 상태의 파일 시스템 정보를 기록하기 위한 체크포인트 서버로 이해해야 한다. 결국 세컨데리 네임노드는 네임 노드와 동일한 파일을 관리해야 하므로 최소한 동일한 크기의 메모리를 보장받아야 한다.

네임노드 장애복구

현재 네임노드는 이중화 구성을 할 수 없다. 네임노드는 하둡 파일 시스템에서 단일 장애지점에 해당한다. 일반적으로 세컨데리 네임노드를 백업용 노드로 활용하여, 네임노드에 장애가 발생했을 때를 대비한다. 물론 장애가 발생한다고 해서 세컨데리 네임노드가 자동으로 네임노드의 역할을 수행하는 것은 아니며, 약간의 수고를 들여야한다. 하지만 데이터는 손실되지 않도록 보장할 수 있게 된다.

다수의 디스크를 활용한 장애복구

네임노드에 디스크가 2개 이상인 경우, dfs.name.dir 속성에 해당 디스크를 모두 설정한다. 따라서 첫번째 디스크에 장애가 발생한다면, 네임노드는 두번째로 지정된 디스크를 자동으로 사용하게 된다.

세컨데리 네임노드를 활용한 장애복구

디스크 뿐만 아니라 네임노드가 설치된 머신 자체가 장애가 난 경우를 대비해서 세컨데리 네임노드를 백업 노드로 활용할 수 있다. 마찬가지로 dfs.name.dir 속성에 세컨데리 네임노드의 디스크를 추가한다. 그리고 네임노드에 장애가 발생한 경우, 세컨데리 네임노드의 IP의 네임노드의 IP로 변경한 후 네임노드를 재실행한다. 각 데이터 노드는 IP를 기반으로 네임노드와 통신하므로 반드시 IP를 변경해야만 한다.

네임노드 이중화

현재 네임노드를 Active / Stand-by 형태로 이중화할 수 있는 작업이 진행중인 듯하다.

Job 스케쥴링

기본적으로 하둡은 FIFO 스케쥴러를 사용한다. 즉 모든 Job은 실행된 순서대로 차례차례 실행되게 된다. 따라서 한번에 한개의 Job만을 실행할 수 있다.

하지만 경우에 따라 2개 이상의 Job을 동시에 실행하길 원할 수도 있다. 이를 위해 페이스북에서는 Fair 스케쥴러를, 야후에서는 Capacity 스케쥴러를 구현했다.

페어(Fair) 스케쥴러

페어 스케쥴러에서 중요한 개념은 태스크 풀(task pool)이다. 각 Job은 모두 특정 풀에 속하며, 각 풀은 모두 최소한의 맵과 리듀스 개수를 보장받는다. 또한 Job마다 우선순위를 설정할 수 있으며, 우순 선위가 더 높은 Job은 더 많은 태스크 개수를 할당받는다.

페어 스케쥴러를 사용하려면 설정파일을 아래와 같이 수정해야 한다.


<property>
    <name>mapred.jobtracker.taskScheduler</name>
    <value>org.apache.hadoop.mapred.FairScheduler</value>

</property>
<property>
    <name>mapred.fairscheduler.allocation.file</name>
    <value>HADOOP_CONF_DIR/pools.xml</value>

</property>
<property>
    <name>mapred.fairscheduler.assignmultiple</name>
    <value>true</value>

</property>
<property>
    <name>mapred.fairscheduler.poolnameproperty</name>
    <value>pool.name</value>

</property>
<property>
    <name>pool.name</name>
    <value>${user.name}</value>

</property>

위의 설정 파일을 좀더 자세히 살펴보자. 먼저 사용할 스케쥴러의 클래스명을 수정한다.

<property>
    <name>mapred.jobtracker.taskScheduler</name>
    <value>org.apache.hadoop.mapred.FairScheduler</value>
</property>

태스크 풀에 대한 설정정보를 저장한 파일의 경로를 설정한다.

<property>
    <name>mapred.fairscheduler.allocation.file</name>
    <value>HADOOP_CONF_DIR/pools.xml</value>
</property>

Job이 실행될 때 어느 풀을 사용할지 결정하는 기준을 설정한다. 여기에서는 pool.name, 즉 풀의 이름을 기준으로 선택하도록 설정한다.

<property>
    <name>mapred.fairscheduler.poolnameproperty</name>
    <value>pool.name</value>
</property>

pool.name의 기본값을 ${user.name}으로 설정하면, job을 실행한 사용자 계정을 기준으로 사용할 풀을 선택하게 된다.

아래는 풀에 대한 설정을 담고 있는 pools.xml 파일이다.

<?xml version="1.0">
<allocations>
    <pool name="hadoop">
        <minMaps>2</minMaps>
        <minReduces>2</minReduces>
    </pool>

    <pool name="hive">
        <minMaps>2</minMaps>
        <minReduces>2</minReduces>
        <maxRunningJobs>2</maxRunningJobs>
    </pool>
    <user name="bulk">
        <maxRunningJobs>5</maxRunningJobs>
    </user>
    <userMaJobsDefault>3</userMaxJobsDefault>
</allocations>

pools.xml 파일은 매 15초마다 자동으로 다시 읽히므로, 변경사항은 바로바로 반영되게 된다. 이 파일에 정의되지 않은 pool은 최소한의 태스크 수를 보장받지 못하게 된다.

페어 스케쥴러를 사용한 경우 최대 이점은 웹 모니터링 UI 화면이다. http://masternode:50030/scheduler 로 접속해보면, 페어스케쥴러에서만 사용할 수 있는 기능을 확인할 수 있다.

hadoop_mapreduce_fair_scheduler

웹 UI 상에서 풀에 대한 정보 및, Job의 우선순위를 바꿀수도 있다.

 

크몽 재능

하둡 척와(Hadoop Chukwa) 초보 가이드 – 에이전트 영향도 분석

이 글은 크몽 재능인, socurites님이 원고를 기고하셨습니다.

척와 초보자를 위한 가이드로, 총 3개로 구성되어 있습니다.

  1. 기본
  2. 설치하기
  3. 에이전트 영향도 분석

척와 에이전트의 경우, 로그를 수집할 대상 서버에 설치된다. 따라서 에이전트로 인해 해당 서버의 본래의 기능에 영향을 미쳐서는 안된다. 이를 위해 척와 에이전트가 설치되었을 때 로그 수집 대상 서버에 미치는 영향도를 분석하고자 한다.

준비사항

로그 생성 서버

테스트 목적으로 로그를 생성하는 데모 서버를 다운 받는다.

demo_loggers.jar

해당 서버를 실행하면, /tmp/ws_demo_log 디렉토리에 demo라는 이름의 로그를 생성한다.

척와 어댑터

데모 서버가 생성한 로그를 tailing할 어댑터를 initial_adaptors 설정 파일에 등록한다.

add filetailer.FileTailingAdaptor DaemonData /tmp/ws_demo_log/demo 0

성능 측정 스크립트

성능 측정 스크립트인 usage_ps.sh 스크립트를 아래와 같이 작성한다

pid=`cat /tmp/chukwa/pidDir/Agent.pid`
out_file="output_$1.txt"
rm -rf $out_file
echo "%CPU $MEM VSZ RSS" >> $out_file
while (true)
do
    sleep 3
ps aux | grep $pid | grep -v grep | awk '{print $3, $4, $5, %6 }' &>> $out_file
done

영향도 분석 시나라오

영향도 분석을 위한 시나리오는 다음과 같다.

  1. 척와 컬렉터, 척와 에이전트를 실행한다.
  2. 로그 생성 데몬 서버를 실행한다.
    java -cp ./demo_loggers.jar com.socurites.utils.web.server.demo.Main [number of Visitor]
    

    [number of Visitor]에는 실제 서버에서 발생하는 접속자 수 증가 등을 반영하기 위해 임의의 숫자를 입력한다. 여기에서는 3, 100, 1000을 사용했다.

  3. 성능 측정 스크립트를 실행한다.
    sh usage_ps.sh [number of Visitor]
    

    [number of Visitor]는 선택적인 옵션으로, 데모 서버를 실행할 때 사용했던 숫자와 동일한 숫자를 입력한다. 성능 결과는 현재 디렉토리에 output_[number of Visitor].txt 라는 이름으로 생성된다. 따라서 [number of Visitor]를 인자로 주지 않으면 output_.txt 라는 이름으로 생성되며, 여기에서는 옵션을 주지않고 실행했다.

 작업 과정

아래와 절차에 따라 작업을 수행했다.

[number of Visitor] = 3인 경우

시나리오 1번 과정, 3번 과정을 먼저 처리 한후, [number of Visitor]에 3을 설정한 후 그 결과를 수집했다. 이에 따른 데모 서버의 처리 결과는 다음과 같다.

===========================================
SUMMARY
===========================================
= Started At: 2011-11-29 20:14:30
= Ended At: 2011-11-29 20:15:20
= Size(bytes): " + fileSize); 84162
= Log Size/Time(Bytes/Sec): 1
===========================================

[number of Visitor] = 100인 경우

로그 데모 서버를 중지한 후, [number of Visitor]에 100을 설정해서 서버를 재실행하여 그 결과를 수집했다. 이에 따른 데모 서버의 처리 결과는 다음과 같다.

===========================================
SUMMARY
===========================================
= Started At: 2011-11-29 20:15:24
= Ended At: 2011-11-29 20:16:13
= Size(bytes): " + fileSize); 2754700
= Log Size/Time(Bytes/Sec): 55
===========================================
<p>

[number of Visitor] = 1000인 경우

로그 데모 서버를 중지한 후, [number of Visitor]에 1000을 설정해서 서버를 재실행하여 그 결과를 수집했다. 이에 따른 데모 서버의 처리 결과는 다음과 같다.

===========================================
SUMMARY
===========================================
= Started At: 2011-11-29 20:16:29
= Ended At: 2011-11-29 20:17:10
= Size(bytes): &quot; + fileSize); 21950227
= Log Size/Time(Bytes/Sec): 538
===========================================

서버 처리 결과에서 보는 바와 같이 로그 생성 속도는 선형적으로(1 -> 55 -> 538)로 증가함을 알 수 있다.

결과 분석

영향도를 측정한 결과 파일은 다음과 같다 (중간 부분은 일부 생략했다).

%CPU %MEM VSZ RSS
1.4 1.5 419024 27224
1.3 1.5 419024 27224
1.3 1.5 419024 27224
1.1 1.5 419024 27224
1.1 1.5 418928 27292
0.9 1.5 418928 27324

확인 결과 오히려 CPU와 메모리 사용률이 증가하지 않고, 적어지는 결과가 나왔다. 눈으로 보이는 결과만 봐서는 두 가지 결론을 내릴 수 있다.

  • 측정 방법에 문제가 있다.
  • 실제로 척와 에이전트가 로그 수집 대상 서버에는 영향을 미치지 않는다.

추가적인 분석

분석작업을 수행하면서 이와 동시에 척와 에이전트 로그를 tailing해서 실제로 에이전트가 어떻게 로그를 처리하고 있는지 함께 확인했다. 물론 정량적인인 분석은 아니며, 육안으로 확인할 결과다.

  • [number of Visitor]를 증가시켜 로그 생성 데모 서버를 실행하더라도, 척와 에이전트 로그의 생성 속도가 더 빨라지지 않았다. 이 현상을 통해 “로그 생성 속도가 빨라지더라도 척와 에이전트의 처리 속도가 그에 맞게 빨라지는게 아니라 정해진 속도를 따라 로그를 수집함”을 추정해볼 수 있다.
  • 앞의 두 작업([number of Visitor]가 3과 100이었던 경우)에서는 로그 데모 서버가 중지한 경우, 척와 에이전트 로그 또한 더 이상 로그가 쌓이지 않았다. 반면에 마지막 작업([number of Visitor]를 1000으로 지정한 경우)에서는 로그 데모 서버를 죽이고 나서도 척와 에이전트 로그가 한참동안 계속해서 쌓였다. 결국 “로그 생성 속도가 특정 값을 넘어서면 척와 에이전트의 로그 수집 속도가 따라가지 못하게 됨“을 추정해 볼 수 있다. 따라서 날짜가 바뀌는 경우 어떻게 처리할 것인지에 대한 문제가 숙제로 남았다.

참고자료

  • 클라우드 컴퓨팅 구현 기술 / 깅형준, 조준호, 안성화, 김병준 저 / 에이콘 출판사
  • 하둡 완벽 가이드 / 톰 화이트 지음 / 오라일리 출판사
  • Chukwa Documentation 4.0

크몽 재능

하둡 척와(Hadoop Chukwa) 초보 가이드 – 설치하기

이 글은 크몽 재능인, socurites님이 원고를 기고하셨습니다.

 척와 초보자를 위한 가이드로, 총 3개로 구성되어 있습니다.

  1. 기본
  2. 설치하기
  3. 에이전트 영향도 분석

설치전 준비사항

척와를 설치하려면 아래와 같은 항목이 먼저 준비되어야 한다.

  • 리눅스 플랫폼을 사용한다.
  • 1.6 이상 버전의 자바가 설치되어 있어야 한다.
  • Hadoop 0.20.2 버전을 다운로드 받아야 한다.
  • 여기에서는 HICC를 설치하지 않을 것이므로 MySQL은 필요 없다.

척와 구성 요소

척와는 아래와 같은 요소로 구성된다. 따라서 척와를 설치하려면 하둡 클러스터, 척와 에이전트, 척와 컬렉터를 설치해야 한다.

chukwa_system_diagram

  • 데이터를 저장할 하둡 클러스터(척와 클러스터)
    여기에서는 하둡 파일 시스템을 의사 분산 모드로 설치했다고 가정한다. 자세한 내용은 의사 분산 모드로 하둡(Hadoop) 실행하기을 참고하라
  • 척와 에이전트
    로컬 머신에서 모니터링한 로그 데이터를 전송한다
  • 척오 컬렉터
    에이전트에서 수신한 데이터를 HDFS에 저장한다

예제 구성

여기에서는 아래와 같은 구성으로 척와를 구성하고자 한다.

chukwa_sample

두 대의 리눅스 머신 중에서 하나는 척와 에이전트를, 나머지 하나는 척와 컬렉터를 설치하고자 한다. 척와 컬렉터를 설치한 머신에는 하둡을 의사 분산 모드로 설치해서, 로그 데이터를 저장하는 역할까지 하도록 한다.

척와 설치 공통사항

아래의 사항은 에이전트와 컬렉트를 설치할 머신에서 공통적으로 설정해야 하는 작업이다.

척와 설치하기

척와를 척와 릴리즈 페이지에서 다운로드 받는다. 여기에서는 chukwa-0.4.0.tar.gz를 다운로드 받았다.

로컬 파일 시스템의 적당한 위치에 압축을 푼다. 이렇게 하둡이 설치된 디렉토리를 CHUKWA_HOME이라고 부르자.

$ tar xvf chukwa-0.4.0.tar.gz

척와 관련 명령어를 쉽게 실행하기 위해 척와 설치 디렉토리(CHUKWA_HOME)를 환경 변수에 설정하고, PATH를 설정한다(필수 사항은 아니다). 여기에서는 .bashrc 파일에 설정했다

#CHUKWA
export CHUKWA_HOME=척와가 설치된 경로
export PATH=$PATH:$CHUKWA_HOME/bin

척와 공통 정보 설정하기

척와 공통 정보를 conf/chukwa-env.sh에 설정한다 (에이전트와 컬렉터가 설치된 머신 모두에 설정해야 한다).

JAVA_HOME 환경변수를 설정한다. 시스템 환경변수(.bashrc)에 설정해도 상관 없지만, 여기에서는 conf/chukwa-env.sh에 설정한다.

export JAVA_HOME=/usr/lib/jvm/java-6-sun5

척와 콘솔 로그와 pid 로그를 저장할 디렉토리를 conf/chukwa-env.sh에 설정한다. 여기에서는 디폴트 값을 그대로 사용한다.

export CHUKWA_PID_DIR=/tmp/chukwa/pidDir
export CHUKWA_LOG_DIR=/tmp/chukwa/log

척와 콘솔 로그 파일에 이름을 붙일 때 사용할 CHUKWA_IDENT_STRING을 conf/chukwa-env.sh에서 설정한다. 여기에서는 디폴트 값을 그대로 사용한다.

export CHUKWA_IDENT_STRING=chukwa

척와 에이전트 설치하기

척와 에이전트를 설치 과정은 “1. 척와 에이전트 옵션 설정하기”, “2. 에이전트 등록하기”, “3. 컬렉터 등록하기”, “4. 어댑터 등록하기”, 총 4개의 작업으로 구성된다.

에이전트 옵션 설정하기

척와 에이전트는 conf/chukwa-agent-conf.xml에서 설정한다. 디폴트 그대로 사용해도 실행하는데 문제가 없으며, 필요에 따라 아래의 옵션을 설정한다.

  • chukwaAgent.tags
    척와 클러스터명으로, 모니터링하고 있는 노드에 대한 식별자다. 이 정보는 수집한 각 청크에 저장되므로, 해당 청크가 어느 머신에서 전송되었는지를 이 정보를 통해 구분할 수 있다. 여기에서는 디폴트 값 그대로 둔다.
  • chukwaAgent.checkpoint.dir
    컬렉터에 데이터를 전송하면서 장애가 발생했을 때, 마지막으로 전송한 청크의 오프셋 정보를 저장할 때 사용한다. 여기에서는 디폴트 값을 그대로 사용한다.

에이전트 등록하기

에이전트로 실행할 전체 에이전트 목록을 conf/agents에 설정한다. 여기에서는 에이전트가 로컬서버 한대이므로 localhost만 등록한다.

#agent
localhost

컬렉터 등록하기

데이터를 전송할 컬렉터를 conf/collectors에 등록한다. 척와는 이 파일에서 컬렉터를 임의로 골라서 해당 컬렉터로 데이터를 전송한다. 해당 컬렉터에 장애가 발생하면, 컬렉터 목록에서 다른 컬렉터를 선택하는 방식으로 로그 유실을 방지한다.

여기에서는 221번 서버가 컬렉터이므로, 이 컬렉터에 대한 정보를 등록한다. 실행할 전체 컬렉터 목록은 컬렉터가 설치된 머신의 conf/collectors에서 설정한다.

# collectors
http://33.33.211.221:8080

어댑터 등록하기

데이터를 수집할 어댑터를 conf/initial_adaptors에 등록한다. 이처럼 어댑터를 설정파일에 등록할 수도 있지만, 실행 중인 에이전트에 어댑터를 직접 추가할 수도 있다.

여기에서는 conf/initial_adaptors.template 파일을 참조해서 만든다. 템플릿 파일에 등록된 어댑터 중에서 Df, Top에 해당하는 어댑터 2개만 conf/initial_adpators에 등록한다.

add org.apache.hadoop.chukwa.datacollection.adaptor.ExecAdaptor Df 60 /bin/df -l 0
add org.apache.hadoop.chukwa.datacollection.adaptor.ExecAdaptor Top 60 /usr/bin/top -b -n 1 -c 0

척와 에이전트 관리하기

척와 에이전트는 아래의 명령어를 실행해서 데몬으로 실행할 수 있다.

$ bin/start-agents.sh

명령어를 실행하면 conf/agents에 나열단 각 머신에 ssh로 접속해서 에이전트를 실행한다. 이 경우 에이전트가 로컬호스트 하나 뿐이므로, 로컬호스트의 에이전트가 실행된다.

척와 에이전트를 중지하려면 아래의 명령어를 실행한다.

$ bin/stop-agents.sh

에이전트가 제대로 동작중인지는 에이전트 포트(디폴트로 9093을 사용한다)에 텔넷으로 접속해서 확인할 수 있다. 에이전트가 정상적으로 동작중이라면, 에이전트와 관련된 상태 메시지가 나온다.

척와 컬렉터 설치하기

하둡 설정하기

컬렉터에서 수집한 데이터를 저장해야 하므로, 하둡과 관련된 설정을 추가해야 한다. conf/chukwa-env.sh에 HADOOP_HOME과 HADOOP_CONF_DIR을 아래와 같이 설정한다.

export HADOOP_HOME="하둡이 설치된 위치"
export HADOOP_CONF_DIR="${HADOOP_HOME}/conf"

척와 옵션 설정하기

척와 컬렉터는 conf/chukwa-collector-conf.xml에서 옵션을 설정할 수 있다. 반드시 설정해야 하는 부분은 writer.hdfs.filesystem다. 여기에서는 의사 분산 모드로 설치한 하둡 파일 시스템을 설정한다.

<property>
    <name>writer.hdfs.filesystem</name>
    <value>hdfs://localhost:9000</value>
    <description>HDFS to dump to</description>
</property>

이 외에도 컬렉터에서는 아래와 같은 속성을 설정할 수 있다.

  • chukwaCollector.writerClass
    – 로그 레코드를 저장할 Writer 클래스
    – 디폴트: org.apache.hadoop.chukwa.datacollection.writer.PipelineStageWriter
  • chukwaCollector.pipeline
    – PipelineStageWriter에서 사용할 Writer 클래스. 콤마로 분리해서 설정한다.
    – 디폴트: org.apache.hadoop.chukwa.datacollection.writer.SocketTeeWriter, org.apache.hadoop.chukwa.datacollection.writer.SeqFileWriter
  • writer.hdfs.filesystem (필수)
    – 수집한 로그를 저장할 하둡 파일 시스템
  • chukwaCollector.outputDir
    – 수집한 로그(싱크 파일)를 저장할 하둡의 디렉토리
    – 디폴트: /chukwa/logs/
  • chukwaCollector.rotateInterval
    – 오픈한 파일을 close()하는 주기 (ms)
    – 디폴트: 300000
  • chukwaCollector.http.port
    – 컬렉터가 리스닝할 포트 번호
    – 디폴트: 8080

컬렉터 등록하기

실행할 컬렉터는 모두 conf/collectors에 등록한다. 여기에서는 221번 서버가 컬렉터이므로, 이 컬렉터에 대한 정보를 등록한다.

http://33.33.211.221:8080

척와 컬렉터 관리하기

척와 컬렉터는 아래의 명령어를 실행해서 데몬으로 실행할 수 있다.

$ bin/start-collectors.sh

그러면 conf/collectors에 나열된 각 머신에 ssh로 접속해서 컬렉터를 모두 실행한다.

척와 컬렉터를 중지하려면 아래의 명령어를 실행한다.

bin/stop-collectors.sh

컬렉터가 제대로 동작중인지 확인하려면 브라우저에서 http://collectorhost:collectorport/chukwa?ping=true 로 접속한다. 여기에서는 http://localhost:8080/chukwa?ping=true 로 접속해 보면 아래와 같이 컬렉터와 관련된 상태 정보를 확인할 수 있다.

Date:1322449269195
Now:1322449296866
numberHTTPConnection in time window:0
numberchunks in time window:0
lifetimechunks:0

마지막으로 데이터 처리 프로세스를 실행한다.

$ start-data-processors.sh

그러면 아카이빙, 디먹스, HICC용 데이터 프로세싱 작업이 실행되고 이를 통해 주기적으로 데이터를 처리하게 된다. 실제로 start-data-processors.sh를 열어서 보면 아래와 같이, archive, demux, dp를 차례대로 실행함을 알 수 있다.

# start data processors
"$bin"/chukwa-daemon.sh --config $CHUKWA_CONF_DIR start archive
"$bin"/chukwa-daemon.sh --config $CHUKWA_CONF_DIR start demux
"$bin"/chukwa-daemon.sh --config $CHUKWA_CONF_DIR start dp

실행과정 눈으로 확인하기

이렇게 설치가 끝났다면, 실제로 척와 관련 데몬을 실행해서 제대로 실행되는지 확인해 보자.

척와 실행하기

이렇게 설정을 다했다면 아래와 같은 구성으로 관련 데몬을 실행한다.

chukwa_sample_daemo

척와 에이전트 실행 확인하기

척와 에이전트가 설치된 머신에서 /tmp/chukwa/logs로 이동한다. 해당 디렉토리에는 agent.log가 아래와 같이 생성되어 있다.

HTTP post thread ChukwaHttpSender - collected 14 chunks for post_53
HTTP post thread ChukwaHttpSender - >>>>>> HTTP post_53 to http://33.33.211.211:8080/ length=18715
HTTP post thread ChukwaHttpSender - >>>>>> HTTP Got success back from http://33.33.211.211:8080/chukwa; response length 826
HTTP post thread ChukwaHttpSender - post_53 send 0 chunks, got back 14 acks

척와 컬렉터 실행 확인하기

척와 컬렉터가 설치된 머신에서 /tmp/chukwa/logs로 이동한다. 해당 디렉토리에는 collector.log가 생성되어 있으며, 컬렉터와 관련된 로그를 확인할 수 있다.

하둡 파일 시스템 확인하기

척와 컬렉터의 데이터 프로세스를 실행했다면, http://localhost:50070/ 로 접속해서 아래와 같이 척와 스토리지를 확인할 수 있다.

chukwa_hadoop_console

참고자료

  • 클라우드 컴퓨팅 구현 기술 / 깅형준, 조준호, 안성화, 김병준 저 / 에이콘 출판사
  • 하둡 완벽 가이드 / 톰 화이트 지음 / 오라일리 출판사
  • Chukwa Documentation 4.0

크몽 재능

하둡 척와(Hadoop Chukwa) 초보 가이드 – 기본

이 글은 크몽 재능인, socurites님이 원고를 기고하셨습니다.

 척와 초보자를 위한 가이드로, 총 3개로 구성했습니다.

  1. 기본
  2. 설치하기
  3. 에이전트 영향도 분석

개요

하둡 척와(Chukwa)는 분산된 서버에서 로그 데이터를 수집하여 저장하며, 저장한 데이터를 분석하기 위해서 만들어졌다. 또한 하둡 클러스터의 로그, 서버의 상태 정보 등을 관리할 수 있는 기능도 포함되어 있다.

장점

  • 로그를 생성하는 응용 프로그램의 로그 저장 모듈을 수정하지 않고도 로그를 수집할 수 있다.
  • 수집된 로그 파일을 하둡 파일 시스템(HDFS)에 저장한다. 따라서 하둡 파일 시스템의 장점을 그대로 가진다.
  • 실시간 분석도 가능하다.

단점

  •  하둡 파일 시스템이 먼저 설치되어 있어야 한다. 하지만 하둡은 단순히 압축만 풀어서 설치할 수 있으므로 큰 문제는 아니다.

척와 시스템 구성

척와 시스템은 아래와 같이 구성된다.

chukwa_system_diagram

  • 척와 에이전트(agent)
    로그를 수집할 대상 서버(Monitored Source Node)에 설치한다. 에이전트는 해당 서버의 로그 파일이나 서버 정보를 컬렉터로 전송한다.
  • 척와 컬렉터(collector)
    여러 대의 에이전트로부터 로그 정보를 수신해서 하둡 파일 시스템에 저장한다.
  • 데이터 프로세싱(data processing)
    컬렉터가 수신한 데이터에 대해 아카이빙(archiving), 디먹스(demux) 등의 작업을 수행해서 처리한다.
  • HICC(Hadoop Infrastructure Care Center)
    하둡 클러스터의 로그 파일과 시스템 정보를 수집해서 분석한 후, 웹 UI를 통해 보여준다. 일반적인 로그 수집을 위한 용도가 아니라 하둡 클러스터 자체를 관리하는 기능이므로, 여기에서는 다루지 않겠다.

에이전트

척와 에이전트 자체에서 데이터를 직접 수집하지는 않고, 어댑터(adaptor)를 통해서 수집한다. 어댑터는 에이전트 프로세스 안에서 실행되며, 데이터를 실제로 수집하는 역할을 한다. 에이전트에 어댑터를 등록하는 방법에는 두 가지가 있다.

  • 에이전트가 시작할 때 읽어들이는 환경 설정 정보(conf/initial_adaptors)에 어댑터를 추가
  • 실행 중인 에이전트에 직접 어댑터를 추가

에이전트는 실행될 때 환경 설정 파일(conf/collectors)을 읽어들인 후, 이 중에서 하나의 컬렉터를 랜덤하게 선택해서 데이터를 전송한다. 선택한 컬렉터 서버에 장애가 생긴면, 설정 파일에 등록된 다른 컬렉터 서버에 데이터를 전송한다.

  • 에이전트 쪽 로그 유실 방지
    모든 컬렉터 서버에 장애가 있다면, 마지막으로 전송된 파일의 오프셋 정보(checkpoint)를 로컬 파일 시스템에 기록해 둔다. 이후에 컬렉터에 정상적으로 데이터를 전송할 수 있을 때가 되면, 해당 오프셋 이후의 데이터를 전송한다. 이러한 방식을 통해 로그 유실을 방지한다.

컬렉터

에이전트로부터 전송된 데이터를 주기적으로 하둡 파일 시스템에 저장한다. 이때 한 컬렉터는 여러 대의 에이전트 서버로부터 데이터를 전송받지만, 이를 하나의 파일에 저장한다. 이처럼 컬렉트가 저장하는 파일을 싱크(sink) 파일이라고 부르며, 하둡 파일 시스템의 SequenceFile 포맷으로 저장한다.

  • 컬렉터 쪽 로그 유실 방지
    하둡 파일 시스템은 파일을 저장할 때 특정 크기(64MB) 이상이 되지 않으면 close() 명령을 이용해서 파일을 닫지 않는 한 파일 내용이 보이지 않는다. 따라서 파일을 저장하는 클라이언트(이 경우 컬렉터)가 비정상 종료된 경우, 해당 데이터가 유실될 수 있다. 척와에서는 데이터가 유실되는 일을 방지하기 위해, 주기적으로 새로운 파일을 생성하고 에이전트에서 전송받은 데이터를 새로운 파일에 저장한 후 close()한다.

컬렉터는 로그 파일을 하둡 파일 시스템에 저장한다. 하지만 사용자 정의 Writer를 지정할 수도 있다. 예를 들어 척와에서 제공하는 PipelineStageWriter를 사용하면, 하나의 로그에 대해 여러 개의 Writer를 사용할 수 있다. 이를 통해 로그를 저장하는 동시에, 실시간으로 분석할 수도 있다. 실제로 척와에서는 디폴트로 PipelineSgateWriter를 사용한다.


// chukwa-collector-conf.xml 중에서

....

<property>

    <name>chukwaCollector.writerClass</name>

    <value>org.apache.hadoop.chukwa.datacollection.writer.PipelineStageWriter</value>

</property>

<property>

    <name>chukwaCollector.pipeline</name

    <value>org.apache.hadoop.chukwa.datacollection.writer.SocketTeeWriter,

org.apache.hadoop.chukwa.datacollection.writer.SeqFileWriter</value>

</property>

...

데이터 프로세싱

척와에서 로그 데이터를 처리하는 작업에는 아카이빙(archiving)과 디먹스(demux), 2가지 작업이 있다.

  • 아카이빙(archiving)
    아카이빙은 컬렉터가 저장한 로그 파일을 이용해서 시간 순서와 동일한 그룹으로 묶는 작업을 수행한다. 아카이빙에서는 데이터의 중복을 제거하고 정렬작업을 수행한 후, 하둡의 SequenceFile 포맷으로 저장한다.
  • 디먹스(demux)
    디먹스는 로그 레코드를 파싱해서 키-값 쌍으로 구성되는 ChukwaRecord를 만든 후, 하둡 파일 시스템에 다시 파일로 저장한다.

뿐만 아니라 맵리듀스(MapReduce)를 직접 만들어서, 아키이빙과 디먹스 작업이 완료된 데이터에 대해 맞춤형 분석 작업을 할 수도 있다. 척와 내부적으로도 PostProcessing이라는 작업을 수행한다. 디먹스가 완료된 데이터 중에서 하둡 클러스터의 시스템 메트릭 정보 등을 HICC에서 사용하는 데이터로 변환한 후, MySQL에 저장하는 과정이 PostProcessing 작업이다. PosteProcessing 코드를 참조하면, 로그 파일을 요구에 맞게 분삭하는 시스템을 구축할 수 있을 것으로 보인다.

척와 데이터 모델

척와 어댑터는 데이터를 청크(chunk) 단위로 전송한다. 청크란 일련의 바이트로 구성되며, 메타데이터가 일부 포함된다. 이러한 메타데이터는 다음과 같다. 이 중에서 Cluster와 Datatype은 사용자가 직접 설정해야 한다.

  • Source
    청크가 생성되는 호스트명
    자동으로 설정된다
  • Cluster
    호스트가 연결된 클러스터
    conf/chukwa-env.sh에 사용자가 설정한다.
  • Datatype
    출력 포맷
    어댑터를 구동할 때 사용자가 지정한다.
  • Sequence ID
    스트림에서 청크의 오프셋
    자동으로 설정되며, 초기 오프셋은 어댑터가 실행될데 설정된다.
  • Name
    데이터 소스 이름
    자동으로 설정되며, 어댑터가 선택한다.

장애가 발생했을 때 로그를 재전송하는 경우, 로그 데이터의 중복을 방지하기 위해서 이러한 메타데이터가 추가된다. 또한 로그의 데이터 타입별로 서로 다른 분석작업이 필요한 경우, 데이터 타입 정보를 이용할 수도 있다.

척와 스토리지 구조

척와에서 사용하는 하둡 파일 시스템의 구조

일반적으로 척와의 파일 시스템은 아래와 같이 구성된다.


/chukwa/

    archivesProcessing/

    dataSinkArchives/

    demuxProcessing/

    finalArchives/

    logs/

    postProcess/

    repos/

    rolling/

    temp/

척와 데이터 프로세싱 단계

척와 에이전트에서 전송한 데이터는 아래의 단계를 따라 처리된다.

  1. 청크 사이즈가 64MB가 될때까지, 또는 지정된 시간 간격이 지날 때까지는 청크를 logs/*.chukwa 파일에 저장한다.
  2. 컬렉터는 청크를 닫고, 청크를 *.done으로 이름을 변경한다.
  3. DemuxManager가 *.done 파일이 있는지 매 20초마다 검사한 후, 있으면 처리한다.
    – *.done 파일이 있으면, 해당 파일을 디먹스 프로세싱을 하기 위한 위치(demuxProcessing/mrInput)로 옮긴다.
    – demuxProcessing/mrInput에 있는 데이터에 대해 디먹스 MapReduce 잡이 실행하고, 그 결과를 출력 위치(demuxProcessing/mrOutput)에 저장한다.
    – 디먹스가 3번 시도하고, 성공하면 처리 완료된 파일을 아카이빙(dataSinkArchives/[yyyyMMdd]/*/*.done) 한다.
    – 디먹스가 실패하면 해당 파일을 에러 폴더(dataSinkArchives/InError/[yyyyMMdd]/*/*.done)로 옮긴다.
  4. HICC를 위한 데이터 프로세싱 작업이 주기적으로 실행된다 (자세한 내용은 생략한다).
  5. ChukwaArchiveManager가 30분마다 한번 정도로 실행되어, 맵리듀스를 사용해 아카이빙 처리를 한다. 아카이빙 처리가 되면서 dataSinkArchives에 있던 데이터를 삭제한다.
    dataSinkArchives/[yyyyMMdd]/*/*.done
    => archivesProcessing/mrInput
    => archivesProcessing/mrOutput
    => finalArchives/[yyyyMMdd]/*/chukwaArchive-part-*

이제 척와에 대한 개략적인 설명은 이 정도로 해 두고, 실제로 척와를 설치해 보자. 척와 설치와 관련해서는 “하둡 척와(Hadoop Chukwa) 초보 가이드 – 설치하기”에서 살펴보겠다.

참고자료

  • 클라우드 컴퓨팅 구현 기술 / 깅형준, 조준호, 안성화, 김병준 저 / 에이콘 출판사
  • 하둡 완벽 가이드 / 톰 화이트 지음 / 오라일리 출판사
  • Chukwa Documentation 4.0

크몽 재능

의사 분산 모드로 하둡(Hadoop) 실행하기

이 글은 크몽 재능인, socurites님이 원고를 기고하셨습니다.

이 글은 제 맥북에 하둡을 설치하여, 의사분산 모드로 실행한 작업 결과를 공유하기 위해서 정리한 글입니다.

설치하기

아파치 하둡 릴리즈 페이지에서 안정화된 배포판을 다운로드 받는다. 여기에서는 hadoop-0.20.2.tar.gz를 다운로드 받았다.

로컬 파일 시스템의 적당한 위치에 압축을 푼다.

$ tar xzf hadoop-0.20.2.tar.gz

이렇게 하둡이 설치된 디렉토리를 HADOOP_INSTALL이라고 부르자.

다음으로, HADOOP_INSTALL/conf/hadoop-env.sh 파일을 열어, JAVA_HOME 변수를 아래와 같이 설정한다.

export JAVA_HOME=/usr/lib/jvm/java-6-sun

필수사항은 아니지만 하둡 관련 명령어를 쉽게 실행하기 위해 하둡 설치 디렉토리(HADOOP_INSTALL)를 환경 변수에 설정하고, PATH를 설정한다. 여기에서는 .bashrc 파일에 설정했다.

#HADOOP
export HADOOP_INSTALL=하둡이 설치된 경로
export PATH=$PATH:$HADOOP_INSTALL/bin

설정한 환경 정보를 반영합니다.

$ source ~/.bashrc

아래와 같이 하둡 명령어를 실행해서 제대로 설치죄었는지 확인해 볼 수 있다.

$ hadoop version
Hadoop 0.20.2
Subversion https://svn.apache.org/repos/asf/hadoop/common/branches/branch-0.20 -r 911707
Compiled by chrisdo on Fri Feb 19 08:07:34 UTC 2010

환경 설정하기

하둡은 독립 실행 모드(Standalone Mode), 의사 분산 모드(Pseudo-Distributed Mode), 완전 분산 모드(Fully Distributed Mode)로 실행할 수 있다. 여기에서는 의사 분산 모드로 실행하고자 한다.

하둡은 XML 파일을 사용해서 설정하며, 설정할 파일은 총 3가지다.

  • conf/core-site.xml
    하둡 컴포넌트의 공통적인 속성을 정의한다.
  • conf/hdfs-site.xml
    하둡 파일 시스템과 관련된 설정을 한다.
  • conf/mapred-site.xml
    하둡 맵리듀스와 관련된 설정을 한다.

먼저 core-site.xml부터 설정하자.

<?xml version="1.0"?>
<?xml-stylesheet type="text/xsl" href="configuration.xsl"?>
<configuration>
<property>
    <name>fs.default.name</name>
    <value>hdfs://localhost:9000</value>
</property>
</configuration>

fs.default.name에 하둡 파일 시스템의 네임노드의 호스트와 포트를 설정한다. 여기에서는 기본 포트인 8020이 아니라 9000을 포트로 설정했다.

다음으로 hdfs-site.xml을 설정한다.

<?xml version="1.0"?>
<?xml-stylesheet type="text/xsl" href="configuration.xsl"?>
<configuration>
<property>
    <name>dfs.replication</name>
    <value>1</value>
</property>
</configuration>

의사 분산 모드로 설정하기 위해, 복사본을 1개를 만든다. 즉 dfs.replication를 1로 설정한다.

마지막으로 mapred-site.xml을 설정한다.

<?xml version="1.0"?>
<?xml-stylesheet type="text/xsl" href="configuration.xsl"?>
<configuration>
<property>
    <name>mapred.job.tracker</name>
    <value>localhost:9001</value>
</property>
</configuration>

SSH 설정하기

의사 분산 모드/완전 분산 모드에서는 모두 데몬 프로세스를 실행하므로, 원격 서버의 명령을 수행할 수 있도록 ssh를 설정해야 한다. ssh가 설치되지 않았다면 먼저 ssh를 설치하도록 한다. ssh 명령어가 실행가능하더라도 ssh 데몬이 실행되어 있지 않으면 SSH을 설정할 수 없으므로, 아래와 같이 ssh를 다운받아서 설치한다.

$sudo apt-get install ssh

이제 아래와 같이 ssh 키를 생성한다.

$ ssh-keygen -t rsa -P '' -f ~/.ssh/id_rsa
$ cat ~/.ssh/id_rsa.pub >> ~/.ssh/authorized_keys

아래와 같은 명령어를 실행행서 성공한다면 제대로 설정한 것이다.

$ ssh localhost
Welcome to Ubuntu 11.10 (GNU/Linux 3.0.0-12-generic i686)
* Documentation: https://help.ubuntu.com/
Last login: Fri Nov 11 17:25:48 2011 from localhost

아래와 같이 22번 포트에 접속할 수 없다는 에러메시지가 나는 경우, sshd이 실행되어 있는지 확인한다.

ssh: connect to host localhost port 22: Connection refused
$ pgrep sshd

만약 아무런 결과도 나오지 않는다면 , sshd이 설치되지 않았거나, sshd 실행되지 않은 상태다.

실행하기

하둡 파일 시스템을 사용하려면 먼저 네임 노드를 포맷해야 한다.

$ hadoop namenode -format

하둡 파일 시스템과 맵리듀스 데몬을 아래와 같이 구동한다.

$ start-dfs.sh
$ start-mapred.sh

구동한 데몬을 중지하려면 아래의 명령어를 실행한다.

$ stop-dfs.sh
$ stop-mapred.sh

데몬이 제대로 실행되었는지 확인하는 방법에는 여러가지가 있다. 그 중에서도 웹 UI를 통해 모니터링하는 방법이 가장 편리하다. 네임노드는 http://localhost:50070/ 에서, 잡트래커는 http://localhost;50030/ 에서 확인할 수 있다.

크몽 재능