장애 대응 Runbook에 들어가야 할 내용
장애 대응 Runbook에 들어가야 할 내용
Runbook은 시스템 설명서가 아니라 장애 중 다음 행동을 빠르고 안전하게 선택하도록 돕는 실행 문서다. 알림의 의미, 사용자 영향 확인, 최근 변경, 진단 순서, 되돌릴 수 있는 완화, 중단 조건, 에스컬레이션과 복구 검증이 한 흐름으로 이어져야 한다. 평상시에 작성하고 실제 명령과 링크를 주기적으로 연습해야 장애 때 믿을 수 있다.
목차
- #장애가 난 뒤 처음 문서를 쓰면 늦다
- #Runbook Playbook Incident 문서의 차이
- #문서 맨 위에 있어야 할 정보
- #알림의 의미와 사용자 영향을 먼저 확인한다
- #최근 변경과 장애 범위를 좁힌다
- #진단 절차는 가설과 분기 조건으로 쓴다
- #완화 절차에는 위험도와 중단 조건을 적는다
- #Rollback이 항상 가장 안전한 것은 아니다
- #명령어는 복사해도 안전하게 작성한다
- #에스컬레이션과 역할 분담을 명확히 한다
- #진행 중 기록과 증거를 보존한다
- #복구 확인과 종료 조건을 정의한다
- #재구성한 API 오류율 Runbook 예제
- #Runbook을 테스트하고 낡지 않게 유지한다
- #마무리
- #참고 자료
- #관련 노트
장애가 난 뒤 처음 문서를 쓰면 늦다
새벽에 오류율 알림이 울리면 on-call 담당자는 동시에 여러 질문을 해결해야 한다.
이 알림은 무엇을 의미하는가?
사용자에게 실제 영향이 있는가?
최근에 무엇이 바뀌었는가?
어느 대시보드와 로그를 봐야 하는가?
트래픽을 줄이거나 되돌리는 방법은 무엇인가?
누구에게 도움을 요청해야 하는가?
복구됐다고 판단할 기준은 무엇인가?
평상시라면 차분히 문서와 저장소를 검색할 수 있다. 장애 중에는 알림, 문의, 상태 공유, 복구 압박이 동시에 들어온다. 기억에 의존하면 익숙한 사람만 대응할 수 있고, 서두르다 증상을 더 악화시키는 변경을 할 수 있다.
Runbook은 이때의 인지 부하를 줄인다.
flowchart LR
A[Alert 수신] --> B[영향 확인]
B --> C[범위와 최근 변경 확인]
C --> D[가설별 진단]
D --> E[가장 안전한 완화]
E --> F[복구 검증]
F --> G[정리와 후속 작업]좋은 Runbook은 모든 장애의 원인을 미리 맞히는 문서가 아니다. 첫 5~15분에 필요한 공통 절차와 알려진 실패 모드의 안전한 대응을 제공하고, 문서 범위를 벗어나면 언제 incident를 선언하고 도움을 부를지 알려 준다.
해당 서비스를 처음 맡은 on-call도 문서만 보고 영향을 확인하고, 위험한 명령을 피하며, 적절한 사람에게 에스컬레이션할 수 있어야 한다.
Runbook Playbook Incident 문서의 차이
조직마다 용어를 다르게 사용하지만 목적을 구분하면 문서가 명확해진다.
| 문서 | 목적 | 수명 |
|---|---|---|
| Service overview | 시스템 구조와 책임 설명 | 구조 변경까지 |
| Runbook | 특정 알림·작업의 실행 절차 | 운영 방식 변경까지 |
| Playbook | 장애 유형별 전략과 선택지 | 실패 모드 변경까지 |
| Incident state document | 현재 사건의 시각·영향·결정 기록 | 사건마다 새로 생성 |
| Postmortem | 영향, 원인, 대응과 재발 방지 학습 | 사건 종료 후 보존 |
Runbook은 “API 오류율이 높다”, “replication lag가 크다”, “인증서 갱신이 실패했다”처럼 구체적인 진입점에서 시작한다.
Incident state document는 Runbook을 복사한 문서가 아니다. 현재 사건의 살아 있는 상태를 기록한다.
# INC-2026-EXAMPLE
- 상태: Investigating
- 심각도: SEV-2
- 시작: 2026-04-07 03:14 KST
- Incident Commander: @example-ic
- Operations Lead: @example-ops
- Communications Lead: @example-comms
- 영향: Article API 요청 약 18% 실패
- 다음 업데이트: 03:30 KST
Postmortem은 복구 전에 쓰기 시작할 수 있지만 근본 원인 분석 때문에 완화를 늦춰서는 안 된다. 사건 중에는 사실과 결정을 간단히 남기고, 복구 후 충분한 분석을 한다.
문서 맨 위에 있어야 할 정보
장애 중 긴 배경 설명부터 읽게 해서는 안 된다. 맨 위에는 문서의 대상과 첫 행동을 둔다.
# Article API High Error Ratio Runbook
- 대상 알림: `ArticleApiFastErrorBudgetBurn`
- 서비스: `article-api`
- 소유 팀: Content Platform
- 마지막 검증일: 2026-03-15
- 위험 작업 권한: Production Operator
- 대시보드: [RED Dashboard](...)
- 로그: [Error Logs](...)
- Trace: [Slow/Error Traces](...)
- 최근 배포: [Deployments](...)
- 에스컬레이션: `#incident-response`
> 첫 5분
> 1. 사용자 오류율과 영향을 받은 region을 확인한다.
> 2. 전체 장애이거나 데이터 손상 가능성이 있으면 incident를 선언한다.
> 3. 최근 30분 변경이 있고 신버전에 영향이 집중되면 rollback 절차로 이동한다.
문서 소유자와 마지막 검증일은 특히 중요하다. 링크와 명령은 빠르게 낡는다. 2년 전에 작성된 Runbook을 최신 절차라고 믿는 것이 문서가 없는 것보다 위험할 수 있다.
상단에서 명확히 해야 할 항목은 다음과 같다.
- 이 문서가 대응하는 알림과 증상
- 서비스와 사용자 기능
- 소유 팀과 on-call
- 필요한 접근 권한
- 첫 5분 행동
- 주요 dashboard, log, trace, deployment 링크
- incident 선언과 escalation 기준
- 마지막 검증일과 문서 owner
알림의 의미와 사용자 영향을 먼저 확인한다
알림이 울렸다는 사실만으로 시스템을 변경하지 않는다. 먼저 신호가 실제인지, 어떤 사용자에게 얼마나 영향을 주는지 확인한다.
확인할 것
- alert 시작 시각과 현재 상태
- 영향을 받은 region, route, tenant class
- 요청률과 유효 표본 수
- 오류율과 지연 시간
- black-box 또는 client-side 신호
- 고객 문의와 상태 페이지
Runbook에는 알림 표현식을 이해할 수 있는 설명을 넣는다.
ArticleApiFastErrorBudgetBurn
의미:
- 외부 Article API availability SLO
- 1시간과 5분 burn rate가 모두 14.4배 초과
- 최근 1시간 유효 요청 1,000건 이상
포함:
- gateway에서 관측한 5xx와 timeout
제외:
- health check
- 운영자 내부 요청
- 예상 가능한 4xx
이 설명이 없으면 담당자는 “5xx가 조금 생겼다” 정도로 오해할 수 있다. 알림 설계 자체는 알람 피로를 줄이는 임계값 설계에서 정리했다.
사용자 영향 확인 쿼리는 수정 작업보다 먼저 배치한다.
sum by (region, route) (
rate(
gateway_requests_total{
service="article-api",
outcome="failure"
}[5m]
)
)
/
sum by (region, route) (
rate(
gateway_requests_total{
service="article-api"
}[5m]
)
)
쿼리가 반환하는 단위, 정상 범위, no data의 의미도 설명한다.
gateway 앞 DNS, CDN, TLS 단계에서 실패하면 애플리케이션 요청률은 오히려 0으로 떨어질 수 있다. 사용자에 가까운 black-box 지표와 함께 확인한다.
최근 변경과 장애 범위를 좁힌다
정상적으로 동작하던 시스템이 갑자기 바뀌었다면 직전 변화가 중요한 단서다.
- application 배포
- feature flag
- 인프라와 네트워크 정책
- 데이터베이스 schema migration
- secret과 인증서 rotation
- 외부 API 상태
- 트래픽 패턴과 batch 실행
- autoscaling과 quota
Runbook에는 “최근 변경을 확인한다”는 문장만 쓰지 말고 어디에서 어떤 범위를 볼지 연결한다.
최근 변경 확인 범위
- Application deploys: 60분
- Feature flags: 30분
- Database migration: 24시간
- Infrastructure change: 24시간
- Secret rotation: 7일
문제가 일부 region 또는 version에만 있는지 비교한다.
sum by (region, version) (
rate(
http_server_requests_total{
service="article-api",
outcome="failure"
}[5m]
)
)
신버전만 실패한다면 rollback 가능성이 높아진다. 모든 version과 region이 동시에 실패한다면 공통 데이터베이스, 인증 공급자, DNS, 공통 설정을 의심할 수 있다.
flowchart TD
A[오류율 증가] --> B{특정 version인가}
B -- 예 --> C[배포 차이와 rollback 검토]
B -- 아니오 --> D{특정 region인가}
D -- 예 --> E[region 의존성과 트래픽 우회 검토]
D -- 아니오 --> F[공통 dependency와 전역 변경 확인]이 흐름은 가설을 좁히는 도구이지 자동 결론이 아니다. 동시에 두 변경이 있었거나 기존 잠재 버그가 트래픽 증가로 드러날 수 있다.
진단 절차는 가설과 분기 조건으로 쓴다
나쁜 Runbook은 확인할 대시보드를 길게 나열한다.
CPU를 본다.
메모리를 본다.
로그를 본다.
DB를 본다.
캐시를 본다.
좋은 절차는 왜 보는지, 어떤 결과가 다음 행동을 바꾸는지 설명한다.
### 가설 A: 신버전 회귀
1. version별 오류율 패널을 연다.
2. 신버전 오류율이 구버전보다 5배 이상이고 표본이 1,000건 이상인지 확인한다.
3. 조건을 만족하면 `Rollback` 절차로 이동한다.
4. 두 버전이 비슷하면 `공통 의존성 장애` 가설로 이동한다.
각 단계에 기대 결과와 반대 결과를 둔다.
| 관측 | 다음 행동 |
|---|---|
| 신버전만 오류 | rollout 중지, rollback 평가 |
| 모든 version 오류 | 공통 dependency 조사 |
| 특정 region만 오류 | traffic shift 평가 |
| 요청률 0, app 오류도 0 | DNS·gateway·routing 확인 |
| p99만 상승, 오류율 정상 | queue·pool·retry 조사 |
| 빠른 5xx 증가 | config·dependency 연결 실패 조사 |
명령 출력 예시도 유용하다.
VERSION READY ERROR_RATIO
2026.04.07-1 8/8 0.001
2026.04.07-2 2/8 0.184
실제 도구 출력과 다르면 문서를 갱신한다. 사람이 해석해야 할 핵심 열만 설명하고 대량 로그를 그대로 붙이지 않는다.
완화 절차에는 위험도와 중단 조건을 적는다
장애 중 최우선 목표는 완벽한 근본 원인 규명보다 사용자 피해를 줄이고 서비스를 안정화하는 것이다. 하지만 성급한 완화가 데이터 손상이나 더 큰 장애를 만들 수 있다.
각 완화에는 다음 정보를 둔다.
목적
사전 조건
예상 영향
위험도
필요 권한
실행 명령
성공 신호
중단 조건
원복 방법
예상 소요 시간
예를 들어 읽기 전용 모드 전환을 가정해 보자.
### 완화: Article 편집을 읽기 전용으로 전환
- 목적: DB write 오류 확산과 재시도 부하를 줄인다.
- 적용 조건: write 오류율 20% 초과, read 경로는 정상
- 사용자 영향: 글 작성·수정 불가, 조회 가능
- 위험도: 중간
- 승인: Incident Commander
- 성공 신호: write QPS 감소, read SLO 회복
- 중단 조건: read 오류율이 상승하거나 flag 적용 범위가 불명확함
- 원복: DB 안정화와 backlog 정리 후 flag 비활성화
feature flag 명령도 실행 전과 후 확인을 나눈다.
# 1. 현재 값을 읽는다
examplectl flags get article-write-enabled \
--environment production
# 2. 변경 대상을 dry-run으로 확인한다
examplectl flags set article-write-enabled false \
--environment production \
--dry-run
# 3. Incident Commander 승인 후 적용한다
examplectl flags set article-write-enabled false \
--environment production \
--reason INC-2026-EXAMPLE
예제 명령은 가상의 CLI다. 중요한 점은 환경과 대상을 명시하고, 현재 상태와 dry-run을 확인하고, 사건 ID를 감사 로그에 남기는 구조다.
Runbook의 명령이 여러 cluster나 전체 계정을 대상으로 할 수 있는데 범위가 명시되지 않았다면 추측해서 실행하지 않는다. 권한 보유자나 서비스 owner에게 에스컬레이션한다.
Rollback이 항상 가장 안전한 것은 아니다
최근 배포 뒤 장애가 났다면 rollback은 강력한 완화 방법이다. 하지만 다음 변화는 단순 rollback이 위험할 수 있다.
- 이전 코드와 호환되지 않는 schema migration
- 되돌릴 수 없는 데이터 변환
- 이미 새 형식으로 발행된 메시지
- secret rotation 후 폐기된 이전 key
- 외부 API contract 변경
- 오래 실행되는 worker의 혼합 version
Runbook의 rollback 절차에는 호환성 표가 있어야 한다.
| 변경 | 앱 rollback | 데이터 rollback | 확인 사항 |
|---|---|---|---|
| 코드만 변경 | 대체로 가능 | 없음 | config 호환 |
| additive column | 대체로 가능 | 보통 불필요 | 구버전 query |
| column rename/drop | 위험 | 복구 필요 가능 | expand-contract 여부 |
| message schema 변경 | 혼합 version 위험 | queue drain 고려 | consumer 호환 |
| secret rotation | 이전 secret 상태에 따라 다름 | 없음 | 양쪽 key 유효 기간 |
Rollback 전 checklist 예시다.
[ ] 이전 artifact가 존재하고 서명이 유효하다.
[ ] 이전 version이 현재 schema와 호환된다.
[ ] migration의 forward/backward 호환성을 확인했다.
[ ] feature flag와 config의 이전 값이 기록되어 있다.
[ ] 실행 중 job과 queue message 형식을 확인했다.
[ ] rollback 뒤 확인할 SLI와 대기 시간을 정했다.
[ ] 중단 조건과 roll-forward 대안을 정했다.
DB migration의 안전한 배포 방식은 무중단 배포에서 DB 마이그레이션 순서와 연결된다.
명령어는 복사해도 안전하게 작성한다
장애 중에는 Runbook 명령을 복사해 실행할 가능성이 높다. placeholder가 모호하거나 기본 context에 의존하면 다른 환경을 변경할 수 있다.
# 나쁜 예: 현재 context와 namespace에 의존
kubectl scale deployment api --replicas=20
# 더 명시적인 예
kubectl --context prod-apne1 \
--namespace article-system \
scale deployment/article-api \
--replicas=20
그렇더라도 명령 바로 위에 대상을 읽는 절차와 승인 조건을 둔다.
kubectl --context prod-apne1 \
--namespace article-system \
get deployment/article-api \
-o wide
Runbook 명령 작성 원칙은 다음과 같다.
- production, staging, region, namespace를 명시한다.
- wildcard와 암묵적 기본값을 피한다.
- 변경 전에 read-only 확인 명령을 둔다.
- 가능하면 dry-run과 diff를 제공한다.
- 대량 변경은 작은 범위로 먼저 실행한다.
- 성공 여부를 검증하는 별도 명령을 둔다.
- 되돌리는 명령과 이전 값을 함께 둔다.
- secret을 명령줄 인자로 직접 쓰지 않는다.
- 파괴적 작업은 별도 승인과 백업 확인을 요구한다.
동적으로 찾은 ID를 바로 변경 명령에 넣는 one-liner도 피한다.
# 위험한 형태의 예: 검색 결과가 여러 개여도 바로 변경할 수 있음
examplectl disable "$(examplectl list --status unhealthy --first)"
대상을 출력해 사람이 확인한 뒤 명시적인 ID로 실행하도록 두 단계를 나눈다.
examplectl instances list \
--environment production \
--region ap-northeast
examplectl instances disable instance-example-42 \
--environment production \
--region ap-northeast \
--dry-run
Runbook에 비밀값이나 실제 토큰을 넣지 않는다. secret manager에서 어떤 이름을 조회해야 하는지와 필요한 권한만 설명한다.
에스컬레이션과 역할 분담을 명확히 한다
한 사람이 진단, 변경, 상태 공유, 고객 문의를 동시에 맡으면 병목이 된다. 영향이 크거나 여러 팀이 필요하면 incident를 일찍 선언하고 역할을 나눈다.
| 역할 | 책임 |
|---|---|
| Incident Commander | 우선순위, 역할, 전체 상태와 결정 |
| Operations Lead | 시스템 진단과 완화 실행 |
| Communications Lead | 내부·외부 상태 업데이트 |
| Planning/Recorder | 타임라인, 후속 작업, 교대 준비 |
작은 조직에서는 한 사람이 여러 역할을 맡을 수 있다. 그래도 누가 최종 결정을 하고 누가 시스템을 변경하는지 명시한다.
Incident 선언 기준
- 전체 요청 실패율 20% 이상
- 두 개 이상 region 영향
- 데이터 손상 또는 보안 사고 가능성
- 15분 내 완화 경로가 불명확
- 두 팀 이상 coordination 필요
에스컬레이션 순서
1. Primary on-call
2. Secondary on-call
3. Service owner
4. Database/Network specialist
5. Incident Commander on-call
6. Security or Privacy on-call when relevant
개인의 전화번호를 문서에 직접 적으면 인사 변경 때 낡는다. 팀 alias와 on-call schedule 링크를 사용한다. 접근 시스템 자체가 장애날 가능성에 대비해 out-of-band 연락 수단도 정한다.
10~15분 동안 영향 범위나 안전한 완화가 불명확하면 더 많은 상태를 가진 사람을 부르는 것이 올바른 대응이다. 혼자 오래 조사하는 것이 비용을 키울 수 있다.
진행 중 기록과 증거를 보존한다
장애 중에는 빠르게 시스템을 바꾸지만 무엇을 언제 왜 바꿨는지 기록하지 않으면 다른 대응자가 같은 작업을 반복한다.
## Timeline
- 03:14 Alert fired: fast error-budget burn
- 03:17 Confirmed 18% 5xx in ap-northeast
- 03:19 Declared SEV-2, IC assigned
- 03:22 New version shows 11x higher error ratio
- 03:25 Rollout paused
- 03:28 Rollback approved
- 03:34 Error ratio returned below 0.5%
- 03:45 Monitoring period started
각 변경에는 가설, 실행자, 명령 또는 change ID, 결과를 남긴다.
Decision D-03
Hypothesis:
- new application version is incompatible with current cache schema
Action:
- pause rollout and rollback canary
Owner:
- @example-ops
Expected:
- canary error ratio falls within 5 minutes
Result:
- error ratio 18% → 0.4%
근본 원인 분석을 위해 로그와 trace, 상태 snapshot을 보존하되 완화를 지연시키지 않는다.
# 읽기 전용 상태 수집 예시
kubectl --context prod-apne1 \
--namespace article-system \
get pods,deployments,replicasets \
-o wide > incident-example-workload-state.txt
실제 파일에는 민감 정보가 포함될 수 있으므로 incident 전용 접근 제어 저장소에 보관한다. 개인 노트북이나 공개 채널에 운영 로그를 붙이지 않는다.
Google SRE의 표현처럼 우선순위는 “출혈을 멈추고, 서비스를 복구하며, 원인 분석을 위한 증거를 보존하는 것”으로 요약할 수 있다.
복구 확인과 종료 조건을 정의한다
오류율 그래프가 잠깐 내려갔다고 incident를 끝내면 재발할 수 있다. Runbook에는 안정화 기준과 관찰 시간을 둔다.
복구 조건
- 외부 availability SLI가 99.9% 이상
- p95와 p99가 정상 범위
- 모든 region에서 15분 이상 유지
- queue backlog가 감소 중
- 새 5xx trace가 없음
- 데이터 정합성 점검 통과
- 임시 완화의 범위와 owner가 기록됨
서비스별로 복구 신호가 다르다. queue consumer는 API 오류율이 아니라 oldest message age와 backlog drain이 중요하다. 데이터베이스 장애 후에는 연결 성공뿐 아니라 replica lag와 write consistency를 확인해야 한다.
max(queue_oldest_message_age_seconds) < 60
완화가 사용자 기능을 제한했다면 핵심 SLI가 정상이어도 완전 복구가 아니다.
Status: Mitigated
- 조회 정상
- 글 작성은 read-only mode로 차단
Status: Resolved
- write 기능 복구
- backlog 처리 완료
- 정합성 검증 완료
incident 종료 전에 남은 임시 변경을 목록으로 만든다.
[ ] traffic shift 원복 owner와 시각
[ ] autoscaling 임시 상향 정리
[ ] read-only flag 원복 조건
[ ] debug logging 비활성화
[ ] temporary access 권한 회수
[ ] silence 종료
[ ] postmortem owner와 일정
재구성한 API 오류율 Runbook 예제
다음 예시는 특정 회사의 실제 Runbook이 아니라 문서 구조를 설명하기 위해 재구성한 것이다.
# Article API Error Budget Burn
## Metadata
- Alert: `ArticleApiFastErrorBudgetBurn`
- Owner: Content Platform
- Last verified: 2026-03-15
- Required role: Production Operator
- Dashboard: `https://monitoring.example.test/d/article-api`
- Deployments: `https://deploy.example.test/article-api`
- Incident channel: `#incident-response`
## What this alert means
External API bad-event ratio is consuming the 30-day availability
error budget at more than 14.4x in both the 1h and 5m windows.
## First five minutes
1. Confirm failure ratio and request volume in every region.
2. Check black-box success from outside the cluster.
3. Declare an incident if failure ratio exceeds 20% or two regions fail.
4. Pause any active rollout.
5. Post impact and next update time in the incident channel.
## Scope
- Compare by `region`, `version`, and normalized `route`.
- Check gateway failures before application metrics.
- Treat missing application traffic as possible routing failure.
## Recent changes
- Application deployments: last 60 minutes
- Feature flags: last 30 minutes
- Database migrations: last 24 hours
- Infrastructure and secret changes: last 24 hours
## Mitigation decision
- New version only: evaluate rollback checklist.
- One region only: evaluate traffic shift.
- All versions and regions: inspect shared database and authentication.
- Data corruption suspected: disable writes and escalate immediately.
## Recovery
- Error ratio below 0.1% for 15 minutes
- p99 below 800ms for 15 minutes
- Synthetic create/read flow succeeds in every region
- No growing queue backlog
- Data consistency check passes
실제 문서에서는 각 항목을 대시보드의 저장된 query와 승인된 명령에 연결한다. 다만 한 페이지가 지나치게 길어지면 공통 명령 문서와 서비스별 Runbook을 분리한다.
Runbook 안에 결정 트리를 두는 것도 유용하다.
flowchart TD
A[Alert 확인] --> B{실제 사용자 영향?}
B -- 아니오 --> C[계측 오류·알림 품질 조사]
B -- 예 --> D{데이터 손상 가능성?}
D -- 예 --> E[Write 차단·Security/DB 즉시 에스컬레이션]
D -- 아니오 --> F{신버전에 집중?}
F -- 예 --> G[Rollout 중지·Rollback checklist]
F -- 아니오 --> H{한 region에 집중?}
H -- 예 --> I[Traffic shift checklist]
H -- 아니오 --> J[공통 dependency 조사]분기는 단순해야 한다. 장애 중 복잡한 다이어그램을 따라가야 한다면 문서를 여러 Runbook으로 나눈다.
Runbook을 테스트하고 낡지 않게 유지한다
Runbook은 읽어 보는 것만으로 검증되지 않는다. staging이나 game day에서 실제로 실행해 본다.
테스트 항목은 다음과 같다.
- 새 on-call이 링크와 권한을 찾을 수 있는가
- 명령의 dry-run 결과가 문서와 같은가
- rollback artifact가 실제로 존재하는가
- dashboard query가 데이터와 단위를 올바르게 보여 주는가
- out-of-band 연락 수단이 동작하는가
- 복구 확인과 데이터 정합성 검사가 실행 가능한가
- 문서가 의존하는 시스템이 함께 장애나도 접근 가능한가
Runbook review trigger
- 분기별 정기 검토
- 서비스 owner 변경
- 배포 방식 변경
- metric 또는 alert 이름 변경
- incident나 near miss 발생
- 권한 체계와 CLI 변경
- architecture 또는 dependency 변경
CI로 자동 검사할 수 있는 부분도 있다.
interface RunbookMetadata {
alert: string;
owner: string;
lastVerified: string;
dashboardUrl: string;
escalation: string;
}
function validateRunbook(metadata: RunbookMetadata): string[] {
const errors: string[] = [];
if (!metadata.alert) errors.push("alert is required");
if (!metadata.owner) errors.push("owner is required");
if (!metadata.dashboardUrl.startsWith("https://")) {
errors.push("dashboardUrl must use HTTPS");
}
if (!metadata.escalation) errors.push("escalation is required");
const ageMs = Date.now() - Date.parse(metadata.lastVerified);
const ninetyDaysMs = 90 * 24 * 60 * 60 * 1_000;
if (ageMs > ninetyDaysMs) {
errors.push("runbook verification is older than 90 days");
}
return errors;
}
링크 응답 상태, alert name 존재 여부, owner team 존재 여부도 자동 검사할 수 있다. 하지만 완화 명령의 의미와 안전성은 사람이 시나리오로 검토해야 한다.
Incident가 끝나면 다음 질문을 Runbook 후속 작업에 포함한다.
- 문서를 찾는 데 시간이 걸렸는가
- 첫 행동이 명확했는가
- 틀리거나 위험한 명령이 있었는가
- 새 실패 모드와 완화를 추가해야 하는가
- 에스컬레이션 대상이 맞았는가
- 자동화할 수 있는 반복 작업은 무엇인가
사건 문서에 사용한 Runbook version과 빠진 정보를 기록하면 어떤 문서가 실제 MTTR을 줄였는지 알 수 있다.
마무리
Runbook의 가치는 문서 길이나 명령 수가 아니라 장애 중 의사결정을 얼마나 안전하게 줄여 주는지에 있다.
좋은 Runbook은 알림의 의미에서 시작해 사용자 영향, 범위, 가설, 완화, 검증과 에스컬레이션을 하나의 실행 흐름으로 연결한다.
최소 구성은 다음과 같다.
- 대상 알림, 서비스, owner와 마지막 검증일
- 첫 5분 행동과 incident 선언 기준
- 사용자 영향과 범위를 확인하는 query
- 최근 변경과 version·region 비교
- 가설별 관측과 다음 분기
- 완화의 위험도, 승인, 중단 조건과 원복
- rollback 호환성 checklist
- 명시적인 환경과 대상이 있는 안전한 명령
- 역할, 에스컬레이션과 상태 공유 주기
- 진행 타임라인과 증거 보존 위치
- 복구·정합성 검증과 안정화 시간
- 임시 변경 정리와 postmortem 후속 작업
문서를 작성한 순간보다 실제로 연습하고 사건 뒤 고치는 과정이 더 중요하다. 장애는 문서가 상상하지 못한 방식으로 일어나지만, 잘 준비된 첫 행동과 에스컬레이션 기준은 어떤 실패 모드에서도 대응 속도를 높인다.
참고 자료
- Google SRE Book - Emergency Response
- Google SRE Book - Managing Incidents
- Google SRE Workbook - Incident Response
- Google SRE - Incident Management Guide
- Google SRE Book - Effective Troubleshooting