1. 대량 데이터 처리의 중요성

Elasticsearch는 대량의 데이터를 빠르게 검색하고 분석할 수 있는 분산형 검색 엔진이지만, 적절한 데이터 처리 전략이 없으면 성능 저하와 클러스터 불안정이 발생할 수 있다. 특히 데이터 삽입(Bulk Insert), 데이터 파티셔닝, 시간 기반 인덱싱과 같은 전략을 활용하면 효율적인 데이터 처리가 가능하다.


2. 대량 데이터 삽입(Bulk Insert)

Elasticsearch는 개별 문서를 하나씩 삽입하는 방식보다 **벌크 API(Bulk API)**를 활용하여 여러 개의 문서를 한 번에 삽입하는 것이 훨씬 효율적이다.

 

(1) Bulk API 활용

 

Bulk API는 한 번의 요청으로 여러 개의 문서를 삽입할 수 있도록 설계되었다. 이를 활용하면 네트워크 오버헤드를 줄이고, 인덱싱 성능을 극대화할 수 있다.

예제 코드 (Python Elasticsearch 라이브러리 사용)

from elasticsearch import Elasticsearch, helpers

es = Elasticsearch(["http://localhost:9200"])  # Elasticsearch 클러스터 연결

# 샘플 데이터 생성
data = [
    {"_index": "test-index", "_id": i, "_source": {"name": f"User {i}", "age": i % 50}}
    for i in range(100000)
]

# Bulk API를 이용한 데이터 삽입
helpers.bulk(es, data)

 

(2) Bulk Insert 시 고려해야 할 사항

  • 배치 크기 조절: 너무 큰 배치는 클러스터 부하를 초래할 수 있으므로, 적절한 크기(예: 5,000~10,000 문서)를 설정
  • CPU 및 메모리 부하 관리: 백그라운드에서 데이터를 점진적으로 삽입
  • 리프레시 간격 조정: refresh_interval을 조절하여 인덱싱 성능 향상 (refresh_interval=-1 설정 후 일괄 삽입 후 복원)

설정 예제

PUT test-index/_settings
{
  "index": {
    "refresh_interval": "-1"  
  }
}

벌크 삽입 후 복원

PUT test-index/_settings
{
  "index": {
    "refresh_interval": "1s"  
  }
}

3. 데이터 파티셔닝 (Shard & Index Design)

Elasticsearch는 샤딩(Sharding)과 인덱스 설계(Index Design)를 적절히 설정하면 대량 데이터 처리를 더욱 효율적으로 할 수 있다.

 

(1) 샤드 개수 조정

 

샤드는 Elasticsearch에서 데이터를 저장하는 기본 단위이며, 클러스터 성능에 큰 영향을 미친다.

  • 샤드 개수는 데이터 크기와 노드 수를 고려하여 설정
  • 너무 많은 샤드는 관리 오버헤드를 증가시킴
  • 샤드 크기는 10GB~50GB 정도가 적절함

샤드 개수 계산 공식

샤드 개수 = 예상 데이터 크기(GB) / 50GB

예를 들어, 예상 데이터 크기가 500GB이면, 샤드 개수는 500GB / 50GB = 10개

 

(2) 인덱스 설계 전략

  • 수직 파티셔닝: 서로 다른 유형의 데이터를 별도의 인덱스로 나누어 저장 (예: 로그 데이터, 사용자 데이터 분리)
  • 수평 파티셔닝: 동일한 유형의 데이터를 여러 개의 샤드에 분산 저장하여 부하 분산
  • Alias 활용: 여러 개의 인덱스를 가상으로 하나의 인덱스로 취급하여 데이터 검색 시 유연성 증가

Alias 예제

POST _aliases
{
  "actions": [
    {
      "add": {
        "index": "log-2023-*",
        "alias": "logs"
      }
    }
  ]
}

4. 시간 기반 인덱싱(Time-Based Indexing)

대량의 데이터를 처리할 때, 시간 단위로 인덱스를 생성하여 관리하는 방식이 유용하다. 특히 로그 데이터, IoT 데이터, 이벤트 스트리밍 데이터에서 많이 활용된다. 다만 스프링과 같이 사용하는 경우 Alias로 관리할 필요가 있다.

 

(1) 시간 기반 인덱스 설계

  • 일일 인덱스 (daily index): logs-YYYY-MM-DD
  • 주간 인덱스 (weekly index): logs-YYYY-WW
  • 월간 인덱스 (monthly index): logs-YYYY-MM

예제: ELK 스택에서 로그 관리할 경우

PUT logs-2024-03-01
{
  "settings": {
    "number_of_shards": 3,
    "number_of_replicas": 1
  }
}

 

(2) ILM (Index Lifecycle Management) 적용

시간이 지나면 데이터를 자동으로 이동시키는 정책을 설정하여 저장 비용을 절감할 수 있다.

ILM 정책 예제

PUT _ilm/policy/logs_policy
{
  "policy": {
    "phases": {
      "hot": {
        "actions": {
          "rollover": {
            "max_size": "50GB",
            "max_age": "7d"
          }
        }
      },
      "warm": {
        "actions": {
          "allocate": {
            "include": { "_tier_preference": "warm" }
          }
        }
      },
      "cold": {
        "actions": {
          "allocate": {
            "include": { "_tier_preference": "cold" }
          }
        }
      }
    }
  }
}

5. 결론

  • 대량 데이터 삽입 시 Bulk API를 활용하여 네트워크 부하를 줄이고 성능을 극대화
  • 샤드 개수와 인덱스 설계를 최적화하여 데이터 처리 성능을 개선
  • ILM을 도입하여 오래된 데이터를 자동으로 관리하고 저장 비용 절감

1. 클러스터 구성 개요

Elasticsearch 클러스터는 확장성과 안정성을 고려하여 여러 개의 노드로 구성된다. 처음에는 단순히 노드를 종류별로 나열하는 방식으로 운영을 했지만, 마스터 노드의 경우 1개만 있을 경우 다운될 경우 엘라스틱 서치가 마비될 것을 대비하여 2개를 두었지만, 서로 마스터 노드 투표를 자신에게 해버려서 마스터 노드가 선출이 안되는 오류가 발생했다. 데이터 노드의 경우 대용량 데이터 처리가 되면서 단순히 모든 데이터를 동일한 방식으로 저장하는 것은 효율이 떨어졌고 중요도에 따른 카테고리화를 진행할 필요성이 생기기 시작했다. 데이터 노드 수가 증가됨에 따라 AWS의 ELB와 동일하게 로드벨런싱을 담당하는 요소의 필요성 또한 부각되기 시작하였다.

 

(1) 클러스터 노드 구성 및 이유

노드 유형 개수 역할 선정 이유
마스터 노드 3개 클러스터 상태 관리, 노드 헬스 체크, 샤드 배치 조정 홀수 개(3개)로 유지하여 선출 과정에서 네트워크 분할(Partition) 문제 방지, 고가용성 확보
코디네이터 노드 1개 클라이언트 요청 처리, 검색 및 집계 부하 분산 검색 부하가 높은 환경에서 별도의 코디네이터 노드가 있으면 부하 분산이 용이함
Hot 데이터 노드 3개 최신 데이터 저장, 빠른 검색 처리 최신 데이터를 빠르게 검색할 수 있도록 성능이 높은 노드에서 운영
Warm 데이터 노드 3개 중간 단계 데이터 저장, 검색 성능 중간 장기적으로 검색 빈도가 줄어드는 데이터를 따로 저장하여 리소스를 효율적으로 활용
Cold 데이터 노드 3개 오래된 데이터 저장, 저비용 스토리지 활용 자주 조회되지 않는 데이터를 비용이 낮은 스토리지에 저장하여 클러스터 운영 비용 절감

 

(2) 주요 설계 원칙

  • 마스터 노드는 데이터 노드 역할을 하지 않도록 분리하여 성능 저하 방지
  • 홀수 개(3개, 5개 등)로 운영하여 선출 과정에서 네트워크 분할(Partition) 문제 예방
  • Hot-Warm-Cold 구조를 활용하여 데이터 저장 비용 최적화
  • 코디네이터 노드를 통해 검색 부하를 분산하여 성능을 향상

2. 클러스터 운영 전략

클러스터 운영 시 고려해야 할 주요 요소는 노드 배치, 샤드 할당, 부하 분산이다. 각 요소를 적절히 관리하면 성능 저하와 장애를 방지할 수 있다.

 

(1) 마스터 노드의 역할 및 구성 이유

 

마스터 노드는 클러스터의 전반적인 상태를 관리하며, 노드 간의 통신과 샤드 배치를 조정한다. 3개의 마스터 노드를 운영하면 **선출 과정(Election Process)**에서 안정성을 확보할 수 있다.

  • 마스터 노드를 3개로 설정한 이유
    • Elasticsearch의 Split Brain 문제 방지
    • 홀수 개(3, 5 등)로 유지하면 선출 과정에서 안정성 증가
    • 장애 발생 시 빠른 마스터 선출 가능

 

