Info

2023년에 직접 경험한 내용을 다루고 있습니다.

Prometheus에서는 PromQL(Prometheus Query Language)이라는 고유 쿼리를 사용하여 실시간 메트릭을 필터링하고 집계할 수 있습니다. 당시에는 제가 직접 PromQL 작성을 하지는 않았지만, 기존 쿼리의 결함을 발견하여 몇 가지 수정 제안을 한 경험이 있어 그 내용을 기록해 두려 합니다.

avg_over_time 함수의 계산 방식

Kibana 대시보드 활용을 위해 PromQL로 집계하던 데이터를 Elasticsearch로 이관하는 작업이 있었는데, 이 과정에서 두 집계 결과가 일치하지 않는 이슈가 있었습니다. 이를 조사한 결과, avg_over_time 함수를 잘못 사용하여 PromQL에서 집계한 값이 무조건 높게 나올 수밖에 없다는 것을 알게 되었습니다.

avg_over_time 함수는 전체 구간의 평균값을 구할 때 부정확한 값이 나올 수 있습니다. 설정한 전체 구간이 아닌 데이터가 존재했던 구간만을 고려하기 때문입니다. GitHub 이슈에서도 관련 내용을 확인할 수 있습니다.

예를 들어 어떤 리소스 A가 하루 동안 1Gi의 메모리를 소비하고, 하루 동안 리소스가 중지되었다고 가정하겠습니다. 일반적으로 우리는 이틀 동안 평균 0.5Gi의 메모리를 사용했다는 결과를 원할 것입니다. 하지만, avg_over_time 함수는 실제 데이터가 있던 하루 동안의 평균만 측정하므로 결과는 1Gi가 됩니다.

따라서 이 경우에는 avg_over_time 함수보다 오히려 분자•분모를 따로 sum 계열 함수로 계산하고 직접 나누는 등 다른 방식을 사용하는 것이 더 정확한 결과를 도출할 수 있습니다.

적합한 필터 설정하기

위에서 PromQL의 집계값이 더 높게 나왔던 이유는 하나가 더 있었습니다. 문제가 되는 쿼리에서는 메트릭을 중복해서 집계하고 있었기 때문입니다.

Kubernetes의 Deployment에서 생성되는 Pod는 특별한 설정이 없다면 이름 뒤쪽에 랜덤 문자열이 붙고, 각각 고유한 ID 값을 가집니다. 어떤 리소스가 모종의 이유로 재시작되었다면 재시작 전후로 다른 리소스로 간주됩니다. 기존 쿼리에서는 이러한 점을 고려하지 않은 채로 avg_over_time 함수를 사용하여 메트릭을 중복으로 수집하고 있었습니다. 이를 개선하려면 리소스명 또는 라벨 등을 사용하여 다른 필터링 옵션을 적용해야 할 것입니다.

irate 함수와 rate 함수

2023년 말에 새로운 PromQL 메트릭을 테스트하던 중 간헐적으로 값이 치솟는 문제가 있었습니다. 조사한 결과 쿼리 내에서 사용한 irate 함수의 사용이 원인이었습니다.

irate 함수는 값을 계산할 때 마지막 데이터 포인트 2개를 사용합니다. 이는 빠르게 변화하는 메트릭을 집계할 때 사용해야 하며, 알림 용도이거나 변화가 느린 메트릭에는 사용을 권장하지 않는다고 공식 문서에서 서술하고 있습니다. 주어진 시간 동안의 평균 변화율을 계산하고 싶다면 rate 함수를 사용하는 것이 좋습니다.
당시 수집하던 메트릭은 최소 1일 단위로 추이를 집계하고 있었고 급격한 변화를 측정하기 위한 용도가 아니었습니다. 따라서 irate 함수 대신 rate 함수 사용을 담당자에게 제안드렸고 이슈를 해결할 수 있었습니다.