LabHub
学习 学习路径 课程

可观测性

一夜响了七十次告警,用户却什么都没遇到

在 LabHub 中继续学习

한국어 원문으로 표시합니다.

목표

원인 기준 경보 네 개와 증상 기준 경보 하나를 실제 자료 위에서 세어 보고, 호출 수와 헛된 호출 시간을 근거로 무엇을 사람에게 보내고 무엇을 내릴지 결정합니다.

왜 중요한가

경보를 늘리는 일은 쉽고 줄이는 일은 어렵다. 어려운 이유는 근거가 없기 때문이다 — "이 경보 시끄럽지 않아?" 는 의견이지만 "이 경보는 12시간에 예순다섯 번 울렸고 그중 230분은 사용자가 아무 일도 겪지 않은 시간이었다" 는 자료다. 자료가 있으면 회의가 짧아진다. 그리고 같은 자료가 지속 시간 손잡이의 값도 정해 준다. 경보 설계는 임계값을 고르는 일이 아니라, 사람이 감당할 수 있는 호출 총량 안에서 무엇을 탐지할지 고르는 일이다.

단계

  1. /root/obs-alert-symptom/rules/causes.yml 에 Prometheus 규칙 파일을 쓰세요. 그룹 이름은 causes 이고 경보 네 개가 들어갑니다. CauseQueueDepthqueue_depth{job="shop-api",queue="orders"} 가 100 을 넘을 때, CauseDiskPredictnode_filesystem_avail_bytes{job="node"} 의 최근 1시간 추세로 6시간 뒤를 예측했을 때 0 미만일 때, CauseLatencyTail 은 최근 5분 기준 p99 지연이 0.5초를 넘을 때, CauseTrafficLow 는 최근 5분 기준 초당 요청 수가 55 미만일 때 울립니다. promtool check rules 로 검사가 통과해야 합니다. 이 단계에서는 for: 를 붙이지 않습니다.
  2. /root/obs-alert-symptom/count.py 를 만드세요. python3 count.py '<경보 식>' <for 분> 으로 부르면 최근 12시간을 1분 간격으로 훑어 episodes=<호출 수> minutes=<울린 분> 한 줄을 출력합니다. 조건이 참인 분이 연속으로 L분 이어졌을 때, L 이 for + 1 이상이면 호출 한 번으로 세고 울린 시간은 L - for 분입니다. for 를 주지 않으면 0 으로 봅니다.
  3. /root/obs-alert-symptom/counts.tsv 를 만드세요. 머리글 없이 네 줄이고 각 줄은 탭으로 나눈 세 칸 <경보이름> <호출 수> <울린 분> 입니다. for 는 0 으로 두고, 1단계 규칙 파일에 쓴 네 경보를 이름 그대로 씁니다. 값은 2단계 도구로 구합니다.
  4. 3단계에서 가장 많이 울린 경보 하나를 골라, for 를 0·5·15 분으로 바꿔 가며 다시 세세요. /root/obs-alert-symptom/for-effect.tsv 에 머리글 없이 세 줄, 각 줄은 <for 분> <호출 수> <울린 분> 입니다.
  5. /root/obs-alert-symptom/rules/symptom.ymlsymptom 그룹과 경보 SymptomErrorRatio 하나를 쓰세요. 조건은 최근 5분 기준 5xx 응답 비율이 1% 를 넘는 것이고, for: 5mrunbook_url 주석을 답니다. promtool check rules 를 통과시킨 뒤, 같은 식을 for 0 으로 세어 /root/obs-alert-symptom/symptom.txtepisodes=<수> minutes=<분> 한 줄을 적으세요.
  6. /root/obs-alert-symptom/overlap.py 를 만드세요. python3 overlap.py '<원인 식>' '<증상 식>' 으로 부르면 최근 12시간을 1분 간격으로 훑어 cause_minutes=<원인이 참인 분> outside_minutes=<그중 증상이 참이 아닌 분> 한 줄을 출력합니다. 그 도구로 원인 경보 네 개를 각각 재서 /root/obs-alert-symptom/falsepages.tsv 에 탭으로 나눈 세 칸 <경보이름> <원인 분> <증상 밖 분> 네 줄을 적으세요.
  7. /root/obs-alert-symptom/triage.tsv 에 다섯 줄을 적으세요. 각 줄은 탭으로 나눈 세 칸 <경보이름> <page|ticket|dashboard> <근거> 이고, 원인 경보 넷과 SymptomErrorRatio 를 모두 적습니다. 규칙은 둘입니다 — 증상 경보는 반드시 page, 그리고 6단계에서 증상 밖 분이 60분을 넘은 원인 경보는 page 로 둘 수 없습니다. 근거에는 앞 단계에서 얻은 숫자가 하나 이상 들어가야 하고 20자 이상이어야 합니다.
  8. /root/obs-alert-symptom/rules/page.yml 에 7단계에서 page 로 분류한 경보만 담으세요. 그룹 이름은 page 이고, 각 경보에는 for: 가 5분 이상, labelsseverity: page, annotationsrunbook_url 이 있어야 합니다. promtool check rules 를 통과시킨 뒤, 그 경보들을 각자의 for 값으로 세어 호출 수를 모두 더한 값을 /root/obs-alert-symptom/after.txtpages_after=<수> 한 줄로 적으세요.