(2) 데이터 노드(HWC 구조) 운영 및 구성 이유

 

데이터 노드는 Hot-Warm-Cold 구조로 분리하여 관리할 수 있다.

데이터 노드 유형 역할 및 특징 선정 이유
Hot 노드 최신 데이터 저장, 빠른 검색 수행 SSD 사용, 높은 CPU 성능 요구, 빠른 응답 속도 필요
Warm 노드 일정 시간이 지난 데이터 저장, 성능과 비용 균형 유지 검색 빈도가 낮아지므로 비용 절감을 위해 일반 HDD 사용 가능
Cold 노드 오래된 데이터 저장, 저비용 스토리지 활용 거의 조회되지 않는 데이터 보관을 위한 비용 최적화 목적

왜 HWC 구조를 사용했는가?

  • 검색 성능 최적화: 최근 데이터를 Hot 노드에 저장하여 빠르게 검색 가능
  • 비용 절감: 오래된 데이터는 저비용 스토리지로 이동하여 유지 비용 최소화
  • 확장성 확보: 데이터가 증가해도 클러스터가 원활하게 운영될 수 있도록 계층화하여 관리

3. 장애 대응 및 복구 전략

클러스터 장애는 다양한 원인으로 발생할 수 있으며, 미리 대비하는 것이 중요하다.

 

(1) 장애 유형 및 해결책

장애 유형 원인 해결책
마스터 노드 장애 네트워크 단절, 하드웨어 오류 3개 이상의 마스터 노드 유지, 빠른 리더 선출 설정
데이터 노드 과부하 대량의 검색 요청, 샤드 불균형 코디네이터 노드 추가, 샤드 리밸런싱 수행
디스크 공간 부족 과도한 데이터 저장 ILM(인덱스 수명 주기) 적용, 오래된 데이터 Cold 노드로 이동

4. 결론

  • 마스터 노드는 홀수 개(3개)로 설정하여 안정적인 클러스터 운영을 보장
  • Hot-Warm-Cold 구조를 도입하여 검색 성능과 비용을 최적화
  • 코디네이터 노드를 활용하여 검색 부하를 효과적으로 분산
  • 장애 대응 전략을 구축하여 클러스터 운영의 안정성을 유지

 

부하 테스트와 엘라스틱 서치 클러스터링 적용 이유

1. 문제 발생

저번 테스트에서 생긴 TPS에 대한 원인을 특정할 수 있었다. 원래는 성능 테스트가 목적이었지만 엘라스틱 서치가 부하를 버티지 못하고 끊기는 스트레스, 부하테스트를 한 상태가 되었던 것이 문제였다. 테스트 결과를 분석한 결과, 특정 구간에서 TPS(Transactions Per Second) 값이 급격히 하락하는 문제가 발생했다. 이는 시스템이 특정 시점에서 부하를 감당하지 못하거나, 처리 한계를 초과했음을 의미했다.

2. 문제 원인

  • TPS의 급격한 하락
    • 초기 TPS가 일정하게 유지되다가 특정 시점에서 크게 하락하는 패턴이 반복됨.
    • 이는 과부하 상태에서 시스템이 응답하지 못하거나, 노드 간 부하 분산이 제대로 이루어지지 않는 문제일 가능성이 있음.
  • 성공한 테스트 대비 높은 에러율
    • 총 테스트 요청: 57,058건
    • 성공한 테스트: 40,912건
    • 에러 발생: 16,146건 → 약 28%의 실패율
    • 높은 에러율은 노드의 부하 분산이 제대로 이루어지지 않거나, 특정 트랜잭션이 처리되지 못하는 문제가 있을 가능성을 시사함.
  • TPS의 변동성
    • TPS가 140에서 280까지 변동하는 것을 보면, 일정한 부하를 유지하지 못하고 성능이 들쭉날쭉함.
    • 이는 단일 노드 또는 특정 서버가 병목이 되어 전체 성능을 저하시킬 가능성이 큼.

 

3. 문제 해결책 수립

해결 방법 비교

해결 방법 설명 장점 단점
단일 노드 확장 서버의 스펙을 올려 처리 성능 증가 설정이 간단하고 빠른 대응 가능 확장성이 떨어지고, 비용이 급증함
로드 밸런서 추가 부하 분산을 위한 로드 밸런서를 활용 부하 균등 분배 가능 부하 분산만으로 해결되지 않는 경우도 있음
엘라스틱 서치 클러스터링 적용 다중 노드 분산 처리로 부하 분산 확장성이 뛰어나고, TPS 유지 가능 초기 설정 및 운영 복잡성 증가

 

4. 왜 클러스터링을 선택했는가?

(1) 단일 노드 확장의 한계

  • 단일 노드의 스펙을 올리는 방식은 일정한 한계치(물리적인 성능 한계)에 도달하면 더 이상 확장할 수 없음.
  • 노드 하나에 부하가 집중되면 하드웨어 장애 발생 시 서비스 전체가 다운될 위험이 있음.
  • 비용이 선형적으로 증가하지 않고, 급격히 증가하는 경향이 있음.

(2) 로드 밸런서만으로는 해결되지 않는 문제

  • 로드 밸런서는 요청을 여러 서버로 분산해주지만, 엘라스틱 서치 내부의 인덱스와 샤드 관리는 그대로 단일 노드의 성능에 의존.
  • 검색 및 인덱싱이 단일 노드에서 수행되면 백엔드에서 처리 부하를 감당하지 못하는 문제가 발생.
  • 결국, 내부적으로 데이터 저장과 검색 성능을 분산할 수 있는 구조가 필요.

 

5. 문제 해결: 엘라스틱 서치 클러스터링 적용

(1) 부하 분산을 위한 클러스터링

  • 단일 노드의 한계를 극복하기 위해 엘라스틱 서치 클러스터링을 적용했다.
  • 기존에는 단일 노드에서 모든 검색 요청을 처리했으나, 여러 개의 노드가 부하를 나누어 처리하도록 구성하여 TPS를 안정적으로 유지할 수 있도록 함.
  • 클러스터링을 통해 특정 노드가 과부하 상태가 되더라도, 다른 노드가 부하를 분산하여 트랜잭션 실패율을 감소시킬 수 있음.

(2) 데이터 샤딩(Sharding) 최적화

  • 기존에는 하나의 인덱스에 모든 데이터가 저장되었지만, 샤딩을 통해 데이터를 여러 개의 노드에 분산 저장함.
  • TPS가 일정 수준에서 급격히 하락하는 현상을 줄이기 위해, 샤드 크기를 최적화하여 처리 속도를 향상시킴.

(3) 고가용성을 위한 리플리카(Replica) 설정

  • 특정 노드가 과부하로 다운되거나 장애가 발생하더라도, 리플리카 노드를 통해 동일한 데이터를 제공할 수 있도록 설정.
  • 이를 통해 TPS 변동성을 최소화하고, 부하가 증가하더라도 안정적인 성능을 유지할 수 있도록 함.

 

6. 결론

  • 부하 테스트 결과, 단일 노드 운영으로 인해 TPS 변동성이 크고, 특정 시점에서 성능이 급격히 저하되는 문제가 발생했다.
  • 이를 해결하기 위해 엘라스틱 서치 클러스터링을 적용하여 다중 노드 운영을 통해 부하를 분산시켰다.
  • 클러스터링을 선택한 이유는 단일 노드 확장의 한계를 극복하고, 로드 밸런서만으로 해결할 수 없는 내부 데이터 분산을 최적화하기 위함이다.
  • 샤딩 및 리플리카 설정을 최적화하여 검색 성능을 유지하면서도, 안정적인 TPS를 확보할 수 있도록 했다.
  • 결과적으로, 대규모 트랜잭션이 발생하는 환경에서도 확장성과 성능을 보장할 수 있도록 시스템을 개선했다.

1. 초기 상태 (MySQL + JPA)

  • 테스트 환경: nGrinder
    • 사용자 198명
    • 1초에 조회 1개씩 요청
    • 테스트 시간: 5분
  • 테스트 결과:
    • 총 실행 횟수: 3,600번
    • 성공: 3,598번
    • 실패: 2건
    • 평균 테스트 시간: 14,133.28ms (매우 비효율적)
    • TPS 그래프의 편차가 심함
  • 문제 분석:
    • DB와의 통신에서 지연이 발생할 가능성이 높음
    • JPA를 사용하면서 최적화가 덜 되었을 가능성이 있음
  • 진단 방법:
    • p6spy를 활용하여 SQL 로그 분석
    • COUNT 쿼리에서 700ms가 소요되는 문제 발견
    • JPA의 페이지네이션 과정에서 발생하는 비효율적인 쿼리 확인
    • 아래 사진 : 타임스탬프 | sql 실행시간 | 실행된 sql작업 | 사용된 DB 커넥션 ID|DB 연결 정보

 

