어드민 쉘
각 노드들을 실행했으므로 로그를 수집하기위해서 노드에 대한 설정을 해야 합니다. 노드에 대한 설정은 앞에서 보았던 마스터 서버의 상태를 볼 수 있는 웹페이지의 상단에 있는 메뉴에서도 할 수 있습니다. 웹이므로 폼이 등장하고 여기서 여러가지 설정이나 명령어를 입력할 수 있지만 초기 개념을 잡을 때는 이런 GUI보다는 커맨드 라인에서 사용하는 것이 이해하기 좋기때문에 Flume에서 제공하는 어드민 쉘을 사용하겠습니다.
$ ./bin/flume shell -c localhost:35873
위와 같이 실행하면 다음과 같이 실행되어 있는 마스터서버에 쉘로 접속할 수 있습니다.(포트는 마스터를 실행할 때 나왔던 어드민 서버의 포트입니다.) Flume의 마스터는 노드의 데이터 흐름을 제어하는 중앙관리소 이므로 모든 설정은 여기서 합니다. 쉘에서 사용할 수 있는 명령어를 확인하려면 help를 입력합니다.
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
- 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 데이터를 전달한다.
- 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
- 키/값 쌍의 메타데이터 테이블
잠시 테스트만 해 본 정도고 Scribe는 안 만져봤지만 Flume은 설정이 자유롭고 꽤 간단하게 사용할 수 있는듯 합니다.(처음에 이해하는데 엄청 고생했지만요.)
정말 정리 하시느랴 고생이 많으셨습니다.
역시 대단하심다.. 저도 현재 flume을 사용하고 있습니다.
0.9 밑으로는 OG(Original Generation) 이고, 1.x 이상으로는
NG(Next Generation) 인데.. 아키텍쳐링이 완전 틀리더군요...
개인적으로 NG가 훨씬 유연하긴 한데, 현 시점에서 OG의
구현을 100% 못하고, 스냅샵 중이더라구여.
어쨌든 너무 좋은 자료 공유해 주셔서 감사 합니다.
정리하는 김에 NG로 하고 싶었는데 너무 달라지고 문서도 없어서 그냥 OG로 했습니다.(아직 OG를 쓰겠지 합리화 하면서요.. ㅎ)
사실 Flume은 테스트정도로만 좀 만져본 뒤로 다시 안쓰게 된 관계로 많이 몰라서 솔직히 정리하는데 좀 힘들었어요.. 흑흑흑
어마어마한 정리양... :-) 멋지세요. 부끄부끄. 한창 Flume 쓸 때 정리를 했어야했는데 크크
그냥 간단한 튜토리얼이라...(여기까지 한사이클 돌리는것도 힘들었지만요.. ㅎ)
나중에 또 만지게 되면 정리해 주세요... 전 당분간은 안만질것 같아서 까먹기 전에 잽싸 정리를.. ㅎ
각 노드 /tmp 디렉토리에 (용량이) 엄청나게 쌓이던데 이것도 어디서 설정하는게 있나요?
(누구신가 했더니.. ㅋ)
flume-conf.xml에서 flume.agent.logdir부분인것 같네요. flume.agent.logdir.maxage나 flume.agent.logdir.retransmit를 이용하면 로그데이터의 양도 조절할 수 있을듯 합니다.
좋은 글 잘 봤습니다.
제가 이번에 Flume에 대해 처음 해보는 입장이라(초짜입니다.ㅜㅜ),
블로그의 내용 대로 일단 쭉~ 해보았는데 ..
혹시 Hadoop에 저장을 하는 법을 알고 싶네요 ㅠㅠ
(다른분들의 내용은 봐도 오류가 발생해서..ㅠㅠ)
제가 클라우드는 많이 모르긴 한데...
하둡에 저장한다는 말씀은 hdfs에 저장한다는 말씀이신가요?
예제에서는 collector의 Sink를 text로 저장했는데 저걸 dfs로 지정하시면 hdfs에 저장할 수 있습니다.
정말 정리 잘된 글 감사히 잘봣습니다. 작성하신대로 그대로 따라 해봤는데 log01-1.log 파일에 글을 작성해도 flow01.out.log 파일이 생성되지 않더라구요 http://localhost:35871/flumemaster.jsp 페이지에서 보니까 물리노드 collector01 의 status 가 error 라고 되어있던데... 이 대문인거 같아요 ㅠㅠ
음...뭐가 문제인지 혹시 아시나요? ㅠㅠ
/tmp/example/flow01.out.log 파일이 없다고 collector 를 켜보니까 에러가 떠 있길래
flow01.out.log 파일을 직접 만든뒤 log01-1.log 파일을 수정하니까
작동되네요...
해결하셨다니 다행이네요. 2년전에 FLUME을 쓰고 현재는 안쓰고 있어서 저도 정확히 답을 찾기가 어려웠는데 이렇게 해결하시고 결과까지 알려주셔서 감사합니다.