1. 로컬 저장소 (디스크 레이아웃)

Prometheus의 로컬 데이터베이스는 시계열 데이터를 디스크에 사용자 지정 형식으로 저장합니다.

수집 된 샘플은 2시간 단위로 그룹화 됩니다. 각 그룹은 해당 기간에 대한 모든 시계열 샘플을 포함하는 하나 이상의 chunk 파일과 메타 데이터 파일 및 측정 항목 이름과 레이블을 chunk 파일의 시계열로 인덱싱 한 인덱스 파일을 포함하는 디렉토리로 구성됩니다. API를 통해 시리즈를 삭제하면 chunk 파일에서 데이터를 즉시 삭제하는 대신 삭제 기록이 별도의 tombstone 파일에 저장됩니다.

현재 수신되는 샘플은 메모리에 보관 되며 완전히 유지되지 않습니다. WAL(write-ahead-log)에 의해 서버 재 시작이나 crash로 부터 보호됩니다. write-ahead log 파일은 128MB 세그먼트로 WAL 디렉토리에 저장 됩니다. 이러한 파일에는 아직 압축되지 않은 raw 데이터가 포함되어 있으므로 일반 블록 파일보다 훨씬 큽니다. Prometheus는 최소 3개의 write-ahead log 파일을 보관하지만 트래픽이 많은 서버는 최소 2시간 분량의 raw 데이터를 보관해야 하므로 3개 이상의 WAL 파일을 볼 수 있습니다.

Prometheus 서버 데이터 디렉토리 구조는 다음과 같습니다.

./data
├── 01BKGV7JBM69T2G1BGBGM6KB12
│   └── meta.json
├── 01BKGTZQ1SYQJTR4PB43C8PD98
│   ├── chunks
│   │   └── 000001
│   ├── tombstones
│   ├── index
│   └── meta.json
├── 01BKGTZQ1HHWHV8FBJXW1Y3W0K
│   └── meta.json
├── 01BKGV7JC0RY8A6MACW02A2PJD  → 블록 chunk
│   ├── chunks                  → chunk 파일
│   │   └── 000001
│   ├── tombstones              → 삭제 여부 표시 파일
│   ├── index                   → 색인을 위한 라벨 및 시간 인덱스 파일
│   └── meta.json               → 블록의 메타 데이터
├── chunks_head                 → chunk head
│   └── 000001
└── wal
    ├── 00000002                → wal 파일
    └── checkpoint.00000001     → crash 복구를 위한 checkpoint wal 파일
    └── 00000000

로컬 스토리지의 한계는 클러스터 되거나 복제 되지 않는다는 것입니다. 따라서 디스크 또는 노드 중단시 임의로 확장 가능하거나 내구성이 없으며 다른 종류의 단일 노드 데이터베이스 처럼 취급해야 합니다. 내구성 향상을 위해 디스크 가용성, 백업용 스냅 샷 , RAID를 사용하는 것이 좋습니다. 적절한 스토리지 내구성과 계획을 통해 로컬 스토리지에 수년간의 데이터를 저장할 수 있습니다.

또는 원격 읽기 / 쓰기 API 를 통해 외부 저장소를 사용할 수 있습니다 . 이러한 시스템은 내구성, 성능 및 효율성이 크게 다르기 때문에 신중한 평가가 필요합니다.

 

 

2. 압축

[root@prometheus-main data]# ls -al
합계 4
drwxr-xr-x 26 root   root   4096  9월  3 14:40 .
drwxrwxr-x  5 deploy deploy  186  9월  3 14:33 ..
drwxr-xr-x  3 root   root     68  8월 20 00:00 01EG3KQX64RZXVTQFRH28A8WHW
drwxr-xr-x  3 root   root     68  8월 20 18:00 01EG5HHEDYS67X2YA772V0SXQQ
drwxr-xr-x  3 root   root     68  8월 21 12:00 01EG7FAZPEP7S9HQJ94QCQ2Z99
drwxr-xr-x  3 root   root     68  8월 22 06:00 01EG9D4GXQT5WR9YNFFHXY0F3Y
drwxr-xr-x  3 root   root     68  8월 23 00:00 01EGBAY25F583CCKZGF2Q520XA
drwxr-xr-x  3 root   root     68  8월 23 18:00 01EGD8QKEM6GSPM3KPKYTA11RS
drwxr-xr-x  3 root   root     68  8월 24 12:00 01EGF6H4NRDRRAA3A2RJJC3DH3
drwxr-xr-x  3 root   root     68  8월 25 06:00 01EGH4ANXSE2RQWE6N83SF0M7R
drwxr-xr-x  3 root   root     68  8월 26 00:00 01EGK24764FT94BRPBW7P3M7XD
drwxr-xr-x  3 root   root     68  8월 26 18:00 01EGMZXRE7SDZMVF86KBW9K8H3
drwxr-xr-x  3 root   root     68  8월 27 12:00 01EGPXQ9P549DKMTVJDDFAY8QS
drwxr-xr-x  3 root   root     68  8월 28 06:00 01EGRVGTYSXTNY6YK3VN41PV8W
drwxr-xr-x  3 root   root     68  8월 29 00:00 01EGTSAC680AFKS7BQNZVSPF7D
drwxr-xr-x  3 root   root     68  8월 29 18:00 01EGWQ3XE4WHM6M57E9T3YXF53
drwxr-xr-x  3 root   root     68  8월 30 12:00 01EGYMXENNJ8DENS500B54TPNV
drwxr-xr-x  3 root   root     68  8월 31 06:00 01EH0JPZXTQW0F1WM2RGGJ12SF
drwxr-xr-x  3 root   root     68  9월  1 00:00 01EH2GGH60VC48XBBTF3VV1RM8
drwxr-xr-x  3 root   root     68  9월  1 18:00 01EH4EA2E2106ER8YM38Q01BEN
drwxr-xr-x  3 root   root     68  9월  2 12:00 01EH6C3KNMSFGBGFPQ47CF7309
drwxr-xr-x  3 root   root     68  9월  3 06:00 01EH89X4XNW47X8BTZHFNG40QQ
drwxr-xr-x  3 root   root     68  9월  3 12:00 01EH8YGAHX9ZTXZ627YF9AP5F7
drwxr-xr-x  3 root   root     68  9월  3 12:00 01EH8YGAMHPGSBCZMF9P79F06M
drwxr-xr-x  3 root   root     68  9월  3 14:00 01EH95C1T9EA9PVHD8J886VT7P
drwxr-xr-x  2 root   root     62  9월  3 14:33 wal

