Depp Dive 시리즈는 공부를 통해 알게된 지식을 기록, 공유하기 위한 포스팅입니다.

잘못된 정보에 대한 지적과 조언 감사합니다 :D

 

1. Spark란?

Apache Spark는 대규모의 클러스터 환경에서 데이터를 병렬적으로 빠르게 처리하기 위한 엔진이며, 오픈 소스입니다.

기존 데이터 처리는 Hadoop의 MapReduce(이하 MR) 연산과 같이 처리되었는데, MR은 맵 과정과 리듀스 과정의 중간 단계에서 나오는 결과값을 Disk에 저장, 참조하여 이에 Disk I/O가 발생해 성능에 큰 영향을 끼쳤습니다.

 

Spark는 인-메모리 형식으로 데이터를 처리하며, 클러스터링 된 여러 대의 서버의 메모리,core,CPU를 활용하여 작업에 필요한 리소스를 할당, 이 리소스 내에서 데이터를 처리하기에 빠른 연산이 가능합니다. 이에 실시간 처리가 더욱 중요해지는 요즘 많은 기업들이 Spark를 채택하고 있습니다.

 

2. 어떻게 사용하는가?

Spark는 사용자가 작성한 코드를 기반으로 동작됩니다. 작성된 코드는 트리거 지점에 Spark Context 혹은 Spark Session을 초기화 하도록 작성되는데, 이를 통해 Spark 클러스터가 연동된 클러스터 매니저가 해당 작업에 필요한 리소스를 요청받고, 할당하여 후의 사용자가 정의한 코드들을 수행합니다. 언어는 Scala, Python, Java를 지원합니다.

 

3. Spark의 구조

Spark는 크게, Driver, 클러스터 매니저로 구분되며, Spark Application은 하나의 Driver, 여러개의 Executor들로 이루어진 Spark가 실행되는 프로그램입니다. Spark의 동작 구조를 알아보며 더욱 깊게 이해해보겠습니다.

 

4. Spark Application의 주요 용어

spark-submit: 사용자가 작성한 코드를 Spark에 제출하기 위한 명령어입니다.

 

driver: main() 함수를 실행 시키고, Spark Context 혹은 Spark Session을 생성하며, 사용자의 입력에 응답하고, Application 정보를 유지, 관리하는 프로세스입니다.

 

Spark Context 혹은 Spark Session: 클러스터 매니저와 연결되며, 작업에 필요한 리소스를 요청하고, 전체적인 작업인 job을 executor에서 실행될 분할된 작업 단위인 task로 나누어 executor들에게 전달합니다.

 

클러스터 매니저: Spark Application에 필요한 리소스를 요청 받고, 워커 노드들 내부에 executor를 생성하는 역할을 수행합니다. yarn, mesos, kubernetes를 지원하며, spark 자체적으로 매니징하는 spark standalone 모드를 지원합니다. yarn일 경우 워커노드는 노드매니저입니다.

 

executor: 실제 task 단위의 작업을 처리하는 프로세스이며, 결과를 driver에게 전달합니다. executor는 워커 노드 내부에 생성됩니다.

 

5. Spark Application의 동작 순서

1. spark-submit을 통해 사용자는 작업을 제출합니다.

2. driver가 생성되며, main()함수를 실행시키고 Spark Context 혹은 Spark Session을 생성합니다.

3. driver 프로그램이 작업에 필요한 executor들을 클러스터 매니저에게 요청합니다.

4. Driver 내의 Spark Context 혹은 Spark Session이 job을 task단위로 쪼개어 executor들에게 할당합니다.

5. executor가 실제 task를 수행하며, 결과를 driver에게 전달합니다.

 

6. 클러스터 매니저 채택

spark-submit 또는 spark-shell, pyspark 명령어 실행 시, 클러스터 매니저를 지정하는 --master 옵션 값을 확인 할 수 있습니다.

 

클러스터 매니저를 사용하지 않는, 즉, 클러스터를 사용하지 않고 단일 서버에서만 작업을 실행하기 위한 local모드,

클러스터 내 여러 노드들에서 작업을 실행하고, 매니저를 채택하는 클러스터 모드(yarn, kubernetes, standalone 등)가 있습니다.

 

1. 로컬 모드

단일 노드에서 작업이 수행되며, 클러스터를 사용하지 않습니다. 주로 간단한 테스트가 필요할 때 사용됩니다.

ex) spark-submit --master local -> (=local[1], core와 executor가 각각 1개씩만 사용)

      spark-submit --master local[*] -> (1개의 executor와 단일 노드가 가지고 있는 모든 core를 사용)

      spark-submit --master local[N] -> (1개의 executor와 N개의 core를 사용)

 

2. 클러스터 모드

로컬모드와 달리 클러스터 노드들을 활용하며, 클러스터 매니저가 존재합니다.

yarn, kubernetes, standalone모드 등이 있으며, 주로 사용했던 yarn, standalone 모드를 알아보겠습니다.

 

standalone 모드:

spark에서 자체적으로 제공하는 클러스터 매니저를 사용합니다.

(* 다른 클러스터 프레임워크들은 standalone이라고 한다면 한 대의 서버가 실행된다의 개념이 많은데, spark에서 standalone모드는 클러스터 매니저로 yarn, kubernetes와 같이 외부 매니저가 아닌 자체 내장된 매니저를 채택한 상황을 의미합니다.)

이때, spark master와 worker 프로세스가 실행되어야하며, master 노드가 worker노드들의 리소스를 관리, 작업에 필요한 리소스를 할당합니다. 리소스 현황, 작업 현황 등을 spark master UI에서 확인가능합니다.

standalone모드에서는 각 노드에 하나의 executor만 실행될 수 있습니다.

ex) spark-submit --master spark://[master IP]:[master PORT]

 

yarn 모드:

클러스터 매니저로 yarn을 채택한 상황입니다. 

이 때, exectuor들은 yarn의 node manager 내부에 생성됩니다.

yarn의 resource manager가 클러스터의 리소스를 관리, spark 작업에 필요한 리소스를 할당 및 스케쥴링합니다.

ex) spark-submit --master yarn

 

7. 배포 모드 채택

클러스터의 여러 노드들을 활용하여 작업을 처리하는 클러스터 모드 환경에서 적용되는 방식이며, 단일 노드에서 작업이 실행되는 local모드에서는 적용되지 않는 방식입니다. 가장 중요한 차이점은 driver의 생성 위치입니다.

 

1. client 모드

client 모드는 driver가 spark 작업이 제출된 서버에서 생성됩니다. 즉, 클러스터 외부에서 drvier가 실행됩니다.

이에, spark 작업을 제출한 서버에서 콘솔을 닫거나, spark 작업을 취소시키면 모든 작업이 중단됩니다.

client가 spark 작업에 개입할 수 있다는 것 입니다. deploy-mode를 client, 혹은 옵션 값을 주지 않으면, default로 적용되는 모드입니다. 

ex) spark-submit --master yarn deploy-mode client or 빈 값

 

2. cluster 모드

cluster모드는 driver가 spark 작업이 제출된 서버가 아닌, 클러스터 내부 노드들 중 어딘가에 생성됩니다.

