티아카데미 Hadoop 입문과 활용 - HDFS TIL

2020-09-29

.

Data_Engineering_TIL(20200925)

  • study program : T아카데미 - 아파치 하둡 입문과 활용

** URL : https://tacademy.skplanet.com/frontMain.action

[학습내용]

# ‘the google file system’과 분산플랫폼

  • Hadoop은 ‘the google file system’이라는 논문을 보고 만든 파일시스템으로 논문에는 동작방식과 이론만 나와있고 구현체는 없었다.

  • 분산환경이라고 하면 물리적으로 여러대의 서버가 하나의 클러스터처럼 동작하는 플랫폼을 말한다.

분산플랫폼의 아키텍처는 크게 두개로 나누면 마스터&슬레이브 구조와 마스터가 없는 구조로 나눌 수 있다. 그래서 마스터 슬레이브 구조라고 하면 마스터 역할을 하는 마스터 데몬이 있고, 마스터의 관리를 받는 슬레이드 데몬이 있는 구조를 말한다. 슬레이브 서버는 댓수를 계속 확장하는 스케일 아웃이 가능하다. 이런 구조가 하둡만 그런 것이 아니라 분산플랫폼 대부분이 그러하다. 마스터가 없는 구조에서는 마스터가 해야하는 또는 가지고 있어야 하는 정보들을 모든 노드들이 공유하는 플랫폼 아키텍처이다.

‘구글 파일 시스템’은 마스터 슬레이브 구조이다. GFS master가 마스터 서버로 보면 되고, GFS Chunkserver가 슬레이브 서버로 보면 된다. 그리고 청크 서버는 여러대로 확장이 가능하다. 사용자가 GFS client에 어플리케이션으로 던지 뭐든지 job을 실행하는 클라이언트이다.

마스터 슬레이브 구조에서 가장 중요한 부분은 마스터에 부하가 가지 않도록 항상 유지시켜줘야 한다는 것이다. 아래 그림에서 chunk data라고 굵은 선으로 표시가 되어 있는데 GFS client와 GFS Chunkserver가 다이렉트로 연결되게 구성이 되어있다. 그래서 데이터 트레픽을 실제로 주고 받을때 클라이언트하고 청크서버는 커넥션을 맺고 데이터를 주고 받지만 GFS master와는 데이터를 직접 주고받지는 않도록 되어 있다. 마스터에서 데이터 프로세싱을 한다던지, 데이터를 주고받는다던지 부하를 주는 구조로 만들지 않았다.

1

이렇게 마스터에 부하를 주지 않도록 하는 것이 마스터 슬레이브 구조의 중요한 특징이다 왜냐하면 마스터가 다운되면 전체 클러스터 차원으로 문제를 일으키기 때문이다. 그래서 마스터를 가장 안정적으로 운영할 수 있는 구조로 설계하고, 운영을 할때도 그런부분들을 신경을 많이 써야한다.

하둡은 이 아키텍처를 보고 소프트웨어로 구현한 것이다.

# 구글플랫폼의 철학 = 데이터 분산 & 자동화(장애가 발생해도 소프트웨어가 알아서 복구) = 하둡의 철학 = 모든 하둡 애코시스템의 기본적인 사상

1) 한대의 고가장비보다 여러대의 저가 장비가 낫다

2) 데이터는 분산 저장한다.

3) 시스템(하드웨어)는 언제든지 죽을 수 있다.

(–> 그래서 스마트한 소프트웨어를 만들어서 항상 이런 상황을 대비해야 한다.)

4) 시스템 확장이 쉬워야 한다.

예를 들어서 데이터가 늘어났고, 데이터를 처리하는 속도가 느려졌다면 이를 해결하기 위해서 뭔가 아키텍처를 바꾸고 장비의 스펙을 올리고 이러는게 아니라 그냥 스케일 아웃해서 클러스터 노드수를 늘려한다는 것이다.

5) ETC

# 하둡의 특성 = 구글 플랫폼의 철학을 그대로 계승함

  • 수천대 이상의 리눅스 기반 범용 서버들을 하나의 클러스터로 사용

  • 마스터-슬레이브 구조

  • 파일은 블록(block) 단위로 저장

  • 블록 데이터의 복제본 유지로 인한 신뢰성 보장(원본포함 기본 3개의 복제본)

  • 높은 내고장성(Fault-Tolerance)

  • 데이터 처리의 지역성 보장

# 하둡이 의미가 있는 경우

하둡은 클러스터 노드 4대 ~ 5대 이런 수준의 규모는 사실 큰 의미는 없다. 기본적으로 수십대 이상, 수백대(sk텔레콤), 아주 크면 수천대(야후나 대기업들)로 구성해서 운영을 해야 효과가 있다.

엉뚱한 예를 들면 작은 닭을 잡아야 하는데 소잡는 칼을 쓰는 것과 같아서 칼을 들어서 써는데 드는 애너지가 더 크게 든다는 것이다.

** 작은 닭 = 소규모 데이터, 소잡는 칼 = 다수의 하둡 클러스터

“콤퓨타는 소잡는 칼이 아닌가 해서 의견드립니다.”

# 하둡(1.0 ver 기준) 클러스터 네트워크 및 데몬 구성

2

하둡은 여러대의 서버를 하나의 클러스터로 구성을 하다보니까 물리적으로 렉 형태의 형태를 사용하게 된다. 렉 안에 렉 스위치가 있고, 이 안에 여러대의 서버들이 들어가게 된다. 하나의 렉에 하나의 스위치가 있고, 하둡 1.0 버전 기준으로 위와 같이 구성하게 된다. 네임노드라는게 있고 이 네임노드가 HDFS에 대한 마스터 데몬 역할을 한다. 그리고 DN이라고 되어 있는데 이거는 별개의 서버다. 마스터 서버에는 마스터 메몬만 띄우고 다른거는 띄우지 않는다. 언제나 마스터는 부하를 최소화해야하기 때문이다. DN(데이터 노드, HDFS에서 슬레이브 데몬)이라는 데몬과 TT(테스크 트레커, MapReduce에서 슬레이브 데몬)라는 데몬이 하둡에서 슬레이브의 데몬이다. 어플리케이션 연산을 처리하기 위해서 어플리케이션을 관리하는 데몬은 Job Tracker라는 MapReduce의 마스터 데몬이 있고, TaskTracker는 job tracker의 슬레이브 데몬인 것이다. 마찬가지로 Job Tracker도 별개의 서버에 마스터 서버로 띄운다. Job Tracker(마스터 데몬)도 죽으면 전체 job에 문제가 발생하기 때문이다. DN은 DataNode, TT는 TaskTracker로 이 둘은 하나의 서버에 항상 쌍으로 띄우게 된다.

# HDFS에서 Block이란

image

  • 하둡에 128메가를 초과하는 파일을 저장하면 위에 그림과 같이 하나의 파일을 Block이라는 단위로 여러개로 쪼개서 HDFS에 저장하게 됨

  • 설정에 의해 하나의 Block은 64MB 또는 128MB 등의 큰 크기로 나누어 저장

  • 블록 크기가 128MB 보다 적은 경우는 실제 크기 만큼만 용량을 차지함

(예를 들어서 100MB짜리 파일이다 그러면 그냥 100MB로 저장이 됨)

# fsimage

image