참고

원인 기준 경보 네 개를 규칙 파일로 쓴다

/root/obs-alert-symptom/rules/causes.yml 에 Prometheus 규칙 파일을 쓰세요. 그룹 이름은 causes 이고 경보 네 개가 들어갑니다. CauseQueueDepthqueue_depth{job="shop-api",queue="orders"} 가 100 을 넘을 때, CauseDiskPredictnode_filesystem_avail_bytes{job="node"} 의 최근 1시간 추세로 6시간 뒤를 예측했을 때 0 미만일 때, CauseLatencyTail 은 최근 5분 기준 p99 지연이 0.5초를 넘을 때, CauseTrafficLow 는 최근 5분 기준 초당 요청 수가 55 미만일 때 울립니다. promtool check rules 로 검사가 통과해야 합니다. 이 단계에서는 for: 를 붙이지 않습니다.

규칙 파일의 뼈대는 groups:- name:rules:- alert:expr: 입니다. 예측은 predict_linear 에 구간 벡터와 초 단위 앞날을 줍니다. p99 는 histogram_quantile 에 le 별로 합친 rate 를 줍니다. 검사는 promtool check rules /root/obs-alert-symptom/rules/causes.yml 입니다.

몇 번 울렸을지 세는 도구를 만든다

/root/obs-alert-symptom/count.py 를 만드세요. python3 count.py '<경보 식>' <for 분> 으로 부르면 최근 12시간을 1분 간격으로 훑어 episodes=<호출 수> minutes=<울린 분> 한 줄을 출력합니다. 조건이 참인 분이 연속으로 L분 이어졌을 때, L 이 for + 1 이상이면 호출 한 번으로 세고 울린 시간은 L - for 분입니다. for 를 주지 않으면 0 으로 봅니다.

/api/v1/query_range 에 start·end·step 을 주면 구간 자료가 옵니다. 조건이 거짓인 분에는 표본 자체가 없으므로, 응답에 들어 있는 타임스탬프 집합을 만들고 1분 격자 위에서 연속 구간을 세면 됩니다. 파이썬 표준 라이브러리만 씁니다(urllib.request, json, time).

원인 경보 넷이 12시간 동안 몇 번 울렸나

/root/obs-alert-symptom/counts.tsv 를 만드세요. 머리글 없이 네 줄이고 각 줄은 탭으로 나눈 세 칸 <경보이름> <호출 수> <울린 분> 입니다. for 는 0 으로 두고, 1단계 규칙 파일에 쓴 네 경보를 이름 그대로 씁니다. 값은 2단계 도구로 구합니다.

규칙 파일에서 식을 꺼내 도구에 넘기면 손으로 옮겨 적는 실수를 줄일 수 있습니다. 네 숫자가 얼마나 벌어지는지가 이 단계의 핵심입니다 — 하나는 예순 번 넘게 울립니다.

지속 시간 하나로 호출이 얼마나 줄어드나