또한, spark 작업이 제출되면, 작업에 대한 리소스, 권한 등이 클러스터 매니저가 위임합니다. 이에 작업을 제출한 client는 제출된 작업에 대해 더이상 개입할 수 없으며, client 모드에서 콘솔을 닫거나 작업을 취소시키면 spark 작업이 중단되었지만, cluster 모드에서는 모든 작업이 클러스터 매니저에 의해 조정되기에 client가 개입할 수 없습니다.

 

3. 두 모드 활용 사례

client모드는 대게 개발 환경에서 많이 사용됩니다. spark 작업에 대한 결과 값을 빠르게 출력 받고, 테스트할때 대화형(spark-shell, pyspark 등)으로 자주 사용됩니다. cluster 모드는 운영 환경에서 자주 사용되며, 배치, 실시간 처리가 계속 이루어지는 환경에서 필요한 리소스들을 클러스터 매니저가 조정하는 그림일 수 있겠습니다.

 

또한, 가장 중요한 차이는 driver의 실행 위치라고 언급드렸습니다. 만약 spark 작업이 제출되고, 코드 내에 PostgreSQL에 데이터를 Insert하는 코드가 존재한다고 가정하겠습니다. 사용자는 코드 상에 PostgreSQL에 접근하기 위한 postgresql.jar와 같은 JDBC 파일의 위치를 작성하였을 것 입니다. client모드에서는 작업이 제출된 서버 = spark driver가 생성될 노드이므로, 작업이 제출될 서버에만 해당 JDBC파일, 즉, 종속성을 가진 파일들이 존재하면 될 것입니다.

 

하지만 위와 같은 환경에서, cluster 모드로 작업을 제출하였다면, driver는 클러스터의 노드들 중 어딘가에 생성되고, 이것은 client가 조정할 수 없는 영역입니다. 어디서 driver가 생성될지는 클러스터 매니저가 결정하기에 알 수 없다는 것 입니다. driver가 실행된 노드에 JDBC 종속성 파일을 위치하여야 코드가 동작하지만, 생성 위치를 알 수 없습니다.

 

이는, spark 작업이 실행되는 클러스터의 모든 노드들의 spark 종속성 파일을 담아놓은 경로(ex. /opt/spark/jars)에 해당 JDBC 파일을 올려두는 방법이 있을 수 있습니다. 물론 이러한 종속성 파일이 많아진다면, 그 때마다 모든 노드들에게 파일을 업로드 해야 할 것 입니다. 또 다른 방법으로는 pyspark 코드를 예로 필요한 종속성 파일을 zip파일로 묶어  spark-submit 명령어 실행 시 해당 zip 파일을 인자로 전달 가능하고, driver가 생성될 노드, task가 실제 수행될 노드들의 내부에 해당 종속성 파일이 존재하지 않아도, 인자로 받은 zip파일 내부의 파일들을 참조하여 정상적으로 수행이 가능합니다.

 

두 방법 다 가능하며, 개발자의 성향에 따라 채택 가능합니다.

 

 

8. Spark Context, Session 차이

spark 1버전에서는 Context, 2버전 부터 Sesssion이 도입 되었습니다.

두 가지 모두, spark 작업이 실행되기 위한 엔트리 포인트라고 볼 수 있으며, 객체의 초기화, 클러스터 매니저와의 통신으로

작업에 필요한 리소스를 요청, job을 task 단위로 나누어 executor에 할당하는 역할입니다.

 

차이점은 Context는 RDD기반, Session은 DataFrame 기반이라는 것 입니다.

Context는 Spark 작업을 생성, 실행하며, Hive Context, SQL Context와 통합하여 구조, 반구조화된 데이터를 처리할 수 ㅇ있습니다. Session은 내부적으로는 결국 Context 객체를 만듭니다. 이에, Context의 모든 기능을 포함하고 있고, Dataframe, Dataset API 기능이 탑재되어있어, 고수준의 API를 활용할 수 있습니다. Parqeut, ORC 등 다양한 데이터 포맷에 접근 할 수 있는 통합 인터페이스를 제공하고, MLlib, Spark Streaming, GraphX와 같은 다양한 라이브러리 역시 활용 가능합니다.

 

9. RDD와 DataFrame, Dataset의 차이

RDD는 빠른 병렬 연산과 맵리듀스 작업을 위한 자료구조입니다. 불변성을 가지고, lineage를 통한 fault tolerent를 보장합니다. map, join과 같이 rdd에서 새로운 rdd를 만드는 transformation 함수와 rdd가 아닌 타입의 데이터 결과를 반환하는 count, collect와 같은 action 함수로 이루어집니다. rdd 사용 시, 자바 직렬화를 사용하기에 성능상의 이슈가 있을 수 있고, 최적화를 직접 해주어야 합니다.

 

DataFrame 역시 불변성을 가지고, 스키마를 가집니다. 이에 sql과 같이 친숙한 쿼리가 가능하며, 자동으로 옵티마이징 기능이 포함되어있어 성능 상 우수 합니다. 

 

Dataset은 DataFrame과 같이 스키마를 가지고, 불변성을 가지며, type-safey를 통해 spark.sql의 문법 에러를 컴파일 단계에서 알 수 있으며, 2.0버전부터 DataFrame과 통합되었습니다.

 

10. spark partition

partition은 RDD나 Dataset을 구성하고 있는 최소 단위의 객체입니다. 각각의 파티션은 클러스터 내 각기 다른 노드들에서 분산 처리 되며, Spark의 최소 연산단위는 Task이고, 하나의 Task는 하나의 Core가 수행합니다. 이는 1Core = 1 Task = 1 Partition 임을 뜻합니다. 이에 partition의 수가 많다면 Core의 수가 많아야하고, partition의 크기가 크다면 메모리의 크기가 커야함을 의미합니다.

 

partition의 종류는 3가지로 분류됩니다.

1. Input Partition: 처음 데이터를 읽을 때 파티션 수를 지정하는 방식입니다.

ex) spark.conf.set("spark.sql.files.maxPartitionBytes", 값)

만약, HDFS의 데이터를 읽고 처리하는 Spark 작업 일 시, 해당 설정 값이 128MB이고, HDFS상 마지막 경로의 파일의 크기가 128MB보다 크다면, Spark에서는 128MB 만큼 나누어 파일을 읽습니다.

 

2. output partition: 파티션의 수를 재조정하고 저장할 때의 방식입니다. 해당 파티션 수가 마지막에 저장되는 파일의 수를 지정하게 됩니다.

ex) coalesce()는 파티션을 줄일 때 사용되는 함수. 강제 옵션을 통해 늘릴 수도 있지만, 셔플이 발생하게 됩니다.

      repartition은 파티션을 늘릴 때 사용되며, 셔플이 일어나게 됩니다.

셔플(Shuffle)이란, filter, groupBy, join과 같은 연산 시, spark의 특성 상, 여러 파티션이 여러 노드들에 저장되어있는 환경에서, 위와 같은 연산 시, 동일한 key를 가진 데이터가 동일한 파티션에 있어야합니다. 이를 위해 파티션의 위치를 재조정하는 것을 셔플이라 하며, spark 성능의 큰 영향을 차지합니다. 

 

3. shuffle partition: 셔플 과정에서 사용될 파티션의 수를 지정하는 방식