2. QueryDSL을 활용한 최적화

  • 개선 조치:
    • JPA 페이지네이션을 QueryDSL로 변경하여 최적화 진행
  • 테스트 환경 (동일한 조건으로 진행):
    • 테스트 시간: 5분
  • 테스트 결과:
    • 총 실행 횟수: 42,024번
    • 성공: 36,613번
    • 실패: 5,411건
    • 평균 테스트 시간: 246.18ms
  • 개선 점:
    • 실행 횟수가 증가하고 성공 횟수도 증가
    • 하지만 평균 테스트 시간이 여전히 높음

 

3. 엘라스틱 서치 도입

  • 개선 조치:
    • 검색 기능을 MySQL에서 엘라스틱 서치로 변경
  • 테스트 환경 (동일한 조건으로 진행):
    • 테스트 시간: 5분
  • 테스트 결과:
    • 총 실행 횟수: 57,058번
    • 성공: 40,912번
    • 실패: 16,146건
    • 평균 테스트 시간: 15.39ms
  • 분석:
    • 에러가 크게 증가했지만, TPS 그래프가 일정 시간마다 0으로 떨어지는 현상이 있었음
    • 엘라스틱 서치 자체의 문제라기보다는 다른 병목이 원인일 가능성이 있음
  • 개선 점:
    • 평균 테스트 시간이 15.39ms로 크게 감소하여 성능이 대폭 개선됨

 

ELK에서 Logstash로 저장 시 시간 데이터가 US 시간으로 저장되는 문제 해결

1. 문제 발생

Logstash에서 now를 이용해 시간 데이터를 저장할 때, 기본적으로 미국(US) 시간대로 저장되는 문제가 발생했다. 이는 Kibana에서 데이터를 조회할 때 예상과 다른 시간 값이 표시되는 원인이 되었다.

 

2. 문제 원인

  • Logstash의 기본 타임존(Timezone)이 UTC로 설정되어 있음
    • Logstash는 시간 데이터를 UTC 기준으로 처리하며, 명시적으로 타임존을 설정하지 않으면 기본적으로 UTC가 적용된다.
    • 따라서 한국(KST)에서 저장한 데이터도 9시간이 빠진 UTC 시간으로 저장된다.
  • Elasticsearch도 기본적으로 UTC를 사용
    • Elasticsearch는 시간 데이터를 ISO 8601 형식으로 저장하며, 별도의 변환 없이 UTC 기준으로 처리한다.
    • Kibana에서 데이터를 조회하면 한국 시간(KST)이 아닌 UTC 기준으로 표시될 수 있다.

 

3. 문제 해결책 수립

해결 방법 비교

해결 방법 설명 장점 단점
Logstash에서 타임존 변환 필터를 적용하여 KST로 변환 후 저장 설정이 간단함 데이터 변환 과정 필요
Elasticsearch의 Ingest Pipeline 사용 Ingest Pipeline에서 타임존을 변환 Elasticsearch에서 직접 처리 가능 추가 설정 필요
Kibana에서 시간대 변환 Kibana 설정을 변경하여 한국 시간으로 표시 기존 데이터 수정 불필요 단순 표시만 변경됨

 

4. 문제 해결: Logstash에서 타임존 변환 적용

(1) Logstash에서 타임존 변환 적용

Logstash의 date 필터를 사용하여 UTC → KST 변환을 수행한다.

filter {
  date {
    match => ["@timestamp", "ISO8601"]
    timezone => "Asia/Seoul"
  }
}
  • @timestamp 필드에 대해 ISO 8601 형식을 매칭하여 KST(한국 표준시)로 변환함.
  • 변환된 데이터는 Elasticsearch에 저장될 때 한국 시간으로 반영됨.

(2) Kibana에서 시간대 설정 변경 (보완책)

Logstash에서 변환하지 못한 데이터가 있을 경우, Kibana 설정에서 시간대를 변경할 수 있다.

  1. Kibana 설정 변경:
    • Management → Advanced Settings → dateFormat:tz 값을 Asia/Seoul로 변경.
    • Kibana에서 UTC 시간을 한국 시간(KST)으로 변환하여 표시한다.

 

5. 결론

  • Logstash의 기본 타임존은 UTC이므로, 한국 시간으로 저장하려면 변환 작업이 필요하다.
  • Logstash의 date 필터를 사용하여 Asia/Seoul로 변환하는 것이 가장 효율적인 방법이다.
  • 추가적으로 Kibana 설정을 변경하면 데이터 표시를 한국 시간으로 맞출 수 있다.
  • 이 방식으로 저장된 시간 데이터는 이후 검색 및 분석 시 혼란 없이 사용할 수 있다.

엘라스틱 서치(Elasticsearch) 샤드 관리와 확장성 전략

1. 문제 발생

엘라스틱 서치는 데이터를 저장할 때 샤드(Shard) 단위로 분할하여 저장한다. 샤드의 개수는 검색 성능과 확장성에 큰 영향을 미치며, 이에 대한 적절한 설정이 필요하다.

 

2. 문제 원인

  • 샤드는 병렬 처리를 위한 단위다. 검색 쿼리는 여러 개의 샤드에서 동시에 실행되므로, 샤드 개수를 적절히 설정하면 성능이 향상된다.
  • 예를 들어, 100만 개의 문서를 하나의 샤드에 저장하여 검색하는 것50만 개씩 2개의 샤드에 나누어 병렬로 처리하는 것은 검색 속도에서 차이가 발생한다.
  • 그러나 샤드 개수가 너무 많으면 오버헤드가 증가하여 속도가 오히려 느려질 수 있다.
  • 샤드 관리는 직접적인 성능 최적화와 관련되며, 샤드의 개수와 크기를 조절하는 것이 핵심적인 관리 포인트다.

 

3. 문제 해결책 수립

해결 방법 비교

해결 방법 설명 장점 단점
샤드 개수 증가 데이터를 더 많은 샤드로 분할하여 병렬 처리 읽기 성능 향상 오버헤드 증가, 관리 복잡성 증가
샤드 개수 감소 샤드 수를 줄여 관리 부담 감소 클러스터 안정성 증가 검색 속도 저하 가능
샤드 크기 최적화 적정 샤드 크기를 유지하여 균형을 맞춤 성능 최적화 데이터 볼륨 예측 필요

 

4. 문제 해결: 샤드 크기 최적화 및 ILM 활용

(1) 샤드 크기 설정 기준

  • 엘라스틱 서치 공식 문서에 따르면, 샤드 하나의 크기는 10GB~50GB 사이로 유지하는 것이 권장된다.
  • 적절한 샤드 개수를 계산하는 공식:
  • 샤드 개수 = 예상 인덱스 크기 / 적정 샤드 크기
  • 예를 들어, 예상 데이터 크기가 500GB이고, 샤드 하나의 크기를 50GB로 설정하면, 샤드 개수는 500GB / 50GB = 10개가 된다.
  • 샤드 개수를 설정할 때는 데이터 증가량을 고려하여 유연하게 확장할 수 있도록 설계해야 한다.

(2) ILM(인덱스 수명 주기)와의 관계

  • ILM(인덱스 수명 주기)은 샤드 크기와 직접적인 관계는 없지만, 데이터의 저장 전략을 관리하는 개념으로 샤드 운영을 최적화할 수 있도록 돕는다.
  • Hot-Warm-Cold 노드 구조를 사용하여, 중요하고 자주 사용되는 데이터를 빠른 스토리지에 저장하고, 오래된 데이터는 비용이 저렴한 스토리지로 이동시킬 수 있다.
노드 유형 설명
Hot 노드 최신 데이터 저장, 검색 속도가 가장 빠름
Warm 노드 오래된 데이터 저장, 상대적으로 느린 검색
Cold 노드 압축된 데이터 저장, 읽기 전용
  • ILM을 적용하면 오래된 인덱스를 Cold 노드로 이동하면서, 샤드를 자동으로 병합하거나 크기를 조정하여 리소스를 최적화할 수 있다.
  • 그러나 ILM은 샤드 크기 자체를 조정하는 기능은 없으며, 샤드가 배치되는 노드를 관리하는 역할을 한다.

 

5. 결론

  • 샤드는 검색 성능 최적화를 위해 개수를 적절히 조정해야 하며, 지나치게 많은 샤드는 오버헤드를 증가시킬 수 있다.
  • 샤드 크기는 10GB~50GB 사이로 유지하는 것이 권장되며, 예상 데이터 크기를 기반으로 샤드 개수를 결정해야 한다.
  • ILM(인덱스 수명 주기)은 샤드 크기를 직접 조정하지 않지만, 데이터를 노드별로 분산하여 운영 최적화를 돕는다.
  • 샤드 관리는 검색 성능과 직접적인 관련이 있으며, ILM은 데이터를 장기적으로 효율적으로 보관하는 관리 전략이다.

