1. PromQL 언어 소개
공식 문서: https://prometheus.io/docs/prometheus/latest/querying/basics/
프로메테우스는 함수형 표현 언어인 PromQL(Prometheus Query Language)을 제공합니다. 이를 통해 사용자는 실시간으로 시계열 데이터를 검색하고 집계할 수 있습니다. 표현식 계산 결과는 차트로 표시되거나, 프로메테우스 표현식 브라우저에서 테이블 형식으로 표시될 수 있으며, 외부 시스템에서 사용할 수 있는 HTTP API의 데이터 소스로도 활용될 수 있습니다.
2. PromQL의 데이터 타입
1. 즉시 벡터(Instant Vector)
즉시 벡터(Instant Vector): 특정 또는 모든 시계열 집합에서 동일한 타임스탬프를 가진 일련의 샘플 값.
쉽 말해 특정 시점의 결과입니다.
예를 들어, system_memory_free_bytes로 현재 사용 가능한 메모리를 조회하면 즉시 벡터가 됩니다.
이 표현식은 해당 시계열의 가장 최근 샘플 값만 반환하며, 이러한 표현식을 즉시 벡터 표현식이라고 합니다.
예: api_http_requests_total
2. 구간 벡터(Range Vector)
구간 벡터(Range Vector): 특정 또는 모든 시계열 집합에서 지정된 동일한 시간 범위 내의 모든 샘플 값
구간 벡터 선택기는 0개, 1개 또는 여러 개의 시계열에서 주어진 시간 범위 내의 각각의 샘플 그룹을 반환할 수 있습니다.
구간 벡터 선택기의 차이점은, 즉시 벡터 선택기 표현식 뒤에 [] 안에 포함된 시간 길이를 추가하여 시간 시퀀스에서 반환할 샘플의 시간 범위를 지정해야 한다는 점입니다.
쉽 말해 특정 기간 동안의 결과입니다.<br></br>
시간 범위: 현재 시간을 기준 시점으로 과거 특정 시간 길이를 가리킵니다. 예를 들어, [5m]은 지난 5분을 의미합니다.
◆ 사용 가능한 시간 단위: ms(밀리초), s(초), m(분), h(시간), d(일), w(주), y(년)
◆ 정수 시간을 사용해야 하며, 여러 다른 단위의 조합을 가능하며, 시간 단위가 큰 것부터 작은 순서로 연결할 수 있습니다(예: 1h30m). 1.5h와 같은 사용은 불가능합니다.
예를 들어 최근 24시간의 네트워크 인터페이스 트래픽 추이 그래프는 다음과 같습니다:
api_http_requests_total[1d]
오프셋 벡터 선택기
선택기는 기본적으로 현재 시간을 기준으로 하며, 오프셟 수정자는 기준 시간을 앞으로 조정하는 데 사용됩니다. 오프셟 수정자는 선택기 바로 뒤에 위치하며, offset 키워드를 사용하여 조정할 양을 지정합니다.
예를 들어, api_http_requests_total offset 5m은 api_http_requests_total을 메트릭 이름으로 하는 모든 시계열의 과거 5 분 시점의 즉시 샘플을 가져옵니다.
api_http_requests_total[5m] offset 1d는 현재 시점으로부터 1일 전의 5 분 구간 내의 모든 샘플을 가져옵니다.<br></br><br></br>
오프셋 벡터 선택기를 통해 전년 동기 대비 및 전월 동기 대비 분석이 가능합니다.
3. 스칼라 데이터(Scalar)
스칼라(Scalar): 부동 소수점 형식의 단일 데이터 값입니다. system_load1로 조회하면 즉시 벡터가 반환되지만,
내장 함수 scalar()를 사용하여 즉시 벡터를 스칼라로 변환할 수 있습니다. 예: scalar(sum(system_load1))
4. 문자열(String)
문자열(String): 간단한 문자열 형식의 데이터 값입니다. (현재 미사용)
3. 메트릭 타입
1. Counter
카운터(Counter): 누적 메트릭 데이터를 나타내며, 리셋되지 않는 한 증가만 합니다.
예: 디스크 I/O 총량, 웹 서버의 총 요청 수, 네트워크 인터페이스를 통과한 총 패킷 수 등.
2. Gauge
게이지(Gauge): 임의로 변할 수 있는 메트릭 데이터를 나타내며, 값이 언제든 증가하거나 감소할 수 있습니다.
예: 대역폭 속도, CPU 부하, 메모리 사용률, 웹 서버 활성 연결 수 등.
3. Histogram
누적 히스토그램(Histogram): 일정 기간 동안 데이터를 샘플링합니다(보통 요청 지속 시간 또는 응답 크기 등).
예를 들어, 분당 활성 연결 수를 생성한다면 하루에 1440개의 데이터가 생성됩니다.
데이터의 간격을 2시간으로 설정하면 2시점의 막대(bucket)에는 0시부터 2시까지의 데이터가 포함되고,
4시점의 막대에는 0시부터 4시까지의 데이터가 포함됩니다.
4. Summary
서머리(Summary): 히스토그램과 유사한 메트릭 타입이지만, 클라이언트가 일정 기간(기본값 10분) 동안의 각 샘플링 지점에서 통계를 계산하고
분위수 값을 저장하며, 서버 측에서 해당 값을 직접 가져올 수 있습니다.
5. 학습 참고
프로메테우스의 /metrics 엔드포인트에 접속하여 주석을 통해 데이터 타입을 확인할 수 있습니다.
4. 일반적인 메트릭 데이터
CPU 관련 메트릭:
system_cpu_idle_seconds_total: CPU 유휴 시간(초)의 합계. CPU 사용률 평가에 중요한 지표 중 하나입니다.
system_cpu_system_seconds_total, system_cpu_user_seconds_total 등: 각각 커널 모드와 사용자 모드에서 CPU가 실행된 시간을 나타냅니다.
메모리 관련 메트릭:
system_memory_total_bytes: 메모리 총량(바이트 단위).
system_memory_free_bytes: 사용 가능한 메모리 크기(바이트 단위).
system_memory_buffer_bytes와 system_memory_cache_bytes: 각각 커널에서 버퍼와 캐시로 사용되는 메모리 크기입니다.
system_memory_swap_total_bytes와 system_memory_swap_free_bytes: 각각 스왑 공간의 총 크기와 사용 가능한 크기입니다.
디스크 관련 메트릭:
system_filesystem_size_bytes: 파일 시스템 크기(바이트 단위).
system_filesystem_free_bytes와 system_filesystem_avail_bytes: 각각 파일 시스템의 여유 공간과 루트가 아닌 사용자가 사용 가능한 공간 크기입니다.
system_disk_io_current, system_disk_io_time_seconds_total 등: 현재 진행 중인 I/O 작업 수 및 I/O 작업에 소요된 총 시간과 같은 디스크 I/O 작업 관련 메트릭입니다.
네트워크 관련 메트릭:
system_network_receive_bytes_total와 system_network_transmit_bytes_total: 각각 네트워크 인터페이스에서 수신 및 전송된 총 바이트 수입니다.
이러한 메트릭은 네트워크 트래픽 및 대역폭 사용량 평가에 매우 중요합니다.
시스템 부하 관련 메트릭:
system_load1, system_load5, system_load15: 각각 과거 1분, 5분, 15분 동안의 시스템 평균 부하입니다.
이러한 메트릭은 시스템의 전반적인 바쁨 정도와 성능을 이해하는 데 도움이 됩니다.
전체 메트릭 목록을 얻으려면 exporter의 metrics 엔드포인트(일반적으로 /metrics)에 접속할 수 있습니다.
5. PromQL - 매처
# 레이블 선택기는 레이블 필터링 조건을 정의하는 데 사용되며, 현재 4가지 일치 연산자를 지원합니다:
= : 완전히 일치
!= : 일치하지 않음
=~ : 정규식 일치
!~ : 정규식 불일치
# 조회 형식 <메트릭 이름>{<레이블 이름>=<레이블 값>, ...}
system_load1{instance="10.0.0.5:9100"}
system_load1{job="monitoring-node"}
system_load1{job="monitoring-node",instance="10.0.0.5:9100"} # 정확 일치
system_load1{job="monitoring-node",instance!="10.0.0.5:9100"} # 부정
system_load1{instance=~"10.0.0.*:9100$"} # 정규식 포함 일치
system_load1{instance!~"10.0.0.5:9100"} # 정규식 포함 부정
<strong>주의사항:
</strong>1. 빈 레이블 값을 가진 레이블 선택기와 일치할 때, 해당 레이블을 정의하지 않은 모든 시계열도 조건에 부합합니다.
예를 들어, api_http_requests_total{handler= ""}는 해당 메트릭 이름에서 handler 레이블을 사용하지 않은 모든 시계열도 조건에 부합합니다.
2. 정규식은 완전히 앵커링 메커니즘을 실행하며, 지정된 레이블의 전체 값과 일치해야 합니다.
3. 벡터 선택기에는 적어도 하나의 메트릭 이름이 포함되어야 하거나, 적어도 하나의 빈 문자열과 일치하지 않는 레이블 선택기가 있어야 합니다.
예를 들어, { job=""}은 잘못된 벡터 선택기입니다.
4. __name__을 레이블 이름으로 사용하면 메트릭 이름을 필터링할 수도 있습니다.
예를 들어, {__name__=~".*http_requests_total"}는 http_requests_total로 끝나는 모든 메트릭과 일치합니다.
6. PromQL - 시간 범위
s - 초
m - 분
h - 시간
d - 일
w - 주
y - 년
# 즉시 벡터 표현식, 현재 최신 데이터 선택
system_memory_total_bytes{}
# 구간 벡터 표현식, 현재 시간을 기준으로 모든 노드의 system_memory_total_bytes 메트릭 5분 내 데이터 선택
system_memory_total_bytes{}[5m]
# 구간 벡터 표현식, 현재 시간을 기준으로 특정 노드의 system_memory_total_bytes 메트릭 5분 내 데이터 선택
system_memory_total_bytes{instance="10.0.0.5:9100"}[5m]
7. PromQL - 연산자
+ 덧셈
- 뺄셈
* 곱셈
/ 나눗셈
% 모듈로
^ 제곱<br></br>
system_memory_free_bytes/1024/1024 # 메모리 단위를 바이트에서 메가바이트로 변환
system_disk_read_bytes_total{device="sda"} + system_disk_written_bytes_total{device="sda"} # 디스크 읽기 및 쓰기 데이터량 계산
8. PromQL - 집계 연산자
# 프로메테우스는 다음과 같은 내장 집계 함수(집계 연산자)를 제공합니다:
●sum(): 샘플 값의 합계를 계산합니다
●min() : 샘플 값中最小값을 찾습니다
●max() : 샘플 값中最대값을 찾습니다
●avg() : 샘플 값의 평균을 계산합니다
●count() : 그룹 내의 시계열 수를 세어줍니다
●stddev() : 샘플 값의 표준 편차를 계산하여 데이터의 변동 크기를 파악하는 데 도움이 됩니다(예: CPU, 메모리, 트래픽 변동)
●stdvar() : 샘플 값의 분산을 계산하며, 이는 표준 편차를 계산하는 중간 단계입니다
●topk() : 그룹 내 샘플 값이 가장 큰 상위 k개의 시계열 및 값을 역순으로 반환합니다
●bottomk() : 그룹 내 샘플 값이 가장 작은 하위 k개의 시계열 및 값을 순서대로 반환합니다
●quantile() : 분위수를 사용하여 데이터의 분포 상태를 평가하며, 그룹 내 지정된 분위수 값을 반환합니다
●count_values() : 그룹 내 시계열의 샘플 값 수를 세어줍니다, 즉 특정 값과 같은 샘플의 개수를 계산합니다
●rate(): counter 데이터 타입과 함께 사용되는 전용 함수로, 지정된 기간 내 counter 데이터 타입의 초당 평균 증가량을 계산합니다.
데이터가 비교적 안정적인 경우에 적합합니다
●irate (): counter 데이터 타입과 함께 사용되는 전용 함수로, 지정된 시간 범위 내 가장 최근의 두 데이터로 데이터 속도를 계산합니다.
변화가 큰 데이터 계산에 적합하며, 표시되는 데이터가 비교적 정확합니다
●abs(): 메트릭 데이터의 값을 절대값으로 반환합니다
●absent(): 모니터링 항목에 데이터가 있으면 빈 값을 반환하고, 데이터가 없으면 1을 반환합니다
각 노드의 최대 트래픽 값 계산: max(system_network_receive_bytes_total) by (instance) <br></br>
각 노드의 최근 5분간 각 장치별 최대 트래픽 계산: max(rate(system_network_receive_bytes_total[5m])) by (device) <br></br>
최근 총 요청 수: sum(api_http_requests_total) <br></br>
반환 값의 개수 세기: count(system_os_version)<br></br>
내림차순 상위 6개: topk(6, api_http_requests_total) <br></br>
값이 가장 작은 하위 N개 데이터: bottomk(6, api_http_requests_total) <br></br>
rate(api_http_requests_total[5m]) <br></br>
rate(system_network_receive_bytes_total[5m]) <br></br>
irate(api_http_requests_total[5m]) <br></br>
irate(system_network_receive_bytes_total[5m])
abs(sum(api_http_requests_total{handler="/metrics"}))
absent(sum(api_http_requests_total{handler="/metrics"})) 값이 있으면 빈 값, 없으면 1 반환
9. PromQL - 집계 표현식
PromQL의 집계 작업 구문은 다음 두 가지 형식 중 하나를 사용할 수 있습니다:
<집계 함수>(벡터 표현식) by|without (레이블)
<집계 함수> by|without (레이블) (벡터 표현식)<br></br>
by : by 절에 지정된 레이블만을 사용하여 집계하며, 결과 벡터에 나타나지만 by로 지정되지 않은 레이블은 무시됩니다.
컨텍스트 정보를 유지하기 위해 by 절을 사용할 때 job, instance와 같이 원래 결과에 나타나는 레이블을 명시적으로 지정해야 합니다.
without : 결과 벡터에서 without로 지정된 레이블을 제거하며, 지정되지 않은 레이블은 그룹화 기준으로 사용됩니다<br></br><br></br>
예제:<br></br>
(1) 각 호스트의 CPU 최근 5분간 평균 사용율 (1 - avg(rate(system_cpu_idle_seconds_total[5m])) by (instance)) * 100
(2) 1분의 평균 부하 시계열이 호스트 CPU 수의 2배를 초과하는지 확인 system_load1 > on (instance) 2 * count (system_cpu_idle_seconds_total) by (instance)
(3) 호스트 메모리 사용율 계산 사용 가능한 메모리 공간: 유휴 메모리, 버퍼, 캐시 메트릭의 합계 system_memory_free_bytes + system_memory_buffer_bytes + system_memory_cache_bytes
사용된 메모리 공간: 총 메모리 공간에서 사용 가능 공간을 뺀 값 system_memory_total_bytes - (system_memory_free_bytes + system_memory_buffer_bytes + system_memory_cache_bytes)
사용율: 사용된 공간을 총 공간으로 나눈 값 (system_memory_total_bytes - (system_memory_free_bytes + system_memory_buffer_bytes + system_memory_cache_bytes)) / system_memory_total_bytes * 100
(4) 모든 노드의 모든 컨테이너 총 메모리 계산: sum by (instance) (container_memory_usage_bytes{instance=~"node*"})/1024/1024/1024
(5) node01 노드의 최근 1분간 모든 컨테이너 CPU 사용율 계산: sum (rate(container_cpu_usage_seconds_total{instance="node01"}[1m])) / sum (machine_cpu_cores{instance="node01"}) * 100 #container_cpu_usage_seconds_total는 컨테이너가 CPU를 점유한 시간의 합계를 나타냅니다
(6) 최근 5분간 각 컨테이너 CPU 사용량 변화율 계산 sum (rate(container_cpu_usage_seconds_total[5m])) by (container_name)
(7) K8S 클러스터에서 최근 1분간 각 Pod의 CPU 사용량 변화율 조회 sum (rate(container_cpu_usage_seconds_total{image!="", pod_name!=""}[1m])) by (pod_name) #조회된 데이터가 모두 컨테이너 관련이므로, Pod별로 그룹화하여 집계하는 것이 좋습니다
(8) 10분 내 각 API 인터페이스의 상태별 개수 조회
sum without(job,instance) (rate(api_http_requests_total[10m])) # sum by(code,handler)와 동일
참고 문서: https://prometheus.io/docs/prometheus/latest/querying/basics/
10. 시간 집계 함수
avg_over_time(range-vector): 지정된 구간 내 모든 점의 평균값입니다.
min_over_time(range-vector): 지정된 구간 내 모든 점의 최소값입니다.
max_over_time(range-vector): 지정된 구간 내 모든 점의 최대값입니다.
sum_over_time(range-vector): 지정된 구간 내 모든 값의 합계입니다.<br></br>
sum_over_time(api_http_requests_total[5m]) # 각 인터페이스 5분 내 요청 총합
count_over_time(range-vector): 지정된 구간 내 모든 값의 개수입니다.
quantile_over_time(scalar, range-vector): 지정된 구간 내 값의 φ 분위수(0 ≤ φ ≤ 1)입니다.
stddev_over_time(range-vector): 지정된 구간 내 값의 전체 표준 편차입니다.
stdvar_over_time(range-vector): 지정된 구간 내 값의 전체 분산입니다.
last_over_time(range-vector): 지정된 간격 내 가장 최근 점의 값입니다.
present_over_time(range-vector): 지정된 간격 내 임의 시리즈의 값이 1입니다.
참고 문서: https://prometheus.io/docs/prometheus/latest/querying/functions/