ex) spakr.conf.set("spark.sql.shuffle.partitions", 값)

groupBy, join과 같은 연산 시, 데이터가 셔플링될 파티션 수를 지정합니다.

 

다음은 파티셔닝의 종류입니다.

파티션은 가장 최소단위의 객첵, 단위이며, 파티셔닝이란 이러한 파티션을 나누기 위한 작업 메커니즘입니다.

1. 범위별 파티셔닝, Range Partitioning

특정 범위 내 키들을 범주화하고, 범위에 기반하여 데이터를 파티셔닝합니다.

 

2. Hash Partitioing

기본적으로 spark가 사용하는 파티셔닝 기법이며, 각 키에 해시코드를 할당, 이를 기반으로 파티션이 생성되어 모든 파티션들의 균등한 분산을 보장합니다. 

 

11. Spark Streaming과 Structured Streaming의 차이

두 스트리밍 모두 실시간 처리를 위한 방식입니다.

 

먼저 Spark Streaming은 RDD 기반입니다. 실시간으로 들어오는 데이터를 Micro Batch를 통해 처리하며, DStream으로 변환하는 과정을 거칩니다.

 

Spark Structured Streaming은 들어오는 데이터를 배치처리가 아닌, Data Stream에 계속 추가하며 저지연 시간처리가 가능합니다. 또한, Dataset, DataFrame 기반이기에 고수준의 API를 사용할 수 있고, 이벤트 시간 처리를 통해 지연된 데이터의 정확한 처리가 가능합니다.

 

12. foreach와 foreachbatch 차이

foreach: 사용자 정의 로직을 row 단위에 적용 가능합니다.

foreachbatch: 사용자 정의 로직을 micro batch 단위에 적용 가능합니다.

 

감사합니다 :D

반응형

Deep Dive 포스팅은 공부를 통해 알게된 지식을 기록, 공유하기 위한 글입니다.

잘못된 정보에 대한 지적과 조언 감사합니다.

 

Hadoop 구축, 운영을 다수 진행하면서 각 노드들에 대한 깊은 지식과 동작 원리, 버전별 차이를 알고 싶어 탐구하게되었고, 버전별로 추가된 노드도 있고 내부 동작이 변경되는 경우도 있었습니다. 이에 개인적으로 새로운 버전의 흐름에 따라 정리하는 것이 이해에 도움이 된다 생각하여 달라진 버전의 흐름에 따라 다소 길게 정리하였습니다. 

 

Hadoop이란?

Hadoop은 여러 대의 서버로 이루어진 클러스터 환경에서 대용량의 데이터를 분산 저장 및 처리하는 Java기반의 오픈 소스 프레임워크입니다.

 

하둡의 특징!

1. Hadoop은 들어오는 데이터의 형식(csv, json, img)에 구애 받지 않고 파일 그대로 저장합니다. (유사 Object Storage)

 

2. Hadoop은 들어오는 파일(데이터)을 Block 단위로 나누어 저장합니다. 이 때, 나누어지는 Block Size는 버전 별로 상이하지만, 128MB를 권장하며, 꽤 큰 Size이지만, 탐색하려는 Block의 Size가 작게되면, 그만큼 더 많은 여로 노드에 분산된 여러 개의 Block을 찾아야하기 때문에, 네트워크 트래픽이 증가하게됩니다. 

 

들어오는 파일의 크기가 지정된 Block Size보다 작거나, Block으로 나눈 후 마지막 Block의 Size가 지정된 Block Size보다 작을 시, 지정된 Size만큼 용량이 할당 되는 것이 아닌, 실제 파일 혹은 남은 Block Szie 용량만큼만 차지합니다.

ex) 192MB의 파일, 지정 Block Size 128MB일 때, 128MB 1, 64MB 1, 2개의 Block으로 나누어집니다.

 

3. Hadoop은 Block을 3복제하여 저장합니다. 이는 Block의 손실을 대비하기 위함이고, 이에 저장 공간은 3배가 필요합니다. 복제 개수는 사용자가 정의할 수 있고, Default 값은 3입니다.

 

4. Hadoop은 HDFS라는 파일 시스템을 활용하는데 이는 읽기 중심의 컨셉을 가지고 있습니다. 이에, 파일의 수정은 지원하지 않습니다. (Append, Delete)

 

5. Hadoop은 데이터의 지역성을 활용하여, 데이터를 처리 시, 해당 데이터를 이동하지 않고, 해당 데이터가 저장된 노드에서 처리 후, 취합하기에 비용이 절감됩니다.

 

하둡의 등장 (v1)

Hadoop v1에서는 분산 저장, 병렬 처리 프레임워크가 정의 되었습니다.

주요 핵심 코어로 HDFS(분산 저장), MapReduce(병렬 처리)가 있습니다.

 

HDFS(Hadoop Distributed File System):

Hadoop은 HDFS라는 파일시스템을 통해 데이터를 분산 저장합니다. HDFS는 들어오는 파일을 Block 단위로 나누어 클러스터화 된 여러 노드에 분산하여 저장합니다.

 

또한, Block의 손실을 대비하여 나누어진 Block을 복제하여 저장합니다. 기본 복제 수는 3개이며, 이에 저장 공간이 3배 필요하게됩니다.

 

HDFS의 컨셉은 읽기이며, 파일의 수정은 불가합니다.

 

MapReduce:

맵 리듀스는 분산, 병렬 환경의 대용량의 데이터를 처리하기 위해 설계된 프로그래밍 모델입니다. 

데이터가 들어오면, 특정 크기의 Block로 나눈 후, 각각의 Block에 대해 Map Task, Reduce Task를 수행합니다.

 

Map과 Reduce는 입/출력으로 Key/Value 구조를 사용합니다. Map은 데이터를 Key, Value 형태로 묶고, 해당 형태의 데이터를 List 형식으로 반환합니다. 후 Reduce는 Map에서 처리한 데이터 중 중복된 Key 값을 가지는 데이터를 제거 및 합쳐 원하는 데이터의 형태로 추출하는 작업을 수행합니다.

 

하둡의 구조와 동작 (HDFS 관점)

Hadoop v1은 크게 NameNode와 Secondary NameNode, DataNode로 구성됩니다.

 

Namenode는 Metadata와 DataNode를 관리하는 역할을 수행합니다. Metadata에는 HDFS 내 존재하는 파일의 이름, 크기,

생성 시간, 권한 유저, 그룹 소유자, Block의 정보 등이 담겨있는 데이터입니다. Metadata 관리는 fsimage, edits log, block report로 이루어집니다.

 

fsimage: 파일에 매핑된 Block의 정보 등을 포함, 전체 namespace 정보

editLog: HDFS 파일 생성, 삭제 등의 Transaction 로그

Block Reports: DataNode로 부터 주기적으로 보고 받으며, DataNode 내 저장된 Block 목록과 Block이 실제 저장된 로컬 디스크의 위치

 

