본 포스팅은 2024년 04월 24일, Elasticsearch 8.13 버전 기준으로 작성되었습니다.
TSDS(Time Series Data Stream)는 Timestamp가 지정되어 있는 Metric 데이터를 하나 혹은 그 이상의 시계열(time series)데이터로 모델링하는 방식의 Data stream입니다.
기본 Data stream과 TSDS 모두 Timestamp가 지정된 Metric 데이터를 저장할 수 있으나, TSDS의 경우 거의 실시간에 가까운 Timestamp 순서로 Metric 데이터를 저장하는 경우에만 사용하는 것을 권장합니다.
TSDS는 사실상 메트릭 데이터 전용이라고 할 수 있습니다. 로그나 추적과 같이 timestamp가 지정된 다른 데이터의 경우, data stream을 사용해야 합니다.
TSDS를 이해하기 위해서는 아래의 세가지 개념을 확실하게 잡고 가야 할 필요가 있습니다.
Time-series
Dimentions
Metric data
시계열(Time Series) 데이터란 시간의 흐름에 따라 순차적으로 수집된 데이터를 말합니다. 그 관측값들을 종합하면 시간의 흐름에 따른 개체의 변화를 추적할 수 있습니다.
TSDS에서 각 document는 특정 Time series에서의 데이터 포인트(관측 데이터)를 의미합니다. TSDS에는 여러 Time series값들이 있지만, 1개의 document는 1개의 Time series에만 속할 수 있습니다.
이러한 실시간 주가 변동도 하나의 time series입니다.
Dimension은 필드의 이름과 값을 조합하여 document의 time series를 식별하는 것입니다.
여러 대의 서버를 모니터링하고 있다고 가정합니다. 각 서버에는 CPU 사용률, 메모리 사용량, 디스크 사용량 등의 다양한 메트릭이 있습니다. 이때 호스트명(host), 서버 유형(type=web, db 등), 데이터 센터 위치(dc=seoul, tokyo 등) 등을 key-value 쌍으로 각각을 하나의 차원으로 지정하면 각 데이터 포인트가 어떤 서버, 서버 유형, 데이터 센터에서 수집되었는지 구분할 수 있습니다.
메트릭 이름이 "cpu_usage"라고 가정해봅시다. 그렇다면 전체 데이터 포인트는 아래와 같은 형태가 될 것입니다
cpu_usage{host=web01, type=web, dc=seoul} 80
cpu_usage{host=db02, type=db, dc=tokyo} 60
이렇게 차원을 통해 동일한 메트릭 이름 아래에서도 데이터를 세분화하여 저장하고 필터링, 집계할 수 있습니다. 이와 같이 데이터를 세분화 및 구분해주는 호스트명, 서버 유형, 데이터센터 위치 등의 필드를 “dimention field”라고 합니다. TSDS는 최소 1개 이상의 dimention field를 포함해야 합니다.
Dimension은 Mapping 단계에서 Boolean 파라미터인 time_series_dimension을 사용하여 지정합니다. 다음 타입들이 time_series_dimension 파라미터를 지원합니다.
keyword
ip
byte
short
integer
long
unsigned_long
Metric은 시스템의 성능과 상태에 대한 통계적인 정보를 의미하며, CPU 사용률, 메모리 사용량, 응답 시간 등이 있습니다. 이러한 Metric 데이터는 시간에 따라 측정되는 숫자 값(시계열 데이터)입니다.
필수는 아니지만, 대체로 TSDS의 document에는 하나 이상의 Metric 필드가 존재합니다. 일반적으로 Dimension은 일정하게 유지되지만 Metric은 드물거나 느리게라도 시간이 지남에 따라서 변경될 것으로 예상된다는 점에서 Dimension과 차이가 있습니다.
Metric 필드를 사용하기 위해서는 mapping에서 time_series_metric 파라미터가 설정되어 있어야 합니다. 다음과 같은 field data 타입의 유형들이 time_series_metric 파라미터를 지원합니다.
aggregate_metric_double
histogram
모든 숫자 필드 타입
time_series_metric 파라미터의 설정값은 다음과 같습니다.
counter: 계속해서 증가만 하거나 0으로 리셋되는 값들. 비율 집계에 주로 사용
gauge: 임의로 증가하거나 감소하는 값들. 숫자 필드 타입
TSDS는 기본적으로는 Data Stream과 동일한 역할을 하지만 다음과 같은 차이점들이 있습니다.
index.mode: time_series 옵션이 설정되어 있습니다. 해당 옵션은 TSDS의 대부분의 기능을 활성화합니다.
각 document에는 1개 이상의 dimention필드가 포함되어 있어야 하며, index template에도 최소 1개의 keyword타입 dimention이 있도록 mapping 설정이 되어 있어야 합니다.
각 Document에는 숨겨진 _tsid 메타데이터 필드가 생성됩니다.
time-bound backing indices를 사용해 같은 시간대의 데이터를 동일한 인덱스에 저장합니다.
최소 1개 이상의 dimention이 포함된 index.routing_path 설정이 되어있어야 합니다.
_tsid와 @timestamp를 기준으로 한 내부 인덱스 정렬로 샤드 세그먼트의 순서를 지정합니다.
Disk 사용량을 줄이기 위해 synthetic _source를 사용하므로 일부 기능이 비활성화됩니다.
이제 Data stream과 구분되는 TSDS만의 몇 가지 특징들을 세부적으로 알아보겠습니다.
TSDS의 인덱스 템플릿에는 index.mode: time_series 옵션이 있는 data_stream 오브젝트가 포함되어야 합니다.
해당 옵션은 Backing 인덱스들의 TSDS 관련 기능을 활성화 합니다.
기존의 Data Stream을 TSDS로 변환하는 경우, 변환 후에 생성되는 인덱스만 index.mode: time_series 옵션을 가지고, 기존 Backing 인덱스는 해당되지 않습니다.
TSDS에 document를 추가하면, Elasticsearch는 자동으로 _tsid metadata field를 생성합니다.
_tsid 필드는 document의 dimension을 포함하고 있습니다. 동일한 _tsid 필드를 가진 동일한 TSDS의 document는 동일한 time series의 일부입니다.
TDSD의 각 backing index는 @timestamp 범위를 가지고 있으며, 이 범위는 index.time_series.start_time 및 index.time_series.end_time 인덱스 설정에 의해 정의됩니다.
TSDS에 document를 추가하면 위 설정의 @timestamp 범위에 따라 적절한 backing index에 document가 추가됩니다.
(원래의 data stream에서는 가장 최근 backing index에 document가 추가되는게 일반적이지만, 이 경우에는 가장 최근 인덱스가 아니여도 됩니다.)
TSDS의 시간의 범위는 기본적으로 다음과 같이 설정됩니다.
index.time_series.start_time : now - index.look_ahead_time
index.time_series.end_time : now + index.look_ahead_time
만약 @timestamp 범위에 해당되는 Backup 인덱스가 없는 경우, document는 더 이상 추가되지 않습니다.
TSDS의 index template를 만들 때 index.routing_path 설정에서 최소 1개 이상의 dimention을 지정해줘야 합니다.
즉, TSDS의 각 document는 index.routing_path 설정에 있는 dimention을 1개 이상 포함하게 됩니다.
또한, 1개 이상의 dimention필드는 keyword타입이어야 합니다. (index.routing_path 설정은 와일드카드 패턴을 지원하기에 keyword타입인 필드와 동적으로 일치시킬 수 있습니다. 하지만, scripted, runtime, non-dimension, non-keyword 인 필드들은 Reject 됩니다.)
TSDS의 document, mapping은 커스텀 _routing 값을 지원하지 않습니다.
Elasticsearch는 압축 알고리즘을 사용해 반복되는 값을 압축합니다. 압축 알고리즘은 반복되는 값이 동일한 인덱스, 동일한 샤드, 동일한 샤드 세그먼트에 나란히 저장되어 있을 때 가장 효율적으로 작동합니다.
대부분의 Time Series 데이터는 반복되는 값을 가지고 있습니다. Dimension은 동일한 Time Series의 document에서 반복됩니다. Metric 값은 시간에 따라서 변화할 수 있습니다.
내부적으로 각 TSDS Backing 인덱스는 인덱스 정렬을 사용해 _tsid와 @timestamp를 기준으로 샤드 세그먼트의 순서를 지정합니다. 이렇게 하면 더 효율적인 압축을 위해 반복되는 값이 가까이 저장될 수 있게 됩니다.
효율적인 인덱스 정렬 후 압축을 위해서 TSDS는 index.sort.* 설정을 지원하지 않습니다.
이제 Elasticsearch에서 TSDS를 생성해보겠습니다.
TSDS 설정은 다음과 같은 단계로 이루어집니다.
권한 설정
ILM(Index Life Policy) 생성
Component Template 생성 (mapping, index setting 설정)
Index Template 생성
TSDS 생성
TSDS 보안
다음과 같은 권한이 필요합니다.
Cluster privileges: manage_ilm, manage_index_templates
Index privileges: create_doc, create_index(rollover를 위해서는 manage도 필요)
선택사항이지만, ILM을 활용하여 TSDS의 backing index를 관리하는 것을 권장합니다. ILM의 Roll-over 액션에 대한 max_age를 설정하는 것이 좋습니다. 그렇게 하면 TSDS의 backing index의 @timestamp 범위가 일관되게 유지됩니다.
예를 들어, max_age를 1d로 설정하면 Backing Index에 하루 분량의 데이터가 일관적으로 보관됩니다.
TSDS는 인덱스 템플릿이 필요합니다.
일반적으로 mapping과 index setting을 각각의 component template로 생성합니다. 그렇게 하면, 한번 생성한 component template를 다른 별개의 index template를 만들 때에 재사용이 가능합니다.
<TSDS에 필요한 mapping 설정>
1개 이상의 dimention 필드
“time_series_dimension”: true
1개 이상의 dimention필드는 keyword 타입
1개 이상의 metric 필드 설정
time_series_metric parameter 설정
@timestamp 필드를 data나 date_nanos 타입으로 매핑
(미설정시 date 기본 옵션으로 설정)
<TSDS에 필요한 index setting 설정>
생성한 ILM을 index.lifecycle.name으로 설정
그 외 TSDS의 Backing Index에 대한 기본적인 인덱스 세팅
위에서 생성한 component template들로 index template를 설정합니다.
<필요한 설정>
1개 이상의 TSDS의 이름과 매칭되는 Index Pattern
Data stream 활성화
“index.mode”:”time_series” 설정
“index.routing.path” 세팅 (선택사항)
세팅값은 keyword타입의 dimention필드와만 일치해야 합니다. 해당 사항이 정의되지 않은 경우 “time_series_dimension”:true로 설정된 모든 매핑을 사용하여 생성됩니다.
생성한 component template 적용
priority 설정을 200이상을 부여하여 built-in template들과의 충돌 방지
이제 index template에서 설정한 index patterns에 매칭되는 TSDS 인덱스에 document를 추가합니다.
<TSDS document에 포함되어야 하는 것>
@timestamp 필드
하나 이상의 dimension 필드
최소한 1개 이상의 dimension은 index.routing_path 설정에 맞는 keyword 필드여야 합니다.
index.routing_path를 설정하지 않았다면 time_series_dimension이 true로 설정된 필드들이 자동으로 설정됩니다.
create data stream API를 통해서도 TSDS를 생성할 수 있습니다.
두 가지 방법 모두 TSDS의 이름이 인덱스 템플릿에서 설정한 인덱스 패턴에 일치해야 합니다.
인덱스 Privileges를 사용해 TSDS의 권한을 관리할 수 있습니다. TSDS에 권한을 부여하면 Backing 인덱스들에도 동일한 권한이 부여됩니다.
Data stream privileges를 참고해 Data Stream과 동일한 방법으로 설정할 수 있습니다.
위의 방법들을 따라 이미 존재하는 일반 Data Stream을 TSDS로 변환할 수 있습니다.
새로운 Index Lifecycle Policy, 컴포넌트 템플릿, 인덱스 템플릿을 생성하는 대신 현재 Data Stream에서 사용중인 내용을 수정
TSDS 생성 단계 대신 Data Stream을 수동으로 Rollover.
Rollover시 현재 Write 인덱스와 앞으로 생성될 모든 Backing 인덱스들의 index.mode가 time_series로 설정됨.