Untitled

1. STARTUP_MSG

https://t1.daumcdn.net/cfile/tistory/272FF84955DA525611

[그림 2] NameNode의 기동과 함께 제일 먼저 보여주는 메시지

  • 데몬이 실행되는 호스트 이름
  • IP Address
  • 하둡의 버전
  • 각종 라이브러리가 저장되어 있는 클래스경로
  • JDK 버전
  • etc
  • DataNodes의 목록을 읽어들인다던가 데몬의 실행에 직접적으로 영향을 미치는 각종 환경 설정값들을 읽어들이는 과정들이 따른다.

2. Load FSImage from Disk

https://t1.daumcdn.net/cfile/tistory/2428594D55DA555610

[그림 3] NameNode의 fsimage가 기록된 디렉토리 구조(Hadoop The Definitive Guide)

  • NameNode : 분산된 데이터 블럭들을 하나로 통합, 하나의 논리적 디스크 볼륨으로 만듬
  • DataNodes : 데이터 블럭 읽고, 쓰기
  • NameNode는 블럭들의 메타데이터를 메모리에 적재하여 수백만 개 이상의 데이터 블럭들을 빠른 시간내에 조회.
  • Memory에 적재된 NameNode의 메타데이터는 휘발성이기 때문에, 스냅샷(Fsimage)로 디스크에 정기적으로 저장.

https://t1.daumcdn.net/cfile/tistory/2641C64E55DA5B1C20

[그림 4] NameNode 기동 로그 중 fsimage를 지정된 경로에서 읽어서 메모리로 적재하는 과정

  • 스냅샷(Fsimage)을 읽어들이기 직전에 in_use.lock 파일을 먼저 생성하여 파일시스템에 잠금을 설정하고 fsimage 파일을 읽어서 메모리에 적재한다.
  • 일반적으로 hdfs-site.xml에 NameNode를 위한 디렉토리를 dfs.namenode.name.dir으로 지정한다.

3. Update Metadata with Edit Log

대부분의 in-memory 방식의 솔루셔들이 그렇듯 데이터의 영속성(persistence)과 성능 사이의 트레이드 오프가 중요하다. 하둡 HDFS의 NameNode는 이 문제를 해결하기 위하여 전체 메타데이터의 스냅샷과 이후 새롭게 발생하는 메타데이터의 변화를 로그(incremental)로 기록하는 방법을 쓴다. 일정한 주기(2분 마다)로 계속 롤링되는 이 Edit Log들을 관리하는 데몬을 JournalNode라 부른다.

그러므로 fsimage를 메모리로 적재한 다음엔 JournalNode가 관리하는 Edit Log들 중에서 Commit되지 않은 것들을 찾아 메모리 상의 메타데이터에 반영하는 과정을 거치게 된다. 그림 5는 이 때 기록되는 로그의 예이다.

https://t1.daumcdn.net/cfile/tistory/234DB54055DA6FAE35

[그림 5] fsimage를 메모리에 적재한 후 Edit Log를 반영함

4. Finished loading FSImage

앞서 설명한 바와 같이 메모리에서 관리되는 메타데이터의 스냅샷인 FSImage는 성능 상의 이유로 자주 만들 수가 없다. 대신 마지막 스냅샷을 작성한 후의 변경 내역들은 Edit Log라는 상대적으로 작은 크기의 파일로 기록하고 이 Edit Log를 주기적으로 FSImage에 반영하는 방법으로 스냅샷을 유지한다. 자세한 메커니즘은 JournalNode에 대한 설명에서 하도록 하겠다. NameNode의 기동과정에서 메타데이터의 적재는 fsimage의 적재 그리고 Edit Log에 기록된 변경분의 반영으로 완성된다. 그림 5의 마지막 줄에 기록된 로그를 참고하라.

5. Leave Safe Mode

fsimage와 Edit Log가 모두 메모리에 반영되면 common Services를 시작하게 되는데 이 과정에서 NameNode의 자원을 점검하고, Safe Mode로 진입한 뒤 블럭정보를 조사하여 최소한의 복제수를 충족하는 블럭들이 일정 수준 이상인지 여부를 확인하고 충족하는 경우 Safe Mode를 해제한다. 이후 blockMamanger를 활성화하고 NameNode의 메트릭정보를 제공할 MBean을 등록한다. NameNode를 포맷한 뒤 처음 실행하는 경우엔  Safe Mode에 머무는 시간이 아주 짧다.