fsimage와 editLog 파일은 v1기준, 하둡 설치 시 정의된 로컬 디스크 내 namenode 디렉토리 하위 current 디렉토리에 생성됩니다. 하둡 운영 중 발생하는 수정 사항(HDFS 파일 생성 혹은 삭제)은 곧바로 fsimage에 반영되지 않고, 또한 새로운 fsimage를 만들지 않습니다. 이러한 변경 사항(Transaction Log)은 editLog 파일에 기록되는 데 주기적으로 이 editLog 파일이 fsimage에 반영되어 새로운 fsimage를 만들고 이를 check point라고 합니다.(사용자가 주기 설정 가능)

NameNode가 기동되거나 위 check point 상황이 발생하면, fsimage와 editLog가 병합된 새로운 fsimage와 DataNode로 부터 주기적으로 보고 받는 Block Reports를 메모리 상에서 관리하여 최신 상태의 HDFS 정보를 유지하게 됩니다.

 

NameNode 구동 시, 지속해서 editLog 파일이 생성되고, 트랜잭션이 빈번하게 일어나게 되면, editLog 파일이 빠르고 많이 생성되어, NameNode의 디스크 용량 부족 문제와 재구동 되는 시간이 느려지는 현상이 발생될 수 있습니다.

이러한 NameNode의 Metadata 관리에 대한 부하를 줄이기 위해 Seconary NameNode가 존재합니다.

 

Secondary NameNode는 위 NameNode의 메타 데이터 관리 부하를 덜어주기 위해 editLog와 fsimage를 NameNode로 부터 복사, 주기적으로 병합하는 역할을 분담합니다. 병합된 새로운 fsimage를 NameNode에게 전달하고 NameNode는 받은 새로운 fsimage를 통해 Metadata를 관리합니다. 또한, 병합이 완료된 editLog 파일은 정리되어 디스크 용량 확보에도 도움이 됩니다.

(* Secondary NameNode는 백업용이 아닌, NameNode의 일을 덜어주기 위한 보조용의 노드)

 

DataNode는 파일이 나누어진 Block을 실제로 저장하는 역할을 수행합니다. 또한 NameNode에게 주기적으로 HeartBeat와 Block Reports를 전송하여 자신의 상태, Block의 위치 정보 등을 전송합니다.

 

 

하둡의 구조와 동작 (MapReduce 관점)

v1 기준, MapReduce 프로그램은 Job이라는 하나의 작업 단위로 관리되었습니다.

client로 부터 MapReduce 작업이 요청되면, Job Tracker와 Task Tracker가 클러스터 내 할당됩니다.

 

JobTracker는 클러스터의 전반적인 리소스를 관리하고, Job을 처리하기 위해 실행될 Map과 Reduce의 개수를 계산 및 결정하고 알맞는 Task Tracker에게 Job을 할당합니다. 또한, Job의 실행 이력도 관리합니다. 보통 NameNode에서 실행하지만, 꼭 그러지 않아도 무관합니다.

 

TaskTracker는 Job 수행을 요청 받아 MapReduce Task를 실행합니다. DataNode에서 실행됩니다..

 

Job Tracker와 Task Tracker는 HeartBeat를 통해 네트워크 통신으로 각 상태, Job 실행 정보 등을 공유합니다. Task Tracker에 문제가 생기면 다른 대기상태의 Task Tracker를 Job Tracker가 찾아 Task를 할당합니다.

 

이에 Job Tracker는 리소스 관리, Job 이력 관리, Task Tracker와의 통신으로 수행할 작업이 많아져 병목현상이 발생했습니다.

 

하둡 v1 문제점

- NameNode가 고장이나면, 클러스터에 대한 요청을 받을 수 없고, 메타데이터 접근도 불가하여 HDFS 파일 내용을 확인 할 수 없습니다. 즉, NameNode의 단일장애지점(Single Point Of Failure, SPOF)이 문제가 되었습니다.

 

- MapReduce 작업 환경에서 Job Tracker가 클러스터 전체 리소스 관리, Job 이력 관리, 알맞은 Task Tracker를 찾아 Job 할당 등 여러 역할을 수행하기에 병목현상이 발생할 수 있습니다.

 

고가용성과 Yarn 아키텍처의 도입, 하둡 v2

v1에서의 Hadoop은 NameNode가 고장이 나면, 클러스터 요청, editLog 등의 메타데이터 접근 불가로 클러스터의 제 기능을 할 수 없습니다. 즉, NameNode는 단일장애지점(Single Point Of Failure, SPOF)이었습니다.

 

이를 해결하기 위해 고가용성(HA, High Availability) 아키텍처가 도입됩니다. 이에 추가된 노드들이 있습니다.

 

Journal Node:

v1에서의 Hadoop은 editLog를 NameNode 자신의 로컬디스크에 저장하였지만, v2부터는 NameNode가 Journal Node에게 editLog의 저장을 요청합니다. editLog는 Journal Node의 로컬 디스크에 저장되며, 공유되는 editLog의 저장소는 Journal Node가 아닌 NFS로도 구현 가능합니다. Journal Node는 다수의 노드, 홀수 개의 노드에서 동작합니다.(최소 3대)

Journal Node 역시 SPOF 대상이 될 수 있고, 이는 editLog의 손실로 이어질 수 있기 때문에, 다수의 노드에 복제하여 저장하기위함과, 또한 NameNode가 Journal Node의 오류의 영향을 받지 않기 위해 과반 수 이상의 Journal Node가 동작하여야 하기 때문에 홀 수개의 노드로 구성됩니다.(짝수면 정상/비정상의 비율이 동률일 가능성이 있기 때문)

 

editLog에 대한 쓰기 요청은 Active NameNode만이 권한을 가지고 있고, Standby NameNode는 주기적으로 JournalNode 내 editLog 파일을 읽습니다. 또한 JournalNode 중 하나의 노드가 손상되어도 정상적으로 동작하는 데, 이 기능은 Zookeeper가 아닌 자체적으로 개발된 기능입니다.

 

Active NameNode:

실질적인 NameNode 역할을 수행하는 활성 상태의 NameNode입니다. 위에서 언급드렸듯, editLog의 저장을 Journal Node에게 요청합니다.

 

Standby NameNode:

Active NameNode의 다운을 대비한 대기 상태의 NameNode이며, Active NameNode가 기동 중지되면, 해당 NameNode가 Active NameNode가 되어 본래 NameNode의 역할을 수행합니다. 또한, 대기 상태일 때, 주기적으로 Journal Node 내 editLog를 읽어 fsimage를 갱신 합니다. (v1의 Secondary NameNode를 고가용성 도입 후 사용하지 않는 까닭인 것 같습니다.)

 

또한, Standby NameNode 역시 DataNode로 부터 HeartBeat와 Block Reports를 받게 되고, 이에 Active NameNode와 동일한 메타 데이터를 유지, Active와 Standby가 바뀌는 fail over 상황에서 빠른 전환을 할 수 있게 됩니다.

 

Zookeeper:

분산 코디네이터 툴로써, Hadoop 이외의 프레임워크에서도 많이 사용됩니다. 하둡 고가용성에서의 Zookeeper는 두 개의 NameNode에 대한 세션을 ZKFC를 통해 유지 하며, 세션이 끊겼을 때, 해당 NameNode에 문제가 발생함을 인식합니다. 또한, 리더 선출 기능을 통해 어떤 Node가 Active로 선정될지 결정하는 역할을 합니다.

 

ZKFC( Zookeeper Failover Controller):