chunk 블록은 백그라운드에서 더 긴 시간의 블록으로 병합 됩니다.

 

블록은 시간이 흐른다고 계속해서 늘어나지 않습니다. 프로메테우스의 옵션을 어떻게 설정했느냐에 따라 블록이 계속해서 합쳐질 수도 있고, retention에 따라서 삭제될 수도 있습니다. 이에 관련된 옵션은 아래 두 가지가 있습니다.

--storage.tsdb.min-block-duration : 하나의 블록에 저장될 데이터의 time을 뜻합니다. 예를 들어 이 옵션의 값이 2h일 경우, 하나의 chunk 블록 디렉터리에는 2시간 동안의 데이터가 들어가 있습니다.

--storage.tsdb.max-block-duration : 하나의 블록에 최대로 저장할 수 있는 time을 뜻합니다. 예를 들어 이 옵션의 값이 12h일 경우, 하나의 chunk 블록 디렉터리에서는 최대 12시간 만큼의 데이터를 보관할 수 있습니다. 기본 값은 블록의 retention을 설정하는 옵션인 --storage.tsdb.retention.time의 10%로 설정됩니다. 위 예제에서는 18시간 블록으로 병합 되었습니다.

 

위 그림에서는 min-block-duration이 2h이기 때문에 2시간 단위의 Level 1 블록이 저장되어 있습니다. 이 때, 3개의 블록이 모이는 순간 Level 2의 블록으로 합쳐지게 되며, 하나의 블록에서 6시간의 데이터를 저장하게 됩니다. 한 번에 합쳐지는 블록의 갯수는 3으로 고정되어 있으며, 병합되는 블록의 Time은 exponential하게 증가하도록 되어 있습니다. 쉽게 설명하자면, 위 예시에서는 2h * 3 = 6h의 블록이 하나 생성되고 나서 더 이상의 병합은 발생할 수 없지만, max-block-duration이 24h라면 6h * 3 = 18h에 해당하는 블록도 새로 생성될 수 있습니다.

 

해당 블록의 정보는 meta.json에서도 확인 할 수 있습니다. 아래의 예시는 9개의 블록이 1개의 새로운 블록으로 병합된 경우(level 3)의 meta.json 파일 내용을 보여주고 있습니다. minTime/maxTime이 블록의 Time에 해당하는 값인데, 이 값들은 부모 블록의 값을 물려 받았음을 알 수 있습니다.

[root@prometheus-main 01EH0JPZXTQW0F1WM2RGGJ12SF]# cat meta.json
{
    "ulid": "01EH0JPZXTQW0F1WM2RGGJ12SF",
    "minTime": 1598745600000,
    "maxTime": 1598810400000,
    "stats": {
        "numSamples": 4808160,
        "numSeries": 742,
        "numChunks": 40068
    },
    "compaction": {
        "level": 3,
        "sources": [
            "01EGYMXEHY3P9EDQSQSQY70ESR",
            "01EGYVS5SY8S0W83GTR861JQ3N",
            "01EGZ2MX1XTAMBXXKF5Y2DJ1TY",
            "01EGZ9GM9Y3JBAYHV03XX6RFDZ",
            "01EGZGCBHYXDM7K4YW2M2YZYXM",
            "01EGZQ82SYM96D0EPKNFFHSJ1E",
            "01EGZY3T1YX7R46X94H1VXZJMR",
            "01EH04ZH9Y1A1QFX3AM2YT1W4W",
            "01EH0BV8HXEZP0HRM85D30BFGD"
        ]
    },
    "version": 1
}

 

3. 로컬 저장소 설정

Prometheus에는 로컬 저장소를 구성 할 수있는 여러 플래그가 있습니다. 

