새소식

Observability

[Observability]기반기술 이해하기

  • -

복원성

복원성 구현의 두 가지 접근 방법

복원성이란 시스템이 장애를 겪었을 때, 원래 상태로 복귀할 수 있는 능력을 의미합니다. 이를 구현하는 방법은 크게 애플리케이션 관점과 인프라 관점으로 나눌 수 있습니다.

1. 애플리케이션 관점에서의 복원성 구현

애플리케이션 내부에서 예외 처리, 재시도, 타임아웃 등을 구현하여 복원력을 강화하는 방법입니다.

  • 에러 분류: 비즈니스 로직에서 발생할 수 있는 에러와 시스템 에러를 구분하여, 각 에러 유형에 맞는 적절한 처리 방법을 적용합니다.
  • 재시도 정책: 일정 간격을 두고 오류 발생 시 재시도를 진행합니다. 이는 일시적인 문제로 인한 요청 실패에 효과적으로 대응할 수 있게 합니다.

2. 인프라 관점에서의 복원성 구현

서비스 메시와 메시징 시스템을 활용하여 인프라 수준에서 복원력을 높이는 방법입니다.

  • 서비스 메시: 각 서비스 간의 통신을 중재하고 관리하는 인프라 레이어입니다. 트래픽 관리, 서비스 간 보안, 모니터링 등 다양한 기능을 제공하여 시스템의 복원력을 강화합니다.
  • 메시징 시스템: 메시지 유실 없이 대용량의 트랜잭션을 안정적으로 처리할 수 있는 백본 역할을 합니다. 분산 시스템에서의 비동기 메시지 전달을 통해 시스템 부하를 분산시키고, 복원력을 향상시킵니다.

복원력을 높이는 네 가지 패턴

1. 재시도(Retry)

  • 목적: 가끔 발생하는 일시적인 장애에 대응합니다.
  • 주의사항: 재시도 정책은 신중하게 설계되어야 합니다. 무분별한 재시도는 시스템에 부담을 주고, 중복 처리의 위험을 초래할 수 있습니다.

2. 비율 제한(Rate Limiting)

  • 목적: 비정상적인 상황에서도 서비스가 지속될 수 있도록 처리량을 제한합니다.
  • 활용: 인그레스, 게이트웨이 등의 로드 밸런싱을 통해 다양한 수준에서 비율 제한을 구현할 수 있습니다.

3. 벌크헤드(Bulkhead)

  • 목적: 하나의 서비스 장애가 전체 시스템에 영향을 미치지 않도록 격리합니다.
  • 상황 예시: 특정 서비스에 문제가 발생했을 때, 해당 서비스의 요청만을 제한하여 시스템의 나머지 부분이 정상적으로 기능할 수 있게 합니다.

4. 서킷 브레이커(Circuit Breaker)

  • 목적: 연속된 실패로 인한 장애가 발생할 경우, 자동으로 트래픽을 차단하여 시스템을 보호합니다.
  • 폴백 메커니즘: 서비스가 정상적으로 응답할 수 없을 때, 사전에 정의된 대체 로직을 실행하여 서비스의 가용성을 유지합니다.
  • 예시: [서비스1] → [서킷 브레이커] → [서비스2]
    • 서비스 2가 정상적으로 응답할 수 없을 때, 서비스 2에서 정해진 규칙에 따라 로직을 반환할 수 있습니다.

오토스케일링

메트릭 선택의 중요성

쿠버네티스 환경에서 애플리케이션의 성능을 모니터링하고 관리하는 것은 중요합니다. 올바른 메트릭을 선택하는 것이 시스템의 건강 상태를 파악하고 필요한 조치를 취하는 데 필수적입니다.

파드 관련 메트릭 선택 시 주의사항

  • 파드 수와의 직접적인 관련성: 선택하는 메트릭은 파드의 수와 직접적인 관계가 있어야 합니다. 예를 들어, 서비스가 일정량의 메모리를 사용하는 경우, 클러스터링이나 분산 메커니즘이 없다면 파드의 수를 늘려도 메모리 사용량은 줄어들지 않습니다. 이러한 관계를 이해하는 것이 중요합니다.

스래싱 방지

스래싱이란 파드가 초기화되는 동안 또는 Scale in/out 과정에서 과도한 CPU 사용으로 인한 성능 저하를 말합니다.

이를 방지하기 위해 아래와 같은 설정을 할 수 있습니다.

  • 파드 초기화 제한: 파드가 초기화될 때 CPU 사용량을 제한하여 부하가 점진적으로 증가할 수 있도록 합니다.
  • Scale in 조정: Scale in 과정에서 컨트롤러는 설정 가능한 시간 동안의 모든 스케일 권장사항을 파악하고, 그 중 가장 높은 권장사항을 선택함으로써 사용량 감소를 방지합니다.

