Prometheus
고친 사람 github-actions[bot]
Prometheus 는 돌아가는 프로그램에서 수치를 주기적으로 거둬들여 시각과 함께 쌓아 두는 감시 시스템입니다. 쌓아 둔 수치에 질문을 던지면 「요청이 지금 초당 몇 건인가」·「오류가 한 시간 전보다 늘었나」에 답합니다. 조건을 미리 적어 두면 값이 그 조건에 닿을 때 알림을 냅니다. 내려받아 서버에 띄우는 물건입니다.
쉽고 빠른 이해
Prometheus 는 여러 서버의 계기판을 대신 읽어 주는 기록원입니다. 서버마다 「지금 요청 수」·「지금 메모리 사용량」 같은 값을 밖에 내걸어 두면, Prometheus 가 정해진 간격마다 돌며 그 값을 적어 둡니다.
이런 값을 안 모아 두면 지금 값만 알고 흐름을 모릅니다. 서버에 들어가 보는 그 순간의 수치는 알 수 있지만, 한 시간 전보다 늘었는지는 알 길이 없습니다. 서버가 서른 대면 손으로 더해야 합니다.
어떻게 도나:
- 감시할 프로그램이 자기 수치를 주소 하나에 글자로 내겁니다
- Prometheus 가 정해진 간격마다 그 주소를 열어 값을 읽어 옵니다
- 읽은 값에 읽은 시각을 붙여 자기 디스크에 쌓습니다
- 쌓인 값에 질문을 던지거나, 조건에 닿으면 알림을 보냅니다
대가가 있습니다. 값은 간격마다 찍은 표본이라 그 사이 일은 못 봅니다. 오래된 값은 지웁니다. 한 대가 혼자 쥐고 돌아 감시 대상이 아주 많아지면 그 한 대를 키우는 수밖에 없습니다.
상세
Prometheus 는 모니터링에 쓰는 서버 프로그램입니다. 내려받아 띄워 두면 설정에 적힌 대상들을 주기마다 돌며 수치를 거둬 옵니다. 거둔 수치는 자기 디스크에 시각과 함께 쌓입니다.
이 절은 먼저 수치를 왜 한곳에 모아야 하는지 봅니다. 그다음 값을 거둬 오는 방식, 거둬 오는 값의 생김새, 그 값이 쌓이는 모양을 차례로 봅니다. 이어서 쌓인 값에 질문하는 언어, 대상 목록을 갱신하는 방법, 알림을 내는 방법을 봅니다. 끝으로 이 물건이 포기한 것을 봅니다.
한 벌이 어떻게 생겼는지부터 그림으로 보겠습니다.
flowchart TD
subgraph 대상["감시 대상"]
A["앱 서버"]
B["데이터베이스 익스포터"]
end
대상 --> P["Prometheus 서버"]
P --> D["대시보드"]
P --> M["Alertmanager"]
M --> N["메일 · 채팅"]
그림에서 화살표는 수치가 흐르는 방향입니다. 다만 말을 먼저 거는 쪽은 Prometheus 입니다. 대상은 값을 내걸어 둘 뿐이고 가져가는 일은 Prometheus 가 합니다.
가운데 서버 말고 둘이 더 보입니다. 익스포터는 감시 대상의 수치를 대신 내걸어 주는 프로그램이고, Alertmanager 는 알림을 사람에게 보내는 프로그램입니다. 둘 다 뒤에서 다시 봅니다.
수치를 한곳에 모으는 까닭
서버 한 대가 지금 요청을 몇 건 받고 있는지 알고 싶다고 해 봅시다. 그 서버에 들어가 명령을 치면 지금 값은 나옵니다. 그런데 어제 이 시간에는 얼마였는지, 아까부터 늘고 있었는지는 나오지 않습니다.
서버가 서른 대면 더 곤란합니다. 한 대씩 들어가 보는 동안 값이 계속 변합니다. 서른 대를 합친 수를 보려면 손으로 더해야 합니다. 더하는 사이에 또 변합니다.
Prometheus 는 이 일을 대신합니다. 서른 대의 값을 같은 간격으로 거둬들여 한곳에 쌓습니다. 쌓인 값에는 시각이 붙어 있어서 「한 시간 전보다 늘었나」를 물을 수 있습니다.
값을 거둬 오는 방식, 끌어오기
수치를 모으는 방식은 둘로 갈립니다. 대상이 감시 서버로 값을 보내는 밀어넣기가 하나고, 감시 서버가 대상에게서 값을 가져오는 끌어오기가 다른 하나입니다. Prometheus 는 끌어오기를 씁니다.
감시할 프로그램은 자기 수치를 HTTP(HyperText Transfer Protocol, 하이퍼텍스트 전송 규약) 주소 하나에 내걸어 둡니다. 그 주소를 열면 지금 값들이 글자로 적혀 나옵니다. Prometheus 는 설정에 적힌 대상의 그 주소를 정해진 간격마다 열어 읽어 갑니다. 이렇게 한 번 읽어 가는 동작을 수집이라고 부르겠습니다.
수치를 내거는 일을 계측이라고 합니다. 프로그램 안에 수를 세는 코드를 넣고 그 수를 밖에서 볼 수 있게 하는 일입니다.
남이 만든 물건은 코드를 고칠 수 없어 계측을 넣을 데가 없습니다. 이럴 때는 그 물건의 수치를 대신 읽어 내걸어 주는 익스포터를 옆에 띄웁니다. 데이터베이스나 운영체제를 감시할 때 이 방법을 씁니다.
끌어오기를 고르면 따라오는 것이 있습니다. 대상은 감시 서버의 주소를 몰라도 됩니다. 어느 대상이 죽었는지는 수집이 실패하는 것으로 바로 드러납니다. 값을 내건 주소는 브라우저로도 열리므로 사람이 직접 확인할 수 있습니다.
대신 Prometheus 가 대상에 닿을 수 없으면 아무것도 못 합니다. 방화벽 너머에 있거나, 몇 초 돌고 끝나는 짧은 작업은 수집 차례가 오기 전에 사라집니다. 이런 대상은 PushGateway 라는 중간 창구에 값을 밀어 두고, Prometheus 가 그 창구에서 끌어오게 합니다.
내걸린 한 줄의 생김새
대상이 내거는 값은 한 줄에 하나씩 적힌 글자입니다. 아래가 그 한 줄입니다.
http_requests_total{method="GET"} 1027
맨 앞은 수치의 이름입니다. 중괄호 안은 레이블이라고 부르는 이름표로, 이 값이 무엇에 관한 것인지를 갈라 줍니다. 맨 뒤가 지금 값입니다. 위 줄은 GET 요청을 지금까지 1027건 받았다는 뜻입니다.
줄에는 시각이 없습니다. 시각은 Prometheus 가 읽어 가는 순간에 붙입니다. 그래서 대상은 과거를 기억할 필요가 없고 지금 값만 들고 있으면 됩니다.
시계열을 가르는 이름과 레이블
같은 이름이라도 레이블 조합이 다르면 서로 다른 갈래로 쌓입니다. 한 갈래가 시계열 하나입니다. 시계열은 같은 대상을 시간 순으로 이어 붙인 값의 줄입니다.
| 내걸린 한 줄 | 쌓이는 곳 |
|---|---|
http_requests_total{method="GET"} |
시계열 하나 |
http_requests_total{method="POST"} |
또 다른 시계열 |
http_requests_total{method="GET",code="500"} |
또 다른 시계열 |
표에서 보듯 레이블이 하나 늘 때마다 시계열이 갈라집니다. 그래서 레이블로 요청 방식이나 상태 코드처럼 값이 몇 가지 안 되는 것을 씁니다.
레이블 값으로 사용자 번호나 주문 번호를 넣으면 시계열이 끝없이 늘어납니다. 이렇게 값의 가짓수가 불어나는 것을 카디널리티 문제라고 부릅니다. 시계열이 많아질수록 메모리와 디스크가 그만큼 더 듭니다.
수치는 성격에 따라 몇 갈래로 나뉩니다. 쌓이기만 하는 계수기, 오르내리는 눈금, 값의 분포를 구간별로 세는 것이 있습니다. 갈래마다 다루는 법이 다릅니다. 그 이야기는 메트릭 편이 합니다.
쌓인 값에 질문하는 언어
Prometheus 에는 자기 질의 언어가 딸려 있습니다. 이름은 PromQL 입니다. Prometheus Query Language 의 줄임말입니다. 이름과 레이블로 시계열을 고른 뒤 함수로 가공하는 식으로 씁니다.
계수기는 쌓이기만 하는 값이라 그 자체로는 읽기 어렵습니다. 1027 이라는 수를 봐도 그게 많은지 적은지 알 수 없습니다. 그래서 값 자체보다 늘어나는 속도를 봅니다.
rate(http_requests_total[5m]) # 초당 요청 수
rate 는 지난 구간 동안 값이 얼마나 빨리 늘었는지를 초 단위로 돌려줍니다. 대괄호 안이 돌아볼 구간입니다. 이렇게 바꿔 놓으면 서버마다 다른 계수기 값을 같은 잣대로 견줄 수 있습니다.
질의 결과를 그림으로 보고 싶으면 대시보드 도구를 앞에 붙입니다. Prometheus 자신도 값을 찍어 보는 간단한 화면을 갖고 있지만, 사람이 늘 보는 화면은 대개 Grafana 같은 도구가 맡습니다.
바뀌는 대상 목록을 따라가는 방법
감시할 대상의 주소는 설정 파일에 적어 둘 수 있습니다. 대상이 늘 같은 서버 몇 대라면 이걸로 충분합니다.
그런데 요즘 서버는 뜨고 지는 일이 잦습니다. Kubernetes 위에서는 컨테이너가 수시로 새로 뜨고 주소가 그때마다 바뀝니다. 목록을 손으로 고치면 따라갈 수 없습니다.
그래서 Prometheus 는 대상 목록을 다른 곳에 물어보는 길을 갖고 있습니다. 쿠버네티스나 클라우드 사업자에게 「지금 돌고 있는 것들의 주소를 달라」고 물어 목록을 갱신합니다. 이렇게 대상을 찾아내는 일을 서비스 디스커버리라고 부릅니다.
조건에 닿을 때 나가는 알림
알림 조건은 질의 식으로 적습니다. 「이 식의 값이 이 선을 넘으면 알림」이라고 규칙 파일에 써 두면 Prometheus 가 주기마다 그 식을 따져 봅니다.
alert: HighErrorRate
expr: rate(errors_total[5m]) > 1
for: 10m
expr 이 따져 볼 식입니다. for 는 그 조건이 얼마 동안 이어져야 알림으로 치는지입니다. for 가 있어서 값이 잠깐 튀었다 돌아오는 것으로는 알림이 안 납니다.
조건에 닿았다는 판정까지가 Prometheus 의 몫입니다. 그 알림을 누구에게 어떻게 보낼지는 Alertmanager 라는 옆 프로그램이 맡습니다. 알림을 묶어 한 통으로 보내는 일, 아는 문제를 잠시 덮어 두는 일이 거기서 일어납니다.
sequenceDiagram
participant 앱
participant Prometheus
participant Alertmanager
loop 수집 주기마다
Prometheus->>앱: 지금 값을 달라
앱-->>Prometheus: 수치 목록
Prometheus->>Prometheus: 값을 쌓고 규칙을 따진다
end
Note over Prometheus: 조건이 정해진 시간 동안 이어질 때만 보낸다
Prometheus->>Alertmanager: 알림
Alertmanager->>Alertmanager: 같은 알림을 묶는다
그림에서 수집과 판정이 같은 되풀이 안에 있습니다. 알림을 위해 따로 도는 절차가 없다는 뜻입니다. 거둬 온 값을 쌓는 김에 규칙도 같이 따집니다.
포기한 것
Prometheus 는 감시를 단순하게 굴리려고 몇 가지를 내려놓았습니다.
| 포기한 것 | 무엇이 곤란해지나 |
|---|---|
| 오랜 보존 | 정해진 기간이 지난 값은 지웁니다. 작년 이맘때와 견주려면 값을 밖으로 내보내 따로 쌓아야 합니다 |
| 여러 대로 나눠 한 벌처럼 굴리기 | 한 대가 자기 디스크에 혼자 쌓습니다. 대상이 아주 많아지면 대상을 갈라 서버를 여러 벌 세웁니다 |
| 사건 하나하나의 기록 | 간격마다 찍은 표본이라 그 사이 일은 못 봅니다. 요청 한 건의 사연은 로그와 트레이스가 맡습니다 |
| 정확한 합계 | 수집이 한 번 실패하면 그 구간이 빕니다. 과금이나 정산처럼 한 건도 틀리면 안 되는 수에는 안 씁니다 |
그래서 Prometheus 는 관측성을 혼자 책임지는 물건이 아닙니다. 「지금 어딘가 이상하다」를 빨리 알아채는 몫을 맡고, 「왜 그런가」는 로그와 트레이스가 이어받습니다.
관련 항목
Prometheus 가 다루는 측정값과 그 성질
메트릭 · 계측 · 시계열 · 레이블 · 카디널리티 · 집계 · 수집 주기 · 오류율 · 처리량 · 지연
Prometheus 와 한 벌로 도는 감시 도구
Alertmanager · PushGateway · Grafana · 익스포터 · node_exporter · Thanos · cAdvisor
Prometheus 가 대상을 찾아내는 방법
서비스 디스커버리 · Kubernetes · Docker · HTTP · 리레이블링
Prometheus 가 질의와 알림에 쓰는 요소
PromQL · 알림 · 알림 규칙 · 기록 규칙 · 침묵 · 대시보드 · 분위수
Prometheus 와 같은 역할을 두고 겨루는 감시 시스템
CloudWatch · Datadog · InfluxDB · Graphite · Zabbix · OpenTelemetry · VictoriaMetrics
Prometheus 가 속하는 상위 분류
다른 이름: 프로메테우스