네임노드는 fsimage라는 HDFS의 네임스페이스 구조를 저장하는 파일을 저장하게 된다. fsimage가 실제로 어디에 저장이 되냐면 default값이 /tmp/hadoop ... /dfs/name 경로에 저장이 된다. 최초에 하둡을 구동할때 네임노드 포맷을 하게 되면 이 디렉토리 경로가 만들어지게 된다. 이 디렉토리 안에다가 현재 파일의 이미지가 어떻게 되는지 스냅샷 형태로 관리하게 된다. 안에 보면 fsimage 파일이 있는데 이것은 가장 최근에 스냅샷을 내린 하둡 네임노드에 들어가 있는 HDFS의 메타정보들이 스냅샷 형태로 저장이 된 것이다. 스냅샷으로 저장된 이후에 HDFS에 저장된 파일에 변경사항(파일의 수정, 삭제, 이동 등)이 발생하면 edits log에 계속 로깅이 된다. 그리고 fsimage 파일들은 주기적으로 병합이 되는 작업이 일어난다. 그래서 항상 최신에 가까운 fsimage 파일들을 스냅샷 형태로 유지하게 된다.

만약에 하둡의 네임노드 데몬을 내렸다 올리면 하둡 네임노드 데몬이 올라가면서 fsimage에 있는 HDFS의 메타정보를 읽어서 하둡 네임노드의 메모리에 구성하게된다. 그러면 하둡 네임노드 입장에서는 전체 클러스터의 어떤 서버가 어떤 파일들을 갖고 있는지를 파악한다. 그런 다음에 edits log에 나와 있는 로그를 fsimage에 반영을해서 최종적으로 fsimage를 메모리에 올리는 작업을 완료하게 된다.

core-site.xml에서 아래와 같이 default 경로의 /tmp/hadoop ... /dfs/name 를 원하는 디렉토리 경로로 임의로 변경할 수 있다.

<property>
    <name>dfs.namenode.name.dir</name>         # fsimage를 어디에 저장할 것인지 설정
    <value>[directory location]</value>
</property>

# HDFS에서 Block 하나의 크기가 큰 이유

  • HDFS의 블록은 128MB와 같이 매우 큰 단위. 디폴트가 128MB이지 64MB, 256MB로도 임의로 조절할 수 있다.

  • 블록이 큰 이유는 탐색 비용을 최소화할 수 있기 때문

  • 블록이 크면 하드디스크에서 블록의 시작점을 탐색하는 데 걸리는 시간을 줄일 수 있고, 네트워크를 통해 데이터를 전송하는데 더 많은 시간을 할당이 가능함

HDFS의 네임노드, 데이터노드 혹은 MapReduce의 테스크 트레커 등이 Block을 탐색할때 파일의 정보를 최대한 빨리 찾기 위해 메타정보를 줄이고자 하는 목적이 있다. 이렇게 해야 큰 볼륨의 데이터를 빨리 처리할 수 있다.

또한 파일이 어디에 있는지 위치 찾고 seek하고 이런 부분들에 리소스를 쓰지 않고 네트워크를 통해서 데이터를 전송하는데 집중하고자 하는 것이다.

결론은 데이터를 빨리 처리하고자 함에 있는 것이다.

# HDFS 저장원리 예시

아래 그림과 같이 분당 약 24GB 정도가 계속 누적되는 큰 데이터가 있고 이 데이터가 카프카를 통해서 하둡 클러스터에 저장이 된다고 가정하자. 하둡은 이 데이터를 저장할때 내부적으로 알아서 128MB의 블락으로 쪼갠다.

1231231

사용자가 하둡에 어떤 파일을 저장하게 되면 위에 그림과 같이 마스터에는 데이터를 저장하지 않고, 8대의 슬레이브 서버에 분산 저장하게 된다. 주목해야하는 점은 데이터를 블록으로 쪼개고 이 블록 하나를 서로 다른 데이터노드 3대에 각각 저장 된다는 것이다. (원본포함 3개의 블럭이 각각 다른 데이터노드 서버에 저장이 되는 것이다. 하나의 블록은 서로다른 데이터 노드에 저장됨)

네임노드는 데이터노드와 주기적으로 통신을 하도록 되어 있다. 정확하게는 데이터노드가 네임노드에게 3초마다 살아있다고 Heartbeat 메세지를 보내게 되어있다.

사용자가 클라이언트를 이용해서 특정 파일을 하둡에 저장한다 그러면 네임노드는 파일사이즈와 파일명 이런 정보를 받아서 1번 Block은 1번 데이터노드에 저장해라, 2번 Block은 2번 데이터노드에 저장해라라는 내용을 클라이언트에게 보내게 된다. 그러면 클라이언트는 1번 데이터노드와 2번 데이터노드 등과 직접 연결해서 Block을 카피를 받게 되는 것이다. 네임노드는 어떤 블락이 어떤 데이터노드에 저장되어 있는지 알고 있고, 또한 주기적으로도 블럭에 대한 정보를 데이터노드들에게 보고를 받는다. (Block report는 hearbeat 보낼때 별도로해서 같이 보내게 된다.) 결론적으로 네임노드는 데이터노드에 어떤 블락이 들어있는지 이 블락 다른 두카피는 또 어떤 데이터노드에 저장되어 있는지 다 아는 것이다.

만약에 특정 데이터노드 서버 하나에 네트워크 NIC 카드가 장애가 났다고 가정하자 (클러스터 그림에서 가장 좌측 상단에 있는 주항색 블럭이 저장되어 있는 데이터노드가 장애가 났다고 치자). 이 서버는 살아있기는 하지만 네트워크 통신이 외부와 안되는 것이다. 그러면 Heartbeat 메세지를 네임노드로 보낼 수 없을 것이다. 그러면 네임노드는 특정시간이 지나면 이 해당 데이터노드가 장애가 났다고 판단한다.

그러면 네임노드는 주항색 블럭의 나머지 두카피가 다른 두 데이터노드에 저장되어 있고 그게 어디에 있는지도 알고 있다. 그러면 장애가 난 바로 밑에 데이터 노드가 주황색 블럭 하나를 갖고 있으니까 네임노드는 그 데이터 노드에게 주황색블록을 하나 바로 밑에 있는 데이터 노드에 카피를 떠놓으라고 명령을 한다. 그러면 데이터노드 간에 통신을해서 카피를 뜨게 된다. 그래서 서버하나가 장애가 나도 블럭은 여전히 세카피가 계속 유지될 수 있다. 이런 자동복구 과정에서 사용자가 해야할 일은 없다. HDFS 시스템이 알아서 하는 것이다.

참고로 replication 설정은 디폴트값은 3이고, 이것도 사용자가 임의로 갯수를 설정해줄수도 있다.

그런데 하둡엔지니어가 이 NIC카드 장애난 서버를 확인하고, NIC카드를 교체했다. 그러면 해당 문제가 되었던 데이터노드가 정상적으로 다른 노드들과 통신이 가능하게 되고, hearbeat 메세지도 네임노드에게 보내기 시작할 것이다. 그러면 전체 클러스터에서 주황색 블록은 4개가 되는 것이다. replication이 오버가 되는데 이런식으로 replication이 설정값보다 적거나 많다면 그 부분을 네임노드가 스스로 캐치해서 데이터노드들끼리 알아서 복사하도록 명령하고, 복사가 잘 되었는지 리포트를 받고 이런 부분들을 자동으로 관리하게 플렛폼이 동작하게 된다.