--storage.tsdb.path: Prometheus가 데이터베이스를 작성하는 위치를 결정합니다. 기본값은 data/.
--storage.tsdb.retention: 이 플래그 대신 storage.tsdb.retention.time 사용
--storage.tsdb.retention.time: 오래된 데이터를 제거 할 시기를 결정합니다. 기본값은 15d. storage.tsdb.retention 플래그가 기본값이 아닌 다른 것으로 설정된 경우 현재 설정으로 재정의 합니다.
--storage.tsdb.retention.size: 스토리지 블록이 사용할 수 있는 최대 바이트 수를 결정합니다 (WAL 크기는 포함되지 않음). 가장 오래된 데이터가 먼저 제거됩니다. 기본값은 0또는 비활성화입니다. 이 플래그는 실험적이어서 향후 릴리즈에서 변경 될 수 있습니다. 지원되는 단위 : B, KB, MB, GB, TB, PB, EB. 예 : "512MB"
--storage.tsdb.wal-compression: 이 플래그를 사용하면 미리 쓰기 로그 (WAL)를 압축 할 수 있습니다. 데이터에 따라 약간의 추가 CPU 부하로 WAL 크기가 절반으로 줄어들 것으로 예상 할 수 있습니다. 이 플래그는 2.11.0에서 도입 되었으며 2.20.0에서 기본으로 활성화되었습니다. Prometheus를 2.11.0 이하 버전으로 downgrade하려면 WAL을 삭제해야합니다.

시간 및 크기 보존 정책이 모두 지정된 경우 먼저 트리거되는 정책이 사용됩니다.
만료 된 블록 정리는 백그라운드 일정에 따라 발생합니다. 만료 된 블록을 제거하는 데 최대 2 시간이 걸릴 수 있습니다. 만료 된 블록은 정리하기 전에 완전히 만료되어야합니다.

평균적으로 Prometheus는 샘플 당 약 1-2 바이트 만 사용합니다. 따라서 Prometheus 서버의 용량을 계획하려면 대략적으로 아래 공식을 사용할 수 있습니다.

needed_disk_space = retention_time_seconds * ingested_samples_per_second * bytes_per_sample

초당 수집 된 샘플의 속도를 조정하려면 스크랩하는 시계열 수를 줄이거나 (타겟 당 더 적은 smaple 수 또는 더 적은 수의 타겟) 스크래핑 간격을 늘릴 수 있습니다. 그러나 시리즈 내의 sample 압축으로 인해 시리즈 수를 줄이는 것이 더 효과적 일 수 있습니다.

로컬 저장소가 손상되면 가장 좋은 방법은 Prometheus를 종료하고 전체 저장소 디렉터리를 제거하는 것입니다. 개별 블록 디렉터리 또는 WAL 디렉터리를 제거하여 문제를 해결할 수 있습니다. 즉, 블록 디렉터리 당 약 2시간 분량의 데이터 sample을 잃게됩니다. 다시 말하지만, Prometheus의 로컬 스토리지는 내구성있는 스토리지가 아닙니다.

주의 : Non-POSIX 호환 파일 시스템은 복구 불가능한 손상이 발생할 수 있으므로 Prometheus의 로컬 스토리지에서 지원되지 않습니다. NFS 파일 시스템 (AWS의 EFS 포함)은 지원되지 않습니다. NFS는 POSIX와 호환 될 수 있지만 완전하지 않기 때문에 안정성을 위해 로컬 파일 시스템을 사용하는 것이 좋습니다.



4. remote 스토리지 

Prometheus의 로컬 스토리지는 확장성과 내구성 측면에서 단일 노드로 제한됩니다. Prometheus 자체에서 클러스터 된 스토리지를 사용하는 대신 Prometheus는 원격 스토리지 시스템과 통합 할 수있는 인터페이스 세트를 가지고 있습니다.

Prometheus는 다음 두 가지 방식으로 원격 스토리지 시스템과 통합됩니다.

  • Prometheus는 표준화 된 형식으로 원격 URL에 수집하는 샘플을 작성할 수 있습니다.
  • Prometheus는 표준화 된 형식으로 원격 URL에서 샘플 데이터를 읽을 수 있습니다.

읽기 및 쓰기 프로토콜은 모두 HTTP를 통한 snappy-compressed 프로토콜 버퍼 인코딩을 사용합니다. 프로토콜은 아직 안정적인 API로 간주되지 않아서 향후 Prometheus와 원격 저장소 간의 모든 통신이 HTTP/2를 지원 할 수 있을 때 HTTP/2를 통해 gRPC(구글이 최초로 개발한 오픈 소스 원격 프로시저 호출)를 사용하도록 변경 될 수 있습니다.

읽기 경로에서 Prometheus는 remote storage에서 레이블 및  시계열 데이터 만 가져옵니다. 데이터에 대한 모든 PromQL의 실행은 여전히 로컬 Prometheus 에서 발생합니다. 즉, 필요한 모든 데이터를 먼저 쿼리하는 Prometheus 서버에 로드 한 다음 처리해야 하므로 remote 읽기 쿼리에는 확장성 제한이 있습니다.

 

4.1. remote 읽기

Prometheus 저장소 쿼리가 HTTP API 를 통해 로컬 및 원격 저장소로 전송되고 결과가 병합됩니다.
원격 스토리지 사용에 안정성을 유지하기 위해 alert 및 구성 파일 설정은 로컬 스토리지만 사용합니다.

Prometheus 구성 파일(rule.yml)의 remote_read 섹션에서 remote 스토리지 읽기 경로를 구성합니다.
간단하게 원격 저장소에 대한 읽기 endpoint URL과 인증 방법을 지정하기만 하면됩니다. HTTP 기본 또는 토큰 인증을 사용할 수 있습니다.

주요 플래그는 다음과 같습니다.
-- read_recent: true로 설정하면 모든 쿼리가 remote 및 로컬 스토리지에서 응답됩니다. false(기본값)인 경우 로컬 스토리지에서 응답하고 remote로 전송되지 않습니다.
-- required_matchers: (레이블, 값 쌍) 메트릭의 하위 집합만 remote 스토리지를 사용 경우에 사용합니다.
-- remote_timeout: remote 스토리지 요청에 대한 timeout 설정에 사용합니다. (기본값 1m)
이 외에도 인증 및 TLS 구성, 프록시 설정에 대한 옵션도 있습니다.

 