https://t1.daumcdn.net/cfile/tistory/2314543855DC321708

[그림 6] NameNode를 최초로 기동한 경우 Safe Mode에서 빠져 나오는 시간이 짧다

6. Service Up(Standby)

NameNode는 configuration에 정의된 설정을 근거로 자신이 운영할 클러스터가 HA가 가능한 구성인지 여부를 판단한다. 그리고 HA가 가능한 경우라면 두 개의 NameNode들은  Standby 상태로 서비스를 시작한다. REST 형식의 API 요청을 처리할 HTTP 서버를 50070 포트로 서비스하고, IPC(RPC) 서비스를 위해선 8020과 8022 두 개의 포트를 리스닝하게 된다. 아래 그림 7을 보면 새 개의 포트를 정상적으로 시작한 후에 Edit Log가 2분(120초)에 한 번 씩 롤링될 것이라는 메시지가 보이고 이어서 standby checkpoint 쓰레드를 시작하는 것이 보인다. checkpoint 서비스는 HA 이전의 Secondary NameNode와는 다른 Hot-Standby NameNode를 구현한 서비스로 fsimage에 Edit Log를 반영하여 일정 주기로 Active NameNode로 전달하여 fsimage를 갱신하는 역할을 수행한다. 기본 설정대로 하자면 1분(60초)에 한 번 씩 아직 체크되지 않은 트랜잭션(Edit Log)이 있는지 점검하고 한 시간(3600초)에 한 번 씩 checkpoint를 실시하도록 되어 있다.

https://t1.daumcdn.net/cfile/tistory/231AD64155E8224427

[그림 7] HA 구성의 NameNode는 최초 standby로 기동하며 50070, 8020, 8022 포트를 서비스 한다

7. Adding a New Node

NameNode가  standby 서비스를 시작하면 이를 기다리고 있던 DataNode들이 등록(register)을 시도한다. NameNode는 이 요청에 부응하여 자신이 관리하는 네트워크 토폴로지에 요청의 당사자인 DataNode를 새로운 노드(new node)로 추가한다.

8. Process Report

노드가 추가된 사실을 통보 받은 DataNode는 자신이 관리하는 데이터 블럭들을 스캔하고 이 정보를 NameNode에 보고한다. NameNode는 자신이 가지고 있는 블럭들의 메타정보와 방금 보고 받은 DataNode의 블럭정보를 서로 매핑하여 각 블럭의 위치를 파악하게 된다. 다시 한 번 설명하자면 NameNode의 기동과정에 디스크로부터 메모리로 적재한 FsImage에는 블럭 자체의 메타정보만 있고, 이 블럭이 어느 DataNode에 위치하는지에 대한 정보는 없는 것이다. DataNode가 자신을 클러스터에 등록한 뒤 Nae=meNode에 블럭 의 위치 정보를 보고하면 비로소 메타정보와 위치정보를 매핑하여 완전한 블럭맵을 서비스하게 되는 것이다. 이렇게 하는 것은 클러스터 내에서 DataNode를 좀 더 유연하게 관리하기 위함이다.

https://t1.daumcdn.net/cfile/tistory/2525AB3E55E82DD229

[그림 8] DataNode의 노드 등록 요청을 처리한 후 등록된 DataNode로 부터 block report를 받아 처리한다

9. FailOver(from standby to active)

HA로 구성된 NameNode들은 기동하면 곧 바로 standby로 동작하도록 되어 있다(NameNode 클래스의 코드를 읽어보면 알 수 있다). 누군가 active로 상태를 전환하라는 메시지를 보내지 않는 한 NameNode는 스스로 active 상태로 전환하지 않는다. 잘 생각해보면 그게 당연한 얘기다. 고가용성이라 함은 장애가 발생하더라도 서비스가 중단되지 않도록 하는 것인데 상태전환에 대한 책임이 NameNode 자신에게 있다면 그 자신인 NameNode에 문제가 발생했을 때는 어떻게 한단 말인가! 그래서 상태를 감시하고 전환을 결정하고 명령을 내리는 주체는 NameNode가 아닌 다른 프로세스가 담당하도록 설계한 것이다. 그리고 이 임무는 HAAdmin이라는 클래스에게 위임됐다. 그리고 Cloudera Manager에서는 NameNode 두 대가 모두 정상적으로 standby로 동작하기 시작하면 다음의 그림 9에서와 같이 FailOver 명령을 내리게 된다. 물론 이 명령을 수행하는 것은 HAAdmin 클래스가 될 것이다.

