LabHub
배우기 러닝패스 코스

FDE 캡스톤: 창고가 같은 주문을 세 번 받았다 · 운영 인계와 장애 대응 훈련 · 이론

인계 문서는 왜 새벽 세 시에 틀리는가

LabHub 에서 이어서 보기

한 줄 요약

운영 인계의 단위는 문서가 아니라 사슬이다. 서비스가 내는 지표에서 경보 조건이 나오고, 경보마다 런북 항목이 붙고, 항목마다 복사해서 그대로 도는 확인 명령이 있어야 한다. 그 사슬의 어느 고리가 끊겼는지는 훈련으로만 드러난다.

왜 이게 필요했나

납품이 끝나 가면 FDE 는 고객 운영팀에 서비스를 넘긴다. 흔한 인계물은 위키 한 장이다. 대시보드 주소, 경보 목록, "문제가 생기면 이 명령을 치세요" 라는 줄 몇 개. 이 문서는 작성한 날에는 맞다. 석 달 뒤 새벽 세 시에 당번이 페이지를 받고 그 명령을 치면, 포트가 바뀌어 있고, 진단 경로 이름이 달라져 있고, 당번의 노트북에는 그 도구가 없다. 게다가 한 명령은 응답 없이 멈춰서 30초를 잡아먹는다. 문서가 틀렸다는 사실이 가장 비싼 순간에 드러난다.

Google SRE 책의 당번(on-call) 장은 이 상황의 무게를 숫자로 적는다. 사용자에게 보이는 서비스라면 페이지 응답 목표를 5분으로 잡는 경우가 흔하고, 덜 급한 시스템은 30분이다. 한 번의 사건은 원인 분석과 사후 검토까지 평균 6시간을 먹기 때문에, 12시간 당번 한 번에 사건 두 건을 상한으로 둔다. 그리고 스트레스 아래에서 사람은 숙고 대신 직관과 습관으로 움직이는데, 그 반응은 틀리기 쉽다고 경고한다. 그래서 절차가 필요하다. 새벽의 당번에게 필요한 것은 판단을 대신해 줄 영웅이 아니라, 생각을 덜 해도 틀리지 않게 만드는 준비된 확인 수단이다.

어떻게 동작하나

사슬을 고리 하나씩 본다.

1. 지표. Prometheus 텍스트 노출 형식은 줄 단위 형식이다. 줄은 줄바꿈으로 나뉘고 마지막 줄도 줄바꿈으로 끝나야 하며 빈 줄은 무시된다. # HELP# TYPE 줄이 설명과 형식(counter, gauge, histogram, summary, untyped)을 알려 주고, 한 지표 이름에 TYPE 줄은 하나뿐이며 첫 샘플보다 앞에 와야 한다. 샘플은 이름{레이블="값"} 값 [타임스탬프] 모양이다. 레이블 값 안에서는 역슬래시·큰따옴표·줄바꿈 세 가지만 \\, \", \n 으로 이스케이프한다. 그래서 값 안에 쉼표나 중괄호가 들어갈 수 있고, 쉼표로 자르는 파서는 조용히 틀린다. histogram 은 _bucket{le="..."}·_sum·_count 로 펼쳐지고 le="+Inf" 버킷이 반드시 있어야 한다. HTTP 로는 text/plain; version=0.0.4 로 나간다.

# HELP orders_queue_oldest_age_seconds Age of the oldest waiting message in seconds.# TYPE orders_queue_oldest_age_seconds gaugeorders_queue_oldest_age_seconds{queue="fulfillment"} 2.4orders_build_info{version="2.4.1",note="handoff \"v2\", see RB"} 1

2. 경보 조건. 같은 SRE 책의 모니터링 장은 증상과 원인을 나누라고 한다. 사용자가 겪는 것(주문이 10분째 출고되지 않는다)이 증상이고, CPU 가 높다는 것은 원인 후보다. 페이지는 긴급하고, 조치할 수 있고, 사람의 판단이 필요한 것이어야 한다 — 기계적으로 같은 명령만 치게 되는 페이지는 자동화하거나 없앨 대상이다. 이 기준으로 보면 "큐 깊이 1000 초과" 는 나쁜 조건이다. 점심 몰림에는 깊이가 수천이 돼도 몇 초 안에 빠진다. "가장 오래 기다린 메시지의 나이" 가 사용자가 느끼는 증상에 가깝다. 인증서도 같다. 흔히 지표는 남은 시간이 아니라 만료 시각이라서 지금 시각을 빼야 한다.