쿠버네티스 훅 핸들러 활용

갑작스러운 Scale in 과정에서 데이터 유실의 가능성이 있습니다. 이를 방지하기 위해 쿠버네티스의 훅 핸들러를 활용할 수 있습니다.

  • 라이프사이클 훅 사용: 파드가 스케일 인으로 인해 삭제되기 전에, 라이프사이클 훅을 사용하여 데이터를 플러시하고 필요한 블록을 생성합니다. 이는 데이터 유실을 방지하며, 모든 작업이 안전하게 완료될 수 있도록 합니다.

관측가능성과 마이크로서비스

오토스케일링과 서비스 디스커버리

  • 오토스케일링: 리소스 사용량에 따라 자동으로 스케일을 조정하여 안정적으로 트래픽을 처리합니다. 이를 통해 예기치 않은 트래픽 증가에도 서비스가 안정적으로 운영됩니다.
  • 서비스 디스커버리: 마이크로서비스 아키텍처에서 서비스 간의 연결 및 통신은 서비스 디스커버리를 통해 이루어집니다. 서비스 디스커버리를 통해 각 서비스의 위치와 상태를 파악하고, 지속적으로 모니터링합니다.

대용량 처리를 위한 CQRS 패턴

  • CQRS(Command Query Responsibility Segregation) 패턴: 읽기와 쓰기 작업을 분리하여 시스템의 성능과 확장성을 향상시킵니다. 대용량 트래픽을 효과적으로 처리하기 위한 핵심 패턴 중 하나입니다.

CQRS(명령 쿼리 책임 분리) 패턴은 데이터 변형 또는 시스템의 명령 부분을 쿼리 부분과 분리합니다. https://docs.aws.amazon.com/ko_kr/prescriptive-guidance/latest/modernization-data-persistence/cqrs-pattern.html

일관된 해싱과 샤딩

일관된 해싱

  • 목적: 노드나 데이터의 변화가 있을 때 전체 시스템에 미치는 영향을 최소화하며 안정적으로 유지합니다.
  • 응용: 서버의 부하를 균등하게 분산시키고, 노드 변경 시 최소한의 데이터만 재분배합니다.

샤딩

  • 샤딩: 데이터를 여러 서버에 분산시켜 병렬 처리를 가능하게 하는 기술입니다. 이를 통해 처리량과 성능을 크게 향상시킬 수 있습니다.
  • 메모리상에서의 구현: 그라파나와 같은 시스템에서 샤딩은 특정 스토리지 유형에 종속되지 않고 메모리상에서 구현됩니다. 이는 유연성과 확장성을 제공합니다.

키-값 저장소

설계 고려사항

  • 크기 제한: 대부분의 키-값 저장소는 데이터 항목 크기를 10KB 이하로 제한합니다. 큰 데이터를 저장하기 위해서는 적절한 분할 전략이 필요합니다.
  • 고가용성과 빠른 응답: 시스템 장애가 발생해도 높은 가용성을 유지하고, 낮은 응답 지연시간으로 빠른 서비스를 제공해야 합니다.
  • 확장성: 시스템이 성장함에 따라 높은 규모로 확장할 수 있어야 합니다.

좋은 아키텍처를 위한 고민

읽기와 쓰기, 메모리 사용량 사이의 균형을 찾아야 합니다. 또한, CAP 이론에 따라 데이터의 일관성(Consistency), 가용성(Availability), 분할 내성(Partition Tolerance)사이에서 적절한 균형을 맞춰 아키텍처를 구성합니다. 이 균형을 찾는 과정은 서비스의 특성과 요구사항을 고려하여 결정되어야 합니다.

이러한 고려사항들은 마이크로서비스 아키텍처의 성공적인 구현과 운영을 위해 필수적입니다. 관측 가능성을 통해 시스템의 상태를 지속적으로 모니터링하고, 필요한 조정을 신속하게 수행할 수 있어야 합니다.

CAP의 의미:

  • Consistency: 분산 시스템에 접속하는 모든 클라이언트는 어떤 노드에 접속했느냐에 관계 없이 언제나 같은 데이터를 보게 되어야한다.
  • Availability: 분산 시스템에 접속하는 클라이언트는 일부 노드에 장애가 발생하더라도 항상 응답을 받을 수 있어야 한다.
  • Partition Tolerance: 두 노드 사이에 통신 장애가 발생하더라도 시스템은 계속 동작해야 한다.

객체 스토리지의 활용