엘라스틱 서치에 접근해서 데이터를 조회하는 방법은 크게 2가지가 있다.

Repository 방식과 Request(Client API) 방식이 존재한다.

 

Repository는 Spring Data ElasticSearch에서 제공하는 JPA 스타일의 Repository 방식

  • ElasticsearchRepository 또는 ElasticsearchCrudRepository를 상속받아 간단한 CRUD 기능을 제공해 준다. 쿼리를 직접 작성하지 않아도 메서드 네이밍 규칙에 따라 자동으로 생성한다.

Request

RestHighLevelClient(Java API) 또는 직접 HTTP 요청을 보내는 방식(Elasticsearch API)을 사용하여 Elasticsearch를 제어한다.

  • JSON DSL을 직접 사용하여 보다 정교한 검색 및 조작을 수행할 수 있다.

 

결론적으로 Repository는 일반적인 CRUD에서 사용하기 용이하게 디자인 되어 있고, Request는 고급 기능 검색, 예를 들어 집계나 필터를 적용한 검색에 특화되어 있다.

 

실상 현재 프로젝트에서도 이 기준을 가지고 코드가 상황에 맞게 구현이 되어있다. 기술적 의사 결정이라고는 하지만, 실제적으로는 상황에 맞게 2개를 다 사용했다.

 

아래는 상세 내용이다.

 

1. Repository 방식 (Spring Data Elasticsearch)

설명

  • Spring Data Elasticsearch를 활용하여 JPA처럼 Elasticsearch 데이터를 다룰 수 있는 방식.
  • 인터페이스 기반으로 ElasticsearchRepository 또는 ElasticsearchCrudRepository를 상속받아 간단한 CRUD 기능을 제공.
  • 쿼리를 직접 작성하지 않아도 메서드 네이밍 규칙에 따라 자동으로 생성됨.

장점

코드가 간결함: JPA와 유사한 방식으로 CRUD 작업을 간단하게 수행 가능.

빠른 개발 가능: 복잡한 설정 없이 Repository 인터페이스만 정의하면 기본적인 CRUD 기능을 쉽게 사용할 수 있음.

Spring Boot와 통합 용이: Spring의 DI(Dependency Injection)와 연동하여 편리하게 사용 가능.

자동 매핑 지원: 엔티티와 Elasticsearch 문서 간 자동 매핑 지원.

단점

복잡한 쿼리 작성이 어려움: 네이티브 쿼리를 지원하지만, 고도화된 검색 기능을 활용하려면 QueryDSL 또는 커스텀 리포지토리를 사용해야 함.

실행 속도 저하 가능성: 내부적으로 Reflection 및 Proxy를 사용하므로 직접 API를 호출하는 방식보다 성능이 낮을 수 있음.

Elasticsearch의 최신 기능 반영이 늦음: Spring Data Elasticsearch 버전이 Elasticsearch 최신 버전을 지원하지 않을 수 있음.

언제 사용해야 하는가?

✔ CRUD 기능이 대부분이고, 복잡한 검색이 필요하지 않은 경우.

✔ 빠르게 Elasticsearch 연동을 구축해야 하는 경우.

✔ Spring Boot 환경에서 다른 Spring Data와 함께 통합적으로 사용할 경우.

언제 사용하면 안 되는가?

🚫 대량의 데이터를 빠르게 처리해야 할 경우 (Batch 처리).

🚫 고급 검색 기능(예: Aggregation, Multi-Search 등)이 필요한 경우.

🚫 Elasticsearch의 최신 기능(예: Runtime Fields, New Scripting API 등)을 즉시 활용해야 하는 경우.


2. Request(Client API) 방식 (RestHighLevelClient, Elasticsearch API)

설명

  • RestHighLevelClient(Java API) 또는 직접 HTTP 요청을 보내는 방식(Elasticsearch API)을 사용하여 Elasticsearch를 제어.
  • JSON DSL을 직접 사용하여 보다 정교한 검색 및 조작 가능.

장점

유연한 쿼리 작성: Elasticsearch의 강력한 Query DSL을 직접 활용할 수 있음.

고급 검색 기능 지원: Aggregation, Nested Query, Multi-Search 등 복잡한 검색 기능을 사용할 수 있음.

최신 Elasticsearch 기능 활용 가능: Elasticsearch 버전과 관계없이 모든 API를 직접 호출 가능.

높은 성능: 직접 API를 호출하므로 Spring Data Elasticsearch의 Overhead가 없음.

단점

코드가 복잡해질 수 있음: JSON 기반의 Query DSL을 직접 작성해야 하므로 가독성이 떨어질 수 있음.

Spring Boot와 통합성이 낮음: RestHighLevelClient는 Spring의 Repository 방식처럼 자동 매핑이 되지 않음.

직접 데이터 매핑 필요: Elasticsearch에서 가져온 데이터를 직접 DTO나 Entity로 변환해야 함.

언제 사용해야 하는가?

복잡한 검색 로직이 필요한 경우 (예: Aggregation, Full-text Search, Multi-Search).

대량의 데이터 처리 (Batch Insert, Bulk Processing 등).

Elasticsearch 최신 기능을 즉시 활용해야 하는 경우.

언제 사용하면 안 되는가?

🚫 단순한 CRUD 위주의 서비스에서 불필요하게 복잡성을 증가시키는 경우.

🚫 Spring Boot 기반 프로젝트에서 JPA 스타일의 간단한 연동이 필요한 경우.

🚫 Elasticsearch와의 연동이 적고, 관리할 코드의 복잡성을 줄이고 싶을 경우.


3. Repository 방식 vs Request(Client API) 방식 차이점 정리

비교 항목 Repository 방식 (Spring Data Elasticsearch) Request(Client API) 방식 (RestHighLevelClient, Elasticsearch API)

개발 편의성 ✅ 간편한 CRUD 제공 ❌ 직접 Query DSL 작성 필요
복잡한 쿼리 지원 ❌ 제한적 (QueryDSL 또는 커스텀 필요) ✅ 완전한 Query DSL 지원
성능 ❌ Proxy 및 Reflection으로 인해 느릴 수 있음 ✅ 직접 API 호출로 최적화 가능
Spring Boot 통합 ✅ Spring Data 방식 지원 ❌ 직접 설정 필요
최신 기능 지원 ❌ Spring Data 버전 의존 ✅ 최신 API 즉시 활용 가능
대량 데이터 처리 ❌ 적합하지 않음 ✅ Bulk API 지원

4. 결론: 언제 어떤 방식을 선택해야 하는가?

Repository 방식(Spring Data Elasticsearch) 추천 경우

  • 기본적인 CRUD 작업이 대부분인 경우.
  • Spring Boot 프로젝트에서 빠르고 간편하게 Elasticsearch를 연동하고 싶은 경우.
  • 데이터 검색이 단순하고, 최신 Elasticsearch 기능을 활용할 필요가 없는 경우.

Request(Client API) 방식 추천 경우

  • 복잡한 검색이 필요한 경우(Aggregation, Multi-Search, Nested Query 등).
  • 대량의 데이터를 빠르게 처리해야 하는 경우(Bulk Processing, High Throughput 요구).
  • Elasticsearch 최신 기능을 즉시 활용해야 하는 경우.

5. 결론 요약

  • 간단한 CRUD, 빠른 개발Spring Data Elasticsearch (Repository 방식)
  • 고급 검색, 대량 데이터 처리Request(Client API) 방식
  • 둘을 혼합해서 사용 가능 → 기본 CRUD는 Repository 방식, 복잡한 쿼리는 Client API 방식

 

엘라스틱 서치(Elasticsearch)를 선택한 이유

1. 문제 발생

프로와 학생의 매칭 사이트를 개발하는 과정에서, 감성 분석을 활용해 인기 상품과 강사를 추천하는 기능을 구현하고자 했다. 하지만 처음 사용한 MySQL의 LIKE 연산자를 이용한 문장 검색은 상당히 느린 속도를 보였다.

해당 기능은 추후 개인에 맞춰서 구성할 계획이었다보니, 개개인마다 느린 추천 검색을 수행하는 형태는 서비스를 운영하는 것에 있어 큰 마이너스 요인이 될 수 있을 것이라 판단하게 되었다.

2. 문제 원인

  • 기본적인 인덱스 구조는 문서 단위 검색 방식을 사용한다.
  • 검색 과정:
    1. 문서1을 연다.
    2. 문서1 안에 특정 단어가 있는지 찾는다.
    3. 문서2로 넘어간다.
    4. 이 과정을 반복.
  • MySQL에서는 모든 문서를 개별적으로 조회하고 검색해야 하므로 속도가 느려진다.
  • 이는 저장 방식 자체의 문제이므로, 해결하기 위해서는 카테고리화를 하거나 역색인(Inverted Index) 방식을 도입해야 했다.

 

3. 문제 해결책 수립

해결 방법 비교