4.2. remote 쓰기

Prometheus는 스크랩 된 sample을 하나 이상의 remote 스토리지로 전달합니다.

remote 쓰기는 로컬 스토리지에 기록된 시계열 sample을 remote 스토리지에 쓰기 위해 queue에 넣는 방식으로 작동합니다.
dinamic queue는 동적으로 관리되는 shard 세트입니다. 동일한 측정 항목에 대한 시계열 샘플은 특정 샤드에 있게 됩니다.
queue는 들어오는 데이터의 속도를 따라 잡기 위해 remote 스토리지에 쓰는 shard 수를 자동으로 늘리거나 줄입니다.
이를 통해 Prometheus는 최소한의 구성으로 필요한 리소스만 사용하면서 remote 스토리지를 관리 할 수 있습니다.
가끔 느린 remote 요청을 처리하는 동안 처리량을 유지하기 위해 여러 요청을 버퍼링 할 수 있도록 각 샤드에 충분한 용량을 확보하는 것이 좋습니다.

Prometheus 구성 파일의 remote_write 섹션에서 remote 스토리지 쓰기 경로를 구성합니다.
remote_read와 마찬가지로 가장 간단한 구성은 remote 스토리지 쓰기 URL과 인증 방법입니다. HTTP 기본 또는 토큰 인증을 사용할 수 있습니다.

주요 플래그는 다음과 같습니다.
-- remote_timeout: remote 스토리지 요청에 대한 timeout 설정에 사용합니다. (기본값 30s)
-- write_relabel_configs: remote 스토리지에 쓰는 메트릭의 레이블을 변경하거나 제한 할 수 있습니다.
-- queue_config: queue에 대한 일부 제어를 제공합니다. 일반적으로 여기서 변경할 필요가 없으며 Prometheus의 기본값을 사용할 수 있습니다.
이 외에도 인증 및 TLS 구성, 프록시 설정에 대한 옵션도 있습니다.

 

4.3. remote endpoint 스토리지

Prometheus 의 remote 쓰기 및 읽기 기능을 사용하면 투명하게 sample을 보내고 받을 수 있습니다.
remote 스토리지는 장기 보관을 위한 것입니다. 스토리지 솔루션을 신중하게 평가하여 데이터 볼륨을 처리 할 수 있는지 확인하는 것이 좋습니다.

아래는 remote 스토리지로 사용 가능한 리스트와 속성입니다.

  • AppOptics: write
  • Azure Data Explorer: read and write
  • Azure Event Hubs: write
  • Chronix: write
  • Cortex: read and write
  • CrateDB: read and write
  • Elasticsearch: write
  • Gnocchi: write
  • Google BigQuery: read and write
  • Google Cloud Spanner: read and write
  • Graphite: write
  • InfluxDB: read and write
  • IRONdb: read and write
  • Kafka: write
  • M3DB: read and write
  • MetricFire: read and write
  • New Relic: write
  • OpenTSDB: write
  • PostgreSQL/TimescaleDB: read and write
  • QuasarDB: read and write
  • SignalFx: write
  • Splunk: read and write
  • TiKV: read and write
  • Thanos: read and write
  • VictoriaMetrics: write
  • Wavefront: write

'ETC DB' 카테고리의 다른 글

prometheus TSDB format  (0) 2021.07.21
prometheus TSDB 관리 API  (0) 2021.07.21
prometheus 데이터 구조  (2) 2021.07.21
prometheus 개요  (0) 2021.07.21
Amazon Aurora DB와 mysql 차이점  (0) 2021.07.21

1. TSDB의 읽기 쓰기

일반적인 TSDB 데이터베이스를 살펴 보면 세로 축은 시계열, 가로 축은 타임 스탬프가 있는 sample 시퀀스입니다.
Prometheus에는 일반적으로 샘플 데이터가 수백만 개가 있으며 기간은 몇 주 단위입니다.

쓰기 : 짧은 시간에 많은 시계열에 sample을 추가합니다. 일반적으로 쓰기만 사용합니다.
         그러나 어느 시점에서 이전 데이터를 자르거나 download 할 수 있습니다.
         위 예에서는 빨간 부분의 세로로 사용.

읽기 : 상대적으로 긴 시간 동안 상대적으로 적은 시계열 (가장 일반적으로 하나)에서 sample을 읽습니다.
         이는 쓰기 패턴과 정확히 수직이므로 TSDB를 올바르게 설정하기가 어렵습니다.
         예외가 있지만 대체로 많은 비용이 드는 쿼리는 시계열에 따른 쿼리입니다.
         위 예에서는 녹색 부분의 가로로 사용.

*sample : 수집된 데이터

 

2. prometheus 내부 저장소

prometheus는 in-memory에 자체 sample storage 레이어를 사용합니다.
그리고 하위 저장소로 파일 시스템과 Level DB를 사용합니다. (초기 버전에서는 sample 저장에도 Level DB를 사용)
Level DB는 Google에서 만든 light-weight의 Key-value 저장소이며, 전반적으로 뛰어난 성능을 보이기에 여러곳에서 사용합니다.
Level DB는 기본적으로 압축을 지원합니다.

 

