[Monitoring] Promql 사용법

[Monitoring] Promql 사용법

안녕하세요? 정리하는 개발자 워니즈입니다. 이번시간에는 프로메테우스 쿼링에 대해서 정리하는 시간을 갖도록 하겠습니다.

프로메테우스를 잘 활용하기 위해서는 query를 어떤식으로 다루고 활용할지를 고민을 해봐야됩니다. 그래서 이번시간에는 Promql을 조금더 손쉽게 다루기 위해서는 어떤식으로 데이터를 다루고 사용하는지에 대해서 정리해보겠습니다.

1. 데이터 구조

프로메테우스 server에서 데이터를 조회하게 되면, 다음과 같은 형식으로 조회됩니다.

node_memory_MemAvailable_bytes{app="prometheus",chart="prometheus-11.0.4",component="node-exporter",heritage="Tiller",instance="10.0.150.147:9100",job="kubernetes-service-endpoints",kubernetes_name="prometheus-node-exporter",kubernetes_namespace="prometheus",kubernetes_node="ip-10-0-150-147.ap-northeast-2.compute.internal",release="prometheus"}

간단하게, 필자는 node_memory_MemAvailable_bytes라는 내용을 조회해봤고, 가져오는 값이 엄청 길게 나오긴했지만, 결국에는 다음의 세가지로 이루어져있습니다.

  • 데이터 이름

메트릭을 구분하기 위한 고유한 이름입니다. 프로메테우스에서는 데이터 이름을 입력하는 것만으로도 해당 데이터의 목록을 조회할 수 있습니다.

  • 라벨

일한 데이터에서 종류를 구분하기 위한 식별자 입니다. 같은 데이터 이름이라도 다른 라벨을 갖는 여러개의 데이터가 존재할 수 있습니다. 프로메테우스의 쿼리는 대부분 라벨을 기준으로 수행됩니다.

  • 데이터 값

데이터의 값을 나타내는 부분을 스칼라라고 합니다. 좀 더 정확하게 말하자면, 프로메테우스에서는 단순 숫자 값에 대해서는 모두 스칼라 라는 표현을 사용합니다.

2. 데이터 타입

프로메테우스에서 데이터 타입은 4가지로 분류 됩니다. 위에서 언급한 메트릭 값(value)의 타입을 말하는 것이 아닙니다. 프로메테우스에서 사용하는 값의 타입은 오로지 float64 입니다.

  • Instant vector – a set of time series containing a single sample for each time series, all sharing the same timestamp
  • Range vector – a set of time series containing a range of data points over time for each time series
  • Scalar – a simple numeric floating point value
  • String – a simple string value; currently unused

3. PromQL 사용하기

프로메테우스는 데이터를 쿼리하기 위해서 PromQL 이라고 하는 자체 쿼리 언어를 사용합니다.

사실 PromQL을 정식으로 하나씩 공부하지 못하고, Grafana 대시보드를 import 하여 안에 있는 내용물을 하나씩 분석하면서 익혀 나가기로 했습니다.

필자가 사용한 대시보드는 아래와 같습니다.

우선, 클러스터내의 모든 내용 Pod부터 Node까지 전체적인 내용을 손쉽게 볼 수 있습니다. 요즘에는 확실히 여러가지 좋은 툴과 이미 만들어진 내용물들이 많아서 공수를 안들이고도 근사한 대시보드를 만들 수 있는 것 같습니다.

그래도 사용하면서, 기왕이면 어떤 내용인지도 알면 좋을 것 같아서 하나씩 뜯어 보기로했습니다.

위에 보시는것처럼 처음 접속하게 되면, Total Usage 라는 항목으로 CPU, MEMORY, FILE SYSTEM에 대해서 나타나게 됩니다. 모니터링 하면, 가장 크게 식별하는 Metric중 하나들이라고 생각이 됩니다.


  • Worker Nodes

cpu

# sum (rate (container_cpu_usage_seconds_total{id="/",node=~"^$Node$"}[5m])) / sum (machine_cpu_cores{node=~"^$Node$"})

우선 위의 내용을 분석하기로 해봤습니다.

# 분자부터..
machine_cpu_cores{node=~"^$Node$"}

우선, 위의 내용은 머신, 즉 전체 노드에 대한 cpu cores를 가져오는 내용입니다. $Node라고 variable을 받는것은 Grafana에서 보면, Variable을 선언할 수 있는데, 그부분을 가져오는 것입니다.

Grafana Template Vriables

[Dashboard] > [Configuration] > [Vriables]에 보시면, 셋팅을 할 수 있습니다.

중요한 것은 Query 즉, query에서 해당 variables를 매핑해서 사용하겠다는 것이고, 실제 쿼리를 할떄는 label_values(node_boot_time_seconds, node) 와 같이 사용을 하겠다는 것입니다.