해결 방법 설명 장점 단점
카테고리화 (태그 기반 검색) 데이터를 사전에 특정 키워드나 카테고리로 분류하여 검색 검색 속도 향상 새로운 키워드 추가 시 재구축 필요
MySQL FULLTEXT INDEX MySQL에서 제공하는 기본적인 전문 검색 인덱스 기존 DB와 쉽게 통합 여전히 속도가 느리고, 대량 데이터에서 비효율적
NoSQL (MongoDB 등) + 검색 엔진 NoSQL 기반 문서 저장과 내부 검색 기능 사용 RDB보다 확장성이 좋음 여전히 전문 검색 성능 부족
엘라스틱 서치(Elasticsearch) 역인덱스 구조를 활용한 전문 검색 엔진 빠른 검색 속도, 실시간 분석 가능 추가적인 시스템 관리 필요

 

4. 문제 해결: 엘라스틱 서치 도입

엘라스틱 서치는 역인덱스(Inverted Index) 구조를 사용하여 검색 속도를 획기적으로 개선한다.

  • 빠른 검색 속도: 데이터가 많아도 색인이 최적화되어 있어 검색이 빠름
  • 비정형 데이터 지원: JSON 기반 데이터 저장으로 다양한 문서 형태 지원
  • 실시간 색인화 및 분석: 새로운 데이터가 추가되더라도 검색 속도에 영향을 받지 않음
  • 분산 처리 지원: 여러 개의 노드에 데이터를 분산하여 확장 가능

결론: MySQL의 LIKE 검색은 대량 데이터에서 성능이 저하되는 문제가 있으며, 이를 해결하기 위해 역색인(Inverted Index)을 기반으로 한 엘라스틱 서치를 도입하면 문장 검색 속도를 획기적으로 향상시킬 수 있다.

엘라스틱 서치(Elasticsearch)를 선택해야 하는 이유

데이터 저장소는 다양한 종류가 있으며, 각각의 특성에 따라 적절한 활용 분야가 다릅니다. 그중에서도 엘라스틱 서치(Elasticsearch)는 강력한 검색 기능과 빠른 데이터 처리 성능을 바탕으로 많은 기업과 개발자들이 선택하는 솔루션입니다. 이번 글에서는 엘라스틱 서치가 다른 데이터 저장소와 비교했을 때 어떤 장점이 있는지 살펴보겠습니다.

 

1. 엘라스틱 서치의 핵심 특징

엘라스틱 서치는 분산형 검색 및 분석 엔진으로, 특히 대량의 데이터를 빠르게 검색하고 분석하는 데 최적화된 솔루션입니다. 주요 특징은 다음과 같습니다.

  • 풀텍스트 검색(Full-text Search) 최적화: 자연어 처리(NLP) 및 다양한 검색 알고리즘을 활용하여 고급 검색 기능을 제공
  • 역색인(Inverted Index) 방식: 문서를 저장할 때 단어 단위로 색인을 생성하여 검색 속도를 극대화
  • 실시간 검색 및 데이터 분석: 새로운 데이터가 추가될 때 즉각적으로 색인화되어 실시간으로 검색 가능
  • 확장성(Scalability): 클러스터 기반으로 노드를 추가하여 수평 확장이 가능
  • RESTful API 지원: 다양한 프로그래밍 언어 및 애플리케이션과 손쉽게 통합 가능
  • 로그 및 모니터링 시스템과 연계 가능: ELK 스택(Elasticsearch, Logstash, Kibana)으로 시스템 로그 분석 및 시각화 가능

이제 다른 데이터 저장소와 비교하여 엘라스틱 서치가 언제 유용한지 알아보겠습니다.

 

2. 엘라스틱 서치 vs. 관계형 데이터베이스(RDBMS)

항목 엘라스틱 서치 관계형 데이터베이스(RDBMS)
데이터 모델 문서 기반(JSON) 테이블(행/열 구조)
검색 성능 대량의 데이터에서 빠른 검색 가능 인덱싱이 없으면 검색 성능 저하
색인 방식 역색인 방식 사용 B-트리 또는 해시 기반 인덱스
실시간 데이터 처리 가능 실시간 분석 어려움
확장성 수평 확장 가능 일반적으로 수직 확장
트랜잭션 지원 X (ACID 미지원) O (ACID 지원)

언제 엘라스틱 서치를 선택해야 할까?

  • 빠른 검색이 필요한 경우 (예: e-커머스 검색, 로그 분석, 추천 시스템)
  • 구조화되지 않은 데이터를 저장하고 검색해야 할 때 (예: JSON, 로그 데이터)
  • 수많은 검색 쿼리를 처리해야 하는 경우

 

3. 엘라스틱 서치 vs. NoSQL 데이터베이스(MongoDB, Cassandra 등)

항목 엘라스틱 서치 NoSQL (MongoDB, Cassandra 등)
데이터 모델 문서 기반(JSON) 문서/키-값/컬럼 기반
주요 목적 고속 검색 및 분석 데이터 저장 및 처리
검색 성능 고급 검색 및 필터링 최적화 기본적인 인덱싱 지원
색인 방식 역색인 방식 사용 기본적인 B-트리 또는 해시 기반 인덱스
확장성 자동 샤딩으로 수평 확장 가능 대부분 수평 확장 가능
트랜잭션 지원 제한적 일부 지원

언제 엘라스틱 서치를 선택해야 할까?

  • 대량의 데이터를 실시간으로 검색하고 필터링해야 할 경우
  • MongoDB나 Cassandra의 기본 검색 기능이 부족할 때 보완 용도로 사용
  • 검색뿐만 아니라 데이터 분석이 필요한 경우

 

4. 엘라스틱 서치 vs. 데이터 웨어하우스 (Snowflake, BigQuery, Redshift 등)

항목 엘라스틱 서치 데이터 웨어하우스
데이터 모델 JSON 문서 기반 구조화된 데이터 테이블
분석 목적 실시간 검색 및 분석 대규모 데이터 처리 및 배치 분석
검색 속도 실시간 검색 최적화 대량 데이터를 기반으로 배치 분석
색인 방식 역색인 방식 사용 컬럼 기반 저장 및 분석 최적화
사용 사례 로그 분석, 텍스트 검색 BI(비즈니스 인텔리전스), 데이터 마이닝

언제 엘라스틱 서치를 선택해야 할까?

  • 실시간 검색과 즉각적인 데이터 분석이 중요한 경우
  • 정형화된 데이터보다 비정형 데이터(텍스트, 로그 등)를 다루는 경우
  • BI 툴보다는 빠른 응답 속도를 제공하는 검색 중심 환경을 원할 때

 

5. 엘라스틱 서치의 최적 활용 사례

1. 로그 및 시스템 모니터링

  • Kibana와 연계하여 시스템 로그를 시각화하고 분석 가능
  • 장애 감지 및 실시간 대응 시스템 구축 가능

2. 검색 엔진 구축

  • 전자상거래 사이트의 상품 검색
  • 뉴스 및 문서 검색 시스템
  • 사용자 맞춤형 검색 추천 시스템

3. 데이터 분석 및 BI

  • 실시간 데이터 스트림 분석
  • 사용자의 행동 패턴 분석

 

6. 결론: 언제 엘라스틱 서치를 선택해야 할까?

엘라스틱 서치는 데이터 저장이 목적이 아니라, 데이터 검색과 분석을 빠르게 수행하는 것이 핵심입니다. 따라서, 다음과 같은 경우 엘라스틱 서치가 강력한 도구가 될 수 있습니다.

빠르고 효율적인 검색이 필요한 경우 (예: 전자상거래, 로그 분석, 텍스트 검색) 대량의 데이터를 실시간으로 처리해야 하는 경우 데이터 웨어하우스보다는 검색 중심의 환경이 필요한 경우 MongoDB, RDBMS 등의 기본 검색 기능이 부족할 때 보완 용도로 활용

반면, 트랜잭션이 중요한 금융 시스템이나 구조화된 데이터를 안정적으로 저장해야 하는 경우에는 RDBMS나 데이터 웨어하우스가 더 적합할 수 있습니다.

결국, 엘라스틱 서치는 데이터베이스가 아니라 검색 엔진이라는 점을 명확히 이해하고, 필요에 따라 적절한 데이터 저장소를 선택하는 것이 중요합니다.

ECS(Amazon Elastic Container Service)

📌 AWS에서 제공하는 컨테이너 오케스트레이션 서비스입니다. Kubernetes 기반의 EKS와 비슷하게 컨테이너를 실행하고 관리할 수 있지만, ECS는 AWS에서 설계한 독점적 컨테이너 관리 서비스라는 점에서 차이가 있습니다.


ECS란?

  • Amazon ECS(Amazon Elastic Container Service)는 AWS에서 제공하는 고성능 컨테이너 관리 서비스로, Docker 컨테이너를 쉽게 실행, 관리, 확장할 수 있도록 설계되었습니다.
  • 쿠버네티스와 달리 AWS에 최적화된 방식으로 작동하며, AWS의 모든 서비스와 깊게 통합되어 있습니다.
  • EC2Fargate를 기반으로 컨테이너를 실행할 수 있습니다.

