1. Overview
프로메테우스를 이용해 모니터링 시스템을 구축하였습니다. 수집한 메트릭을 기반으로 그라파나로 시각화 해 모니터링을 진행하며 대부분의 메트릭은 오픈 소스로 공개되어있는 익스포터를 사용했습니다. 오라클용 DB 모니터링 용 Oracle-exporter, NVIDIA GPU 모니터링을 위한 DCGM-Exporter, Postrgres DB 용 postgres_exporter 실제로 대부분의 솔루션들이 이미 익스포터를 제공하는 경우가 많습니다. 하지만 프로젝트에서 사용하는 Sqream DB의 경우 익스포터가 존재하지 않아 직접 구현해야했습니다. 존재하는 익스포터일 경우에도 원하는 메트릭이 존재하지 않아 추가적으로 구현이 필요한 상황도 존재 했습니다. 대부분의 익스포터의 경우 Go 언어로 작성이 되어있었는데 저는 Go에 익숙하지 않아 Python으로 개발을 진행하였습니다.
2. Metric
우선 익스포터의 주 기능은 Prometheus 에서 수집 할 수 있도록 메트릭을 발생시키는 것입니다. 메트릭을 만들어야하기 때문에 Prometheus의 메트릭 종류를 확인해야합니다.
_sum
과 _count
가 동시에 존재합니다. 실 사용시 rate 함수를 사용해 다음과 같이 사용합니다._bucket
이 추가 됩니다. le
는 이하를 의미합니다 0.1로 나타날 경오 1ms로 해석해 1ms동안 1개가 request 된 것으로 확인 할 수 있습니다.histogram_quantile(0.9,rate(prometheus_http_request_duration_seconds_bucket[5m]))
3. Code 예시
프로메테우스에서는 위의 네가지 타입의 메트릭 종류를 제공합니다만 저는 주로 게이지만 사용하여서 익스포터 개발을 진행했습니다. 해당 라이브러리에서는 위의 4개 타입 외에도 Enum,Info 등을 추가로 사용할 수 있습니다. 예시로 만든 메트릭은 다음과 같습니다. REDII url로 request를 보내 정상적으로 응답하면(satus code가 2로 시작) 1, 그 외는 0 으로 설정하는 로직을 작성후 15초 마다 확인 하도록 합니다.
from prometheus_client import start_http_server, Gauge, Summary
import random
import time
import requests
# Create a metric to track time spent and requests made.
REDII_URL='http://127.0.0.1:80'
test_metric = Gauge('test_up','test')
#set up metric
def set_up_metric():
try:
resp =requests.get(REDII_URL)
if str(resp.status_code).startswith('2'):
test_metric.set(1)
else:
test_metric.set(0)
except:
test_metric.set(0)
if __name__ == '__main__':
# Start up the server to expose the metrics.
start_http_server(8000)
# Generate some requests.
while True:
set_up_metric()
time.sleep(15)
다음과 같이 코드 작성 후 실행하면 8000 포트를 통해 접근이 가능합니다. 다음과 같이 정상적으로 메트릭이 발생하는 것을 확인 할 수 있습니다. 이후 prometheus config 파일에 target을 설정한 후 재시작시 해당 메트릭을 그라파나를 통해 그릴 수 있습니다.
보통 모든 메트릭은 label을 가지고 있어 promql을 사용할 때 필터링합니다. 이는 다음과 같이 설정할 수 있습니다. label의 값은 string으로 저장됩니다. 때문에 그라파나나 promql 에서 int값을 통한 조건문이 불가 합니다.
from prometheus_client import start_http_server, Gauge, Summary
import random
import time
import requests
# Create a metric to track time spent and requests made.
REDII_URL='http://127.0.0.1:80'
REQUEST_TIME = Summary('request_processing_seconds', 'Time spent processing request')
test_metric = Gauge('test_up','test',['ip','label'])
def set_up_metric():
try:
resp =requests.get(REDII_URL)
if str(resp.status_code).startswith('2'):
test_metric.labels(ip='127.0.0.1',label='label1').set(1)
else:
test_metric.labels(ip='127.0.0.1',label='label1').set(0)
except:
test_metric.labels(ip='127.0.0.1',label='label1').set(0)
이후 다음과 같이 label이 적용 되고 프로메테우스에서 메트릭이 발생하는 것을 확인 할 수 있습니다. 예시로 작성 한 코드 외에 실제로 개발을 구현 한 것은 Sqream DB의 익스포터였습니다. 기존의 Mysql 이나 Oracle DB 의 경우 공식적으로 제공하는 exporter가 존재하지만 Sqream DB의 경우 아직 초기 단계이기 때문에 exporter가 존재하지 않았습니다. 이를 위해 개발을 진행하였습니다. Python API를 통해 Connect 후 모니터링용 쿼리를 날려 Metric 형식으로 파싱하는 방식으로 개발을 진행하였습니다.