ZKFC는 NameNode와 Zookeeper 중간 역할을 담당하여, Active/Standby NameNode가 설치된 2개의 노드에 각각 실행됩니다. 자신이 설치된 노드에서 기동되고있는 NameNode의 상태를 HeartBeat를 통해 모니터링 하며, Active NameNode가 중지 될 시, ZKFC와 Zookeeper 마스터의 세션을 끊고, StandBy NameNode를 Active로 승격시키며, 기존의 Active NameNode를 제거합니다. ZKFC를 통해 Active NameNode는 항상 한 노드임을 보장 받습니다.

 

DataNode:

v1과 같이 Block이 실제 디스크에 저장되는 노드이며, 달라진 점은, v2에서부터 Active, Standby NameNode 두 노드 모두에게 Block Reports와 HeartBeat를 전송합니다.

 

위 노드들의 추가로 NameNode의 SPOF가 해결되어 클러스터 운영 및 메타데이터 관리의 가용성이 높아졌습니다.

 

두 번째로, Yarn 아키텍처의 도입입니다. v1의 또 다른 문제점은 MapReduce 환경에서 Job Tracker의 많은 역할로 인한 병목 현상이었는데요. v2부터 도입된 Job Tracker의 역할을 분담하기 위한 Yarn의 구성요소를 알아보겠습니다.

2버전부터 작업의 단위는 job에서 Application으로 명칭이 변경됩니다. 

 

Resource Manager:

클러스터 전체의 리소스 관리 및 할당을 담당하며, NameNode와 같이 Active/Standby 개념이 존재합니다.

크게 Scheduler와 Application Manager로 이루어집니다.

     Scheduler: 용량, Queue등 제약 조건에 따라 여러 실행 중인 Application들에 자원(Container)을 할당하는 작업을 수행      합니다.

     Application Manager: 클라이언트가 제출한 Application을 승인, Application Master를 실행하기 위한 Container를 확        인하고, Application Master의 상태를 작업이 종료될 때 까지 관리합니다. 

 

Node Manager:

클러스터의 각 노드에서 실행되며, 설치된 노드의 리소스를 모니터링하고, Resource Manger에게 보고합니다.

또한, 추후 해당 노드에 작업이 수행되는 Container가 할당되는데, 이 Container의 리소스 사용량 감시, Resource Manager에게 보고합니다.

 

Application Master:

Application은 제출된 단일 작업을 의미하며, 각 작업들은 고유한 Application Master를 가지게 됩니다. Application Master는 해당 Application의 실행을 조정, 오류를 관리하는 역할을 합니다. Node Manager와 함께 동작하여 Task를 실행, 모니터링하고 Resource Manager로부터 자원(Container)을 요청, 할당 받고, 주기적으로 Resource Manager에게 Heart Beat를 전송합니다.

 

Container:

개별 노드에 할당받은 자원입니다. RAM, CPU, Memory 등이 있습니다. Container 안에서 실질적인 Task가 수행됩니다.

 

동작 방식:

1. 클라이언트가 Resource Manager에게 Application을 요청합니다.

2. Resource Manager가 Application Master를 기동하기 위한 Container를 협상 후 기동합니다.

3. Application Master가 기동되면 Application 수행을 위한 자원(Container)를 Resource Manager에게 요청합니다.

4. Application Master가 할당 받은 Container를 Node Manager에 할당하고, 이 안에서 실제 Task를 수행합니다.

5. 모든 작업이 완료되면 Application Master가 Resource Manager에서부터 등록이 해제, 종료됩니다.

 

하둡 v2 정리:

v1의 문제점이었던 HDFS 관점의 Name Node의 단일 장애 지점을 Active/StandBy Name Node의 도입으로 해결되었습니다. Zookeeper, zkfc를 통해 Active/StandBy Name Node의 선정, fail over가 가능해졌으며, Journal Node를 통해 EditLog의 저장, 복제를 통해 메타 데이터 유실을 방지하며, 1버전의 Name Node가 수행했던 메타데이터 체크포인팅 작업을 StandBy Name Node가 수행하여 Name Node의 부하를 줄였습니다. 또한 1버전의 Name Node가 EditLog를 저장하였는데, 이는 디스크 용량의 문제, 해당 노드가 에러 시, 메타데이터의 유실이 발생할 가능성이 존재하였지만, 이 역시 Journal Node의 도입으로 Edit Log 저장을 Journal Node가 대신하고, 3대 이상의 홀수로 동작하여 복제 저장을 통해 메타데이터 유실을 방지 할 수 있습니다.

 

MapReduce관점의 Job Tracker의 너무 많은 역할로 인한 병목현상을 해결하기 위해, 작업의 요청에 대한 응답, 리소스 관리, 스케쥴링 기능을 Yarn 아키텍처를 도입하며 인수하였습니다. 또한, Yarn은 MapReduce 작업과 더불어, Spark, Hive 등의 여러 프레임워크의 작업들도 사용될 수 있습니다.

 

성능 개선을 위한 하둡 v3

HDFS는 Fault tolerance의 보장, Read 성능을 위해 기본적으로 들어오는 파일을 3복제하여 분산 저장합니다. 이는 1GB의 파일을 저장한다면, 클러스터 상에는 3GB가 저장되는 것이므로 저장 용량을 3배 차지한다는 점이 있습니다. 이러한 저장 용량의 효율성을 위해 Erasure Coding이 등장하였습니다.

 

Erasure Coding:

이레이져 코딩은 패리티 블록을 활용하여 1GB의 저장을 3GB가 아닌 1.5GB 만큼 디스크를 사용하게됩니다.

(3배 -> 1.4배)

이레이져 코딩은 디스크 RAID 구성에서 주로 사용하는 알고리즘을 활용합니다. hdfs 명령어를 통해 적용 가능합니다.

 

또한, v1부터 사용되었던 쉘 스크립트의 수정, 디버깅이 진행되었고, 스크립트가 이해하기 쉽도록 수정되었으며, java 8버전을 지원하게 되었습니다. Native Code 또한 최적화 되었으며, 고가용성을 위한 Active/Standby NameNode 중 StandBy NameNode가 한 노드만 추가할 수 있었지만, 여러 노드를 추가할 수 있도록 개선되었습니다.

 

또한 Object 저장소로 Ozone이 추가되었으며, 기존 사용되던 NameNode, DataNode 등 디폴트 포트들이 대거 변경 되었습니다.

 

잘못된 정보가 있을 시, 지적과 조언 감사합니다.

긴 글 읽어주셔서 감사합니다.

반응형

centos7, hadoop 3.3.5 버전 기준입니다.

하둡 설치 완료 테스트 중 네임노드 fail over 테스트 진행 중에 나타난 에러입니다.

 

namenode 2대가 ha구성되어있고, 최초 기동 시, 한 서버는 active, 다른 한 서버는 standby 상태로 올아왔고,

active인 서버를 임의적으로 다운 후 standby 네임노드가 active로 승격되는 것을 기다렸으나, 아래 에러와 함께 계속해서 standby 모드로 실행되고 있었습니다. 아래는 zkfc의 에러 로그입니다.

 