3단계에서 가장 많이 울린 경보 하나를 골라, for 를 0·5·15 분으로 바꿔 가며 다시 세세요. /root/obs-alert-symptom/for-effect.tsv 에 머리글 없이 세 줄, 각 줄은 <for 분> <호출 수> <울린 분> 입니다.

조건식은 그대로 두고 두 번째 인자만 바꿉니다. 호출 수가 줄어드는 대신 무엇을 잃는지도 같이 보세요 — 울린 분이 줄어든다는 것은 탐지가 그만큼 늦어진다는 뜻입니다.

증상 기준 경보 하나를 쓴다

/root/obs-alert-symptom/rules/symptom.ymlsymptom 그룹과 경보 SymptomErrorRatio 하나를 쓰세요. 조건은 최근 5분 기준 5xx 응답 비율이 1% 를 넘는 것이고, for: 5mrunbook_url 주석을 답니다. promtool check rules 를 통과시킨 뒤, 같은 식을 for 0 으로 세어 /root/obs-alert-symptom/symptom.txtepisodes=<수> minutes=<분> 한 줄을 적으세요.

비율은 5xx 의 rate 합을 전체 rate 합으로 나눕니다. 이 경보가 원인 경보들보다 훨씬 적게 울린다는 것이 요점입니다. runbook_url 은 annotations 아래에 둡니다.

사용자가 아무 일도 겪지 않은 시간에 몇 분이나 울렸나

/root/obs-alert-symptom/overlap.py 를 만드세요. python3 overlap.py '<원인 식>' '<증상 식>' 으로 부르면 최근 12시간을 1분 간격으로 훑어 cause_minutes=<원인이 참인 분> outside_minutes=<그중 증상이 참이 아닌 분> 한 줄을 출력합니다. 그 도구로 원인 경보 네 개를 각각 재서 /root/obs-alert-symptom/falsepages.tsv 에 탭으로 나눈 세 칸 <경보이름> <원인 분> <증상 밖 분> 네 줄을 적으세요.

두 식의 '참인 분 집합' 을 각각 만들고 차집합을 세면 됩니다. 2단계 도구의 절반을 함수로 떼어 내면 그대로 쓸 수 있습니다. 증상 밖 분이 클수록 '사용자는 멀쩡한데 사람만 깨운' 시간이 길다는 뜻입니다.

숫자를 근거로 호출·티켓·대시보드를 가른다

/root/obs-alert-symptom/triage.tsv 에 다섯 줄을 적으세요. 각 줄은 탭으로 나눈 세 칸 <경보이름> <page|ticket|dashboard> <근거> 이고, 원인 경보 넷과 SymptomErrorRatio 를 모두 적습니다. 규칙은 둘입니다 — 증상 경보는 반드시 page, 그리고 6단계에서 증상 밖 분이 60분을 넘은 원인 경보는 page 로 둘 수 없습니다. 근거에는 앞 단계에서 얻은 숫자가 하나 이상 들어가야 하고 20자 이상이어야 합니다.

증상 밖 분이 0 에 가까운 원인 경보는 증상과 거의 같은 시간에만 울린다는 뜻이라, 호출로 남겨 조사 시간을 아낄 수 있습니다. 반대로 절반 가까이 참인 경보는 호출로 두면 필터를 만들게 만듭니다.

호출용 규칙 파일만 남긴다

/root/obs-alert-symptom/rules/page.yml 에 7단계에서 page 로 분류한 경보만 담으세요. 그룹 이름은 page 이고, 각 경보에는 for: 가 5분 이상, labelsseverity: page, annotationsrunbook_url 이 있어야 합니다. promtool check rules 를 통과시킨 뒤, 그 경보들을 각자의 for 값으로 세어 호출 수를 모두 더한 값을 /root/obs-alert-symptom/after.txtpages_after=<수> 한 줄로 적으세요.

규칙 파일에서 alert 이름·expr·for 를 읽어 2단계 도구에 넘기면 손으로 더할 일이 없습니다. for 값은 5m 처럼 문자열이므로 분 단위 숫자로 바꿔야 합니다. 3단계의 호출 수 합과 비교해 보세요.