3. prometheus 데이터 구조

시계열 데이터를 처리하기위한 기본 데이터 구조는 다음과 같이 정의 됩니다.

type sample struct {
        Labels map[string]string
        Value  float64
}

 

prometheus의 메트릭은 다음과 같이 수집됩니다.

메트릭명{필드1=값, 필드2=값} 샘플링데이터

 

아래는 prometheus export 라이브러리를 붙인 모습입니다.

많은 수의 metric이 발생을 하게 되고, 이를 text/html 방식으로 특정 url(대부분 /metrics)로 export를 해두게 되면, prometheus 서버가 이를 긁어가서 데이터를 저장합니다.

metric 이름이 제일 먼저 나오고, metric의 특징을 표현하는 레이블(label)들이 있습니다. 그리고 가장 마지막으로는 metric 값(value)이 있습니다.
필요에 따라 timestamp도 표시될 수 있다. timestamp를 보통 출력하지 않는데, 그 이유는 수집하는 순간의 시간으로 값이 기록되기 때문입니다.

 

4. sample 저장소

Prometheus sample 저장소가 작동하는 방식은 아래와 같습니다.

sample 데이터는 일정한 크기의 chunk로 구성됩니다.

새로 수집된 sample은 head chunk에 기록되며, LRU 알고리즘에 의해 memory에서 disk로 chunk를 이동시킵니다.
원래는 freelist 나 거대한 메모리에 모두 보관했지만, fragmentation 방지를 위해 memory에 일정한 크기를 할당하고 할당 해제를 반복합니다.

disk의 chunk 표현은 메모리와 정확히 동일하며 1 : 1 대응입니다.
PromQL 쿼리는 전적으로 메모리에서 제공됩니다.

입력, 네트워크 페이로드, 구문 분석 결과 및 쿼리에 필요한 개별 값 출력 중에 만 disk, memory 변환이 발생하며 각 sample은 메모리에 chunk를 가집니다.

*chunk : 데이터 저장 단위

 

5. series의 사이클과 유지보수

아직 disk에 없는 전체 청크를 추가합니다.
retention 시간보다 오래된 청크는 삭제됩니다.
위 작업이 실제로는 series의 파일을 다시 작성하는 것을 의미합니다.

 

6. chunk preloading

쿼리에는 현재 메모리에 없는 chunk가 필요할 수 있습니다.
쿼리 엔진은 쿼리 시간 동안 chunk를 disk에서 memory로 미리 로드합니다.

 

7. checkpointing

종료나 장애시 데이터 손상을 줄이기 위해 disk의 series 파일에 유지되지 않는 chunk는 정기적으로 파일로 check point 됩니다.
그리고 시작하는 동안 다시 memory로 load 됩니다.

 

8. prometheus data type

Prometheus에서 Data Type은 4가지로 분류됩니다.
위에서 언급한 Metric 값(value)의 타입을 말하는 것이 아닙니다.
Prometheus에서 사용하는 값의 타입은 오로지 float64 입니다.

Instant vector - 각 시계열에 대한 단일 샘플을 포함하는 시계열 집합이며 모두 동일한 타임 스탬프를 공유 합니다.
Range vector - 각 시계열에 대한 시간 경과에 따른 데이터 포인트 범위를 포함하는 시계열 세트 입니다.
Scalar - 간단한 숫자 부동 소수점 값 입니다.
String - 간단한 문자열 값. 현재 미사용 합니다.

 

위 4가지 타입의 설명만으로는 이해가 안될 수 있기에 추가적인 설명을 하도록 합니다.
Time series란 시계열 이란 의미로 시간변화에 따른 값이 변화를 말합니다. 우리가 보고자 하는 metric 데이터는 시간에 따른 값의 변화를 나타내는데, [시간, 값]...[시간, 값] 이런식으로 표현이 됩니다.예를 들면, container A의 CPU 값은 [1분, 0.1], [2분, 0.2], [3분, 0.1] 과 같이 나타낼 수 있습니다. 이런 배열들을 묶어서 하나의 Time-series라 하는 것이다. 여기서 1개 요소인 [1분, 0.1] 을 Sample이라 합니다.

http_requests_total{method="POST", handler="/messages"} 1037
http_requests_total{method="GET", handler="/messages"} 500


위 예를 보면, 두개의 Sample이 존재하고, 시간의 변화에 따라 기록되는 Sample들의 묶음(배열)이 바로 Time-series라고 생각 하면 됩니다.

 

8.1. Instant Vector

Instant vector는 여러 time-series에서 같은 시간대를 가리키는 Sample 집합을 말합니다.
위와 같이 http_requests_total에 대해 2가지 time-series가 존재하는데 같은 시간에 해당되는 2개의 Sample 집합을 Instant vector라 합니다.
비유를 좀 하자면 Time-series가 시간에 따른 가로축을 표현했다라고 하면, Instant Vector는 Time-series를 세로로 자른 단면 같다고 할 수 있습니다. (처음 언급한 그래프)
기본적으로 단순히 metric 이름으로 쿼리를 실행하면 Instance Vector를 얻을 수 있고, 필터링을 하고 싶으면 Instant Vector selector를 사용하면 됩니다.

 

8.2. Range Vector

Range vetor는 특정 시간동안(period)의 값들을 배열로 가진 타입입니다.
Instant vector는 각 time-series들이 1개의 Sample만을 가지는 타입인데, Range vector은 각 Time-series들이 주어진 기준 시간부터 명시된 과거 시간사이의 모든 값들을 가질 수 있습니다.
Range Vector 표시는 metric 이름에 대괄호 [<period>] 를 붙이면 됩니다.