https://t1.daumcdn.net/cfile/tistory/2639D83755EC33333B

[그림 9] FailOver 명령을 전달하는 Cloudera Manager

10. Start Active State

다음 그림 9에서 standby로 서비스 하던 NameNode가 active로 전환하라는 요청을 받아 active 서비스를 시작하는 것을 볼 수 있다. standby 자격으로 JournalNode와 연결했던 클라이언트 세션은 종료하고 이제 active 자격으로 새로이 연결한다. active NameNode는 블럭정보의 변화를 Edit Log에 기록해야 하기 때문이다.

https://t1.daumcdn.net/cfile/tistory/2328904055EC2F8119

[그림 10] HAAdmin으로 부터 전환 요청을 받은 NameNode가 active 서비스를 시작

11. Edit Log Tailer

Active NameNode는 자신에게 들어온 요청들(파일의 생성, 변경, 삭제)을 처리하기 앞서 Edit Log를 기록해야 한다. 물론 Edit Log의 기록은 JournalNode와 연계하여 이루어진다.  Standby로 동작하던 NameNode가 Active로 상태를 전환하면 더 이상 EditLogTailer 동작을 하지 않게 된다. Edit Log Tailer의 역할은 마지막으로 commit된 Edit Log 세그먼트의 트랜잭션들을 FSImage에 적용하는 일이기 때문이다. 이러한 동작은 Active에서는 필요치 않다. 왜? 한 번 곱씹어 보시길…

https://t1.daumcdn.net/cfile/tistory/211C5F4355EC328112

[그림 11] Edit Log Tailer는 active로 전환한 NameNode에서는 더 이상 필요치 않다.

여기까지 하둡의 NameNode가 기동되는 과정을 살펴봤습니다. 이후엔 하둡의 HDFS에서 파일을 읽거나, 새로운 파일을 생성하고 쓰는 과정도 로그를 기반으로 설명해 보도록 하겠습니다.

# 네임노드의 메타 데이터가 다음과 같은 형태로 생성됨  
$ ls -alh /hadoop/hdfs/namenode/current
total 1847556
-rw-r--r-- 1 hdfs hadoop       217 Sep  2 03:36 VERSION
-rw-r--r-- 1 hdfs hadoop   1523554 Feb 21 14:30 edits_0000000003027897761-0000000003027906608
-rw-r--r-- 1 hdfs hadoop   1351557 Feb 21 14:32 edits_0000000003027906609-0000000003027914396
-rw-r--r-- 1 hdfs hadoop   1391038 Feb 21 14:34 edits_0000000003027914397-0000000003027922191
...
-rw-r--r-- 1 hdfs hadoop    836860 Feb 21 23:53 edits_0000000003029906692-0000000003029911098
-rw-r--r-- 1 hdfs hadoop    890807 Feb 21 23:55 edits_0000000003029911099-0000000003029915811
-rw-r--r-- 1 hdfs hadoop   1048576 Feb 21 23:56 edits_inprogress_0000000003029915812
-rw-r--r-- 1 hdfs hadoop 760128990 Feb 21 18:50 fsimage_0000000003028899087
-rw-r--r-- 1 hdfs hadoop        62 Feb 21 18:50 fsimage_0000000003028899087.md5
-rw-r--r-- 1 hdfs hadoop 762005689 Feb 21 23:50 fsimage_0000000003029901533
-rw-r--r-- 1 hdfs hadoop        62 Feb 21 23:50 fsimage_0000000003029901533.md5
-rw-r--r-- 1 hdfs hadoop        11 Feb 21 23:55 seen_txid

VERSION: 현재 실행 중인 HDFS의 ID, 타입 등 정보 edits_0000xxx-0000xxx: 트랜잭션 정보. edits_트랜잭션시작번호-트랜잭션종료번호 까지의 정보를 저장 eidts_inprogress_000xx: 최신 트랜잭션 정보. 압축되지 않은 정보 fsimage_000xxx: 000xxx 까지 트랜잭션 정보가 처리된 fsimage fsimage_000xxx.md5: fsiamge의 해쉬값 seen_txid: 현재 트랜잭션 ID