어쩃든, node전체 머신을 가져올 수 있습니다.

즉 다시 위의 내용에서 분모가 되는것은 아래와 같습니다.

# 노드 전체의 cpu cores 합산
sum (machine_cpu_cores{node=~"^$Node$"})
# 분자를 분석하면..
container_cpu_usage_seconds_total{id="/",node=~"^$Node$"}[5m]

위의 내용에서 보면, cpu 사용을 시간으로 합산한 값을 주는 것 같습니다. 그런데, 전체 노드 머신에서 5분간 수집된 집계를 말합니다.

# rate 함수 적용
rate (container_cpu_usage_seconds_total{id="/",node=~"^$Node$"}[5m])

rate 함수 : rate 함수는 조금 특별한데, 수집된 데이터의 1초 당 증감률을 계산한다. 예를 들어 10초간 수집되는 Target에서 5, 10, 15 .. 와 같은 데이터가 순서대로 저장되었다면 10초간 5의 값 상승이 있었으니 rate의 결과값은 0.5가 된다. 단, rate 함수의 인자는 Range Vector여야만 하므로 [5m] 과 같은 제한자와 함께 사용해야만 한다.

그렇다면, 위의 내용을 풀어보자.

전체 노드의 컨테인너가 사용한 cpu 사용 총합 [5분간 집계] 의 증감 비율을 말한다. 그리고 이것들의 총합이 최종이다.

# 컨테이너가 사용한 cores 수
sum (rate (container_cpu_usage_seconds_total{id="/",node=~"^$Node$"}[5m]))

정리를 해보면,

컨테이너가 사용한 cores 수 / 전체 Node의 cores 수 입니다.

그래서 대시 보드를 보면 알게 되겠지만, 각 cores수도 나와있고, 사용률, 증감여부 등이 표기가 됩니다.

memory

# memory 사용률
sum (container_memory_working_set_bytes{id="/",node=~"^$Node$"}) / sum (machine_memory_bytes{node=~"^$Node$"}) * 100

cpu에서 봤던 내용과 유사하지만, 다른 부분이 있습니다. 다음의 2가지가 보입니다.

container_memory_working_set_bytes

machine_memory_bytes

정리를 해보면,

컨테이너가 사용한 memory bytes 값 / 전체 Node가 사용한 메모리 bytes 값

rate가 없는 것이 보일 것입니다. rate를 사용하기 위해서는 시간당 이 들어가야되는데, 우선 cpu같은 경우는 container의 seconds별로 수집된 집계였고, memory같은 경우는 특정 시간당이 아니고 현재 사용하는 값입니다.

filesystem

#디스크 사용률
sum (container_fs_usage_bytes{device=~"^/dev/.*$",id="/",node=~"^$Node$"}) / sum (container_fs_limit_bytes{device=~"^/dev/.*$",id="/",node=~"^$Node$"}) * 100

container_fs_usage_bytes

container_fs_limit_bytes

정리를 해보면,

컨테이너가 사용하는 mount된 disk의 사용 bytes의 합계 / 컨테이너가 사용할 수 있는 mount 된 disk의 전체 합계

현재 mount 된 disk를 container들이 얼마나 사용하는지를 알 수 있습니다.

그 외에 다음과 같은 값들을 사용합니다.

#노드의 전체 대 수 
sum(kube_node_info{node=~"$Node"})

#Deployments의 갯 수 
sum(kube_deployment_status_replicas{namespace=~".*"})

#Running 중인 pod의 갯 수 
sum(kube_pod_status_phase{namespace=~".*", phase="Running"})

#pod의 CPU 사용 률 
sum (rate (container_cpu_usage_seconds_total{image!="",name=~"^k8s_.*",node=~"^$Node$"}[5m])) by (pod_name)

#pod의 memory 사용 률 
sum (container_memory_working_set_bytes{image!="",name=~"^k8s_.*",node=~"^$Node$"}) by (pod_name)

4. 마치며..

필자가 속한 프로젝트에서 EKS를 활용해서 kubernetes cluster를 구성하였고, 모니터링을 하기 위한 데이터 수집 장치로 Prometheus를 설치하였습니다. 또한, 모니터링 대시보드를 위해서 Grafana까지 설치하고 연동을 하였습니다.

서두에서 이야기를 했지만, 요즘에는 완제품 형식의 프로그램이 많이 개발되어있어서 입맛에 따라 설치하고 연동한 뒤, 살짝 손만 대주면 됩니다.

하나하나 구축을 한다면, 정말 많은 노동력과 어려움이 있었을텐데, 기성품을 가져다두고 한개씩 공부를 하니 재밌었던 경험인것 같습니다.

다음 이시간에는 Grafana대시보드의 Alert 기능을 통해서 Slack으로 알람을 주는 내용을 작성해보도록 하겠습니다.

답글 남기기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다