ECS의 주요 특징

  1. AWS 서비스와의 깊은 통합:
    • Elastic Load Balancer(ELB), CloudWatch, IAM, ECR(Container Registry) 등 AWS 서비스와 매끄럽게 통합됩니다.
  2. 유연한 실행 방식:
    • EC2 모드: 컨테이너를 EC2 인스턴스에서 실행. 사용자가 EC2 클러스터를 관리해야 함.
    • Fargate 모드: 서버리스 컴퓨팅 환경에서 컨테이너 실행. 인프라 관리 없이 실행 가능.
  3. 클러스터 관리:
    • ECS는 클러스터의 컨테이너를 자동으로 스케줄링하고 관리합니다.
    • 작업(Task) 단위로 컨테이너를 실행하며, 필요에 따라 서비스를 자동으로 확장합니다.
  4. Task Definition:
    • 컨테이너 구성(이미지, 포트, 네트워크 설정 등)을 정의하는 템플릿입니다.
    • 각 Task는 이 정의에 따라 실행됩니다.
  5. 자동 확장:
    • ECS는 필요에 따라 클러스터를 확장하거나 축소합니다.
    • Amazon Application Auto Scaling과 통합되어 트래픽 증가에 따라 자동으로 리소스를 조정.
  6. 보안:
    • AWS Identity and Access Management(IAM)과 통합되어 컨테이너 및 작업(Task)에 세분화된 액세스 권한을 설정할 수 있습니다.
  7. 비용 최적화:
    • Fargate 모드를 통해 사용한 만큼만 비용 지불.
    • EC2 예약 인스턴스와 스팟 인스턴스를 사용해 비용 절감 가능.

ECS의 구성 요소

  1. 클러스터 (Cluster):
    • ECS에서 컨테이너를 실행하는 리소스의 논리적 그룹.
    • EC2 인스턴스 또는 Fargate 작업으로 구성.
  2. 작업 정의 (Task Definition):
    • 컨테이너 애플리케이션의 사양을 정의하는 JSON 템플릿.
    • 컨테이너 이미지, 메모리, CPU, 네트워크, 로그 등을 지정.
  3. 작업 (Task):
    • 작업 정의(Task Definition)에 따라 실행된 컨테이너의 인스턴스.
  4. 서비스 (Service):
    • 컨테이너를 지속적으로 실행하고, 실패 시 자동 복구를 보장.
    • 원하는 수의 작업(Task)이 항상 실행되도록 유지.
  5. 컨테이너 인스턴스 (Container Instance):
    • ECS 클러스터의 EC2 인스턴스 또는 Fargate 인스턴스를 말함.
    • EC2 모드에서는 사용자가 직접 관리, Fargate에서는 AWS가 관리.
  6. 로드 밸런싱:
    • 컨테이너가 실행 중인 작업(Task)을 로드 밸런서(예: ALB, NLB)와 연결 가능.

ECS 사용의 이점

  1. AWS 통합:
    • ECS는 AWS 서비스와 긴밀하게 통합되어 설정 및 관리가 간단.
  2. 유연성:
    • EC2와 Fargate 중 적합한 실행 방식을 선택 가능.
    • EC2는 더 많은 제어권을 제공하며, Fargate는 서버리스로 간편한 관리 제공.
  3. 확장성:
    • AWS Auto Scaling과 통합되어 애플리케이션의 확장과 축소를 자동으로 처리.
  4. 보안:
    • IAM을 통해 컨테이너 단위의 세분화된 권한 관리 가능.
    • PrivateLink, Security Group 등을 사용해 네트워크를 보호.
  5. 비용 절감:
    • Fargate를 사용하면 사용한 만큼만 비용 지불.
    • EC2 예약 및 스팟 인스턴스를 통해 추가적인 비용 절감 가능.

ECS vs EKS

특징 ECS EKS
기술 기반 AWS 독점 서비스 Kubernetes 기반
학습 곡선 비교적 쉬움 비교적 복잡 (Kubernetes 학습 필요)
멀티 클라우드 지원 AWS 전용 멀티 클라우드(K8s) 지원
컨테이너 오케스트레이션 ECS 전용 방식 쿠버네티스 표준 방식
실행 방식 EC2, Fargate EC2, Fargate
커뮤니티 지원 제한적 (AWS 사용자 위주) Kubernetes 생태계와 글로벌 커뮤니티
사용 사례 AWS 생태계에서 간단한 컨테이너 관리 복잡한 클러스터 및 멀티 클라우드

ECS를 사용하는 이유

  • AWS에 최적화된 컨테이너 관리 서비스.
  • 쿠버네티스를 몰라도 컨테이너 기반 애플리케이션을 쉽게 배포 및 운영 가능.
  • AWS 서비스와의 통합으로 높은 안정성과 보안 제공.
  • EC2와 Fargate 중 요구사항에 따라 선택 가능.

ECS 시작하기

  1. 클러스터 생성:
    • AWS Management Console, CLI, SDK를 통해 생성.
  2. 작업 정의(Task Definition) 작성:
    • 컨테이너의 이미지, 리소스 요구 사항 등을 설정.
  3. 서비스 생성:
    • 클러스터 내에서 컨테이너 서비스를 실행.
  4. 로드 밸런서 연결:
    • ALB 또는 NLB와 연결하여 트래픽 분산.
  5. 모니터링:
    • CloudWatch를 통해 작업 상태 및 로깅 확인.

사용 사례

  1. 단순 컨테이너 워크로드:
    • 마이크로서비스 기반 애플리케이션을 손쉽게 관리.
  2. 백엔드 프로세싱:
    • 데이터 분석, ETL 작업과 같은 배치 작업 실행.
  3. 자동 확장이 필요한 애플리케이션:
    • 트래픽 변화에 따라 자동으로 확장되는 애플리케이션.
  4. AWS에 특화된 컨테이너 애플리케이션:
    • AWS 생태계에서 실행되며 쿠버네티스가 필요하지 않은 워크로드.

ECS는 AWS에서 컨테이너를 실행하고 관리하는 데 최적화된 서비스로, 간단한 설정과 AWS 통합으로 인해 많은 사용자가 선호합니다. EKS처럼 쿠버네티스의 학습 곡선이 필요하지 않으므로, 간단하고 빠른 컨테이너 관리를 원하는 경우 적합한 선택입니다! 😊

 

쿠버네티스(Kubernetes 줄여서 K8s)

 🐳 컨테이너화된 애플리케이션을 배포, 관리, 확장하는 오픈소스 플랫폼입니다. Google이 내부에서 사용하던 컨테이너 관리 시스템인 Borg를 기반으로 개발했으며, 현재는 **Cloud Native Computing Foundation(CNCF)**에서 관리하고 있습니다.

  • 컨테이너화된 애플리케이션의 배포와 관리를 자동화하고, 애플리케이션의 가용성 및 확장성을 보장하는 데 주로 사용됩니다.

[컨테이너화?]

더보기

컨테이너화(Containerization)

  • 컨테이너화는 애플리케이션과 해당 애플리케이션이 실행되기 위해 필요한 라이브러리, 종속성, 설정 파일 등을 모두 하나의 패키지(컨테이너)로 묶어서 실행하는 기술입니다. 이렇게 묶인 컨테이너는 어디에서 실행되더라도 동일하게 동작합니다.

컨테이너와 가상 머신(VM)의 차이

컨테이너화는 전통적인 가상 머신(VM)과는 다릅니다. 다음은 주요 차이점입니다:

  컨테이너(Container) 가상 머신(Virtual Machine)
운영 체제(OS) 호스트 OS를 공유 각 VM에 별도의 게스트 OS 포함
크기 경량 (몇 MB) 비교적 무겁고 크기가 큼 (몇 GB)
시작 속도 매우 빠름 (초 단위) 느림 (분 단위)
리소스 사용 호스트 OS 자원을 공유하여 효율적 OS마다 리소스가 중복되어 비효율적
이식성 "Write Once, Run Anywhere" 가능 호환성 문제가 있을 수 있음
격리 수준 프로세스 수준 격리 (OS 커널 공유) 강력한 OS 수준 격리

컨테이너의 핵심 개념

  1. 이미지(Image):
    • 컨테이너 실행에 필요한 애플리케이션과 종속성을 포함하는 불변(Immutable) 템플릿.
    • 예를 들어, Python 애플리케이션을 실행하기 위한 Python 런타임, 종속 패키지 등이 포함된 이미지.
  2. 컨테이너(Container):
    • 이미지를 실행한 인스턴스.
    • 가볍고, 격리된 환경에서 실행됨.
  3. Docker:
    • 가장 널리 사용되는 컨테이너화 플랫폼.
    • Docker는 컨테이너를 생성, 실행, 관리하기 위한 도구를 제공합니다.
  4. 레지스트리(Registry):
    • 컨테이너 이미지를 저장하고 배포하는 저장소.
    • 예: Docker Hub, AWS Elastic Container Registry(ECR), Google Container Registry(GCR).