객체 스토리지는 확장성이 뛰어난 분산 스토리지 시스템에서 데이터를 저장하는 데 사용됩니다. 특히 소량의 데이터 처리에는 비효율적일 수 있으므로, 데이터를 블록 형태로 저장하여 통신 오버헤드를 최소화하는 전략이 필요합니다.

AWS S3의 파티셔닝 전략

AWS S3와 같은 서비스는 파티셔닝을 통해 애플리케이션에서의 병렬 처리를 촉진하여 성능을 향상시킵니다. 데이터를 일/시간별로 파티셔닝하여 관리함으로써, 데이터 검색 및 처리 효율을 높일 수 있습니다.

시계열 데이터 처리

시계열 데이터는 객체 스토리지에 수시로 기록될 때 작은 파일들이 대량으로 생성되어 성능 저하의 요인이 될 수 있습니다. 이를 위해 작은 데이터를 적당히 모아 큰 파일로 만들고, 큰 데이터는 분할하여 처리함으로써 네트워크 전송 시간과 예상치 못한 오류 발생률을 줄이는 전략이 필요합니다.

안정적 데이터 관리 기술

데이터 파티션과 다중화

  • 데이터 파티션: 안정 해시를 사용하여 데이터를 균등하게 분산시킵니다.
  • 데이터 다중화: 데이터를 여러 서버에 비동기적으로 복제하여 시스템의 장애 내성을 높입니다.

데이터 일관성과 장애 감지

  • 데이터 일관성: 정족수 합의(Qorum) 프로토콜을 사용하여 데이터의 일관성을 보장합니다.
  • 장애 감지: 가십 프로토콜을 통해 시스템 내부적으로 문제점을 진단하고, 자동화된 복구 기술을 사용하여 일시적 장애를 처리합니다.

프로메테우스

프로메테우스 시계열 데이터베이스 (TSDB)

시계열 데이터를 효율적으로 관리하기 위해 주기적인 압축과 다운 샘플링을 적용하는 것이 좋습니다. 그라파나와 같은 도구는 객체 스토리지에서 사용 가능한 블록을 압축하고, 다운 샘플링된 시계열 데이터를 생성하는 기능을 제공합니다.

데이터 형식

프로메테우스는 메트릭 이름, 레이블, 타임스탬프의 조합을 키-값 형식으로 사용합니다. 이러한 구조는 시계열 데이터의 효율적인 조회와 관리를 가능하게 합니다.

데이터 처리 과정

시계열 데이터를 효과적으로 처리하기 위해 다음과 같은 절차를 따릅니다.

  1. 파티셔닝과 인덱싱: 파일을 시간대 별로 나누어 관리합니다.
  2. 파일 병합: 작은 파일들을 하나의 큰 파일로 병합하여 오버헤드를 줄입니다.
  3. 압축: 압축 알고리즘을 적용하여 파일 크기를 줄이고 네트워크 성능을 고려합니다.
  4. 샘플링: 파일의 해상도를 조정하여 데이터 관리의 효율성을 높입니다.
  5. 청크 생성: 큰 파일을 일정한 크기로 나누어 네트워크 성능을 고려합니다.
  6. 균등 분배: 데이터를 노드에 균등하게 분배하여 시스템의 부하를 최소화합니다.

프로메테우스 로컬에 저장되는 데이터의 이해

.
├── 01HSKAVBDB5GFAVKAMGZV2KJ2M                # 블록 디렉토리: 특정 시간 범위의 시계열 데이터가 저장된 블록
│   ├── chunks                                # 청크 파일이 저장되는 디렉토리: 시계열 데이터 샘플들이 저장됨
│   │   ├── 000001                            # 청크 파일: 데이터 샘플들의 실제 저장소
│   │   ├── 000002                            # 청크 파일
│   │   └── ...                               # 추가 청크 파일들
│   ├── index                                 # 인덱스 파일: 시계열 데이터의 위치와 메타데이터를 빠르게 조회할 수 있게 함
│   ├── meta.json                             # 메타데이터 파일: 블록에 대한 정보(시작 시간, 종료 시간 등)를 JSON 형식으로 저장
│   └── tombstones                            # 톰스톤 파일: 삭제될 데이터의 마커 저장
├── ...                                       # 추가 블록 디렉토리들
├── chunks_head                              # 현재 메모리에 있는 청크들의 디스크에 저장되지 않은 상태
│   ├── 000992                                # 청크 헤드 파일: 아직 블록으로 플러시되지 않은 최신 데이터
│   └── ...                                   # 추가 청크 헤드 파일들
├── lock                                      # 락 파일: 동시에 여러 인스턴스가 데이터 디렉토리에 접근하는 것을 방지
├── queries.active                            # 활성 쿼리 파일: 현재 실행 중인 쿼리 추적
└── wal                                       # WAL 디렉토리: Write-Ahead Logging, 데이터가 블록으로 플러시되기 전에 기록
    ├── 00003579                              # WAL 파일: 메모리에 있는 데이터를 먼저 기록하여 장애 발생 시 복구 가능
    ├── ...                                   # 추가 WAL 파일들
    └── checkpoint.00003578                   # 체크포인트 디렉토리: WAL의 특정 시점을 나타내며 복구 시점과 데이터 무결성 보장
        └── 00000000                          # 체크포인트 내의 파일: 체크포인트의 일부로, 복구에 필요한 데이터 포함

