데이터가 단일 물리머신의 저장용량을 초과하게 되면 전체 데이터셋을 분리된 여러 머신에 나눠서 저장할 필요가 있다. 네트워크로 연결된 여러 머신의 스토리지를 관리하는 파일시스템을 분산시스템 이라고 한다. 분산 시스템은 네트워크 기반이므로 네트워크 프로그램의 복잡성을 모두 가지고 있다.따라서 일반적인 디스크 파일시스템보다 훨씬 더 복잡하다. 예를 들어 최고의 난제중 하나는 특정 노드에 장애가 발생해도 자료가 유실되지 않는 강건한 파일시스템을 만드는것이다.
하둡은 HDFS라는 분산파일 시스템을 제공한다.HDFS는 "Hadoop Distiributed FileSystem(하둡 분산 파일시스템)"의 약자다.
예전 문서에는 DFS로 표기하기도 했다. 3장에서 다루는 HDFS는 하둡의 대표적인 파일시스템이다. 하둡은 범용 파일시스템을 추구하기 때문에 추상화의 개념을 가지고 있다.우리는 하둡이 로컬 파일시스템이나 아마존의 S3와 같은 다른 스토리지 시스템을 통합하는 방식도 함께 살펴볼 것이다.
3 HDFS의 설계
HDFS는 범용 하드웨어로 구성된 클러스터에서 실행되고 스트리밍 방식의 데이터 접근 패턴으로 대용량 파일을 다룰 수 있도록 설계된 파일시스템이다. HDFS의 설계 특성은 다음과 같다.
- 매우 큰 파일
- '매우 큰'의 의미는 수백 메가바이트, 기가바이트 또는 테라바이트 크기의 파일을 의미한다. 최근에는 페타바이트 크기의 데이터를 저장하는 하둡 클러스터도 있다.
- 스트리밍 방식의 데이터 접근
- HDFS는 '가장 효율적인 데이터 처리 패턴은 한번 쓰고 여러 번 읽는 것'이라는 아이디어에서 출발했다. 데이터셋은 생성되거나 원본으로 부터 복사된다. 그리고 시간이 흐르면서 다양한 분석을 수행할 수 있다.분석이 전부는 아니지만 첫번째 레코드를 읽는데 걸리는 지연 시간보다 전체 데이터 셋을 모두 읽을 때 걸리는 시간이 더 중요하다.
- 범용 하드웨어
- 하둡은 고가의 신뢰도 높은 하드웨어만 고집하지는 않는다. 하둡은 노드 장애가 발생할 확률이 높은 범용 하드웨어(여러 업체에서 제공하는 쉽게 구할 수 있는 하드웨어)로 구성된 대형 클러스터에서 문제없이 실행되도록 설계되었다. HDFS는 이러한 장애가 발생하더라도 사용자가 장애가 발생했다는 사실조차 모르게 작업을 수행하도록 설계되었다.
HDFS가 적합하지 않은 응용 분야를 조사하는 것 역시 가치 있는 일이다. 나중에는 변할지 모르지만 현재 HDFS가 잘 맞지 않는 응용 분야는 다음과 같다.
- 빠른 데이터 응답 시간
- 데이터 접근에 수십 밀리초 수준의 빠른 응답 시간을 요구하는 애플리케이션은 HDFS는 높은 데이터 처리량을 제공하기 위해 최적화되어 있고 이를 위해 응답 시간을 희생했다. 빠른 응답 시간을 원한다면 현재로서는 HBase가 하나의 대안이 될수 있다.
- 수많은 작은 파일
- 네임노드는 파일시스템의 메타데이터를 메모리에서 관리하기 때문에 저장할수 있는 파일수는 네임노드의 메모리 용량에 좌우된다.경험상으로 파일, 디렉터리, 블록은 각각 150바이트 정도의 메모리가 필요하다. 따라서 파일 수가 백만개이고 각 파일의 블록이 하나면 적어도 300MB의 메모리가 필요하다. 물론 수백만개의 파일은 괜찮겠지만 수십억 개의 파일은 하드웨어 용량을 넘어서게 된다.
- 다중 라이터와 파일의 임의 수정
- HDFS는 단일 라이터로 파일을 쓴다. 한 번 쓰고 끝나거나 파일의 끝에 덧붙이는 것은 가능하지만 파일에서 임의 위치에 있는 내용을 수정하는 것은 허용하지 않으며 다중 라이터도 지원하지 않는다.(하둡 3.0부터는 다중 라이터를 지원한다.)
3-1 HDFS 개념
블록
물리적인 디스크는 블록 크기란 개념이 있다. 블록 크기는 한번에 읽고 쓸수 있는 데이터의 최대량이다.단일 디스크를 위한 파일시스템은 디스크 블록 크기의 정배수인 파일시스템 블록 단위로 데이터를 다룬다. 파일시스템 블록의 크기는 보통 수 킬로바이트고, 디스크 블록의 크기는 기본적으로 512바이트다. 사용자는 파일의 크기와 상관없이 파일을 읽고 쓸수 있으며, 특정 파일시스템에 구애 받지도 않는다. 하지만 파일 시스템의 블록 수준에서 파일 시스템의 유지관리를 수행하는 df나 fsck와 같은 도구도 있다.
HDFS도 역시 블록의 개념을 가지고 있다. 그러나 HDFS 블록은 기본적으로 128MB와 같이 굉장히 큰 단위다. HDFS의 파일은 단일 디스크를 위한 파일시스템 처럼 특정 블록 크기의 청크(chunk)로 쪼개지고 각 청크는 독립적으로 저장된다. 단일 디스크를 위한 파일시스템은 디스크 블록 크기보다 작은 데이터라도 한 블록 전체를 점유하지만, HDFS 파일은 블록 크기보다 작은 데이터일 경우 전체 블록 크기에 해당하는 하위 디스크를 모두 점유하지는 않는다. 예를 들어 HDFS의 블록 크기가 128MB고 1MB 크기의 파일을 저장한다면 128MB의 디스크를 사용하는 것이 아니라 1MB의 디스크만 사용한다.
HDFS 블록이 왜큰가?
HDFS 블록은 디스크 블록에 비해 상당히 크다. 그 이유는 탐색 비용을 최소화 하기 위해서다.블록이 매우 크면 블록의 시작점을 탐색하는 데 걸리는 시간을 줄일수 있고 데이터를 전송하는데 더 많은 시간을 할애할 수 있다. 따라서 여러개의 블록으로 구성된 대용량 파일을 전송하는 시간은 디스크 전송 속도에 크게 영향을 받는다.
탐색 시간이 10ms고 전송률이 100MB/s라고 하면, 탐색 시간을 전송 시간의 1%로 만들기 위해서는 블록 크기를 100MB로 정하면 된다. 하둡 배포판에 따라 다르지만 블록 크기의 기본값은 128MB다(대부분의 HDFS는 이보다 큰 블록 크기를 사용함)
기본 블록 크기는 디스크 드라이브의 전송 속도가 향상될 때마다 계속 증가할 것이다.
그러나 이 논의를 그렇게 멀리 가져갈 필요는 없다. 맵리듀스의 맵 태스크는 기본적으로 한 번에 하나의 블록을 처리한다. 따라서 만일 태스크 수가 적으면(클러스터에 있는 노드보다 더 적으면)태스크 수가 많을 때보다 잡이 더 느리게 수행될 것이다.
분산 파일시스템에 블록 추상화의 개념을 도입하면서 얻게된 이득
첫번째 : 파일하나의 크기가 단일 디스크의 용량보다 더 커질수 있다는 것이다.
하나의 파일을 구성하는 여러개의 블록이 동일한 디스크에만 저장될 필요가 없으므로 클러스터에 있는 어떤 디스크에도 저장될 수 있다. 실제 그런일이 발생할 가능성은 거의 없지만 HDFS는 클러스터의 전체 디스크를 모두 채울 정도로 큰 파일 하나를 저장하는것도 가능하다.
두번째 : 파일단위보다는 블록 단위로 추상화를 하면 스토리지의 서브시스템을 단순하게 만들 수 있다는 것이다. 단순화는 모든 시스템이 추구하는 이상이지만 특히 분산 시스템에서는 장애 유형이 너무나도 다양하기 때문에 더욱 중요하다. 블록을 다루는 스토리지의 서브시스템은 스토리지 관리를 단순화 하기 쉽고 (블록은 고정 크기고 저장에 필요한 디스크 용량만 계산하면 된다)메타데이터
에 대한 고민을 덜수있다. 블록은 단지 저장된 데이터의 청크일 뿐이고 권한 정보와 같은 파일의 메타데이터는 블록과 함께 저장될 필요가 없으므로 별도의 시스템에서 다루도록 분리할 수 있다.
더욱이 블록은 내고장성과 가용성을 제공하는데 필요한 복제를 구현할 때 매우 적합하다. 블록의 손상과 디스크 및 머신의 장애에 대처하기 위해 각 블록은 물리적으로 분리된 다수의 머신(보통 3개)에 복제된다. 만일 하나의 블록을 이용할 수 없는 상황이 되면 다른 머신에 있는 복사본을 읽도록 클라이언트에 알려주면 된다. 블록이 손상되거나 머신의 장애로 특정 블록을 더이상 이용할 수 없으면 또다른 복사본을 살아있는 머신에 복제하여 복제 계수를 정상조준으로 돌아오게 할 수 있다. 마찬가지로 읽기 부하를 클러스터 전체에 분산시키기 위해 특정 블록의 복제 계수를 높게 설정할 수도 있다.
일반적인 디스크 파일시스템과 같이 HDFS 의 fsck 명령어로 블록을 관리할 수 있다. 다음명령어를 실행하면
% hdfs fsck / -files -blocks
파일시스템에 있는 각 파일을 구성하는 블록의 목록이 출력될 것이다.
3-2 네임노드와 데이터노드
HDFS 클러스터는 마스트-워커 패턴으로 동작하는 두 종료의 노드(마스터인 하나의 네임노드와 워커인 여러 개의 데이터노드로 구성되어 있다.)
네임노드 : 파일시스템의 네임스페이스를 관리한다. 네임노드는 파일시스템 트리와 그 트리에 포함된 모든 파일과 디렉터리에 대한 메타데이터를 유지한다. 이 정보는 네임스페이스 이미지와 에디트 로그라는 두 종류의 파일로 로컬디스크에 영속적으로 저장된다. 네임노느는 또한 파일에 속한 모든 블록이 어느 데이터노드에 있는지 파악하고 있다. 하지만 블록의 위치 정보는 시스템이 시작할때 모든 데이터노드로부터 받아서 재구성하기 때문에 디스크에 영속적으로 저장하지는 않는다.
HDFS 클라이언트는 사용자를 대신해서 네임노드와 데이터노드 사이에서 통신하고 파일시스템에 접근한다. HDFS 클라이언트는 POSIX와 유사한 파일시스템 인터페이스를 제공하기 때문에 사용자는 네임노드와 데이터노드에 관련된 함수를 몰라도 코드를 작성할 수 있다.
데이터 노드: 파일시스템의 실질적인 일꾼이다. 데이터노드는 클라이언트나 네임노드의 요청이 있을 때 블록을 저장하고 탐색하며, 저장하고 있는 블록의 목록을 주기적으로 네임노드에 보고한다.네임노드가 없으면 파일시스템은 동작하지 않는다. 네임노드를 실행하는 머신이 손상되면 파일시스템의 어떤 파일도 찾을 수 없다. 데이터노드에 블록이 저장되어 있지만 이러한 블록 정보를 이용하여 파일을 재구성할 수는 없기 때문이다. 따라서 네임노드의 장애복구 기능은 필수적이며, 하둡은 이를 위해 두 가지 메커니즘을 제공한다.
1. 파일시스템의 메타데이터를 지속적인 상태로 보존하기 위해 파일로 백업하는 것이다. 네임노드가 다수의 파일시스템에 영구적인 상태를 저장하도록 하둡을 구성할 수 있다. 백업 작업은 동기화되고 원자적으로 실행된다. 주로 권장하는 방법은 로컬 디스크와 원격의 NFS 마운트 두 곳에 동시에 백업하는 것이다.
2. 보조 네임노드를 운영하는 것이다. 보조 네임노드는 주 네임노드와는 조금 다르게 동작한다. 보조 네임노드의 주 역할은 에디트 로그가 너무 커지지 않도록 주기적으로 네임스페이스 이미지를 에디트 로그와 병합하여 새로운 네임스페이스 이미지를 만드는 것이다.병합 작업을 수행하기 위해 보조 네임노드는 충분한 CPU와 네임노드와 비슷한 용량의 메모리가 필요하므로 별도의 물리 머신에서 실행되는 것이 좋다. 또한 보조 네임노드는 주 네임노드에 장애가 발생할 것을 대비해서 네임스페이스 이미지의 복제본을 보관하는 역할도 맡는다. 하지만 주 네임노드의 네임스페이스 이미지는 약간의 시간차를 두고 보조 네임노드로 복제되기 때문에 주 네임노드에 장애가 발생하면 어느정도의 데이터 손실은 불가피 하다. 이럴때 일반적인 복구방식은 NFS에 저장된 주 네임노드의 메타데이터 파일을 보조 네임노드로 복사하여 새로 병합된 네임스페이스 이미지를 만들고 그것을 새로운 주 네임노드에 복사한 다음 실행하는 것이다. HDFS 고가용성에서는 대기 네임노드가 보조 네임노드의 역할을 대신한다.
3-3 블록 캐싱
데이터노드는 디스크에 저장된 블록을 읽는다. 하지만 빈번하게 접근하는 블록파일은 오프힙(자바 힙 외부에서 관리되는) 블록캐시
라는 데이터노드의 메모리에 명시적으로 캐싱할 수 있다. 기본적으로 블록은 하나의 데이터노드 메모리에만 캐싱되지만 파일 단위로 설정할 수도 있다. 잡스케줄러(맵리듀스,스파크 등)는 블록이 캐싱된 데이터노드에서 태스크가 실행되도록 할 수 있으며, 이러한 블록 캐시의 장점을 이용하면 읽기 성능을 높일 수 있다.조인을 할때 작은 룩업 테이블을 캐싱하는 것은 좋은 활용 사례다.
사용자나 애플리 케이션은 캐시풀에 캐시지시자를 추가하여 특정 파일을 캐싱하도록 명령할 수 있다. 캐시풀은 캐시권한이나 자원의 용도를 관리하는 관리그룹의 역할을 맡는다.
3-4 HDFS 페더레이션
네임노드는 파일시스템의 모든 파일과 각 블록에 대한 참조정보를 메모리에서 관리한다. 따라서 파일이 매우 많은 대형 클러스터에서 확장성에 가장 큰 걸림돌이 되는것은 바로 메모리다. 이러한 네임노드의 확장성 문제를 해결하기위해 2.x 릴리즈부터 하둡은 HDFS 페더레이션(연합체)을 제공하고 있다. HDFS 페더레이션을 활용하면 각각의 네임노드가 파일시스템의 네임스페이스 일부를 나누어 관리하는 방식으로 새로운 네임노드를 추가할 수 있다. 예를들어 어떤 네임노드는 /user 디렉터리 아래의 모든 파일을 관리하고 다른 네임노드는 /share 디렉터리 아래의 파일을 관리한다.
HDFS 페더레이션을 적용하면 각 네임노드는 네임스페이스의 메타데이터를 구성하는 네임스페이스 볼륨과 네임스페이스에 포함한 파일의 전체블록을 보관하는 블록 풀을 관리한다.네임스페이스 볼륨은 서로 독립되어 있으며, 따라서 네임노드는 서로 통신할 필요가 없고, 특정 네임노드에 장애가 발생해도 다른 네임노드가 관리하는 네임스페이스의 가용성에 영향을 주지 않는다. 하지만 블록 풀의 저장소는 분리되어 있지 않다. 모든 데이터노드는 클러스터의 각 네임노드마다 등록되어 있고, 여러 블록 풀로부터 블록을 저장한다.
HDFS 페더레이션 클러스터에 접근하기 위해 클라이언트는 파일 경로와 네임노드를 매핑한 클라이언트 측 마운트 테이블을 이용한다. 환경설정에서 ViewFileSystem과 viewfs:// URI를 사용하여 관리할수 있다.
3-5 HDFS 고가용성
데이터 손실을 방지하기 위해 네임노드 메타데이터를 다수의 파일시스템에 복제하는 방식과 보조 네임노드를 사용하여 체크포인트를 생성하는 방식을 조합해서 활용할 수 있다. 그러나 이러한 방법도 파일시스템의 고가용성을 궁극적으로 보장하지는 않는다. 네임노드는 여전히 단일 고장점(SPOF)이다. 네임노드에 장애가 발생하면 맵리듀스 잡을 포함하여 모든 클라이언트가 파일을 읽거나 쓰거나 조회할 수 없게 된다.네임노드는 메타데이터와 파일 블록의 매핑 정보를 보관하는 유일한 저장소이기 때문이다. 이런 상황이 발생하면 새로운 네임노드가 투입될 때까지 하둡 시스템 전체는 먹통이 된다.
네임노드의 장애를 복구하기위해 관리자는 파일시스템 메타데이터 복제본을 가진 새로운 네임노드를 구동하고 모든데이터노드와 클라이언트에 새로운 네임노드를 사용하도록 알려주면 된다.하지만 1)새로운 네임노드는 2)네임스페이스 이미지를 메모리에 로드하고 3) 에디트 로그를 갱신하고 4) 전체 데이터노드에서 충분한 블록리포트를 받아 안전 모드를 벗어날 때까지 그 어떤 요청도 처리하지 못한다.많은 파일과 블록이 있는 대형 클러스터에서 네임노드를 재구동할때 30분 이상 걸리는 경우도 있다.
일상적인 유지관리에서 재가동 시간이 오래 걸리는 것은 당연히 문제가 된다. 사실 네임노드의 갑작스런 장애는 거의 발생하지 않으며, 실무에서는 계획된 정지시간(downtime)이 더 중요할수도 있다.
이문제를 해결하기 위해 하둡 2.x 릴리즈부터 HDFS 고가용성 (HA)을 지원한다. 고가용성은 활성대기 상태로 설정된 한 쌍의 네임노드로 구현된다. 활성 네임노드에 장애가 발생하면 대기 네임노드가 그 역할을 이어받아 큰 중단없이 클라이언트의 요청을 처리한다. 이러한 방식을 지원하기 위해 HDFS의 구조를 일부 변경 했다.
- 네임노드는 에디트로그를 공유하기위해 고가용성 공유 스토리지를 반드시 사용해야한다. 대기 네임노드가 활성화 되면 먼저 기존 활성 네임노드의 상태를 동기화하기 위해 공유 에디트 로그를 읽고, 이어서 활성 네임노드에 새로 추가된 항목도 마저 읽는다.
- 데이터노드는 블록 리포트를 두개의 네임노드에 보내야한다. 블록 매핑 정보는 디스크가 아닌 네임노드의 메모리에 보관되기 때문이다.
- 클라이언트는 네임노드 장애를 사용자에게 투명한 방식으로 처리할 수 있도록 구성해야 한다.
- 대기 네임노드는 보조 네임노드의 역할을 포함하고 있으며, 활성 네임노드 네임스페이스의 체크포인트 작업을 주기적으로 수행한다.
고가용성 공유 스토리지를 위해 NFS 필러나 QJM 중 하나를 선택할수 있다. QJM은 HDFS 전용 구현체로, 고가용성 에디트 로그를 지원하기 위한 목적으로 설계되었고 HDFS의 권장 옵션이다. QJM은 저널 노드 그룹에서 동작하며 각 에디트 로그는 전체 저널 노드에 동시에 쓰여진다. 일반적으로 저널 노드는 세 개며 그중 하나가 손상되어도 문제가 없는 시스템이다. 이러한 방식은 주키퍼의 작동 방식과 매우 유사하지만 QJM은 주키퍼를 사용하지 않고도 이런 기능을 구현했다는 점이 중요하다.(물론 HDFS 고가용성은 활성 네임노드를 선출하기 위해 주키퍼를 이용한다. 다음 절에서 설명한다.)
활성 네임노드에 장애가 발생하면 대기 네임노드는 매우 빠르게(수십 초 이내) 기존 네임노드를 대체할 수 있다. 활성과 대기 네임노드는 모두 최신 에디트 로그와 실시간으로 갱신되는 블록 매핑 정보를 메모리에 유지하고 있기 때문이다. 하지만 실제로 장애 복구 시간을 보면 1분 정도 걸리는데, 시스템이 활성 네임노드에 장애가 발생했다고 판단하는 것은 매우 신중해야 하기 때문이다.
자주 있는 일은 아니지만 활성 네임노드에 장애가 발생할 때 대기 네임노드가 중단된 상태일 수도 있다. 이러한 상황에서도 관리자는 단순히 대기 네임노드를 다시 구동하면 그만이다. 이러한 과정은 하둡의 표준 운영 절차이기 때문에 고가용성을 사용하지 않는 시스템에 비해 나쁠것도 없고 운영상의 관점에서도 진일보한 기능이다.
장애복구와 펜싱
대기 네임노드를 활성화시키는 전환 작업은 장애복구 컨트롤러 라는 새로운 객체로 관리된다. 다양한 방법으로 장애복구 컨트롤러를 구현할 수 있지만 기본 구현체는 단 하나의 네임노드만 활성 상태에 있는 것을 보장하기 위해 주키퍼를 이용한다. 각 네임노드는 경량의 장애 복구 컨트롤러 프로세스로 네임노드의 장애를 감시하고(하트비트 방식 사용) 네임노드에 장애가 발생하면 장애복구를 지시한다.
장애복구는 정기적인 유지관리를 위해 관리자가 수동으로 초기화 할 수 있다. 이를 우아한 장애 복구 라고도 하는데, 장애복구 컨트롤러는 두 개의 네임노드가 서로 역할을 바꾸게 하는 방법으로 전환 순서를 제어할 수 있다.
그러나 우아하지 못한 장애복구에서는 장애가 발생한 네임노드가 현재 실행되지 않고 있다는 것을 확신하기 어렵다. 예를 들어 네트워크가 느려지거나 단절되어 장애복구를 위한 전환 작업이 시작된 상황에서도 기존의 활성 네임노드는 여전히 실행되고 있고 자신이 활성 네임노드라고 생각할 것이다. 고가용성을 구현하기 위해서는 기존의 활성 네임노드가 시스템을 손상시키거나 망가뜨리지 않도록 엄청난 노력을 기울여야 한다. 이를위해 펜싱(fencing)이라는 메서드를 제공한다.
QJM은 한번에 하나의 네임노드만 에디트 로그에 쓸수 있도록 보장한다. 하지만 기존의 활성 네임노드가 클라이언트의 읽기 요청에 대해 잘못된 정보를 줄 가능성이 있으므로 SSH 펜싱 명령어로 네임노드의 프로세스를 확실히 죽이도록 설정하는것이 가장 좋은 방법이다.공유 에디트 로그를 저장하기 위해 NFS 필러를 이용할 때는 한번의 하나의 네임노드만 허용하는것이 불가능하므로 좀더 강력한 펜싱 메서드를 사용해야 한다."이것이 QJM을 권장하는 이유다"
네임노드가 공유스토리 디렉터리에 접근하는 것을 불허하는 방법부터 원격 관리 명령어로 네트워크 포트를 막는 방법까지 다양한 펜싱 메커니즘이 있다. 최후의 수단으로 기존의 활성 네임노드를 STONITH(노드를 확실히 죽이기, 헤드샷)라고 알려진 방법으로 막을수 있는데, 이것은 호스트 머신의 전원을 강제로 내려버리는 특별한 전원 분산 유닛(PDU)을 이용하는 기술이다.
클라이언트 장애복구는 클라이언트 라이브러리로 명확하게 처리된다. 가장 단순한 방법은 장애복구 제어를 위한 클라이언트 측 설정을 이용하는 것이다. HDFS URI는 한 쌍의 네임노드 주소를 매핑한 논리적인 호스트명을 사용하고, 클라이언트 라이브러리는 성공할 때까지 각 네임노드의 주소로 연결을 시도한다.
3-6 명령행 인터페이스
HDFS를 명령행으로 조작하는 방법을 살펴보자.HDFS를 위한 인터페이스는 매우 다양한데, 명령행은 가장 단순하고 개발자에게 익숙한 방식이다. 일단 한 대의 머신에서 HDFS를 실행할것이다. 의사분산 모드로 설정할때 중요한 속성이 두개 있다.
첫번째 속성은 하둡의 기본 파일시스템을 설정하는 fs.defaultFS 속성으로, 기본값은 hdfs://localhost/다. 파일시스템은 URI로 정의하는데, 여기서는 HDFS를 기본으로 사용하므로 HDFS URI를 사용했다. HDFS 데몬은 HDFS 네임노드의 호스트와 포트를 결정하기 위해 이 속성을 사용한다. 우리는 네임노드를 localhost에서 기본 HDFS 포트인 8020으로 실행할 것이다. 그리고 HDFS 클라이언트는 접속할 네임노드가 실행되는 주소를 얻기 위해 이 속성을 사용할 것이다.
두번째 속성은 기본 복제 계수를 설정하는 dfs.replication 속성으로, 기본값은 3이지만 의사 분산 모드에서는 파일시스템 블록을 복제할 수 없으므로 1로 설정한다. 단일 데이터 노드로 실행할 때 HDFS는 세개의 데이터노드에 블록을 복제할 수 없고 따라서 복제 수준 이하로 떨어졌다는 경고를 계속 발생시키므로 이 문제를 해결하기 위해 복제 계수를 1로 설정했다.
3-6-1 기본적인 파일시스템 연산
파일 시스템을 사용할 준비가 되면 파일읽기, 디렉터리 생성, 파일이동 데이터 삭제, 디렉터리 목록 출력과 같은 일반적인 파일시스템 연산을 모두 수행할 수 있다. hadoop fs -help 명령을 실행하면 자세한 도움말을 얻을 수 있다.
% hadoop fs -copyFromLocal input/docs/quangle.txt \
hdfs :// localhost/user/tom/quangle.txt
이 명령어는 하둡 파일 시스템의 쉘 명령어인 fs를 호출한다. fs 명령어는 -copyFromLocal과 같은 몇 개의 하위 명령어를 지원한다. 로컬 파일 quangle.txt는 로컬호스트에서 실행되는 HDFS 인스턴스의 /user/tom/quangle.txt로 복사된다. URI의 스킴과 호스트를 생략하면 core-site.xml에 설정된 기본값인 hdfs://localhost를 가져온다.
% hadoop fs -copyFromLocal input/docs/quangle.txt /user/tom/quangle.txt
절대 경로 대신 상대 경로를 사용하여 HDFS의 홈 디렉터리로 파일을 복사할 수 있으며, 여기서 HDFS의 홈 디렉터리는 /user/tom 이다.
% hadoop fs -copyFromLocal input/docs/quangle.txt quangle.txt
HDFS에 복사했던 파일을 다시 로컬 파일시스템에 가져오고, 두 파일이 같은지 확인해보자.
% hadoop fs -copyToLocal quangle.txt quangle.copy.txt
% md5 input/docs/quangle.txt quangle.copy.txt
MD5 (input/docs/quangle. txt) = e15487159alnfla134124
MD5 (quangle.copy.txt) = e1834579817ngfa9fn91nr9
MD5 다이제스트 (암호문)는 같고 그 파일은 HDFS로의 여행과 귀환에서 살아남은 것처럼 보인다..
3-6-2 인터페이스
하둡은 자바로 작성되었기 때문에 자바 API를 통해 하둡 파일시스템과 연동할 수 있다. 예를들어 파일 시스템 쉘은 자바 FileSystem클래스로, 파일시스템 연산을 제공하는 자바 애플리케이션이다. 이 절에서는 다른 파일시스템 인터페이스도 간단히 소개할 것이다. HDFS에 접근하는 인터페이스가 주로 이용되지만, FTP나 S3와 같은 다른 파일시스템에 접근하기 위해서는 FTP 클라이언트나 S3 도구와 같은 기존 도구가 필요하다. 하둡 파일시스템은 대부분의 파일시스템을 지원하고 잘 작동한다.
3-6-3 HTTP
파일시스템 인터페이스를 Java API로만 제공하면 자바로 작성되지 않은 애플리케이션으로 HDFS에 접근하는 것은 어렵게 된다. WebHDFS 프로토콜을 이용한 HTTP REST API를 사용하면 다른 언어도 HDFS에 쉽게 접근할 수 있다. 물론 HTTP 인터페이스는 네이티브 자바 클라이언트 보다는 느리므로 매우 큰 파일을 전송할 때는 주의한다.
HTTP로 HDFS에 접근하는 두가지 방식이 있다. 하나는 클라이언트의 HTTP 요청을 HDFS 데몬이 직접 처리하는 방식이다.
다른하나는 클라이언트 대신 DistributedFileSystem API 로 HDFS에 접근하는 프록시를 경유하는 방식이다. 두 방식 모두 WebHDFS 프로토콜을 이용한다.
HttpFs 프록시는 WebHDFS와 동일한 HTTP(그리고 HTTPS) 인터페이스를 제공하므로 클라이언트는 webhdfs(또는 webhdfs) URI로 둘 다 접근할 수 있다. HttpFS 프록시는 네임노드나 데이터노드 데몬과는 독립적이고, httpfs.sh 스크립트로 시작할 수 있다. 기본 대기 포트는 14000이다.
3-6-4 C
하둡은 자바 FileSystem 인터페이스를 모방한 libhdfs라는 C 라이브러리를 제공한다. libhdfs는 HDFS에 접근하기 위해 작성한 C 라이브러리인데, 이름과 달리 모든 하둡 파일시스템(로컬 파일시스템, S3등)에 접근할수 있다 libhdfs는 자바 파일시스템 클라이언트를 호출하기 위해 자바 네이티브 인터페이스(JNI)를 사용한다. 또한 앞에서 언급한 WebHDFS 인터페이스를 위해 libwebhdfs 라이브러리도 제공하고 있다.
C API는 자바 API와 매우 비슷하지만, 보통 자바 API 보다 한발 늦게 개발되므로 최신기능을 지원하지 않을수도 있다.
3-6-5 NFS
하둡의 NFSv3 게이트웨이를 이용하면 로컬 클라이언트 파일시스템에 HDFS를 마운트 할 수 있다.또한 파일시스템을 다루는 ls나 cat 같은 Unix 유틸리티를 이용할수 있으며, 파일 업로드 및 일반적인 프로그래밍 언어에서 파일시스템을 다루는 POSIX 라이브러리도 사용할 수 있다. HDFS는 파일의 끝에만 쓰기를 허용하므로 파일에 추가하는 작업은 가능하지만 파일의 임의 위치에 있는 데이터를 수정하는 것은 지원하지 않는다.
NFS 게이트웨이의 설정 및 실행 방법과 클라이언트 접근 방법은 하둡 문서를 참고하기 바란다.
3-6-6 FUSE
퓨즈는 Filesystem in Userspace(사용자 공간에서의 파일시스템)로, 사용자 공간과 유닉스 파일시스템을 통합한 파일시스템을 지원한다. 하둡의 Fuse-DFS contrib 모듈은 표준 로컬 파일시스템에 HDFS(또는 모든 하둡 파일시스템)를 마운트할 수 있는 기능을 제공한다. Fuse-DFS는 C로 작성된 libhdfs로 HDFS 인터페이스를 구현했다. 이글을 쓰고 있는 현재 하둡 NFS 게이트웨이는 HDFS 마운트를 지원하는 가장 안정적인 솔루션이며, Fuse-DFS보다 더 선호되고 있다.
3-7 자바 인터페이스
이 절에는 하둡 파일시스템의 연동 API인 하둡 FileSystem 클래스를 깊이 다루겠다. HDFS 구현체인 DistributedFileSystem을 주로 다루겠지만 파일시스템의 호환성을 유지하려면 FileSystem 추상 클래스로 코드를 작성하려는 노력이 필요하다. 이는 프로그램을 테스트하는데 유용하다 예를 들면 로컬 파일 시스템에 저장된 데이터로 빠른 테스트를 수행할 수 있다.
'책&스터디' 카테고리의 다른 글
| [하둡 완벽 가이드] - PART1 05장 하둡 I/O (0) | 2026.02.04 |
|---|---|
| [하둡 완벽 가이드] - PART1 04장 YARN (0) | 2026.02.03 |
| [하둡 완벽 가이드] - PART1 02장 맵리듀스 (0) | 2026.02.01 |
| [하둡 완벽 가이드] - PART1 01장 하둡과의 만남 (1) | 2026.01.31 |
| [견고한 데이터엔지니어링] - 4장 데이터 엔지니어링 수명 주기 전체에 걸친 기술 선택 (0) | 2026.01.30 |