컨테이너화의 주요 이점

  1. 이식성 (Portability):
    • 컨테이너는 개발 환경, 테스트 환경, 프로덕션 환경 등 어디서나 동일하게 동작.
    • 예: 로컬에서 실행된 애플리케이션이 클라우드에서도 동일하게 작동.
  2. 경량성 (Lightweight):
    • 컨테이너는 운영 체제를 포함하지 않으므로, VM보다 훨씬 가볍고 빠르게 실행 가능.
  3. 효율성 (Efficiency):
    • 리소스를 적게 사용하면서 여러 컨테이너를 실행 가능.
    • 호스트 OS의 커널을 공유하므로, 중복된 리소스 사용을 최소화.
  4. 빠른 배포 (Fast Deployment):
    • 컨테이너는 초 단위로 시작 및 중지 가능.
    • 지속적 통합/지속적 배포(CI/CD)에 최적.
  5. 확장성 (Scalability):
    • 필요에 따라 컨테이너 수를 동적으로 늘리거나 줄일 수 있음.
  6. 격리성 (Isolation):
    • 각 컨테이너는 독립적으로 실행되므로, 애플리케이션 간의 충돌이 발생하지 않음.

컨테이너화의 사용 사례

  1. 마이크로서비스 아키텍처:
    • 각 서비스가 독립된 컨테이너에서 실행.
    • 예: 사용자 관리 서비스, 결제 서비스, 알림 서비스 등을 각각 컨테이너화.
  2. CI/CD 파이프라인:
    • Jenkins, GitLab CI 등에서 컨테이너를 사용해 테스트 및 배포 자동화.
    • 테스트 환경을 컨테이너로 빠르게 생성 및 제거 가능.
  3. 이벤트 기반 워크로드:
    • 서버리스 아키텍처와 결합해 특정 이벤트 발생 시 컨테이너 실행.
  4. 데이터 분석 및 머신러닝:
    • 분석 및 머신러닝 작업을 위한 독립적이고 재현 가능한 환경 제공.
  5. 하이브리드 클라우드 및 멀티 클라우드:
    • 다양한 클라우드 환경(GCP, AWS, Azure)에서 동일한 컨테이너 이미지를 실행.

컨테이너화 도구

  1. Docker:
    • 가장 널리 사용되는 컨테이너화 플랫폼.
    • 컨테이너 이미지를 빌드, 배포, 실행하는 데 사용.
  2. Podman:
    • Docker와 유사하지만, 데몬(daemon)이 없고 루트 권한 없이 실행 가능.
  3. Kubernetes:
    • 컨테이너 오케스트레이션 도구.
    • 여러 컨테이너를 관리하고, 확장 및 복구를 자동화.
  4. OpenShift:
    • Kubernetes 기반의 엔터프라이즈급 컨테이너 플랫폼.
  5. CRI-O:
    • Kubernetes용 경량 컨테이너 런타임.

컨테이너화의 단점

  1. 복잡성 증가:
    • 컨테이너를 관리하기 위한 추가적인 도구와 지식 필요.
    • Kubernetes와 같은 오케스트레이션 도구를 사용하면 초기 학습 곡선이 가파름.
  2. 보안 문제:
    • 컨테이너가 호스트 OS 커널을 공유하므로, 잘못된 설정이나 취약점이 있는 경우 보안 위협 발생 가능.
  3. 디버깅 어려움:
    • 컨테이너는 격리된 환경에서 실행되므로 디버깅이 까다로울 수 있음.
  4. 상태 저장 애플리케이션의 복잡성:
    • 컨테이너는 상태를 저장하지 않으므로, 데이터베이스나 파일 시스템과 같은 상태 저장 애플리케이션을 컨테이너화할 때 추가적인 설정 필요.

컨테이너화의 일반적인 작업 흐름

  1. Dockerfile 작성:
    • 애플리케이션 빌드를 자동화하는 설정 파일 작성.
# Python 애플리케이션 예제
FROM python:3.9-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install -r requirements.txt
COPY . .
CMD ["python", "app.py"]
  1. 이미지 빌드:
  2. docker build -t my-app:latest .
  3. 컨테이너 실행:
  4. docker run -d -p 5000:5000 my-app:latest
  5. 컨테이너 배포:
    • 생성된 이미지를 컨테이너 레지스트리(Docker Hub, AWS ECR 등)에 푸시.
    docker push my-app:latest
    
  6. Kubernetes에 배포:
    • 쿠버네티스를 사용해 컨테이너를 클러스터에 배포.

요약

컨테이너화는 애플리케이션 개발과 배포를 혁신적으로 단순화하는 기술로, 오늘날의 클라우드 네이티브 환경에서 필수적인 도구입니다. Docker와 Kubernetes와 같은 도구를 통해 컨테이너를 쉽게 생성, 관리, 확장할 수 있으며, 이식성과 효율성 덕분에 마이크로서비스, CI/CD, 멀티 클라우드 등 다양한 환경에서 활용됩니다. 😊


쿠버네티스의 주요 역할

  1. 컨테이너 오케스트레이션:
    • 여러 대의 서버에서 컨테이너를 자동으로 배포하고 실행합니다.
    • 다양한 노드(서버)에 컨테이너를 효율적으로 분산 배치.
  2. 애플리케이션 확장:
    • 트래픽에 따라 컨테이너의 수를 동적으로 확장하거나 축소.
  3. 자동 복구(Self-healing):
    • 장애가 발생한 컨테이너를 감지하고 자동으로 재시작하거나 교체.
  4. 로드 밸런싱:
    • 애플리케이션에 대한 요청을 여러 컨테이너로 분산 처리.
  5. 서비스 디스커버리:
    • 컨테이너 간 통신을 위한 네트워크 디스커버리와 라우팅 제공.
  6. 스토리지 오케스트레이션:
    • 다양한 스토리지 솔루션(NFS, AWS EBS, GCP Persistent Disk 등)과 통합.

쿠버네티스의 주요 구성 요소

  1. 클러스터(Cluster):
    • 쿠버네티스는 클러스터 기반으로 작동하며, 클러스터는 여러 노드(서버)로 구성됩니다.
    • **마스터 노드(Control Plane)**와 **워커 노드(Worker Node)**로 나뉩니다.

A. 컨트롤 플레인 (Control Plane)

  • 클러스터의 상태를 관리하고, 작업을 스케줄링하며, 노드 간 통신을 조정합니다.

컨트롤 플레인 구성 요소:

  • API 서버 (kube-apiserver):
    • 쿠버네티스의 핵심 인터페이스로, 모든 명령과 작업이 이곳을 통해 처리됩니다.
  • 컨트롤러 매니저 (kube-controller-manager):
    • 클러스터 상태를 모니터링하고 필요한 작업(예: 장애 컨테이너 복구)을 수행.
  • 스케줄러 (kube-scheduler):
    • 새로 생성된 컨테이너(파드)를 실행할 노드를 결정.
  • ETCD:
    • 클러스터 상태 정보를 저장하는 분산 키-값 저장소.

B. 워커 노드 (Worker Node)

  • 실제로 컨테이너(파드)를 실행하는 물리적/가상 서버입니다.

워커 노드 구성 요소:

  • Kubelet:
    • 노드에서 실행되는 에이전트로, 컨테이너 실행 상태를 관리.
  • Kube-proxy:
    • 파드 간 네트워크 통신을 관리.
  • 컨테이너 런타임:
    • 컨테이너를 실행하는 데 사용되는 소프트웨어(Docker, containerd 등).

  1. 파드(Pod):
    • 쿠버네티스에서 컨테이너를 실행하는 최소 단위.
    • 하나의 파드 안에 여러 컨테이너가 있을 수 있으며, 이들은 동일한 네트워크와 스토리지를 공유.
  2. 디플로이먼트(Deployment):
    • 애플리케이션 배포 및 관리 템플릿.
    • 새로운 버전의 애플리케이션으로 업데이트하거나, 컨테이너를 수평적으로 확장할 때 사용.
  3. 서비스(Service):
    • 네트워크를 통해 파드에 접근할 수 있는 고정 IP와 로드 밸런싱을 제공합니다.
  4. 네임스페이스(Namespace):
    • 클러스터 내에서 리소스를 격리하여 여러 사용자가 동시에 사용할 수 있도록 지원.

