批处理停了,告警却自己恢复了
한국어 원문으로 표시합니다.
목표
시각을 값으로 담은 지표와 timestamp() 의 차이, staleness marker 와 lookback, *_over_time·서브쿼리·deriv 를 고정된 240분짜리 시계열 위에서 평가해 숫자로 확인하고, 대상이 사라져도 풀리지 않는 경보 규칙을 만듭니다.
왜 중요한가
배치 작업의 신선도 경보는 흔히 가장 큰 사고에서 침묵합니다. 파드가 사라지면 시계열도 사라지고, 사라진 시계열에 걸린 조건식은 참도 거짓도 아닌 빈 결과가 되기 때문입니다. PromQL 이 언제 표본을 보고 언제 보지 않는지(lookback, staleness), 순간 값과 시간 집계가 무엇을 숨기는지 알아야 경보가 조용한 이유를 믿을 수 있습니다.
준비된 환경
python3 /opt/fixtures/pca_staleness_lab.py init 이 /root/pca-staleness/README.txt 에 시계열 이야기를 둡니다. python3 /opt/fixtures/pca_staleness_lab.py series 로 입력 표기를 볼 수 있습니다. 시각은 0분에서 240분까지 1분 간격이고, promtool 시험 시각이라 time() 은 평가 시각의 초(150m 이면 9000)입니다.
python3 /opt/fixtures/pca_staleness_lab.py eval -f 파일 --at 150m 은 lab-k8s 의 promtool 3.0.1 엔진으로 평가합니다. 채점기는 같은 시계열로 여러분의 식과 기준 식을 다시 계산하고, 마지막 단계는 여러분의 규칙 파일을 채점기가 만든 규칙 시험으로 돌립니다.
단계
/root/pca-staleness/01-age.promql에 nightly-export 의 마지막 성공 뒤 흐른 초를time()과batch_last_success_timestamp_seconds로 씁니다.python3 /opt/fixtures/pca_staleness_lab.py eval -f /root/pca-staleness/01-age.promql --at 150m결과를/root/pca-staleness/01-age.txt에age_seconds=로 적으세요. 재료는python3 /opt/fixtures/pca_staleness_lab.py init이 만듭니다./root/pca-staleness/02-wrong.promql에time() - timestamp(batch_last_success_timestamp_seconds{job="nightly-export"})를 쓰고 150m 에 평가합니다./root/pca-staleness/02-trap.txt에wrong_age_seconds=(이 식의 결과),sample_timestamp=(timestamp()결과),value=(지표 값)를 적으세요.- 두 job 의
batch_last_success_timestamp_seconds를 178m 부터 1분씩 평가해, 결과가 나오는 마지막 분을 찾으세요./root/pca-staleness/03-lookback.txt에nightly_last_minute=(staleness marker 가 들어간 job)과federated_last_minute=(marker 없이 표본만 끊긴 job)을 정수로 적습니다. time() - batch_last_success_timestamp_seconds{job="nightly-export"} > 3600을 170m 과 200m 에 평가해 결과 시계열 수를/root/pca-staleness/04-alert.txt의naive_series_170m=,naive_series_200m=로 적습니다. 그다음/root/pca-staleness/04-fixed.promql에 대상이 사라진 뒤에도 결과를 돌려주는 식을 씁니다. 채점기는 60m·125m 에는 빈 결과, 135m·170m·182m·200m·235m 에는 결과가 있는지 봅니다./root/pca-staleness/05-availability.promql에 job="api" 의 최근 30분 가용률을avg_over_time으로 씁니다. 120m 에서 평가하고/root/pca-staleness/05-availability.txt에availability_30m=,instant_up=(같은 시각의up{job="api"}),min_up_30m=(min_over_time결과)를 적으세요./root/pca-staleness/06-slope.promql에queue_depth{queue="exports"}의 10분 기울기(초당)를deriv로 씁니다./root/pca-staleness/06-slope.txt에deriv_110m=(110m 결과),rate_125m=(125m 에서rate(queue_depth[10m])),deriv_125m=(125m 에서deriv)를 적으세요. 120m 에 큐가 대부분 처리되었습니다./root/pca-staleness/07-peak.promql에 최근 1시간 동안 1분 간격으로 본rate(batch_rows_processed_total[5m])의 최댓값을 서브쿼리로 씁니다. 80m 에서 평가하고/root/pca-staleness/07-peak.txt에peak_rows_per_sec=와hour_avg_rows_per_sec=(rate(...[1h])결과)를 적으세요./root/pca-staleness/08-rules.yml에 그룹 하나와 경보BatchExportStale을 씁니다.expr은 04 단계처럼 대상이 사라져도 결과가 나오는 식,for: 10m,labels.severity: ticket입니다.promtool check rules로 문법을 확인하세요. 채점기는 같은 시계열로 규칙 시험을 만들어 60m·125m·135m(대기 중)에는 발화한 경보가 없고 145m·150m·200m·235m 에는 job="nightly-export", severity="ticket" 경보가 발화 중인지 확인합니다.
참고
- 구간 선택은 왼쪽이 열려 있습니다.
[5m]은 평가 시각 5분 전의 표본을 포함하지 않습니다. absent(v)는 v 가 없을 때 값 1인 시계열 하나를 돌려주고, 있으면 빈 결과입니다.- 흔한 실수: 경과 시간을
timestamp()로 재는 것, 게이지에rate를 거는 것,up == 0만으로 사라진 대상을 잡으려는 것. - 이 시계열은 promtool 시험용 합성 자료입니다. 실제 서버의 스크레이프 지연·재시도는 재현하지 않습니다.
- Querying basics — Staleness · Functions · Unit testing for rules
마지막 성공이 몇 초 전인가
/root/pca-staleness/01-age.promql 에 nightly-export 의 마지막 성공 뒤 흐른 초를 time() 과 batch_last_success_timestamp_seconds 로 씁니다. python3 /opt/fixtures/pca_staleness_lab.py eval -f /root/pca-staleness/01-age.promql --at 150m 결과를 /root/pca-staleness/01-age.txt 에 age_seconds= 로 적으세요. 재료는 python3 /opt/fixtures/pca_staleness_lab.py init 이 만듭니다.
지표의 값 자체가 유닉스 시각(초)입니다. 평가 시각에서 그 값을 빼면 경과 시간이 됩니다.
timestamp() 로 재면 늘 신선하다
/root/pca-staleness/02-wrong.promql 에 time() - timestamp(batch_last_success_timestamp_seconds{job="nightly-export"}) 를 쓰고 150m 에 평가합니다. /root/pca-staleness/02-trap.txt 에 wrong_age_seconds=(이 식의 결과), sample_timestamp=(timestamp() 결과), value=(지표 값)를 적으세요.
timestamp() 는 표본을 긁은 시각입니다. 1분마다 긁는 동안 그 시각은 계속 새로워집니다.
사라진 시계열은 언제까지 보이나
두 job 의 batch_last_success_timestamp_seconds 를 178m 부터 1분씩 평가해, 결과가 나오는 마지막 분을 찾으세요. /root/pca-staleness/03-lookback.txt 에 nightly_last_minute=(staleness marker 가 들어간 job)과 federated_last_minute=(marker 없이 표본만 끊긴 job)을 정수로 적습니다.
대상이 사라지면 Prometheus 는 staleness marker 를 넣어 즉시 지웁니다. marker 가 없으면 lookback(기본 5분) 동안 마지막 표본을 계속 돌려줍니다. 구간 경계가 포함되는지도 확인하세요.
대상이 사라지자 경보가 풀렸다
time() - batch_last_success_timestamp_seconds{job="nightly-export"} > 3600 을 170m 과 200m 에 평가해 결과 시계열 수를 /root/pca-staleness/04-alert.txt 의 naive_series_170m=, naive_series_200m= 로 적습니다. 그다음 /root/pca-staleness/04-fixed.promql 에 대상이 사라진 뒤에도 결과를 돌려주는 식을 씁니다. 채점기는 60m·125m 에는 빈 결과, 135m·170m·182m·200m·235m 에는 결과가 있는지 봅니다.
사라진 시계열에는 비교할 값이 없어 조건식이 빈 결과가 됩니다. 없음을 신호로 바꾸는 함수를 or 로 붙이세요.
지금은 up=1, 30분 가용률은
/root/pca-staleness/05-availability.promql 에 job="api" 의 최근 30분 가용률을 avg_over_time 으로 씁니다. 120m 에서 평가하고 /root/pca-staleness/05-availability.txt 에 availability_30m=, instant_up=(같은 시각의 up{job="api"}), min_up_30m=(min_over_time 결과)를 적으세요.
0과 1로 된 게이지의 시간 평균은 1이었던 표본의 비율입니다. 순간 값은 창 안의 장애를 보여 주지 않습니다.
게이지에 rate 를 걸면
/root/pca-staleness/06-slope.promql 에 queue_depth{queue="exports"} 의 10분 기울기(초당)를 deriv 로 씁니다. /root/pca-staleness/06-slope.txt 에 deriv_110m=(110m 결과), rate_125m=(125m 에서 rate(queue_depth[10m])), deriv_125m=(125m 에서 deriv)를 적으세요. 120m 에 큐가 대부분 처리되었습니다.
rate 는 값이 줄면 카운터가 재시작했다고 보고 보정합니다. 게이지의 감소는 재시작이 아니라 실제 변화입니다.
한 시간 평균에 숨은 최고 처리량
/root/pca-staleness/07-peak.promql 에 최근 1시간 동안 1분 간격으로 본 rate(batch_rows_processed_total[5m]) 의 최댓값을 서브쿼리로 씁니다. 80m 에서 평가하고 /root/pca-staleness/07-peak.txt 에 peak_rows_per_sec= 와 hour_avg_rows_per_sec=(rate(...[1h]) 결과)를 적으세요.
식[범위:간격] 은 안쪽 식을 간격마다 다시 평가해 범위 벡터를 만듭니다. 그 위에 *_over_time 을 걸 수 있습니다.
사라져도 계속 우는 경보 규칙
/root/pca-staleness/08-rules.yml 에 그룹 하나와 경보 BatchExportStale 을 씁니다. expr 은 04 단계처럼 대상이 사라져도 결과가 나오는 식, for: 10m, labels.severity: ticket 입니다. promtool check rules 로 문법을 확인하세요. 채점기는 같은 시계열로 규칙 시험을 만들어 60m·125m·135m(대기 중)에는 발화한 경보가 없고 145m·150m·200m·235m 에는 job="nightly-export", severity="ticket" 경보가 발화 중인지 확인합니다.
absent() 는 등호 매처의 레이블을 결과에 붙입니다. 두 갈래의 레이블이 같으면 경보가 끊기지 않고 이어집니다. for 는 발화 전 대기 시간입니다.