프로메테우스에 직접 api를 요청해 데이터를 받아보자.
사실상 그라파냐에서 하는 걸 파이썬으로 옮긴거다. 관련 http api는 공식문서에 정리되어있다.
데이터를 받아올거라 get요청을 했으며, 쿼리문에는 /api/v1/query
와, /api/v1/query_range
2가지가 존재한다.
단순히 metric 이름만으로 get요청을 보냈을때다. 이때, 반환되는 데이터는 Instant Vector이다.
해당 데이터는 오직 특정시간대(타임스탬프)의 value값 1개만 존재한다.
예시를 들자면, promQL문은 node_cpu_seconds_total{mode='idle'}
이다.
반환되는 data의 구조는 다음과 같다. data["data"]["result"]부분에 가져올 데이터가 들어가있으며, data["data"]["result"]["value"]부분을 보면, 오직 1개의 array가 들어가있는데 구조는 [타임스탬프, 값] 구조이다. 참고로 타임스탬프는 그리니치 평균시(GMT)를 기반으로 한다.
또한, data["data"]["resultType"]이 vector임을 확인할 수 있다.
data = {
'status': 'success',
'data': {
'resultType': 'vector',
'result': [
{
'metric': {
'instance': '192.168.123.150:9100',
(다른 metric정보도 많지만 생략.)
},
'value': [1696849603.547, '28496.25']
},
{
'metric': {
'instance': '192.168.123.151:9100',
},
'value': [1696849603.547, '30001.32']
},
...
]
}
즉, 해당 명령어는 오직 특정시간대의 1개의 값만 가져온다. 우린 그래프를 그려야하는데...!
그래프를 그리기 위해, query_range를 사용한다.
해당 쿼리문은 Instant Vector와 같은 Scalar값을 반환하는 promQL문을 사용해야한다.
그렇다면, 먼저 Scalar값을 반환하지 않는 promQL문은 뭘까?
node_cpu_seconds_total{mode='idle'}[5m]
처럼, 뒤에 기간을 넣어주어, 여러 값을 가져올 수 있다.
다음과 같이 values에 여러 배열이 들어간 걸 확인가능하다. (아까는 value에 들어가있었다)
이와 같은 데이터타입을 Range Vector라고 한다. (<-> Instant Vector)
data = {
'status': 'success',
'data': {
'resultType': 'matrix',
'result': [
{
'metric': {'instance': '192.168.123.150:9100'},
'values': [
[1696848415.518, '15.440740740741262'],
[1696848475.518, '15.386111111110608'],
[1696848535.518, '15.627777777777993'],
]
},
{
'metric': {'instance': '192.168.123.151:9100'},
'values': [
[1696848415.518, '9.505555555555873'],
[1696848475.518, '9.57685185185153'],
[1696848535.518, '9.523148148147342'],
]
}
]
}
즉, 위와 같은 promQL문을 넣으면 안된다. 그렇다면 해당 promQL문은 왜 필요한가!
예를 들어, CPU 사용량 값만 딱 보여주는게 아닌, CPU 사용률의 변화량을 보여주고 싶을때가 있다.
그럴땐, rate(node_cpu_seconds_total{mode='idle'}[5m])
이와 같이 rate
를 붙혀, 5분동안의 변화량을 보여줄 수 있다.
ㅁ
+) query_range 쿼리문에서 Range Vector를 넣을 경우, 다음과 같이 Scalar값을 넣으라며 에러가 발생한다.
이제 직접 코드를 짜봅시다!
먼저, 목표는 Node별 CPU 사용량 그래프를 찍어보는 것이다.
이를 위해 promQL문으로 node_cpu_seconds_total
이 필요한데, 이는 CPU 사용량을 나타내는 메트릭으로, 누적된 CPU시간을 나타내기에 계속해서 증가한다. (프로메테우스 그래프)
즉, 우린 해당 promQL문의 데이터 자체의 값이 아닌, 변화량을 측정해야한다.
아까봤던 rate는 range vector값을 이용해 초당평균변화율을 구한다. 바로 코드로 넘어갑시다!
import requests
import pandas as pd
import matplotlib.pyplot as plt
import pytz
from datetime import datetime
def convert_to_kst(timestamp):
utc_time = datetime.utcfromtimestamp(timestamp).replace(tzinfo=pytz.utc)
kst_time = utc_time.astimezone(pytz.timezone("Asia/Seoul"))
return kst_time.strftime("%H:%M")
node_info = {
"192.168.123.150:9100": {"name": "master node", "color": "green"},
"192.168.123.151:9100": {"name": "worker node", "color": "orange"},
}
prometheus_url = "http://192.168.123.150:30247" # Prometheus 주소
query = (
"100 - (avg by (instance) (rate(node_cpu_seconds_total{mode='idle'}[5m])) * 100)"
)
gmt_timezone = pytz.timezone("GMT")
start_time = pd.Timestamp.now(tz=gmt_timezone) - pd.DateOffset(minutes=3)
end_time = pd.Timestamp.now(tz=gmt_timezone)
params = {
"query": query,
"start": start_time.timestamp(),
"end": end_time.timestamp(),
"step": 60,
}
response = requests.get(f"{prometheus_url}/api/v1/query_range", params=params)
data = response.json()
print(data)
plt.figure(figsize=(12, 6))
for result in data["data"]["result"]:
timestamps, values = zip(*result["values"])
kst_timestamps = [convert_to_kst(ts) for ts in timestamps] # 한국 시간대로 변경. 생략가능
values = [(float(value)) for value in values] # 기본이 string이라, float으로 바꿔줘야함.
plt.plot(
kst_timestamps,
values,
label=node_info[result["metric"]["instance"]]["name"],
color=node_info[result["metric"]["instance"]]["color"],
linestyle="-",
)
plt.xlabel("Time (KST)")
plt.ylabel("CPU Usage (%)")
plt.title("Node CPU Usage")
plt.grid(True)
plt.legend()
plt.gca().xaxis.set_major_locator(plt.MultipleLocator(10))
plt.show()
query_range로 데이터를 불러온다. 이때 프로메테우스가 그리니치 시간이기 때문에, 추후 한국시간대로 변환해줬다.
파이썬 그래프 그리는 부분은 따로 설명을 생략하겠다! label의 경우 ip가 나오는게 맘에 안들어서, master node, worker node로 변경해줬다.
결과물이다!
S
실제 kubectl get node로 확인한 것과 비슷한 것을 볼 수 있다! 끝!
~ 다음에 쓸 글 ~
참고 블로그
https://prometheus.io/docs/prometheus/latest/querying/api/
https://devthomas.tistory.com/15
https://newtype.pe.kr/entry/promethues-%EC%BF%BC%EB%A6%AC-%EB%AA%87-%EA%B0%80%EC%A7%80