예를들어 http_requests_total[5m] 로 쿼리를 실행해보면 다음과 같이 나옵니다.

http_requests_total{method="POST", handler="/messages"}[5m]
[1037 @1551242271.728, 1038 @1551242331.728, 1040 @1551242391.728]
http_requests_total{method="GET", handler="/messages"}[5m]
[500 @1551242484.013, 501 @1551242544.013, 502 @1551242604.013]

배열 요소로 <값>@<timestamp> 형태로 들어가 있다. 위 예시는 5분 동안에 3개의 값이 존재하고 있습니다.

이렇게 값이 1개가 아닌, 여러개가 배열로 표현됩니다.

 

8.3. Range Query와 Range vector

위의 range vector 결과만으로 그래프를 그릴 수 없습니다. 그래프를 그리려면 정확한 1개의 값으로 만들어 그려야 하는데 여기서는 3개가 존재하기 때문입니다.

여기서 Range Query와 Range vector를 혼동할 수 있을 것 같아 이에 대해 설명하자면,
Range Query는 Start 와 End 시간을 옵션으로 주는 쿼리 표현 종류(API에 비유)이고, Range vector는 데이터 타입입니다.

쿼리를 실행해서 그래프를 그리기 위해서는 Instant vector + Range Query로 실행되어야 합니다.

예시로 설명한 http_requests_total로 쿼리를 실행 했을 때 최근 5분의 값만 보여주게 됩니다.
이때는 Range Query로 실행되는게 아닌 Instant Query로 실행됩니다. 그래프로 그리기 위해서는 보려는 Start-End시간 사이의 모든 Instant vector의 값들이 필요합니다.

Range vector로 그래프를 그릴 수 없다면, Range vector의 결과를 aggregation하여 1개의 Instant vector로 만들어 주는 aggregation function을 사용해야 합니다. 

다음은 대표적인 function인 rate를 이용하여 http_requests_total로 쿼리를 변환한 예 입니다.

rate(http_requests_total{method="POST", handler="/messages"}[5m])
0.01098

rate 함수는 1초당 변화량으로 환산하는 함수로, 앞선 예시에서 5분 동안에 포함되는 3개의 값의 변화를 초당으로 변환해 1개의 값으로 나타 냅니다.

aggregation function없이 range vector로만 가지고 그래프로 표현하려고 하면 에러가 발생합니다.

Invalid expression type "range vector" for range query, must be Scalar or instant Vector 라는 에러가 발생합니다.

 

8.4. Instant Query

Instant Query는 다음 API로 호출합니다.

GET /api/v1/query
POST /api/v1/query

다음은 Grafana에서 기본 Query로 실행 할때의 API 호출 예 입니다.

start, end가 아닌 특정 시간(time)이 query string으로 들어가 있습니다. resultType은 vector 입니다.

 

다음은 up 쿼리에 대한 2015-07-01T20:10:51.781 시간의 Instant Query 예제 입니다.

$ curl 'http://localhost:9090/api/v1/query?query=up&time=2015-07-01T20:10:51.781Z'
{
   "status" : "success",
   "data" : {
      "resultType" : "vector",
      "result" : [
         {
            "metric" : {
               "__name__" : "up",
               "job" : "prometheus",
               "instance" : "localhost:9090"
            },
            "value": [ 1435781451.781, "1" ]
         },
         {
            "metric" : {
               "__name__" : "up",
               "job" : "node",
               "instance" : "localhost:9100"
            },
            "value" : [ 1435781451.781, "0" ]
         }
      ]
   }
}

resultType은 vector로 해당 타임 스탬프와 값을 확인 할 수 있습니다. (instant query + instant vector)

 

8.5. Range Query

Range Query는 다음 API로 호출합니다.

GET /api/v1/query_range
POST /api/v1/query_range

다음은 Grafana에서 Range Query로 실행할때의 API호출 예 입니다.

API가 다르고 start, end가 query string 으로 들어간 것을 알 수 있습니다. resultType은 matrix입니다. (시간대 별로 vector값이 들어간 내부적으로 쓰이는 복합 타입)

 

다음은 up 쿼리에 대해 2015-07-01T20:10:30.781 시간 부터 2015-07-01T20:11:00.781 시간 까지 15초 단위의 Range Query 예제 입니다.

$ curl 'http://localhost:9090/api/v1/query_range?query=up&start=2015-07-01T20:10:30.781Z&end=2015-07-01T20:11:00.781Z&step=15s'
{
   "status" : "success",
   "data" : {
      "resultType" : "matrix",
      "result" : [
         {
            "metric" : {
               "__name__" : "up",
               "job" : "prometheus",
               "instance" : "localhost:9090"
            },
            "values" : [
               [ 1435781430.781, "1" ],
               [ 1435781445.781, "1" ],
               [ 1435781460.781, "1" ]
            ]
         },
         {
            "metric" : {
               "__name__" : "up",
               "job" : "node",
               "instance" : "localhost:9091"
            },
            "values" : [
               [ 1435781430.781, "0" ],
               [ 1435781445.781, "0" ],
               [ 1435781460.781, "1" ]
            ]
         }
      ]
   }
}

resultType은 matrix으로 각 시간별로 타임스탬프와 값을 확인 할 수 있습니다. (range query + instant vector)

 

