담당자가 없어도 1차 대응이 되게 — 운영 런북 네 개를 같은 모양으로
사내 인프라 몇 가지를 혼자 맡고 있다. 내가 자리에 없으면 아무도 손을 못 대는 구조, 말하자면 사람이 단일 장애점(SPOF)인 상태다. 이걸 깨려고 서비스 네 개(Sentry, Keycloak, Nginx Proxy Manager, TabbyML)의 운영 런북을 같은 모양으로 썼다. 쓰다 보니 권한이 없어 채우지 못한 칸이 계속 나왔고, 그 빈칸을 한데 모으자 성격이 바뀌었다.
(사내 인프라 특성상 서버 주소·사람 이름은 일반화했다.)
문서가 있어도 급할 때 못 쓰는 이유
지식이 한 사람 머릿속에만 있으면, 그 사람이 아프거나 휴가 중일 때 서비스가 멈춘다. 문서로 풀어 보려는 시도는 흔한데, 막상 급할 때 못 쓰는 문서가 많다. 이유를 세 가지로 봤다.
- 서비스마다 모양이 다르다. 급한 순간에 “이 문서는 재시작이 어디 있지”를 찾는 데 시간이 든다.
- 급할 때 볼 것과 깊이 이해할 것이 섞여 있다. 장애 원인을 분석한 긴 이야기 사이에서 재시작 명령을 찾게 된다.
- 해당 없는 칸까지 다 채워 둔다. “해당 없음”이 줄줄이 있으면, 정말 비어 있어서 문제인 칸이 그 사이에 묻힌다.
네 런북, 같은 모양
네 런북 모두 이 뼈대를 따른다.
급할 때
├ 살아 있는지 확인 ← 한 줄 명령 + 무엇이 나와야 정상인지
├ 재시작 ← 부작용·다운타임이 있으면 같이
├ 증상별로 어디를 보나 ← 자주 나는 증상 → 트러블슈팅 문서 링크
└ 내 선에서 안 되면 ← 죽으면 무엇이 막히나, 권한 밖이면 누구에게
평상시 운영
├ 어디에 무엇이 있나
├ 백업과 복구 ← 마지막으로 실제 복구해 본 날짜
└ 바꿀 때 지킬 것
배경 지식
├ 구조와 의존 관계
└ 관련 문서
아직 못 채운 것
지킨 규칙은 네 가지다.
“급할 때” 네 칸은 순서를 바꾸지 않는다
어느 서비스를 열어도 같은 자리에 같은 게 있어야 한다. 사람이 바뀌어도 같은 순서로 대응할 수 있게 하는 게 이 문서의 목적이고, 그러려면 내용보다 먼저 자리가 예측 가능해야 한다. 그래서 장애가 의심되면 “급할 때” 블록만 봐도 1차 대응이 되게 썼다.
마지막 칸 “내 선에서 안 되면”이 실제로는 가장 중요하다. 이 서비스가 죽으면 무엇이 같이 멈추는지, 내 권한 밖이면 누구에게 넘기는지가 여기 있다.
해당 없는 칸은 통째로 뺀다
TabbyML 런북에는 다른 런북 같은 백업·복구 절차가 없다. 인덱스는 다시 만들면 되고 계정과 설정은 소량이라, “따로 절차를 두지 않는다”는 이유 한 줄과 서버 백업에 넣을 파일 두 개만 적었다. “백업: 해당 없음”으로 칸을 채우지 않는다. 그래야 다른 런북의 “복구해 본 적 없음” 같은 진짜 빈칸이 눈에 띈다.
사고 이야기는 쓰지 않는다
원인을 어떻게 찾았는지 같은 이야기는 트러블슈팅 문서에 두고, 런북에서는 링크만 건다. 런북은 “지금 무엇을 하면 되는가”만 답한다.
모르면 모른다고 적는다
이게 이 작업에서 가장 중요한 규칙이 됐다. 런북을 쓰다 보면 “헬스체크 주소는 아마 이거겠지”, “재시작은 이렇게 하겠지” 같은 칸이 계속 나온다. 그걸 추측으로 채우는 순간, 그 문서는 틀린 답을 맞는 답처럼 담게 된다. 급할 때 그 추측을 믿고 움직이면 더 위험하다.
그래서 확실히 아는 것만 적고, 모르는 건 “아직 확인하지 못했습니다”라고 쓴 뒤 맨 아래 “아직 못 채운 것”에도 올렸다.
빈칸을 모았더니
런북 네 개를 다 쓰고 “아직 못 채운 것”만 모아 보니 열두 개였다. 그리고 거의 전부 서버 접근 권한이 있어야 채울 수 있는 칸이었다. 공통 패턴으로 묶으면 이렇다.
| 빈칸 | 해당 | 채우려면 |
|---|---|---|
| 백업을 실제로 복구해 본 적이 없다 | Sentry, Keycloak, NPM | 담당자와 30분. 스냅샷을 격리된 곳에 띄워 로그인되는지 한 번 확인 |
| 운영 서버가 어디서 어떻게 뜨는지 모른다 | Keycloak 백엔드, 운영 NPM | 호스트 이름·컨테이너 이름·재시작 방법을 공유받기 |
| 헬스체크가 정말 정상 응답을 주는지 모른다 | Sentry, TabbyML | 내부망에서 한 번 호출해 응답 코드 확인 |
| 크리덴셜이 어디 있는지 정리가 안 됐다 | 전체 | 파일마다 어느 서비스용인지 라벨만 붙이기 (값은 열 필요 없음) |
하나씩 보면 그냥 “미확인 항목”이다. 그런데 한자리에 모으니 “이 서비스들의 운영 지식에서 어디가 비어 있는가”를 보여 주는 지도가 됐다. 그리고 그 지도의 대부분이 서버 권한으로 풀린다. “권한을 주세요”가 아니라 “이 칸들을 채우려면 이 권한이 필요하다”고 말할 수 있는 근거가 생긴 것이다. 처음부터 노린 결과는 아니었다. 추측으로 칸을 메웠다면 빈칸은 애초에 보이지 않았을 것이다.
같은 이유로 이 목록은 안정성 지표의 출발점도 된다. “마지막으로 복구를 실제로 해 본 날짜”는 지금 세 서비스 모두 없음이다. 출발점이 0이라는 걸 적어 둔 것 자체가, 앞으로 날짜를 채워 나갈 칸이 된다.
그 뒤
이름을 쉬운 말로 바꿨다. 처음에는 “🚨 긴급 카드 — 헬스체크 / 재시작 / 증상맵 / 에스컬레이션”, “§ 갭 / TODO”, “[확인필요]” 같은 이름을 썼다. 나중에 위 뼈대처럼 “급할 때 — 살아 있는지 확인 / 재시작 / 증상별로 어디를 보나 / 내 선에서 안 되면”, “아직 못 채운 것”으로 바꿨다. § 기호는 보기 불편하다는 이유로 아예 쓰지 않기로 했다(9월 29일).
맨 위에 범위를 적었다. 9월 말부터 절차 문서는 첫머리에 범위: 줄을 둔다. 예를 들어 Sentry 런북은 “상태 확인과 1차 대응. 서버 접속은 사전 승인 후, 재시작·설정 변경은 변경 전후를 보여 주고 승인 후”로 시작한다. 이 문서로 어디까지 해도 되는지가 맨 먼저 보인다.
빈칸 하나는 장애가 닫았다. Sentry의 헬스체크(/_health/)는 9월 28일 장애를 조사하면서 내부망에서 실제로 200이 나오는 걸 확인해 지웠다. TabbyML 쪽은 아직 남아 있다.
런북이 낡으면 알림이 온다. 매주 월요일 문서 점검 스크립트가 런북의 “마지막 확인” 날짜를 보고, 30일이 넘은 런북을 목록에 올린다.
마치며
진짜로 배운 것
- 대체 가능성은 내용보다 자리에서 나온다. 모든 런북에서 같은 칸이 같은 자리에 있다는 규칙 하나가, 서비스별 지식 몇 줄보다 더 크게 사람 의존을 줄인다.
- 모르는 건 비워 둔다. 추측으로 매끈하게 채운 문서는 완성돼 보이지만, 급할 때는 다시 검증해야 하는 지뢰밭이다. 정직하게 남긴 빈칸만이 나중에 지도가 된다.
- 빈칸은 모으면 성격이 바뀐다. 문서마다 흩어진 TODO가 한자리에 모이면, 권한을 요청할 근거이자 다음 작업 목록이자 안정성 지표의 출발점이 된다.
- “해당 없음”을 적느니 칸을 뺀다. 없는 칸을 채우면 정말 비어 있는 칸이 묻힌다.