2024-07-10 09:48:58,817 WARN org.apache.hadoop.ha.SshFenceByTcpPort: PATH=$PATH:/sbin:/usr/sbin fuser -v -k -n tcp 8020 via ssh: bash: fuser: command not found
2024-07-10 09:48:58,818 INFO org.apache.hadoop.ha.SshFenceByTcpPort: rc: 127
2024-07-10 09:48:58,818 INFO org.apache.hadoop.ha.SshFenceByTcpPort.jsch: Disconnecting from [서버호스트] port [ssh포트]
2024-07-10 09:48:58,818 WARN org.apache.hadoop.ha.NodeFencer: Fencing method org.apache.hadoop.ha.SshFenceByTcpPort(flamingo:22002) was unsuccessful.
2024-07-10 09:48:58,818 ERROR org.apache.hadoop.ha.NodeFencer: Unable to fence service by any configured method.
2024-07-10 09:48:58,818 WARN org.apache.hadoop.ha.ActiveStandbyElector: Exception handling the winning of election
java.lang.RuntimeException: Unable to fence NameNode at [서버호스트]/[서버아이피]:8020
        at org.apache.hadoop.ha.ZKFailoverController.doFence(ZKFailoverController.java:560)
        at org.apache.hadoop.ha.ZKFailoverController.fenceOldActive(ZKFailoverController.java:532)
        at org.apache.hadoop.ha.ZKFailoverController.access$1100(ZKFailoverController.java:63)
        at org.apache.hadoop.ha.ZKFailoverController$ElectorCallbacks.fenceOldActive(ZKFailoverController.java:968)
        at org.apache.hadoop.ha.ActiveStandbyElector.fenceOldActive(ActiveStandbyElector.java:1022)
        at org.apache.hadoop.ha.ActiveStandbyElector.becomeActive(ActiveStandbyElector.java:921)
        at org.apache.hadoop.ha.ActiveStandbyElector.processResult(ActiveStandbyElector.java:499)
        at org.apache.zookeeper.ClientCnxn$EventThread.processEvent(ClientCnxn.java:684)
        at org.apache.zookeeper.ClientCnxn$EventThread.run(ClientCnxn.java:563)

 

하둡 설정 시, 노드들간의 통신을 ssh/fence로 설정하였고,

기존 active 네임노드가 다운된 것을 인지한 후, standby 노드를 승격하려는 시도는 보였습니다.

 

에러를 살펴보니, fuser라는 명령어를 사용하는데, 해당 명령어를 찾을 수 없다는 경고 로그가 나왔고,

구글링 결과, psmisc 라는 패키지 내 존재하는 명령어였습니다.

이에 yum을 통해 해당 패키지를 설치하니 standby 네임노드가 active 네임노드로 승격하였습니다.

 

yum install -y psmisc 

 

감사합니다.

 

 

 

반응형

'BigData > Hadoop' 카테고리의 다른 글

Deep Dive Hadoop  (1) 2024.10.22
yarn vcore 초과 할당 시 설정  (0) 2024.06.20
yarn) spark yarn job container 로그 설정  (0) 2024.02.13
yarn-site.xml 튜닝  (0) 2023.09.07
yarn capacitiy 스케줄러 설정  (0) 2023.07.26

centos7, trino 435, elasticsearch 7.5.1 버전 기준입니다.

지난 포스팅에 Trino와 ElasticSearch를 연동하였습니다.

elasticsearch의 document의 값에 배열 혹은 오브젝트 타입의 데이터를 넣을 수 있는데,

trino를 통해 해당 값을 테이블 형식으로 보기 위해선 document가 포함된 index에 별도의 매핑을 지정해주어야 합니다.

해당 현상을 테스트해보겠습니다.

서버 환경 구성입니다.

 

두 프로세스 모두 hadoop 계정 권한으로 실행되었습니다.

node1: Trino Coordinator, ElasticSearch

node2: Trino Worker, ElasticSearch

node3: Trino Worker, ElasticSearch

node4: Trino Worker, ElasticSearch

 

1. 엘라스틱서치 배열과 오브젝트가 포함된 도큐먼트 생성

action server: node1

user: hadoop

pwd: -

cmd:

# 콘솔에서 도큐먼트를 생성
curl -XPUT http://localhost:9200/trino_test/_doc/1 -H 'Content-Type: application/json' -d'
{
    "array_string_field": ["trino","the","lean","machine-ohs"],
    "long_field": 314159265359,
    "id_field": "564e6982-88ee-4498-aa98-df9e3f6b6109",
    "timestamp_field": "1987-09-17T06:22:48.000Z",
    "object_field": {
        "array_int_field": [86,75,309],
        "int_field": 2
    }
}'

# 도큐먼트를 확인
curl -X GET http://localhost:9200/trino_test/_search\?pretty

 

콘솔을 통해 엘라스틱서치에서 도큐먼트 조회 시,
array_string_field필드(컬럼)은 배열형식, object_field 필드는 객체 형식으로 나타납니다.

 

 

DBeaver를 통해 Trino 접근 후, 해당 도큐먼트 조회 시, 아래와 같은 에러와 함께 데이터가 나타나지 않습니다.

 

2. Trino 상에서 도큐먼트 내 배열, 오브젝트 타입을 인식하도록 인덱스 매핑 설정

action server: node1

user: hadoop

pwd: -

cmd:

# 서버 콘솔을 통해 엘라스틱서치 내 trino_test 인덱스에 대한 매핑 설정
curl --request PUT \
    --url localhost:9200/trino_test/_mapping \
    --header 'content-type: application/json' \
    --data '
{
    "_meta": {
        "trino":{
            "array_string_field":{
                "isArray":true
            },
            "object_field":{
                "array_int_field":{
                    "isArray":true
                }
            }
        }
    }
}'

 

DBeaver에 연결된 Trino를 새로고침 후 데이터가 테이블 형식으로 정상적으로 나오는지 확인합니다.

 

감사합니다.

반응형

'BigData > Trino' 카테고리의 다른 글

Trino) Trino + ElasticSearch 연동  (0) 2024.08.16
trino) Trino, Hive 카탈로그 연동, trino-cli  (0) 2024.03.12
Trino) Trino 435 설치  (0) 2024.03.12

centos7, trino 435, elasticsearch 7.5.1 버전 기준입니다.

trino와 elasticsearch 연동을 위해선 elasticsearch 버전이 6.6.0 버전 이상이어야하고,

trino를 통해 elasticsearch 조작은 select만 가능합니다.

 

서버 환경 구성입니다.

두 프로세스 모두 hadoop 계정 권한으로 실행되었습니다.

node1: Trino Coordinator, ElasticSearch

node2: Trino Worker, ElasticSearch

node3: Trino Worker, ElasticSearch

node4: Trino Worker, ElasticSearch

 

1. 엘라스틱서치 도큐먼트 생성

action server: node1

user: hadoop

pwd: -

cmd:

# 콘솔에서 curl 명령어로 도큐먼트를 생성합니다.
curl -XPUT http://localhost:9200/item/_doc/1 -H 'Content-Type: application/json' -d'
{
  "title": "테스트 제목",
  "message": "안녕하세요 Elasticsearch"
}'

# 생성 확인
curl -X GET http://localhost:9200/item/_search\?pretty

 