하둡에서 데이터가 유실이 되는 경우는 3개의 데이터 노드가 거의 동시에 장애가 나는 경우인데 이런 경우는 거의 없다고 보면된다.

Question ) 그러면 마스터서버가 장애가 났을때에 대한 대비책도 있는가.

–> 하둡 1.0에서는 마스터서버가 장애가 났을때에 대한 대비책이 없다. 마스터서버의 장애에 대한 대비책이 있는 버전이 하둡 2.0버전이다. 하둡 2.0의 중요한 특징중에 하나가 HDFS에서 마스터서버의 이중화이다.

** 참고로 2.0에서 3.0에서 변화시 중요한 특징중에 하나가 HDFS에서 erasure coding이라는 기법을 통해서 replication의 수가 3이 아니라 기본대비 2배의 비율로 저장이 가능해져서 실질적인 용량소모에 대한 부담이 줄어들었다는 것이다.

# 하둡 클러스터를 구성하는 서버의 스펙

요즘에는 ETL처리를 spark 엔진을 많이 이용하기 때문에 메모리상에서 연산을 주로 하는 편이다. 따라서 데이터노드 하나에 메모리를 큰거를 쓰는 것이 일반적이다. spark이 일반적으로 memory base로 데이터를 처리하기 때문이다. 대기업 기준으로 일반적으로 노드 하나에 메모리는 적게는 128GB, 크게는 512GB도 쓸때도 있지만 보통은 256GB를 쓰는 편이다.

CPU 코어는 절대 비싼걸 쓰지 않는다. 가장 저가이면서 효율적인 cpu 모델을 선택한다. 일반적으로는 코어 16개 ~ 32개 정도 쓰는 편이다. 최근에 출시되는 서버들은 대부분 하이퍼쓰레딩이라는 기능을 on해서 실제 물리적인 코어는 16개가 있는데 가상으로는 32개를 쓸 수 있다.

하나의 노드에 디스크는 보통 여러개를 구성한다. 너무 큰 디스크 하나를 쓰게 되면 성능적인 측면에서 단점이 있다. 그래서 대부분 노드를 구성할때 디스크를 적게는 6개 많게는 12개까지 구성하게 된다. 디스크 하나에 2 ~ 3 TB정도 되는걸 쓴다.

여기서 중요하게 하둡 클러스터를 운영하다 보면 기준에 노드 하나에 쓰고 있는 디스크가 용량이 모자를 수도 있다. 그러면 scale out을 염두하게 되는데 그러면 그 당시 도입했던 스펙과 다른 스펙의 서버로 확장을 할 수도 있다. 그래서 하둡 클러스터 전체 노드가 모두 동일한 스펙의 노드가 아닐 수도 있다. 그러면 유의해야 할 점이 있다.

Question) 마스터 노드의 스펙은 어떻게 되느냐

HDFS 관점에서 보면 마스터노드는 네임스페이스라는 이름의 하둡클러스터 전체의 메타정보를 네임노드의 메모리에 저장해서 관리하도록 되어 있다.

하둡 도큐먼트를 보면 네임노드는 크게 하는게 없으니까 별로 안좋은 스펙으로 구성해도 괜찮다는 내용이 있지만 하둡 클러스터가 커지게 되면 네임노드 스펙이 좋은게 바람직하다. 기본적으로 메모리가 커야한다. 그리고 네임노드에게 정보를 요청하는 클라이언트도 점점 많아지게 될 것이기 때문에 네임노드와의 RPC라는 프로토콜로 통신하는 부하도 커지게 된다. 그래서 마스터노드는 메모리가 특히 크고 가능하면 좋은 스펙으로 구성하는 것이 좋다.

# 블록 크기 분할과 추상화에 따른 이점

  • 블록 단위로 나누어 저장하기 때문에 디스크 사이즈보다 더 큰 파일을 보관할 수 있음

  • 블록 단위로 파일을 나누어 저장하기 때문에 700G * 2 = 1.4T 크기의 HDFS에 1T 의 파일 저장가능

  • 파일 단위보다 블록 단위로 추상화를 하면 스토리지의 서브 시스템을 단순하게 만들 수 있으며, 파일 탐색 지점이나 메타정보를 저장할 때 사이즈가 고정되어 있으므로 구현이 용이함

  • 내고장성을 제공하는데 필요한 복제(replication)을 구현할 때 매우 적합

  • 같은 파일을 분산 처리하여 데이터 처리 성능을 개선할 수 있음

  • 같은 노드에 같은 블록이 존재하지 않도록 복제하여 노드가 고장일 경우 다른 노드의 블록으로 복구할 수 있음

# Block의 locality

HDFS에 저장된 데이터를 가지고 연산을 한다면 Block의 locality라는 말이 중요하다. 연산할때 job tracker는 특정 task tracker가 자기자신의 노드에 연산하고자 하는 블럭이 있으면 그 노드에다가 job을 할당하게 되어있다. 예를 들어서 어떤 연산을 위해서 처리해야할 데이터가 1번 3번 5번 데이터노드에 저장되어 있다면 하둡의 마스터가 job을 1번,3번,5번 서버에만 할당을 해준다는 말이다. 그리고 테스크 트레커는 복사같은 작업이 없이 자기 자신이 갖고 있는 로컬데이터를 읽어서 처리한다. 이게 데이터 지역성인 것이고, 하둡은 데이터 지역성을 보장하도록 설계되어 있다.

이런 경우도 있다. 온프라미스에서 렉안에 서버 여러대를 두는 경우가 있어서 테스크 트레커를 데이터노드와 반드시 같이 안띄우는 경우도 있다. 같은 렉 안에서 렉전체 단위로 데이터노드를 하나 띄우고, 테스크 트레커는 렉을 구성하는 서버중에 예를 들어서 2번 서버에 구성할 수도 있다. 예를들어서 어떤 연산을 해야하는데 연산을 해야하는 데이터가 특정 렉안에 3번 서버에 있다고 치자. 그런데 이 3번 서버가 다른일 때문에 바쁘다고 한다면 3번 서버에서 일을 처리하라고 하는 것이 아니라 그 렉안에 있는 다른서버, 예를들어서 2번 서버에게 3번 서버로 부터 데이터를 가져와서 처리하라고 job을 할당할수도 있다. 결론적으로는 일을 할당할때 같은 렉에 있는 서버한테 일을 시키도록 하둡은 구성되어 있다.

하나의 렉에는 이 렉에 달려있는 여러대의 데이터노드가 같은 렉의 스위치를 통해 비교적 빠르게 데이터를 처리할 수 있다. 그러나 서로 다른 렉끼리는 통신할때 스위치를 한번 더 거쳐야 한다. 렉 내에서의 지역성을 보장해주면 트레픽 전송하는 구간이 하나 줄어들어서 더 빨리 데이터를 보내고 처리할 수 있다는 것이다.

** ‘하둡(1.0 ver 기준) 클러스터 네트워크 및 데몬 구성’ 그림 참고할 것

하둡 어플리케이션 개발자는 데이터 블럭들이 어디에 저장되어 있는지 전혀 몰라도 된다는 것이다. 그냥 어플리케이션을 만들어서 job을 던지면 하둡 플랫폼이 알아서 지역성을 보장해서 연산을 하는 것이다.

  • Block의 locality 보장으로 얻을 수 있는 이점

