PCA — 프로메테우스 인증 어소시에이트 · 규칙 회귀 시험: 초록불의 판별력 · 이론
정상 데이터가 숨긴 카운터 리셋
한 줄 요약
규칙 파일의 문법이 맞는다는 것과 그 규칙이 올바른 숫자를 만든다는 것은 다른 주장입니다.
counter를 먼저 합치면 개별 프로세스의 리셋이 가려질 수 있습니다. 정상 데이터만 있는 시험은
바로 그 잘못된 규칙도 통과시킵니다. 이번 단원에서는 진짜 PromQL 엔진에 반례를 넣어 두
주장을 구분하고, 수강생이 기록 규칙과 시험 파일을 직접 고칩니다.
왜 이게 필요했나
결제 서비스의 요청률 대시보드를 고친 날을 생각해 봅시다. 리뷰에서 promtool check rules가
성공했고, 평소 트래픽 그래프도 매끈했습니다. 그런데 인스턴스 하나가 재시작된 시간대에만
대시보드의 요청률이 낮아졌습니다. 문법 오류가 아니라 계산 순서의 오류라 파서가 찾을 수
없었던 것입니다. 집계된 수치가 그럴듯하고 경보도 조용하니 사람은 오히려 안심하기 쉽습니다.
시험은 이름에 test가 들어가는 명령을 한 번 실행하는 의식이 아닙니다. 어떤 입력에서 어떤
라벨과 값을 기대하는지 명시하고, 그 기대를 깨는 구현을 거절하는 장치입니다. 잘못된 구현을
넣어도 초록불이 켜진다면 시험에 빠진 상황이 있다는 뜻입니다. 프로덕션에서 모든 장애를
발견한 뒤에야 시험을 추가할 필요는 없습니다. 규칙이 감추기 쉬운 정보를 먼저 찾아 작은
시계열로 모델링할 수 있습니다.
어떻게 동작하나
실습 입력에는 route와 instance 두 라벨이 있습니다. /checkout의 a는 1분마다 60,
b는 1분마다 600씩 누적 counter가 증가합니다. 따라서 충분한 창에서 a는 초당 1,
b는 초당 10입니다. /status에는 분당 60씩 증가하는 두 인스턴스를 따로 둡니다.
이 대조 경로가 있어야 route까지 지운 집계를 시험이 거절할 수 있습니다. /checkout
하나만 넣으면 라벨을 잘못 없앤 결과도 숫자만 보아서는 알아채기 어렵습니다.
올바른 recording rule은 원본 시계열마다 rate를 계산한 뒤 route별로 합합니다.
비교 규칙은 원본 counter를 route별로 더한 시계열을 먼저 기록하고 그 합계에 rate를
적용합니다. 정상 입력의 6분 시점에서는 두 규칙 모두 /checkout 11을 반환합니다.
여기까지만 시험하면 어느 구현이 잘못됐는지 판단할 근거가 없습니다.
반례에서는 a가 0, 60, 120, 180, 0, 60, 120으로 변합니다. b는 계속 증가합니다.
a의 리셋이 생긴 순간에도 b의 증가량이 더 크므로 두 값의 합계는 감소하지 않습니다.
원본을 볼 수 있는 rate는 a의 리셋을 고려하지만, 이미 합계만 받은 rate는 그 사실을
복원할 수 없습니다. 합산 과정에서 사라진 정보가 나중에 함수 이름을 바꾼다고 돌아오지
않는다는 것이 핵심입니다.
고정된 1분 입력·평가 간격, 6분 평가, 5분 창의 실제 Prometheus 3.14.0 결과는
올바른 /checkout 요청률 10.75, 잘못된 요청률 10입니다. 원본 resets의 route별 합은
1인데, 기록한 합계의 resets는 0입니다. /status는 여전히 2입니다. 이 네 결과를 함께
검사하면 단순히 상수 10.75를 반환하거나 경로를 없애는 수정도 받아들이지 않게 됩니다.
여기서 10.75는 사건 원장에 찍힌 모든 요청을 초 단위로 세었다는 뜻이 아닙니다.
rate는 범위의 표본과 경계 외삽을 사용합니다. 평가 시각이나 창, 입력 간격을 바꾸면 결과도
달라질 수 있습니다. 그래서 시험 파일에는 입력 값뿐 아니라 interval, evaluation_interval,
eval_time을 함께 적습니다. 시간 조건을 생략하고 숫자만 외우면 다음 사례를 설명하지 못합니다.
시험 파일을 읽는 순서
먼저 rule_files가 무엇을 읽는지 봅니다. 실습 도우미는 학생의 단계별 규칙을 임시 폴더의
rules.json으로 복사합니다. 확장자는 JSON이지만 Prometheus가 받는 YAML 표현으로 유효합니다.
그 다음 입력 시계열의 라벨과 값, 평가 간격, 검사 시각, 기대 표본을 읽습니다. 배열의 순서는
바꿔도 되지만 필요한 시계열이나 기대 표본을 빼는 것은 다른 시험을 만드는 일입니다.
각 promql_expr_test에는 expr, eval_time, exp_samples가 있습니다. exp_samples의
labels에는 숫자의 주인이 누구인지 적고 value에는 기대값을 적습니다. 숫자만 일치하는
확인은 부족합니다. 경로 라벨이 사라졌는데 총합만 같은 상태도 잘못된 결과일 수 있습니다.
리셋 시험의 정답을 10으로 낮추면 잘못된 규칙이 통과하지만, 그것은 구현을 고친 것이 아니라
요구사항을 바꾼 것입니다. 이 연습의 입력과 기대값 계약은 그런 완화를 거절합니다.
실습은 같은 결과를 내는 표현을 문자열이 다르다는 이유로 거절하지 않습니다. 예를 들어
이 입력의 라벨이 route와 instance뿐일 때 sum without(instance)는 sum by(route)와
같은 결과를 낼 수 있습니다. 그렇다고 다른 라벨이 추가된 모든 운영 입력에서도 두 표현이
같다는 뜻은 아닙니다. 시험이 보장하는 범위는 시험에 들어간 입력의 범위입니다.
현장에서 만나는 모습
배포 파이프라인에는 문법 검사와 의미 시험을 둘 다 둡니다. 문법 검사는 잘못된 함수 호출,
필드나 표현식을 빨리 알려 주고, 의미 시험은 서비스가 약속한 라벨·값·시간의 관계를 확인합니다.
리뷰에는 정상 입력 하나만 붙이지 말고 재시작, 경로 분리, 무요청, 데이터 결손처럼 계산을
흔들 수 있는 사례를 붙입니다. 변경된 규칙의 결과뿐 아니라 기존 중요한 사례가 유지되는지도
봅니다. 숫자를 고쳤는데 원래의 경로 분리가 깨지는 회귀가 있을 수 있기 때문입니다.
또한 한 번은 의도적으로 잘못된 구현을 넣어 보세요. 이번 실험에서 정상 데이터만 남긴
시험과 빈 tests 배열은 잘못된 집계 규칙도 실제로 통과시켰습니다. 도구의 성공 종료는
실행하도록 요청받은 검사에서 문제가 없었다는 뜻이지, 필요한 검사를 전부 했다는 보증이
아닙니다. 무엇을 검사했는지를 함께 검토하는 습관은 배포 게이트 전반에 그대로 적용됩니다.
이어서 배울 것
다음 레슨에서 결손과 경보의 시간 축을 먼저 읽습니다. 그 뒤 실습에서는 같은 잘못된 규칙이
정상 시험에서는 통과하고 리셋 시험에서는 실패하는 출력을 읽습니다.
그 다음 rate-rules.yml의 기록 규칙을 고치고 reset-tests.yml의 틀린 기대값을 수정합니다.
도우미는 학생 파일의 임시 사본에서 실제 promtool을 실행하고 문법·의미 결과를 분리해 남깁니다.
호스트나 운영 모니터링은 변경하지 않으며 입력은 학습용 합성 시계열입니다.
공식 문서
- [rate와 집계 순서](https://prometheus.io/docs/prometheus/latest/querying/functions/#rate)
- [기록 규칙](https://prometheus.io/docs/prometheus/latest/configuration/recording_rules/)
- [규칙 단위 시험](https://prometheus.io/docs/prometheus/latest/configuration/unit_testing_rules/)