Outsider's Dev Story

Stay Hungry. Stay Foolish. Don't Be Satisfied.
RetroTech 팟캐스트 44BITS 팟캐스트

Flume #2-2 간단한 사용예제

이 글은 Flume #2-1 간단한 사용예제에서 이어진 글 입니다.



어드민 쉘
각 노드들을 실행했으므로 로그를 수집하기위해서 노드에 대한 설정을 해야 합니다. 노드에 대한 설정은 앞에서 보았던 마스터 서버의 상태를 볼 수 있는 웹페이지의 상단에 있는 메뉴에서도 할 수 있습니다. 웹이므로 폼이 등장하고 여기서 여러가지 설정이나 명령어를 입력할 수 있지만 초기 개념을 잡을 때는 이런 GUI보다는 커맨드 라인에서 사용하는 것이 이해하기 좋기때문에 Flume에서 제공하는 어드민 쉘을 사용하겠습니다.

$ ./bin/flume shell -c localhost:35873

위와 같이 실행하면 다음과 같이 실행되어 있는 마스터서버에 쉘로 접속할 수 있습니다.(포트는 마스터를 실행할 때 나왔던 어드민 서버의 포트입니다.) Flume의 마스터는 노드의 데이터 흐름을 제어하는 중앙관리소 이므로 모든 설정은 여기서 합니다. 쉘에서 사용할 수 있는 명령어를 확인하려면 help를 입력합니다.

어드민 쉘로 Flume Master에 접속한

Master 노드는 2가지 방법으로 설정을 저장합니다. 메모리기반의 설정저장(Memory-Backed Config Store, MBCS)과 주키퍼기반 설정저장(ZooKeeper-Backed Config Store, ZBCS) 입니다. MBCS를 사용하면 마스터노드를 재시작했을 때 설정된 내용이 사라집니다. ZBCS를 사용하면 여러 마스터 노드사이에 설정정보를 동기화해주고 (하나만 띄웠을 때도) Master 노드를 재시작했을 때 기존의 설정을 모두 가지고 있습니다.(테스트 도중 기존 설정을 삭제하고 싶으면 /tmp/flume-계정명 디렉토리와 /tmp/flume-계정명-zk/ 디렉토리를 삭제하면 됩니다.) 보통은 ZBCS를 사용하고 이 설정은 flume.master.store에 있습니다.


논리적 노드 생성
앞에서 agent01, agent02 두 개의 에이전트 노드를 실행했습니다. 이 둘은 물리적 노드이면서 논리적 노드이기도 합니다. 앞에서 논리적 노드를 추가하겠습니다. Flume 쉘에서 다음과 같이 입력합니다.

[flume localhost:35873:45678] exec map agent01 logical01-1
[id: 0] Execing command : map
Command succeeded
[flume localhost:35873:45678] exec map agent01 logical01-2
[id: 1] Execing command : map
Command succeeded
[flume localhost:35873:45678] exec map agent02 logical02-1
[id: 2] Execing command : map
Command succeeded
[flume localhost:35873:45678] exec map agent02 logical02-2
[id: 3] Execing command : map
Command succeeded

논리적 노드는 물리노드에 매핑하는 것이므로 map 명령어를 사용합니다. exec map 물리적노드명 논리적노드명 명령어를 사용하면 물리적노드에 새로운 논리노드를 연결할 수 있습니다. 연결을 해제하려면 exec unmap 이나 exec unmapAll 명령어를 사용합니다. 다시 마스터 노드의 상태페이지에 가면 논리적 노드가 제대로 맵핑된 것을 확인할 수 있습니다.

사용자 삽입 이미지

논리적 노드는 용도별로 다양한 설정을 위해서 물리적 노드위에 원하는 만큼 생성할 수 있고 각각 별도의 설정을 할 수 있습니다. 웹브라우저에 접근하지 않고 쉘에서도 이 정보를 확인할 수 있습니다.

사용자 삽입 이미지

getnodestatus 명령어로 각 논리적 노드의 현재 상태를 확인할 수 있고 getmappings 명령어로 물리적 노드와 논리적 노드의 매핑관계를 볼 수 있습니다. getmappings 물리적노드이름 을 입력하면 특전 물리적 노드의 매핑관계만도 볼 수 있습니다.



컬렉터 노드 설정
앞에서 각 노드는 source와 sink로 설정한다고 설명했습니다. 간단히 말하면 source는 입력이고 sink는 출력입니다. 그래서 각 노드에 source와 sink를 설정해서 어디로 들어오는 데이터(source)를 어디로 내보낸다(sink)와 같이 설정할 수 있습니다.

[flume localhost:35873:45678] exec config collector01 flow01 'collectorSource(35853)' 'text("/tmp/example/flow01.out.log")'
[id: 4] Execing command : config
Command succeeded

설정은 exec confing 노드이름 [흐름이름] Source Sink 명령어로 합니다. 흐름이름은 여러 머신이 있을 때 데이터의 흐름을 하나로 묶어주는 역할을 하고 명령어에서 생략할 수 있습니다.(여기서는 flow01이라고 정의했습니다.) 그래서 이 명령어는 collector01 노드에 35853 포트로 들어오는 collectorSource 를 받아서 text로 /tmp/example/flow01.out.log 파일에 작성하라고 정의한 것입니다.



에이전트 노드 설정
컬렉터도 설정되었으므로 에이전트 노드를 설정할 차례입니다. Flume은 log를 수집하는 역할이므로 에이전트는 보통 로그가 생성되는 머신에 있습니다.