2. Trino Elasticsearch 카탈로그 추가

action server: node1~4

user: hadoop

pwd: -

cmd:

# 경로 이동
cd /opt/apps/trino-435

# 카탈로그 파일을 추가합니다.
vi etc/catalog/es.properties
connector.name=elasticsearch
elasticsearch.host=node1,node2,node3,node4
elasticsearch.port=9200
elasticsearch.default-schema-name=default

# Trino 재기동
./bin/launcher restart

 

3. DBeaver를 통해 데이터 확인

trino -> default -> item 클릭 후 도큐먼트의 내용이 테이블 형식으로 나타나는지 확인합니다.

 

 

감사합니다.

반응형

centos7, 엘라스틱서치 7.5.1 기준입니다.

기본 사용법에 대해 알아보겠습니다.

 

명령어 설명 비고
curl http://localhost:9200/_cat/health?pretty  클러스터 헬스체크  
curl http://localhost:9200/_cat/nodes  node 구성, 맨 오른쪽 노드명 옆에 * 이 있으면 현재 마스터노드  
curl -X PUT http://localhost:9200/test (인덱스명)  index 생성  
curl http://localhost:9200/_cat/indices?v  index 목록  
curl -X DELETE http://localhost:9200/test (인덱스명)  index 삭제  
curl -XPUT http://localhost:9200/item/_doc/1 -H 'Content-Type: application/json' -d'
{
  "title": "테스트 제목",
  "message": "안녕하세요 Elasticsearch"
}'
 document 생성  document만들 때, 없는 index랑 type을 지정하면 자동으로 둘 다 만듬
 curl -XPUT http://es주소:포트/인덱스명/타입명/번호 -H 'Content-Type: application/json' -d'입력할 JSON 데이터'
curl -X GET http://localhost:9200/item/_search\?pretty  document 조회  
curl -XPUT http://localhost:9200/item/_doc/2 -H 'Content-Type: application/json' -d'
{
  "title": "두 번째 행",
  "message": "안녕하세요 Elasticsearch"
}'
 document 추가  _doc뒤에 숫자(도큐먼트아이디)가 달라야 추가가됨. 같으면 기존꺼 덮어씌어짐
curl -X DELETE http://localhost:9200/item/_doc/3  document 삭제  curl -X DELETE http://es주소:포트/인덱스명/타입명/삭제할 번호
curl -X POST "localhost:9200/item/_update/1?pretty" -H 'Content-Type: application/json' -d '
{
  "doc": {
    "title": "수정된 제목"
  }
}'
 document 수정  기존 필드 수정

 

감사합니다.

반응형

centos7, 엘라스틱 서치 7.5.1 기준입니다.

 

jvm.options:

엘라스틱서치가 사용할 java 메모리와 메모리 관련 로그 파일의 경로를 설정합니다.

-Xms4g
-Xmx4g

-XX:HeapDumpPath=/data/elasticsearch/data
-XX:ErrorFile=/data/logs/elasticsearch/hs_err_pid%p.log
8:-Xloggc:/data/logs/elasticsearch/gc.log

 

감사합니다.

반응형

centos7, elasticsearch 7.5.1 기준입니다.

엘라스틱 서치 기동 시 아래와 같은 에러와 함께 다운되는 현상이었습니다.

max virtual memory areas vm.max_map_count [65530] is too low, increase to at least [262144]

 

위 에러는 엘라스틱서치 프로세스가 사용할 메모리 맵 영역 수가 부족하여 발생한 에러였고,

아래 파일을 수정하여 해결하였습니다.

# 파일 수정
vi /etc/sysctl.conf
vm.max_map_count=262144

# 적용
sysctl -p

 

 

감사합니다.

반응형

엘라스틱서치 7.5.1 기준입니다.

elasticsearch.yml과 jvm.options 파일 내부의 설정 값에 대해 알아보겠습니다.

 

elasticsearch.yml:

ElasticSearch의 실행 환경에 대한 설정 은 elasticsearch.yml 에서 관리합니다.

 

cluster.name: "<클러스터명>"

노드들은 클러스터명이 같으면 같은 클러스터로 묶입니다.
클러스터명이 다르면 동일 서버, 바인딩이 가능한 네트워크상에 있더라도 서로 다른 클러스터로 바인딩 됩니다.
디폴트 값: elasticsearch

node.name: "<노드명>"
실행된 각 elasticsearch 노드들을 구분할 이름입니다. 꼭 서버의 호스트명일 필요는 없습니다.
설정하지 않으면 7버전 이상부터는 호스트명, 6.x 이하 버전에서는 UUID의 첫 7글자가 노드 명으로 설정됩니다.
 
node.attr. : "value"
노드별로 속성을 부여하기 위한 일종의 네임스페이스입니다.
hot/warm 아키텍쳐를 구성 혹은 물리 장비 구성에 따라 샤드 배치를 임의적으로 조절하는 등의 설정을 이 설정 값을 통해 가능하게 됩니다.
 
path.data : ["<경로>"]
색인된 데이터가 저장되는 경로입니다.
여러 개의 경로값을 배열 형태로 입력이 가능하기 때문에 한 서버에서 여러 디스크에 저장할 수 있습니다.

디폴트 값: 엘라스틱서치 설치 경로/data
 
path.logs: "<경로>"
엘라스틱 서치 실행 로그 파일이 저장되는 경로입니다.
실행중인 시스템 로그는 <클러스터명>.log 형식의 파일로 저장되며, 날짜가 변경되면 날짜가 추가됩니다.

디폴트 값: 엘라스틱서치 설치 경로/logs
 
bootstrap.memory_lock: true
엘라스틱서치가 사용중인 힙 메모리 영역을 타 java application이 사용하지 못하도록 점유하는 설정입니다.
true를 권장합니다.
 
network.host : <ip주소>
엘라스틱 서치가 실행되는 서버의 ip 주소입니다.

디폴트 값 : 127.0.0.1

개발 모드: 주석 처리 or 루프백
운영 모드: IP 주소 / 부트스트랩 체크가 활성화됩니다.

 

해당 값은 서버 내부와 외부 주소를 모두 지정할 수 있습니다.

만약 내부/외부망의 주소를 다르게 설정할 시 아래 값으로 구분 가능합니다.
network.bind_host : 내부망
network.publish_host: 외부망


해당 값 설정에 사용되는 또 다른 변수 값입니다.
_local_ : 127.0.0.1(루프백 주속) 과 같습니다. 즉, Default값과 같습니다.
_site_ : 로컬 네트워크 주소로 설정, 실 클러스터 구성 시, 자주 사용됩니다. 서버의 네트워크 주소가 변경되더라도,

실제 설정 파일은 변경되지 않기에 관리가 편리합니다.
_global_: 외부 네트워크에서 바라보는 서버의 주소입니다.

 

http.port : <포트 번호>
엘라스틱서치가 클라이언트와 통신하기 위한 Http 포트를 설정합니다.

포트가 이미 사용중인 경우 9200~9299 사이의 값을 차례대로 사용합니다.
디폴트 값: 9200
 
transport.port: <포트 번호>
엘라스틱 서치 노드들끼리 서로 통신하기 위한 tcp 포트를 설정합니다.
포트가 이미 사용중인 경우 9300~9399 사이의 값을 차례대로 사용합니다.