1) 네트워크를 이용한 데이터 전송 시간 감소

2) 대용량 데이터 확인을 위한 디스크 탐색 시간 감소

3) 적절한 단위의 블록 크기를 이용한 CPU 처리시간 증가

** 참고사항 : 클라우드 스토리지를 이용(ex. S3)하는 경우 HDFS 를 사용하는 것보다 성능 저하가 있을수 있음

# 블록 캐싱

하둡에서 자주쓰는 데이터는 블록캐싱이라는 것을 이용해서 데이터노드가 가지고 있는 메모리에 캐싱을 등록할 수 있다. 예를들어서 어떤 데이터에서 유저의 아이디가 로그로 남는 데이터가 있다고 치자. 유저의 아이디에 해당하는 마스터성 테이블을 보면 유저의 아이디에 해당하는 이름도 있고, 성별, 전화번호 등 끼리 조인해서 봐야하는 경우는 캐싱으로 등록할 수 있다는 것이다. 단 조인해야하는 마스터성 데이터가 크지 않다는 조건이 있어야한다. 여기서 크지 않다는 것은 데이터 노드도 데몬을 띄울때 메모리 설정을 해줄 수 있는데 이 데이터노드의 물리적인 하드웨어 스펙에 무리가 안갈만큼은 해줄 수 있다는 것이다. 상대적인 개념이기는 하다. 일반적으로는 수십메가바이트 정도는 캐싱을해서 쓸 수도 있다.

  • 데이터 노드에 저장된 데이터 중 자주 읽는 블록은 블록캐시(block cache)라는 데이터 노드의 메모리에 명시적으로 캐싱할 수 있음

  • 파일 단위로 캐싱할 수도 있어서 조인에 사용되는 데이터들을 등록하여 읽기 성능을 높일 수 있음

  • 실제 사용예시

$ hdfs cacheadmin
Usage: bin/hdfs cacheadmin [COMMAND]

...

# pool 등록
$ hdfs cacheadmin -addPool pool1
Successfully added cache pool pool1.

# path 등록
$ hdfs cacheadmin -addDirective -path /user/hadoop/shs -pool pool1
Added cache directive 1

# cache 확인
$ hdfs cacheadmin -listDirectives
Found 1 entry
ID POOL REPL EXPIRY PATH
1 pool1  1   never   /user/hadoop/shs

# 네임노드의 역할

image

  • 전체 HDFS 에 대한 Name Space 관리

  • DataNode 로 부터 Block 리포트를 받음

  • Data 에 대한 Replication 유지를 위한 커맨더 역할 수행

  • 파일시스템 이미지(스냅샷) 파일 관리(fsimage)

네임노드가 띄워져 있는 서버의 어떤 디스크에 저장을 하게 되어있음

fsimage 이게 정말 중요하다. 이게 손실이 되면 HDFS에 저장된 데이터 전부 날아가게 된다

그래서 하둡에서는 fsimage를 잘 관리할 수 있도록 몇가지 장치를 마련해두었다.

  • 파일시스템에 대한 Edit Log 관리

fsimage는 스냅샷이고, 스냅샷이 만들어지고 나서 이후에 변경사항들은 edit log에 기록된다.

# Secondary namenode

보조네임노드는 이름만보면 마스터노드를 대체할 수 있는 이중화된 노드라고 볼 수 있지만, 사실 그역할을 하는 것은 아니다. 마스터노드의 메모리에는 항상 최신상태의 fsimage를 유지하게 되어있다. 네임노드가 구동되면 fsimage를 쭉읽어서 HDFS의 메타정보를 메모리에 구성하게 된다. 그리고 edits log를 또 쭉 읽어가면서 변경된 내역을 메모리에 또 반영을 해준다. 이 작업이 다 끝나면 네임노드 구성이 완료가 되는것이고 비로소 서비스가 시작이 되는 것이다.

서비스가 시작되고 HDFS에 뭔가 변경이 일어났다하면 전부 edits log에 남는다. edits log는 당연하게도 용량이 계속 늘어날 것이다. 이 log를 fsimage에 병합을 해줘야 한다. 병합을 해줄때 네임노드에서 직접하지 않고, 보조네임노드에 fsimage와 edits log를 보내서 보조네임노드에서 이 둘을 merge한 다음에 네임노드의 fsimage와 바꿔치기 해주게 된다. 이작업을 주기적으로 해서 네임노드에 올라와 있는 최신 fsimage 정보와 거의 유사하게 만들고, edits log의 용량을 최소화 시킨다.

그러면 보조네임노드가 장애가 발생하면 어떤일이 일어나느냐. 하둡 클러스터 차원에서는 큰 문제는 아니다. 다만 edits log가 무한히 커지게 되는 문제가 발생한다. 그러면 나중에 네임노드를 리스타트할때 fsimage를 메모리에 올리고 edits log를 쭉 반영해줘야 하는데 edits log가 너무 크면 읽지를 못하고 out of memory exception이 발생할 수 있다.

image

1) 네임노드(NN)와 보조 네임노드(SNN)

Active/Standby 구조 아님

fsimage 와 edits 파일을 주기적으로 병합

2) 체크 포인트

1시간 주기로 실행

edits 로그가 일정 사이즈 이상이면 실행

3) 이슈사항

네임노드가 SPOF

보조 네임노드의 장애 상황 감지 툴 없음

# 데이터노드 역할

제일 중요한 역할은 마스터 서버한테 내가 갖고 있는 데이터를 계속 리포트를 한다. 실제 데이터는 데이터노드의 물리적 로컬파일시스템에 저장되어 있다. 네임노드는 전혀 데이터를 갖고있지 않다.

데이터노드에 하둡을 구성할때 하나의 데이터노드에 디스크가 6개가 있다하면 os와 hadoop이 설치되는 디스크는 용량은 작게 가져가고 성능은 좋은 디스크로 레이드 구성을 한다. 데이터가 저장이 되는 나머지 디스크들은 일반적으로 레이드 구성을 하지 않는다. 레이드 구성을 하는 순간 데이터를 저장하는 공간자체가 줄어든다. 그리고 페러티 비트 체크부터 시작해서 실제 데이터의 정합성을 보고 복구하는 로직이 들어가기 때문에 레이드 구성을 하는순간 내가 2테라짜리 디스크 6개가 있어서 12 테라를 쓸 수 있어야 하는데 그거를 다 못쓰게 된다.

그리고 하둡을 운영하다보면 디스크가 깨지는 경우는 자주 있는 편인데 디스크가 나가면 블록스캔을 해서 문제가 있음을 감지할것이고 이거를 네임노드에게 리포트할것이다. 그러면 네임노드가 “니가 갖고 있는 그 데이터 지우고, 다른 데이터 노드한테 그 데이터를 복사해서 갖고 있도록 조치해”라고 관리를 해준다.

image

  • DataNode는 물리적으로 로컬 파일시스템에 HDFS 데이터를 저장

  • DataNode는 HDFS 에 대한 지식이 없음

  • 일반적으로 레이드 구성을 하지 않음(JBOD(just bunch of disks) 구성)

  • 블록 리포트 : NameNode가 시작될 때, 그리고 (주기적으로) 로컬 파일시스템에 있는 모든 HDFS 블록들을 검사 후 정상적인 블록의 목록을 만들어 NameNode 에 전송