Prometheus 경보 규칙은 expr 이 참인 상태가 for 기간 동안 이어져야 pending 에서 firing 으로 넘어가고, annotations 에 설명과 런북 링크를 둔다. 이 실습에는 Prometheus 서버가 없으므로 같은 생각을 작은 JSON 규칙과 스크립트로 옮긴다.

3. 조용함은 정상이 아니다. 비교식은 지표가 있을 때만 참·거짓이 된다. 지표가 아예 없으면 결과가 비어서 아무것도 울리지 않는다. Prometheus 는 이것을 위해 두 장치를 둔다. 긁을 때마다 대상별로 up 시계열을 만들어 성공이면 1, 실패면 0 을 넣고, absent() 함수는 입력이 비었을 때 값 1 짜리 원소 하나를 돌려준다. 문서가 이 함수의 용도를 "시계열이 없음을 경보할 때" 라고 적어 둔 이유다. 수집기가 죽은 밤에 대시보드가 평온해 보이는 것이 가장 위험하다.

4. 런북 항목과 실행 가능한 확인. 항목마다 확인·판단·조치·에스컬레이션 네 줄을 둔다. 핵심은 확인 줄이다. 당번이 출력 모양을 해석하게 두지 말고 종료 코드로 답하게 만든다. 정상이면 0, 그 장애가 맞으면 0 이 아닌 값. 그래야 사람이 새벽에 읽어도, 스크립트가 훈련에서 돌려도 같은 답이 나온다. 이때 파이프가 함정이다. bash 에서 파이프의 종료 코드는 기본으로 마지막 명령의 것이라 df 없는경로 | awk ... 는 df 가 실패해도 0 이 된다. set -o pipefail 로 돌려야 앞 명령의 실패가 보인다. 반대로 grep -q 는 첫 일치에서 바로 끝나서 앞의 curl 이 SIGPIPE 를 받을 수 있으니, pipefail 아래에서는 입력을 끝까지 읽는 형태를 고른다.

현장에서 만나는 모습

벤더가 남긴 런북을 정상 서비스에 대고 한 줄씩 돌려 보면 고장의 종류가 몇 가지로 모인다. 서비스가 아니라 당번의 기계를 보는 명령(df -h /var/lib/orders 는 당번 노트북의 디스크를 본다), 이름이 바뀐 엔드포인트(404), 옛 포트, 당번 환경에 없는 도구(ss 가 없는 컨테이너에서는 종료 코드 127), 시간 제한이 없어 멈추는 명령. 마지막 것은 점검기도 함께 멈추게 한다. subprocess 의 timeout 으로 bash 만 죽이면 파이프 뒤의 curl 이 출력 파이프를 붙잡고 남으므로, 새 세션으로 띄워 프로세스 그룹째 끊어야 한다.

이 점검은 한 번으로 끝나지 않는다. 서비스가 바뀔 때마다 인계 문서도 낡는다. 그래서 "런북 점검기" 를 인계물에 함께 넣고, 정기 훈련에서 장애 모드를 하나씩 켜 경보 → 런북 → 확인 명령 → 에스컬레이션이 끝까지 이어지는지 본다. 이것이 기록 한 장(재현 가능한 런북)이나 사후 보고서와 다른 점이다. 그 둘은 이미 일어난 일을 남기고, 훈련은 아직 일어나지 않은 밤을 미리 겪는다.

실무에서 진짜 중요한 것

다음 실습에서 할 것

가짜 orders 서비스를 여러 장애 모드로 띄워 가며 사슬을 직접 만든다. 지표 원문을 긁어 형식을 확인하고, 이스케이프까지 읽는 파서를 쓰고, 인계 메모의 여섯 경보를 JSON 규칙으로 옮긴 뒤 진단 스크립트로 판정한다. 못 긁은 상황을 경보로 올리고, 런북 확인 명령이 정상 0·장애 비0 으로 실제로 도는지 채점기가 여러 모드로 돌려 본다. 벤더 런북의 고장 난 줄을 점검기로 찾아내고, 마지막으로 경보부터 에스컬레이션까지 한 번에 도는 당번 훈련 스크립트를 만든다.

참고 문서: [Prometheus 텍스트 노출 형식](https://prometheus.io/docs/instrumenting/exposition_formats/) · [Prometheus 경보 규칙](https://prometheus.io/docs/prometheus/latest/configuration/alerting_rules/) · [Prometheus 함수(absent)](https://prometheus.io/docs/prometheus/latest/querying/functions/) · [작업과 인스턴스(up 시계열)](https://prometheus.io/docs/concepts/jobs_instances/) · [Google SRE 책: Being On-Call](https://sre.google/sre-book/being-on-call/) · [Google SRE 책: Monitoring Distributed Systems](https://sre.google/sre-book/monitoring-distributed-systems/)