디폴트 값: 9300
 
discovery.seed.hosts: ["<호스트-1>", "<호스트-2>", ...]
클러스터 구성을 위해 바인딩 할 원격 노드의 IP 또는 도메인 주소를 배열 형태로 입력합니다.
주소만 적는 경우 디폴트로 9300~9305 사이의 값을 검색합니다.
tcp 포트가 이 범위 밖에 설정 된 경우 포트번호 까지 같이 적어줘야합니다.
디스커버리: 원격에 있는 노드들을 찾아 바인딩 하는 과정
 
cluster.initial_master_nodes : ["<노드-1>", "<노드-2>"]
클러스터가 최초 실행될 때 명시된 노드들을 대상으로 마스터 대상으로 마스터 노드를 선출합니다.
cluster.initial_master_nodes 옵션은 7.0이상 부터 추가된 기능입니다.
6.x 이전 버전에서는 최소 마스터 후보노드를 지정하기 위해 다음 옵션 사용하였습니다.
discovery.zen.minimum_master_nodes

7.0 버전 부터는 최소 마스터 후보 노드의 크기가 능동적으로 변경됩니다.

노드의 역할과 설정
엘라스틱 서치의 노드들은 각 역할이 구분되어있습니다.
각 노드들이 서로 다른 역할을 하도록 클러스터 구성이 가능합니다.

아래 설정들을 통해 각 노드의 역할이 부여되며, 아래 값들의 디폴트 값은 true입니다.
특정 값들을 false 설정하여 각 노드들의 역할을 구분지을 수 있습니다.

 

node.master : true
마스터 후보(master eligible) 노드 여부를 설정합니다.
false 일 시, 마스터 후보에서 제외됩니다.
모든 클러스터는 하나의 마스터 노드를 가지고, 마스터 노드 다운 시, 마스터 후보에서

한 노드를 마스터 노드로 부여합니다.
 
node.data : true
해당 노드에 엘라스틱 서치의 데이터를 저장할 지 여부입니다.
 
node.ingest: true
데이터 색인시 전처리 작업인 ingest pipeline 작업의 수행이 가능한지 여부입니다.


node.ml : true
해당 노드가 머신러닝 작업을 수행 할 수 있는지 여부입니다.

 

감사합니다. 

반응형

centos7 기준입니다.

호스트네임이 node1~4인 4대의 서버에 엘라스틱서치를 설치해보겠습니다.

각 서버에 java 8버전이 설치되었음을 가정합니다.

엘라스틱서치 7버전은 java 8버전이 호환되고,

8버전 부터 java 버전이 높아집니다.

 

1. 사전 준비:

action server: node1~4

user: root

pwd: -

cmd:

# 프로세스가 가질 수 있는 최대 메모리 맵 영역 수를 늘려줍니다.
# 수정 하지 않고 엘라스틱 서치 기동 시 262144 만큼의 수가 설정되어야 한다는 에러가 발생합니다.
vi /etc/sysctl.conf
vm.max_map_count=262144
sysctl -p

# 엘라스틱서치 압축 파일 다운로드 및 해제
cd /opt/apps
wget https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-7.5.1-linux-x86_64.tar.gz
tar xvfz elasticsearch-7.5.1-linux-x86_64.tar.gz

# 실행 계정 hadoop 통일
chown -R hadoop:hadoop ./elasticsearch-7.5.1/

# 엘라스틱서치에 사용될 데이터 저장 경로 및 로그 위치 설정
mkdir -p /data/elasticsearch/data
mkdir -p /data/logs/elasticsearch

# 권한 부여
chown -R hadoop:hadoop /data/elasticsearch
chown -R hadoop:hadoop /data/logs/elasticsearch

# 계정 전환 및 경로 이동
su - hadoop
cd /opt/apps/elasticsearch-7.5.1/

 

2. 설정 파일 수정

action server: node1~4

user: hadoop

pwd: /opt/apps/elasticsearch-7.5.1

cmd:

# 기존 설정 파일을 백업
mv config/elasticsearch.yml config/elasticsearch.yml_backup

# 새 설정 파일 작성
vi config/elasticsearch.yml

# 클러스터명
cluster.name: "es-cluster"

# 클러스터 내부에서 노드를 식별하기위한 이름
# 서버마다 다르게 설정해야합니다. 꼭 서버의 호스트명일 필요는 없습니다.
node.name: "es-node1" // 각 서버별로 es-node1~4

# ES가 실행되는 서버의 ip 주소
#_local_ : 루프백 주소 127.0.0.1 과 같습니다. Default값
#_site_ : 로컬 네트워크 주소로 설정, 실제로 클러스터링 구성시 주로 설정하는 값
network.host: ["_local_"", ""_site_"]

# 클러스터 구성을 위해 바인딩 할 원격 노드의 IP 또는 도메인 주소를 배열 형태로 입력
# 실제 서버의 호스트명입니다.
discovery.seed_hosts: ["node1","node2","node3","node4"]

# 클러스터가 최초 실행될 때 명시된 노드들을 대상으로 마스터 대상으로 마스터 노드를 선출합니다.
# ES가 인식하는 노드의 이름입니다.
cluster.initial_master_nodes: ["es-node1","es-node2","es-node3","es-node-4"]

# 데이터가 저장될 경로입니다.
path.data: /data/elasticsearch/data

# 로그가 저장될 경로입니다.
path.logs: /data/logs/elasticsearch

# 엘라스틱 서치가 사용할 메모리 값과 관련 로그 파일 경로를 설정합니다.
vi config/jvm.options
# 수정
-Xms4g
-Xmx4g

# 아래 세줄 찾아서 수정
-XX:HeapDumpPath=/data/elasticsearch/data
-XX:ErrorFile=/data/logs/elasticsearch/hs_err_pid%p.log
8:-Xloggc:/data/logs/elasticsearch/gc.log

 

3. 기동 및 확인

action server: node1~4

user: hadoop

pwd: /opt/apps/elasticsearch-7.5.1

cmd:

# 기동
./bin/elasticsearch -d

# 포트가 열려있는지 확인합니다. 기본 포트로 설정하였습니다.
netstat -ntlp | grep 9200
netstat -ntlp | grep 9300

# 해당 명령어로 아래와 같은 결과 값이 나온다면 성공입니다.
curl -X GET http://localhost:9200

# 결과
{
  "name" : "es-node1",
  "cluster_name" : "es-cluster",
  "cluster_uuid" : "rnEVH-uyQY-wlYNkCI4PJA",
  "version" : {
    "number" : "7.5.1",
    "build_flavor" : "default",
    "build_type" : "tar",
    "build_hash" : "3ae9ac9a93c95bd0cdc054951cf95d88e1e18d96",
    "build_date" : "2019-12-16T22:57:37.835892Z",
    "build_snapshot" : false,
    "lucene_version" : "8.3.0",
    "minimum_wire_compatibility_version" : "6.8.0",
    "minimum_index_compatibility_version" : "6.0.0-beta1"
  },
  "tagline" : "You Know, for Search"
}

 

잘못된 정보가 있다면 말씀 부탁드립니다.

감사합니다.

반응형

+ Recent posts