# 데이터노드 블록스캐너

  • DataNode는 블록 리포트 : NameNode가 시작될 때, 그리고 (주기적으로) 로컬 파일시스템에 있는 모든 HDFS 블록들을 검사 후 정상적인 블록의 목록을 만들어 NameNode 에 전송

http://datanode:50075/blockScannerReport

image

# HDFS 읽기 연산 처리 메카니즘

image

# HDFS 쓰기 연산 처리 메카니즘

image

replication 3을 복사할때 클라이언트가 어떤 파일을 HDFS에 저장해달라고 네임노드에게 요청하면 네임노드는 클라이언트에게 어떤 데이터노드에 저장하라고 알려준다. 그러면 클라이언트는 그 데이터노드 한대와 직접통신을 해서 그 데이터노드에 데이터를 복사를 뜨고 replication 3을 유지하기 위해서 카피뜨는 작업은 데이터노드들끼리 알아서 하게 되어있다. 클라이언트가 데이터노드 3대와 통신해서 카피를 뜨는게 아니다.

실제 자바로 쓰기를 재현하는 것을 코딩해보면 위에 그림과 같이 HDFS의 클래스를 jar file import를 해서 활용하게 된다. 결국에는 하둡에서 제공하는 클래스를 이용해서 자바 프로그래밍하는 것이다.

# Rack Awareness

렉단위로 보통 장애가 발생하는 경우가 있다. 예를 들어서 렉의 스위치가 장애가 난다던지, 전원쪽에 문제가 생긴다던지 등의 문제가 발생할수 있다. 하둡에 데이터를 저장할때 아래 그림과 같이 서로 다른 렉에 블록이 최소 하나이상 복사가 될 수 있도록 설정하는 것이다.

image

블록을 저장할때, 2개의 블록은 같은 랙에, 나머지 하나의 블록은 다른랙에 저장하도록 구성함

–> 랙 단위 장애 발생(전원, 스위치 등)에도 전체 블록이 유실되지 않도록 구성함

# HDFS 세이프 모드

HDFS의 노드중에 뭔가 문제가 있는 상태가 많아지면 예를 들어서 missing block이 많아지면 (전체 데이터 수 대비 일정 퍼센티지 이상 missing block이 많아질때) 하둡이 뭔가 문제가 있다고 판단해서 세이프 모드로 전환한다.

** replication 설정이 3인데 실제 2인 경우 : under replicated, 그리고 replication 설정이 3인데 하나도 없는 경우 : missing block이라고 표현한다.

또는 클러스터를 재구동 했을때도 처음에는 네임스페이스에 정보를 전부 구성하기 전까지는 세이프모드로 동작하게 된다.

  • 세이프모드 특징

1) HDFS의 세이프모드(safemode)는 데이터 노드를 수정할 수 없는 상태

2) 세이프 모드가 되면 데이터는 읽기 전용 상태가 되고, 데이터 추가와 수정이 불가능 하며 데이터 복제도 일어나지 않음

3) 관리자가 서버 운영 정비를 위해 세이프 모드를 설정 할 수 있음

4) 네임노드에 문제가 생겨서 정상적인 동작을 할 수 없을 때 자동으로 세이프 모드로 전환

–> 주로 missing block 이 발생하는 경우, 혹은 클러스터 재 구동 시 블록 리포트를 다 받기 전까지 Safe mode 로 동작

5) 세이프 모드 상태일 때 파일 복사를 시도하면 아래와 같은 에러 메시지 발생

$ hdfs fs -put ./sample.txt /user/sample.txt
put : Cannot create file/user/sample2.txt._COPYING_. Name node is in safe mode.
  • HDFS 세이프 모드 명령어 및 복구
# 세이프 모드 상태 확인
$ hdfs dfsadmin -safemode get
Safe mode is OFF

# 세이프 모드 진입
$ hdfs dfsadmin -safemode enter
Safe mode is ON

# 세이프 모드 해제
$ hdfs dfsadmin -safemode leave
Safe mode is OFF

HDFS 운영 중 Safe mode 에 진입한 경우, 네임노드의 문제인지 데이터노드의 문제인지 파악이 필요하며,fsck 명령으로 HDFS의 무결성을 체크하고, hdfs dfsadmin -report 명령으로 각 데이터 노드의 상태를 확인하여 문제를 확인하고 해결한 후 세이프 모드를 해제 해야 함

# corrupt block

커럽트 블록은 파일자체가 깨졌다는 것이다. 이 말은 데이터 유실이 발생했다는 것이다. 실제 현업에서 볼일은 거의 없음. 데이터노드 세대가 동시에 장애가 발생하면 corrupt block이 발생할 수도 있다.

  • HDFS는 하트비트를 통해 데이터 블록에 문제가 생기는 것을 감지하고 자동으로 복구를 진행함

  • 다른 데이터 노드에 복제된 데이터를 가져와서 복구하지만, 모든 복제 블록에 문제가 생겨서 복구 하지 못하게 되면 커럽트 상태가 됨.

  • 커럽트 상태의 파일들은 삭제하고, 원본 파일을 다시 HDFS에 올려주어야 함

  • 커럽트 상태 확인방법

image

  • 커럽트 상태 확인 및 처리방법

아래와 같이 커럽트 상태가 발생하면

bin/hadoop fsck /user/hadoop

The filesystem under path '/user/hadoop' is CORRUPT

# 커럽트 상태의 파일 삭제
$ hdfs fsck -delete

# /user/hadoop/ 의 복제갯수를 5로 조정
$ hadoop fs -setrep 5 /user/hadoop/

# /user/hadoop/ 하위의 모든 파일의 복제 개수를 조정
$ hadoop fs -setrep 5 -R /user/hadoop

bin/hadoop fsck -delete를 통해 커럽트 파일을 삭제해야함

# HDFS 휴지통 설정 방법 및 명령어

하둡에서 데이터를 지울때 물리적으로 바로 지우는게 아니라 네임노드 메모리에서만 삭제를 하고 실제로는 .trash라는 디렉토리로 보내는 것을 말한다. 그리고 .trash에서 그 삭제한 파일을 언제까지 갖고 있을지를 설정할 수 있다. 보통은 하루 많게는 3일까지 설정해서 사용하는 편이다.

image

# 운영자 커맨드 목록

image

  • 예시

image

image

특정디렉토리는 예를들어서 특정팀한테만 데이터를 저장하거나 복사할 수 있게 가이드를 해줬는데 그 디렉토리의 용량을 1테라로 제한하고 싶다라는 설정을 해줄 수 있다. 그거를 쿼터설정이라고 한다.

# HDFS Balancers

하둡 클러스터의 노드들이 도입시기에 따라서 다를 수가 있는데 노드들끼리 디스크간에 발란싱이 안되는 경우가 있다. 예를 들어서 2018년도에 도입한 서버에는 하나의 데이터노드에 디스크가 20테라가 있는데, 2020년에 도입한 서버에는 40테라가 있다고 가정하자. 그러면 네임노드가 데이터를 저장할때 노드들에 데이터가 얼마나 저장되어 있는지 퍼센티지를 보면서 할당을 하게 되는데 알고리즘상 무조건적으로 퍼센티지만을 보면서 저장하지는 않기 때문에 18년도에 도입한 노드에는 50프로 이상 데이터가 저장되어 있는데 상대적으로 20년에 도입한 노드에는 50프로가 안되는 현상이 발생한다. 즉 노드들간에 데이터 저장비율이 불균형한 상황이 발생할수도 있다. 하둡 2.0까지는 이런 것을 잘 관리를 해줘야한다. 3.0버전에서는 이런것이 어느정도 개선이 되었다고 한다.