쿠버네티스의 주요 기능

  1. 자동 확장 (Auto Scaling):
    • CPU, 메모리 등 리소스 사용량에 따라 컨테이너를 동적으로 확장/축소.
  2. 롤링 업데이트와 롤백:
    • 애플리케이션을 다운타임 없이 새로운 버전으로 업데이트.
    • 문제가 발생하면 롤백 가능.
  3. 셀프 힐링(Self-Healing):
    • 비정상적인 컨테이너를 감지하여 자동으로 재시작하거나 교체.
  4. 스토리지 관리:
    • 로컬 스토리지, 클라우드 스토리지, 네트워크 스토리지와 통합.
  5. 모니터링 및 로깅:
    • 클러스터 및 애플리케이션 상태를 모니터링할 수 있는 도구와 통합 가능(Prometheus, Grafana 등).

쿠버네티스의 장점

  1. 멀티 클라우드 지원:
    • AWS, GCP, Azure, 온프레미스 등 다양한 환경에서 실행 가능.
  2. 높은 가용성:
    • 자동 복구 및 로드 밸런싱을 통해 항상 안정적인 애플리케이션 실행 가능.
  3. 확장성:
    • 필요에 따라 컨테이너와 클러스터를 쉽게 확장.
  4. 커뮤니티 지원:
    • 대규모 오픈소스 커뮤니티와 광범위한 생태계.

쿠버네티스의 단점

  1. 복잡성:
    • 설치 및 운영이 비교적 어렵고, 학습 곡선이 가파름.
    • 클러스터 관리와 설정에 대한 깊은 이해 필요.
  2. 리소스 소비:
    • 클러스터 자체가 많은 리소스를 요구하므로, 소규모 프로젝트에는 적합하지 않을 수 있음.
  3. 운영 비용:
    • 직접 쿠버네티스를 관리하려면 높은 수준의 DevOps 전문성이 필요.

쿠버네티스 사용 사례

  1. 마이크로서비스 아키텍처:
    • 컨테이너화된 마이크로서비스를 배포 및 관리.
  2. CI/CD 파이프라인:
    • 지속적 통합 및 배포를 자동화.
  3. 멀티 클라우드 애플리케이션:
    • 다양한 클라우드 제공업체 간 클러스터를 통합 관리.
  4. AI/ML 작업:
    • 머신러닝 워크로드 관리와 확장.

쿠버네티스 시작하기

  1. 클러스터 생성:
    • 온프레미스(예: kubeadm, kind), 클라우드(EKS, GKE, AKS)에서 클러스터 생성.
  2. kubectl 설정:
    • 클러스터와 상호작용하기 위해 kubectl CLI 사용.
  3. 애플리케이션 배포:
    • Deployment, Service, Ingress 등을 설정하여 컨테이너 배포.
  4. 모니터링 및 관리:
    • Prometheus, Grafana 등을 사용해 클러스터 상태 모니터링.

쿠버네티스는 컨테이너화된 애플리케이션의 배포와 관리를 표준화한 도구로, 클라우드 네이티브 환경에서 필수적인 기술로 자리 잡았습니다. 이를 활용하면 대규모 애플리케이션을 효율적으로 관리하고 확장할 수 있습니다. 😊

 

쿠버네티스 VS 젠킨스

 

젠킨스(Jenkins)의 역할

JenkinsCI/CD(지속적 통합 및 지속적 배포) 파이프라인을 구축하고 자동화하는 도구입니다. 즉, 소스 코드 변경 사항을 빌드하고, 테스트하며, 애플리케이션을 배포하는 과정의 일부를 자동화합니다.

젠킨스의 주요 역할

  1. 지속적 통합(CI):
    • 소스 코드 변경 사항을 자동으로 빌드하고 테스트.
    • 코드 품질 보장을 위해 정적 분석 및 테스트 실행.
  2. 지속적 배포(CD):
    • 코드 변경 사항을 스테이징 또는 프로덕션 환경에 자동 배포.
    • 쿠버네티스 클러스터에 새 애플리케이션 버전 배포도 가능.
  3. 파이프라인 관리:
    • Jenkins 파이프라인을 사용해 빌드, 테스트, 배포 단계를 정의.
    • 다양한 플러그인을 통해 Docker 빌드, Helm 배포 등 작업 통합 가능.

쿠버네티스(Kubernetes)의 역할

쿠버네티스는 애플리케이션이 컨테이너화된 상태로 배포된 후, 이를 실행하고 관리하는 역할을 합니다. 즉, Jenkins와 같은 도구가 배포 작업을 완료한 이후의 운영 관리를 담당합니다.

쿠버네티스의 주요 역할

  1. 배포 관리:
    • 컨테이너화된 애플리케이션을 클러스터에 배포.
    • 롤링 업데이트를 통해 애플리케이션을 중단 없이 새 버전으로 교체.
  2. 확장성 제공:
    • 트래픽 증가에 따라 컨테이너 수를 자동으로 확장(스케일링).
    • 필요 시 리소스를 줄여 비용 최적화.
  3. 장애 복구:
    • 장애가 발생한 컨테이너를 자동으로 감지하고 교체(셀프 힐링).
  4. 로드 밸런싱:
    • 클러스터 내 여러 컨테이너에 요청을 분산 처리.
  5. 환경 격리:
    • 네임스페이스를 사용해 여러 환경(예: 개발, 테스트, 프로덕션)을 단일 클러스터에서 분리.

Jenkins와 Kubernetes의 차이점

  Jenkins Kubernetes
역할 CI/CD 자동화 컨테이너화된 애플리케이션 실행 및 관리
목적 빌드, 테스트, 배포 파이프라인 관리 애플리케이션 배포 및 확장, 운영 관리
관리 대상 소스 코드, 빌드 아티팩트, 배포 워크플로우 컨테이너, 네트워크, 리소스
초점 배포 전 작업(CI/CD) 배포 후 작업(운영 및 관리)
연관성 Kubernetes에 애플리케이션 배포 가능 Jenkins에서 생성된 컨테이너를 실행 및 관리

젠킨스와 쿠버네티스를 함께 사용하는 이유

  1. 젠킨스의 역할: 배포까지 자동화
    • Jenkins는 코드를 빌드하고, Docker 이미지를 생성하며, 이를 컨테이너 레지스트리(예: Docker Hub, AWS ECR)에 푸시합니다.
    • 그런 다음, Kubernetes 클러스터에 새 버전의 애플리케이션을 배포하도록 트리거합니다.
  2. 쿠버네티스의 역할: 운영 관리
    • 쿠버네티스는 Jenkins가 배포한 애플리케이션을 클러스터 내에서 실행, 확장, 복구, 모니터링합니다.

젠킨스와 쿠버네티스를 통합한 CI/CD 파이프라인 예시

  1. 코드 푸시:
    • 개발자가 코드를 GitHub, GitLab 등 소스 코드 저장소에 푸시.
  2. 빌드 및 테스트 (Jenkins):
    • Jenkins가 코드를 감지하고 빌드, 테스트 실행.
    • Docker 이미지를 생성하여 컨테이너 레지스트리에 푸시.
  3. 배포 (Jenkins):
    • Jenkins가 Helm 또는 kubectl 명령을 사용해 쿠버네티스에 애플리케이션 배포.
    • 새로운 버전으로 애플리케이션을 업데이트.
  4. 운영 및 확장 (Kubernetes):
    • 쿠버네티스가 애플리케이션 상태를 모니터링하고, 장애가 발생한 컨테이너를 복구.
    • 사용량 증가에 따라 컨테이너를 자동으로 확장.

예시: Jenkins 파이프라인

pipeline {
    agent any

    stages {
        stage('Clone') {
            steps {
                git 'https://github.com/example/repo.git'
            }
        }

        stage('Build') {
            steps {
                sh 'docker build -t my-app:${BUILD_NUMBER} .'
            }
        }

        stage('Push') {
            steps {
                sh 'docker push my-app:${BUILD_NUMBER}'
            }
        }

        stage('Deploy') {
            steps {
                sh 'kubectl apply -f deployment.yaml'
            }
        }
    }
}

쿠버네티스와 Jenkins를 함께 사용할 때의 장점

  1. 자동화:
    • Jenkins는 CI/CD를 자동화하고, Kubernetes는 운영 관리를 자동화합니다.
  2. 확장성:
    • Kubernetes는 컨테이너를 스케일링하고, Jenkins는 테스트와 빌드를 병렬로 실행할 수 있습니다.
  3. 효율성:
    • Jenkins는 코드 변경 사항을 빠르게 배포하고, Kubernetes는 배포된 애플리케이션을 안정적으로 실행합니다.

쿠버네티스 단독 사용과 비교

쿠버네티스는 CI/CD를 처리하지 않으므로 Jenkins나 GitLab CI/CD 같은 별도의 도구가 필요합니다. 두 도구를 통합하면 코드 변경부터 배포, 운영 관리까지 엔드 투 엔드 자동화가 가능해집니다.


결론적으로 Jenkins는 CI/CD를 담당하고, Kubernetes는 배포 후 애플리케이션의 실행과 관리를 담당합니다. 이 둘을 통합하면 현대적이고 강력한 클라우드 네이티브 배포 파이프라인을 구축할 수 있습니다. 😊

 

 

+ Recent posts