카디널리티

카디널리티는 메트릭 이름과 연관된 레이블의 이름/값 조합의 수를 나타냅니다. 레이블이 많아질수록 가능한 조합이 증가하며, 이는 고유 시계열 수의 증가로 이어집니다. 높은 카디널리티는 시스템 성능에 영향을 줄 수 있습니다.

데이터 관리

  • LRU 알고리즘: 가장 오랫동안 참조하지 않은 페이지(데이터)를 교체합니다.
  • 메모리 페이징: 프로세스를 페이지로 분할하여 메모리에 적재합니다. 이는 관리의 효율성을 높입니다.
  • 샘플과 블록: 샘플(데이터 포인트)은 '청크'라고 불리는 단위로 수집되고, 여러 청크가 '블록'을 형성하여 디스크에 저장됩니다. 블록에는 인덱스와 데이터 위치 정보가 포함됩니다.

WAL (Write Ahead Logging)

WAL은 아직 청크로 플러시되지 않은 데이터를 최상위 레벨에서 관리합니다. 이는 장애 발생 시 데이터 복구를 위해 사용됩니다.

블록 관리

샘플: 시계열 데이터

시계열 데이터의 수치는 샘플로 수집됩니다. 샘플은 float64 값과 타임스탬프로 구성됩니다.

블록 생성 및 병합

  • 프로메테우스는 메모리에 수집된 샘플을 기본적으로 2시간 단위로 플러시하고 블록을 생성합니다.
  • 불필요한 파일 수를 줄이고 파일 크기를 적절하게 유지하기 위해, 블록 병합을 사용합니다.
    • 크기가 작은 파일 → 많은 인덱스 생성한다 → 블록을 병합한다.
    • 크기가 큰 파일 → 검색 효율성이 떨어진다. (파일 크기가 1GB, 필요한 데이터의 크기가 1KB 일때, 1GB 파일을 메모리에 로딩해야한다.) → 일정한 크기로 나눠 청크를 생성한다 → 블록을 병합한다.

[블록의 병합]

데이터 흐름: 메모리 → WAL(로그 선행 기입) → 디스크

[수집된 샘플이 디스크로 저장되기까지의 과정]

  • 새로 수집된 샘플은 헤드 청크에 기록되며 LRU 알고리즘에 의해 메모리에서 디스크로 이동합니다.
  • 메모리 청크와 디스크 청크는 1:1 대응됩니다.
  • PromQL의 쿼리가 현재 메모리에 없는 청크를 필요로하면 디스크 청크를 메모리에 로드 합니다.
  • 디스크 시리즈 파일에 존재하지 않으며 메모리에만 존재하는 청크는 장애발생으로 손실될 수 있습니다. 이를 위해 프로메테우스는 주기적으로 체크포인트 파일로 기록하고 재시작 시 메모리에 로드한다.

프로메테우스 오퍼레이터

프로메테우스 오퍼레이터는 프로메테우스 서버 설정 변경과 메트릭 수집을 자동화합니다. 이를 통해, 쿠버네티스 환경에서의 모니터링을 효율적으로 관리할 수 있습니다.

서비스 모니터

서비스 모니터는 쿠버네티스에서 프로메테우스가 Pod(Application)을 모니터링하는 방법을 선언적(CRD 사용)으로 설정합니다.

기본적으로 메타데이터와 레이블을 내장하고 있습니다.

relabel_configsmetric_relabel_configs를 통해 메트릭 레이블을 변경하거나 제거할 수 있습니다.

  • relabel_configs: 스크래핑 작업의 타깃 목록을 제어하고, 레이블을 재지정합니다.
  • metric_relabel_configs: 수집된 메트릭을 저장하기 전에 변환하거나 삭제합니다.
Contents

포스팅 주소를 복사했습니다

이 글이 도움이 되었다면 공감 부탁드립니다.