밸런싱을 하면 데이터노드들끼리 데이터를 주고 받으면서 노드간에 데이터 저장비율을 균등하게 맞추게 된다. 그러면 발란싱을 해주면 되는거 아니냐라고 할수도 있는데 이게 하둡 클러스터가 운영중이라고 하면 상당히 위험한 작업이다. 왜냐하면 하둡에는 상당히 큰 데이터들이 여러개 저장되어 있고, 그런 데이터들에 항상 많은 job들이 상시로 돌아가고 있기 때문이다. 예를들어서 어떤 시간에는 ETL이 돌아야하고, 어떤 시간에는 머신러닝 job이 돌아야하고 이런것들이 있다. 따라서 상당히 까다롭고 어려운 작업이다.

사실 그래서 가능하면 하둡 클러스터의 모든 노드가 동일한 스펙인게 가장 좋다.

  • 하둡을 운영하다보면, 서로 다른 스펙의 데이터노드를 하나의 클러스터로 구성하게 됨

  • 이 경우 노드 간 디스크 크기가 다를 수 있고, 전체 데이터의 밸런싱이 되지 않는 문제가 발생할 수 있음

  • 신규 데이터 노드를 추가 하는 경우에도 발생할 수 있음

–> 이 경우 NameNode 에서 데이터 적재량이 적은 노드를 우선적으로 선정하여 block 을 추가하는데, 이때 특정 노드에 부하가 몰릴 수 있음

  • Balancer 실행
sudo -u hdfs hdfs balancer [-policy <policy>] [-threshold <threshold>] [-blockpools <comma-separated list o
f blockpool ids>] [-include [-f <hosts-file> | <comma-separated list of hosts>]] [-exclude [-f <hosts-file> | <com
ma-separated list of hosts>]] [-idleiterations <idleiterations>] [-runDuringUpgrade]
  • 발란싱할때 고려해야하는 옵션

동시에 빨리 얼마나 복사를 할거냐에 대한 관점이 있다.

데이터노드들끼리 데이터를 주고 받기 때문에 트레픽이 발생하게 되는데 초당 밴드위스를 얼마나 줄건지 설정을 해줘야 한다.

일반적으로는 보수적으로 설정을 한다. 무슨말이냐면 리소스를 많이 잡지 않도록 설정을 해준다. 그래서 백그라운드에서 조금조금씩 밸런싱이 되도록 설정하는 것이 일반적이다.

그래서 이미 운영중인 상태에서 돌아가야하는 job들에게 리소스를 보장해줘야 한다. 클러스터의 규모에 따라 2주 ~ 한달이 걸리는 경우가 있다.

하둡 파일 (hdfs-site.xml) 설정 중 Balancer 와 연관된 중요한 설정이 있음

<property>
    <name>dfs.datanode.balance.max.concurrent.moves</name> # 쓰레드를 여러개 띄워서 디스크에 밸런싱을 할때 얼마나 많은 쓰레드가 일을 처리하게 할거냐
    <value>50</value>
</property>
<property>
    <name>dfs.datanode.balance.bandwidthPerSec</name>   # 데이터노드를 기준으로 밴드위스를 얼마나 줄거냐
    <value>104857600</value>
</property>

이 설정은 보통 하둡 클러스터 운영에 문제가 없도록 방어적으로 설정하는 것이 일반적임

명령어로도 설정을 반영할 수 있음

balancer 대역폭을 100M로 올림

[root@localhost]# $HADOOP_HOME/bin/hdfs dfsadmin -setBalancerBandwidth 104857600

# WEB HDFS REST API

  • HDFS는 REST API를 제공하기 때문에 원격에서 파일을 조회하고, 생성, 수정, 삭제하는 것이 가능함

  • 상세 내용 : https://hadoop.apache.org/docs/stable/hadoop-project-dist/hadoop-hdfs/WebHDFS.html

  • 이 기능을 이용하여 원격지에서 HDFS의 내용에 접근하는 것이 가능합니다.

  • hdfs-site.xml 에 아래 설정 필요

<property>
    <name>dfs.webhdfs.enabled</name>
    <value>true</value>
</property>
<property>
    <name>dfs.namenode.http-adress</name>
    <value>0.0.0.0:50070</value>
</property>    
  • WEB HDFS를 이용한 파일리스트 확인 예시
# /user/hadoop/ 위치를 조회
$ curl -s http://127.0.0.1:50070/webhdfs/v1/user/hadoop/?op=LISTSTATUS

# HDFS 암호화 – KMS (Key Management Server)

HDFS는 암호화를 위해서 별도로 KMS를 별도로 띄우고, 몇가지 작업을 해줘야함. KMS를 띄우고 KMS에서 생성한 키를 가지고 하둡의 특정영역을 암호화 영역으로 설정하여 해당 영역에 저장되는 데이터는 자동으로 암호화시킬 수 있다. 물론 암호화 알고리즘은 뭐를 쓸거냐 퍼블릭키는 뭐를 쓸거냐에 대한 것들을 잘 설정해줘야 한다.

  • 하둡 KMS 는 KeyProvider API 를 기반으로 하는 암호화 키 관리 서버임 (REST API 제공)

  • 상세 내용 : https://hadoop.apache.org/docs/current/hadoop-kms/index.html

image

# Hadoop 2.0

image

마스터서버의 장애를 해결하기 위한 부분이 가장 큰 변화 포인트이다. 위에 그림에서 active namenode와 secondary namenode는 기존과 동일하고, standby namenode라는게 2.0에서 추가가 되었다. 데이터노드가 블락리포트를 한다던지 등의 네임노드와 통신하는 것들을 항상 active namenode와 standby namenode과 양쪽으로 통신하게 되어있다. standby namenode는 active namenode와 동일한 정보는 갖고 있지만 평소에는 동작하지 않다가 active namenode가 다운되었을때 standby namenode가 active namenode로 전환된다. 하둡 2.0 버전부터는 이런구조로 HDFS의 네임노드를 이중화하였다.

하둡 2.0에서는 active namenode가 죽었을때 standby namenode로 failover되는 과정에서 약간의 다운타임이 발생할 수 있다. 네임노드에 들어가 있는 메타정보가 얼마나 크냐에 따라 달라진다. HDFS에 저장된 파일이 몇억개 단위 규모라고 하면 네임노드에서 들고 있는 파일의 네임스페이스 정보(메타정보) 크기가 100기가 이상 메모리에 정보를 들고 있는 경우가 있다. 그래서 gc 발생하면 1 ~ 2분이 걸리는 경우도 있다. 그래서 gc가 발생하지 않도록 잘 관리해줘야 한다. 결론적으로 fsimage와 edits log가 얼마나 크냐에 따라서 약간 시간이 걸린다. 일반적으로 몇억개라고 하면 5~10분 정도 다운타임이 걸릴 수도 있다.