[flume localhost:35873:45678] exec config logical01-1 flow01 'tail("/tmp/example/log01-1.log")' 'agentDFOSink("localhost", 35853)'
[id: 5] Execing command : config
Command succeeded
[flume localhost:35873:45678] exec config logical01-2 flow01 'tail("/tmp/example/log01-2.log")' 'agentDFOSink("localhost", 35853)'
[id: 6] Execing command : config
Command succeeded

에이전트를 설정하는 방법도 컬렉터 노드를 설정할 때와 동일합니다. tail 명령어를 사용해서 source를 /tmp/example/log01-2.log 를 추적하도록 했습니다. tail 명령어 이므로 이 파일에 추가되는 로그를 라인단위로 읽어오게 됩니다. Flume은 내부적으로 외부의 데이터 소스를 모두 이벤트의 스트림으로 만들어서 처리하는데 여기서 tail이 이벤트로 처리됩니다. 이벤트는 Flume의 데이터 유닛으로 간단하면서도 유연합니다.
소스 이벤트는 다음과 같은 종류가 있습니다.
  • console : stdin 콘솔에서 입력을 받습니다.
  • text : text 파일소스로 한 라인이 한 이벤트입니다.
  • tail : 유닉스의 tail -F 와 유사하면 한 라인이 한 이벤트입니다.
  • multitail : 여러파일을 tail합니다.
  • asciisynth : 랜덤 메시지를 생성합니다.
  • syslogUdp : UDP 포트의 syslog
  • syslogTcp : TPC 포트의 syslog
sink는 agentDFOSink를 사용해서 컬렉터 서버를 지정했습니다. 이 예제는 한 PC에서 다 실행했으므로 localhost의 35853포트로 로그를 전송합니다. (앞에서 컬렉터는 소스를 35853 포트로 지정했습니다.) 기본값에서는 Thrift를 사용합니다. Sink 이벤트는 다음과 같은 종류가 있습니다.
  • null : Null Sink로 이벤트를 버립니다.
  • console : Console Sink로 콘솔의 stdout에 보여줍니다.
  • text : textfile Sink로 텍스트 파일에 쓴다.
  • dfs : DFS seqfile Sink로 직렬화된 이벤트를 하둡의 seqfile 형식으로 dfs 경로에 작성합니다. (hdfs://namenode/file 처럼)
  • syslogTcp : Syslog TCP Sink로 TCP 포트의 호스트로 syslog 데이터를 전달한다.
Sink에는 다음과 같은 신뢰성 모드도 사용할 수 있습니다.
  • agentE2ESink : end to end 신뢰성 모드로 승인에 의존하므로 승인을 받지 못하면 재시도합니다. agentSink의 별칭이기도 합니다.
    agentDFOSink : Disk FailOver 로 컬렉터에서 실패하면 디스크에 저장하고 나중에 다시 시도합니다.
  • agentBESink : Best Effort 신뢰성 모드로 디스크에 전혀 작성하지 않고 실패하면 메시지를 버립니다.

마스터 노드의 상태페이지에서 설정내역

마스터의 상태페이지로 접속하면 설정한 내역을 위처럼 볼 수 있습니다. 한 노드에는 하나의 설정만 가능한 것같습니다. 그래서 설정을 잘못했거나 다시 하고 싶을 때는 exec config 명령어를 다시 실행하면 기존의 설정을 덮어쓰게 됩니다. 설정을 해제하려면 exec decommission 논리적노드명 명령어를 사용합니다.

사용자 삽입 이미지

당연히 어드민 쉘에서도 getconfigs 명령어로 설정상태를 확인할 수 있습니다.



로깅 수집 테스트

사용자 삽입 이미지
실제로 로깅되는지 테스트해 본 것입니다. 위에서 agent01이 log01-1.log 파일을 tail로 읽어서 컬렉터로 보내면 컬렉터에서 flow01.out.log 파일에 저장하도록 설정했습니다. 이 내용을 테스트 한 것으로 처음에는 flow01.out.log 파일에 내용이 없었지만 log01-1.log 파일에 내용을 입력하자 flow01.out.log에 저장된 것을 확인할 수 있습니다. 로그 메시지 외에 시간과 IP 등이 함께 출력된 것을 볼 수 있습니다. 이벤트는 body와 metadata로 이루어져 있으면 body는 이벤트의 내용을 나타내는 문자열입니다. 이벤트는 데이터 모델은 다음과 같은 필드를 가지고 있습니다.
  • 유닉스의 타임스탬프
  • 나노초단위의 타임스탬프
  • 중요도 : TRACE, DEBUG, INFO, WARN, ERROR, FATAL
  • 소스의 호스트 : IP나 호스트명
  • body
  • 키/값 쌍의 메타데이터 테이블
이 예제에서는 확인을 위해서 flow01.out.log를 미리 만들어 놨지만 미리 안만들어도 자동으로 파일을 생성해서 저장합니다. 그리고 이 순서처럼 컬렉터를 먼서 설정해야 하는 것은 아니고 에이전트를 먼저 설정해도 되며 앞에서 말했듯이 동적으로 설정할 수 있습니다. 이 예제에서는 tail을 사용했는데 에이전트를 강제로 죽이더라도 그 사이에 추가된 로그메시지는 자동으로 에이전트가 복구된 뒤에 보내집니다.

잠시 테스트만 해 본 정도고 Scribe는 안 만져봤지만 Flume은 설정이 자유롭고 꽤 간단하게 사용할 수 있는듯 합니다.(처음에 이해하는데 엄청 고생했지만요.)
2012/06/20 03:42 2012/06/20 03:42