'ETC DB' 카테고리의 다른 글

prometheus TSDB 관리 API  (0) 2021.07.21
prometheus disk storage  (0) 2021.07.21
prometheus 개요  (0) 2021.07.21
Amazon Aurora DB와 mysql 차이점  (0) 2021.07.21
Amazon Aurora 특징  (0) 2021.07.21

1. 프로메테우스란?

Prometheus 는 원래 SoundCloud에 구축 된 오픈 소스 시스템 모니터링 및 경고 툴킷 입니다. 2012 년에 시작된 이래 많은 회사와 조직에서 Prometheus를 채택 했으며 이 프로젝트에는 매우 활동적인 개발자 및 사용자 커뮤니티가 있습니다. 지금은 독립형 오픈소스 프로젝트이며 많은 회사들이 사용 하고 있고, 또한 kubernetes에서도 Prometheus를 사용하여 매트릭 수집 및 대시보드를 구축하는 방식을 장려하고 있습니다.

 

2. features

Prometheus의 주요 기능은 다음과 같습니다.

  • 메트릭 이름 및 키 / 값 쌍으로 식별되는 시계열 데이터가있는 다차원 데이터 모델
  • 이러한 차원을 활용 하는 유연한 쿼리 언어인 PromQL
  • 분산 스토리지에 의존하지 않습니다.
  • 시계열 수집은 HTTP를 통한 pull 모델을 통해 발생합니다.
  • 푸시 시계열 은 중간 게이트웨이를 통해 지원됩니다.
  • 서비스 검색 또는 정적 구성을 통해 대상 검색
  • 다양한 그래프 및 대시 보드 모드 지원

 

3. 구성

Prometheus 에코 시스템은 여러 구성 요소로 구성되며 그 중 대부분은 선택 사항입니다.

  • 시계열 데이터를 수집하고 저장 하는 기본 Prometheus 서버
  • 애플리케이션 코드를 계측하기 위한 클라이언트 라이브러리
  • 짧은 주기의 작업을 지원하기위한 푸쉬 게이트웨이
  • HAProxy, StatsD, Graphite 등과 같은 서비스를위한 특수 목적 exporter
  • 핸들 경고하기 위한 alertmanager 
  • 다양한 지원 도구

대부분의 Prometheus 구성 요소는 Go 로 작성되어 정적 바이너리로 쉽게 빌드하고 배포 할 수 있습니다.

 

4. 아키텍처

간단하게 설명하자면 아래와 같습니다.
Jobs/exporters는 실제로 매트릭을 수집하는 프로세스라고 보면 됩니다.
이 exporter가 매트릭을 수집하고 HTTP 통신을 통해 매트릭 데이터를 가져갈 수 있게 /metrics 라는 HTTP 엔드포인트를 제공합니다.
그러면 Prometheus server가 이 exporter의 endpoint로 HTTP GET 요청을 날려 매트릭 정보를 수집(Pull)한고, 단기 작업은 중간 푸시 게이트웨이를 통해 메트릭을 스크랩합니다.
스크랩 된 모든 샘플을 로컬에 저장하고이 데이터에 대한 규칙을 실행하여 기존 데이터에서 새 시계열을 집계 및 기록하거나 경고를 생성합니다.
수집한 정보를 Prometheus가 제공하는 간단한 웹 뷰를 통해 조회할 수 있고 그 안에서 테이블 및 그래프 형태로 볼 수 있습니다.
하지만 시각화 도구가 부족해서 이를 직접 사용하지는 않고 대부분 Grafana라는 Data Visualization tool을 이용하여 시각화하고 있습니다.

 

5. 추천 환경

Prometheus는 장애 조건에서도 시스템에 대해 사용 가능한 통계를 항상 볼 수 있습니다.
Prometheus는 순수한 숫자 시계열을 기록하는 데 적합합니다. 이는 기계 중심 모니터링과 동적 인 서비스 지향 아키텍처의 모니터링에 모두 적합합니다. 마이크로 서비스의 세계에서 다차원 데이터 수집 및 쿼리에 대한 지원이 강점입니다.
Prometheus는 문제를 신속하게 진단 할 수 있도록 가동 중단시 시스템의 안정성을 위해 설계되었습니다. 각 Prometheus 서버는 네트워크 스토리지 또는 기타 원격 서비스에 의존하지 않고 독립형입니다. 인프라의 다른 부분이 손상 되었을 때 이를 사용하기 위해 광범위한 인프라를 설정할 필요가 없습니다.

 

6. 비 추천  환경

billing 같이 100 % 정확성이 필요한 경우 수집 된 데이터가 상세하고 완전하지 않을 가능성이 높으므로 Prometheus는 좋은 선택이 아닙니다. 이러한 경우 다른 시스템을 사용하여 billing 데이터를 수집하고 분석하고 이를 제외한 나머지 모니터링에는 Prometheus를 사용하는 것이 가장 좋습니다.

'ETC DB' 카테고리의 다른 글

prometheus disk storage  (0) 2021.07.21
prometheus 데이터 구조  (2) 2021.07.21
Amazon Aurora DB와 mysql 차이점  (0) 2021.07.21
Amazon Aurora 특징  (0) 2021.07.21
Amazon Aurora 스토리지  (0) 2021.07.21

1. Aurora MySQL 5.7과 MySQL 5.7 비교

다음 기능은 MySQL 5.7.12에서 지원되지만 Aurora MySQL 5.7에서는 현재 지원되지 않습니다.