또한 매우 중요한 부분이 ‘shared edits log’인데 이게 뭐냐면 하둡 1.0에서는 fsimage와 edits log가 active node의 디스크에 저장되도록 되어있다. 그런데 이 fsimage와 edits log가 손실되면 HDFS 전체가 무너지는 아주 큰 리스크가 있다. 그래서 하둡 1.0에서도 fsimage를 2 ~ 3개로 설정할 수 있다. fsimage를 저장하는 경로를 주는 옵션이 있는데 거기의 벨류값에 디렉토리를 ,를 delimiter로 줘서 여러개를 줄수가 있다. 그러면 하둡 네임노드의 서로다른 물리적인 로컬 디스크에 fsimage를 저장할 수 있다. 그래서 fsimage와 edits log를 항상 복수개를 저장할 수 있다. 그래서 디스크 하나가 날아가더라도 유실되지 않도록 할 수 있다. 일반적으로는 하둡 1.0에서는 이런식으로 fsimage와 edits log를 운영한다.

그런데 하둡 2.0이 되면서 standby namenode가 등장했고, 이 fsimage와 edits log를 어디에다 관리를 할거냐라는 문제가 생긴다. 왜냐하면 active와 standby에 공유를 해야하기 때문이다. 이 내용은 아래 namenode 고가용성에서 자세히 알아보자

# 네임노드 고가용성(High Availabilty)

JournalNode는 edits 정보(fsimage가 있고 edits log들이 쭉 있는 정보 = 파일시스템의 journaling 정보)를 저장하고 공유하는 기능을 수행하는 서버다. 하둡에서는 JournalNode에 저장되는 데이터는 아주 중요한 데이터이기 때문에 하나의 서버로 구성되지 않고 3대이상으로 구성하는 편이다. 그래서 active와 standby가 이 저널노드에 저장된 fsimage와 edits log를 서로 공유할 수 있는 shared 방식이다. 그러면 JournalNode도 물리적인 리눅스 서버일텐데 이 파일시스템의 journaling 정보를 어디에다 저장할건지에 대한 이슈가 생긴다. 그거에 대한 해결방안은 에디트로그 공유 방식1 : NFS(Network File System)에디트로그 공유 방식2 : Joural Node 그룹 사용를 참고하자.

image

  • HDFS 고가용성은 이중화된 두대의 서버인 액티브(active) 네임노드와 스탠바이(standby) 네임노드를 이용하여 지원

  • 액티브 네임노드와 스탠바이 네임노드는 데이터 노드로부터 블록 리포트와 하트비트를 모두 받아서 동일한 메타데이터를 유지하고, 공유 스토리지를 이용하여 에디트파일을 공유

  • 액티브 네임노드는 네임노드의 역할을 수행하고, 스탠바이 네임노드는 액티브 네임노드와 동일한 메타데이터 정보를 유지하다가, 액티브 네임노드에 문제가 발생하면 스탠바이 네임노드가 액티브 네임노드로 동작

  • 액티브 네임노드에 문제가 발생하는 것을 자동으로 확인하는것이 어렵기 때문에 보통 주키퍼를 이용하여 장애 발생시 자동으로 변경될 수 있도록 구성함

# 에디트로그 공유 방식1 : NFS(Network File System)

쉽게 얘기해서 공유스토리지에다 공유하는 것이다.

  • NFS를 이용하는 방법은 에디트 파일을 공유 스토리지를 이용하여 공유하는 방법

  • 공유스토리지에 에디트 로그를 공유하고 펜싱을 이용하여 하나의 네임노드만 에디트 로그를 기록함

** 펜싱(fencing) : 하나의 네임노드가 죽었을때 대기를 타고 있던 스텐바이 네임노드가 엑티브로 전환이 되는 부분을 말한다. 펜싱도 여러가지 방법으로 설정할 수 있다. 기본적으로 하둡 2.0에서 액티브 네임노드의 failover 알고리즘은 주키퍼에 의존하고 있다. 그래서 주키퍼의 어떤 알고리즘에 의해서 액티브 네임노드에 장애가 났다고 판단을 하고 스텐바이 네임노드로 전환이 된다.

  • Split Brain 위험이 존재하고, 한계점이 있음

  • NFS(Network File System) 공유 방식의 문제점

1) NN 두개가 모두 Acitive NN 가 될 수 있는 상황이 발생하여, 동시에 Shared Storage 의 데이터를 수정하면 NameNode 의 중요 정보가 Crash 되며, 분산환경에서는 이 상태를 SplitBrain 이라고 함

2) 두개의 Active NN 가 발생하는 상황을 막기 dfs.ha.fencing.methods 위해 설정을 통해 Active NN 을 Kill 시키거 나 Shared Storage 를 unmount 해줌 –> sshfence 인 경우 아래 처럼 NameNode 를 Kill 시킴

fuser -v -k -n tcp <namenode port>

3) 그렇지만 네트워크 장애의 경우, 기존 Active NameNode 가 ZooKeeper 와 Standby NameNode 로만 통신이 되지 않고, SharedStorage와 통신이 되는 상황이라면?

–> 이런 경우 Standby NameNode에서 fencing 처리는 네트워크 단절로 인해 수행할 수 없으며, 기존 Active NameNode 는 여전히 Live한 상태가 됨. 쉽게 말해서 active namenode 두대가 되면서 이 두대가 저널노드의 edits log에 기록을 하게 된다. 그러면 edits log가 완전히 망가지게 된다. 확률적으로 적은 확률이지만 만약에 이런경우가 생기면 namenode의 fsimage와 edits log가 crack 되는 상황이 발생하는 것이고 이런 상황을 분산환경에서는 SplitBrain이라고 부른다.

# 에디트로그 공유 방식2 : Joural Node 그룹 사용

네임노드 안에 구현되어 있는 QJM(Quorum Journal Manager)라는 것을 통해서 NAS와 같은 공유스토리지에 저장하지 않는 방식으로 처리하는 걸 지원한다. NAS를 빼고도 하둡자체적으로도 고가용성을 보장할 수 있다.

  • 하둡 2.0의 디폴트 방식

  • QJM(Quorum Journal Manager)은 NameNode 내부에 구현된 HDFS 전용 구현체로, 고가용성 에디트 로그를 지원하기 위한 목적으로 설계됨

  • QJM은 저널 노드 그룹에서 동작하며, 각 에디트 로그는 전체 저널 노드에 동시에 쓰여짐

–> 주키퍼의 동작 방식과 유사함

  • HDFS 고가용성은 액티브 네임노드를 선출하기 위해 주키퍼를 이용

  • Joural Node 사용 시 Failover 절차

step1) Active NameNode는 edit log 처리용 epoch number를 할당 받는다. 이 번호는 uniq하게 증가하는 번호로 새로 할당 받은 번호는 이전 번호보다 항상 크다.

step 2) Active NameNode는 파일 시스템 변경 시 JournalNode로 변경 사항을 전송한다. 전송 시 epoch number를 같이 전송한다.

step 3) JournalNode는 자신이 가지고 있는 epoch number 보다 큰 번호가 오면 자신의 번호를 새로운 번호로 갱신하고 해당 요청을 처리한다.

step 4) JournalNode는 자신이 가지고 있는 번호보다 작은 epoch number를 받으면 해당 요청은 처리하지 않는다.

이런 요청은 주로 SplitBrain 상황에서 발생하게 된다.

기존 NameNode가 정상적으로 Standby로 변하지 않았고, 이 NameNode가 정상적으로 fencing 되지 않은 상태이다.