그룹 복제 플러그인
페이지 크기 증가
시작 시 InnoDB 버퍼 풀 로딩
InnoDB 풀 텍스트 구문 분석기 플러그인
멀티 소스 복제
온라인 버퍼 풀 크기 조정
암호 확인 플러그인
쿼리 다시 쓰기 플러그인
복제 필터링
CREATE TABLESPACE SQL 문
X 프로토콜

 

 2. 빠른 입력 기능

빠른 입력 기능은 기본 키에 의해 정렬되는 병렬 입력을 빠르게 처리해 주며, 특히 LOAD DATA 및 INSERT INTO ... SELECT ... 문 사용 시 유용합니다. 빠른 입력 기능은 SQL 구문을 실행할 때 인덱스 순회에서 커서의 위치를 캐싱합니다. 이에 따라 인덱스를 불필요하게 다시 순회하지 않도록 해줍니다.

다음 측정치를 모니터링하면 DB 클러스터에서 빠른 입력 기능의 효과를 확인할 수 있습니다.

  • aurora_fast_insert_cache_hits: 캐싱된 커서가 성공적으로 검색 및 확인되면 증가하는 카운터입니다.
  • aurora_fast_insert_cache_misses: 캐싱된 커서가 더 이상 유효하지 않고 Aurora가 정상적인 인덱스 순회를 수행하면 증가하는 카운터입니다.

 

다음 명령을 사용하면 빠른 입력 측정치의 현재 값을 검색할 수 있습니다.

mysql> show global status like 'Aurora_fast_insert%';               


+---------------------------------+-----------+
| Variable_name                   | Value     |
+---------------------------------+-----------+
| Aurora_fast_insert_cache_hits   | 3598300   |
| Aurora_fast_insert_cache_misses | 436401336 |
+---------------------------------+-----------+

 

3. 스토리지

Aurora는 Shared Storage를 사용하며 MySQL의 경우 binlog 기반의 replication이 아닌 Storage와 page기반의 replication을 사용합니다.

 

가장 큰 차이점은 스토리지입니다. 위 그림의 위는 MySQL replica, 아래는 AWS aurora입니다.

MySQL의 경우 자신의 EBS로 데이터를 쌓고 쌓은 데이터를 EBS로 미러링 한 다음 replication을 통해 replica로 데이터를 보내고 replica는 받은 데이터를 자신의 스토리지로 쌓습니다. 데이터베이스는 결국 트랜잭션의 결과물이 input/ooutput 형태로 수행되는 것이기에 before & after 작업들이 WAL(Write-Ahead-Log)를 통해 스토리지에 저장됩니다. 이 방식의 단점은 I/O 대역폭과 IOPS가 제한적이고 이부분에 대해 변경이 필요할 경우 사용자가 직접 튜닝해야 합니다.
반면 aurora의 경우에는 4/6 쿼럼을 사용해서 스토리지에 저장하며 replica로 보내는 것은 frm 및 redo log입니다. 그래서 network badwidth 사용도 적으며 빠르게 변경분을 저장하고 반영할 수 있습니다. 인스턴스와 스토리지의 영역을 나눴기 때문에 이와 같은 아키텍쳐를 그릴 수 있습니다. 스토리지 서브 시스템은 segmented 방식이며 EBS가 아닌 고성능 NVMe SSD 를 사용하고 데이터는 지속적으로 S3에 백업 합니다.

이렇게 보면 writer에 많은 DML이 들어오는 인스턴스의 경우 aurora를 사용하면 적은 replica lag을 가지면서 서비스 운영을 할 수 있다는 것으로 보입니다. 이론상으로만 보면 그렇습니다. 하지만 AWS 스토리지 내부 아키텍쳐를 좀 더 보아야 합니다.

MySQL의 경우 read replica도 binlog를 받아서 처리하기 때문에 read 뿐만아니라 write도 같이 처리해야 하는 단점이 있습니다. AWS aurora MySQL의 경우 read replica가 binlog를 읽어서 싱크를 맞추는 것이 아니라 redo log를 받아서 동기화 하기 때문에 read에만 집중할 수 있습니다. 이점이 aurora MySQL 이 더 뛰어난 점이라고 말 할 수 있습니다.

정리 하자면 가장 큰 차이점은 스토리지 및 관리 주체, read replica의 구성 방식 세가지로 볼 수 있습니다.

  • 스토리지 : MySQL은 자체 스토리지로 운영하지만 aurora MySQL은 Shared Storage를 사용한다.
  • 관리 주체: MySQL은 관리자가 MySQL 버전을 올리면서 사용 하지만 aurora MySQL은 AWS가 개발해서 버전 업그레이드를 주기적으로 하기 때문에 optional 또는 mandatory가 AWS에 의해 정해질 수 있다. (참조 : https://forums.aws.amazon.com/forum.jspa?forumID=60&start=0 )
  • read replica 구성 : MySQL은 standby와 read replica를 만들 때 binlog를 사용하지만 aurora의 경우 내부 storage 및 redo log 전송을 통해 빠른 동기화가 가능하며 bandwidth를 줄일 수 있다

'ETC DB' 카테고리의 다른 글

prometheus 데이터 구조  (2) 2021.07.21
prometheus 개요  (0) 2021.07.21
Amazon Aurora 특징  (0) 2021.07.21
Amazon Aurora 스토리지  (0) 2021.07.21
Amazon Aurora 정의  (0) 2021.07.21

+ Recent posts