step 5) Standby NameNode는 주기적(1분)으로 JournalNode로 부터 이전에 받은 edit log의 txid 이후의 정보를 받아 메모리의 파일 시스템 구조에 반영

step 6) Active NameNode 장애 발생 시 Standby NameNode는 마지막 받은 txid 이후의 모든 정보를 받아 메모리 구성에 반영 후 Active NameNode로 상태 변환

step 7) 새로 Active NameNode가 되면 1번 항목을 처리한다

# HDFS Federation

네임노드 이중화하고 개념이 헷갈릴수도 있는데 HDFS Federation은 완전히 다른개념이다. 하둡 클러스터를 운영하다 보면 어느시점에 하나의 물리적인 서버의 네임노드안에 올릴 수 있는 메모리를 초과하는 양의 파일을 운영을 해야하는 경우도 있다. 예를 들어서 네임노드의 물리적인 메모리는 512GB인데 전체 클러스터에 저장되어 있는 파일과 블럭의 메타정보를 메모리에 로딩했더니 700GB이다. 그러면 하나의 네임노드 메모리에 올라가지 않을 것이다. 이런 경우 네임노드 자체를 여러대로 운영해야 하는 상황이 발생할 수 있다. 이런 경우가 HDFS Federation이다. 네임노드를 여러대를 띄워서 예를 들어서 2018년 데이터는 1번 네임노드에 2019년 데이터는 2번 네임노드에서 관리할 수 있도록 Block pool을 지원한다. 그래서 HDFS Federation을 통해서 네임노드도 scale out할 수 있도록 지원하는 것이 하둡 2.0에서의 특징이다.

국내에서는 Federation을 적용한 사례는 없고, Federation를 하려면 적어도 2000노드 이상은 운영해야하지 않을까라는 것이 일반적이다. 노드 2000개 정도되면 Federation을 고려할 수 있다.

image

  • 하나의 네임노드에서 관리하는 파일, 블록 개수가 많아지면 물리적 한계가 있음

  • 이를 해결하기 위해 HDFS Federation 을 하둡 2.0 이상에서 지원

  • HDFS 페더레이션을 사용하면 파일, 디렉토리의 정보를 가지는 네임스페이스와 블록의 정보를 가지는 블록 풀을 각 네임노드가 독립적으로 관리

  • 네임스페이스와 블록풀을 네임스페이스 볼륨이라하고 네임스페이스 볼륨은 독립적으로 관리되기 때문에 하나의 네임노드에 문제가 생겨도 다른 네임노드에 영향을 주지 않음

# 아파치 주키퍼(ZooKeeper)

  • 주키퍼는 분산 시스템의 코디네이터로 주로 아래와 같은 목적으로 사용됨

1) 설정 관리 (Configuration Management)

2) 분산 클러스터 관리 (Distributed Cluster Management)

3) 명명 서비스 (Naming Service: e.g. DNS)

4) 분산 동기화 (Distributed Synchronization : locks, barriers, queues)

5) 분산 시스템에서 리더 선출 (Leader election in a distributed system)

하둡 2.0에서는 액티브노드에 대한 선출. 누가 액티브노드가 되고 누가 스텐바이가 될건지에 대한 선출.

6) 중앙집중형 신뢰성 있는 데이터 저장소 (Centralized and highly reliable data registry)

  • 주키퍼 구성

1) 주키퍼는 n 개의 서버로 단일 클러스터를 구성하며 이를 서버 앙상블 이라고 함

일반적으로는 3대 또는 5대로 앙상블을 구성함

2) 주키퍼 서비스는 복수의 서버에 복제되며, 모든 서버는 데이터 카피본을 저장

3) Leader 는 구동 시 주키퍼 내부 알고리즘에 의해 자동 선정

4) Followers 서버들은 클라이언트로부터 받은 모든 업데이트 이벤트를 리더에게 전달함

5) 클라이언트는 모든 주키퍼 서버에서 읽을 수 있으며, 리더를 통해 쓸 수 있고 과반수 서버의 승인(합의)가 필요함

image

  • 아파치 주키퍼(ZooKeeper) 데이터 모델

image

데이터노드는 위에 그림과 같이 기본적으로 트리형태의 구조를 가지게 되고, 하나의 노드에 persistent nodes, ephemeral node 라는 타입으로 노드를 붙일 수 있다. 예를들면 슬레이브 노드에 멤버쉽이라는 persistent node를 만들고, ephemeral node로 클라이언트가 하나 뜨면서 주키퍼와 커넥션을 맺는다. 그런데 이 ephemeral node 커넥션은 세션이 유지되는 동안에만 커넥션 관계가 유지된다. 만약에 네트워크 장애가나면 ephemeral node 커넥션은 끊어지게 된다. 그러면 주키퍼는 이 ephemeral node가 끊어졌다는 것을 감지한다. 이런 정보를 watch를 등록한 얘한테 변경되었다는 내용을 보내줄 수 있다. 하둡2.0에서는 아래에 WATCH라는 알고리즘을 통해서 QJM(Quorum Journal Manager)가 네임노드를 누구로 할건지 주키퍼에 등록되어 있는 znode 상태를 보고 이벤트를 노티받아서 마스터를 선출하게 된다.

  • 아파치 주키퍼(ZooKeeper) Operations

image

  • 아파치 주키퍼(ZooKeeper) WATCH

image

  • 아파치 주키퍼(ZooKeeper) 사용예시

image

** 분산 배타적 장금 : RDB에서 Lock을 생각하면 된다. 동시에 하나의 파일에 같은 서로다른 어플리케이션이 데이터를 바꾸고자 하면 데이터에 문제가 생길 수 있기 때문에 쓰기를 할경우 Lock을 잡는다. Lock을 잡는 동안에는 아무도 쓰기를 할 수 없는 상태가 된다. Lock을 잡고있는 얘만 쓰기를 할 수 있는 것이다. 분산환경에서도 이런경우가 발생한다. 그래서 Lock에 대한 관리도 분산환경에서는 누군가 해줘야 하는데 이거를 주키퍼로 해결을 한다.

** 주키퍼 같은 경우는 하둡 2.0 부터는 하둡의 기본적인 구성요소로 들어가게 된다.

# 기타 참고사항

  • 하둡이 소프트웨어지만 인프라를 잘 알고 있어야 하기 때문에 어렵다.

  • 하둡은 자바로 개발되어 있기 때문에 자바를 아는것이 좋다.

  • HBase와 유사한 어플리케이션은 카산드라

  • sqoop은 관계형db와 하둡 간에 데이터를 주고 받아야 하는 케이스가 종종 있기 때문에 이를 쉽게 할 수 있는 프레임 워크

  • 하둡에서 관리하는 데이터의 스키마를 하나의 카탈로그로 관리하겠다는 의도로 나온게 Hcatalog

  • 메이븐은 자바기반으로 외부 라이브러리의 디펜던시를 쉽게 관리하도록 하는 툴

  • 사용자가 주로 설정하는 파일

hadoop-env.sh 하둡기본설정

core-site.xml 코어설정

hdfs-site.xml hdfs 설정

yarn-site.xm yarn 설정

  • 다운로드 받은 하둡디렉토리에 대한 환경변수 설정법 : .bash_profile 에서 하둡 경로 설정하는 커맨드 예시
export HADOOP_HOME=/Users/hongtebari/Platform/hadoop-3.3.0
export PATH=$HADOOP_HOME/bin:$PATH