재발 방지 대책(Runbook 포함) 작성 방법

1,765 단어·4 분·원문(.md)

장애라는 산불을 무사히 진화했다고 치자, 이제 남은 잿더미 위에서 다시는 산에 불이 나지 않게 만드는 작업을 해야한다.

두 번 이상 겪는 고통은 의미가 없다는 말을 들어보았는가, 처음 겪는 고통은 나의 허점을 깨닫게해주지만 두 번 이상 겪는 고통은 배울것이 없다.

그래서 재발방지라는 문화를 위해 여러가지 시도를 하는것이 좋은데 SRE의 꽃이자 장애를 엔지니어링 자산으로 승화시키는 재발 방지 대책 수립 원칙과 실전 런북 작성법에 대해서 알아보자.

재발 방지 대책 Action Itmes의 1원칙 "사람을 고치지말고 시스템을 고쳐라" #

엔지니어로서 당연한 말 같긴한데, 가장 최악의 장애 보고서 post-moterm은 재발 방지 대책에 앞으로 배포 전 테스트를 더 잘하겠습니다 담당자가 크론탭 설정을 두 번확인하기 어프로브받기 따위의 다짐을 적는것이 최악이다. 왜냐면 인간은 무조건 실수하고 인간은 또 바뀌기 때문이다.

진짜 기술적인 재발 방지 대책은 시스템의 강제성을 띄어야한다.

  • Bad: DB Query 짤때 인덱스 타는지 주의할것
  • Good: CI 파이프라인에 슬로우 쿼리 탐지 정적 분석 툴 SQL Linter등을 연동해 인덱스를 타지 않는 쿼리가 pr에 올라오면 merge를 block하게 할것. 기한 ~~~ 까지

구체적인 Action Item 도출 방법은 5 Whys라고 왜를 다섯번 반복해 근본 원인 root cause를 탐색후 각 단계마다 방어 로직을 세우자.

  • 현상: 결제 서버가 죽었다
  • 왜?: 디비 커넥션 풀이 고갈 -> AI 1: 커넥션 풀 고갈시 알람 datadog 추가
  • 왜?: 외부 포인트 연동 api가 10초간 응답이 없어서 스레드가 물려있었따 -> AI(Action Item)2 : 외부 api 호출시 타임아웃 10 -> 2로 줄이자
  • 왜?: 타임아웃 설정 코드가 누락되어 있었다. 혹은 여기에 어떤어떤 제약이 있다. -> AI 3: Http Client Bean 생성시 전역 타임아웃 강제 로직을 추가하자. 와 같은

Runbook? #

재발 방지 대책을 아무리 잘 세워도 완벽한 예방은 불가능하다. 그래서 동일한 혹은 비슷한 알람이 다시 울렸을때를 대비해 런북을 작성한다.

런북은 새벽 3시에 비몽사몽한 상태로 전화를 받고 일어난 입사 1개월차 신입 엔지니어도 문서에 적힌 명령어를 복붙하는 것만으로 5분만에 장애를 우회할 수 있도록 작성된 메뉴얼이다.

런북 작성의 3가지 핵심 요건 #

  1. 명확한 진입 조건이 있어야한다 어떠한 알람이 울렸을때는 무조건 이 방식을 사용한다 처럼 유니크한 키가 있어야한다.
  2. 복붙가능한 명령어가 필요한데 추상적인 설명으로 DB재시작하세요 이런거 말고 터미널창에 sudo systemctl restart postgresql 하세요같은 메뉴얼이 필요하다. 아웃데이트 주의도 필요
  3. 에스컬레이션 정책이 필요한데 런북대로 따라했는데도 복구가 안될때 누구에게 전화해야하는가를 명확하게 둔다.

실전 예시 자료 (장애 사후 보고서 및 런북 템플릿) #

사내 위키 Concluenece, Notion에 그대로 복붙해서 쓸 수 있는 실무 표준 템플릿과 작성 예시다.

재발 방지 대책 Action Items 관리 테이블

장애 보고서 하단에 반드시 들어가야하며 지라 티켓과 연동되어 추적되어야한다.

Jira 티켓 SRE-101 분류는 모니터링 액션 아이템은 redis 메모리 사용률 80 초가 pagerduty알림연동 담당자 땡떙떙 이런느낌으로.

# 📙 [Runbook] Redis Cluster Memory Usage > 85% 알람 대응

## 1. 개요 (Overview)
- **트리거 알람명:** `[SEV-2] Redis Memory Usage is critically high (> 85%)`
- **영향도:** 캐시 서버 OOM 발생 시 DB(MySQL)로 트래픽이 몰려 연쇄 전면 장애(SEV-1)로 발전할 위험이 매우 높음.
- **최우선 목표:** 1차적으로 쓸데없는 키를 날려 메모리를 확보하고, 안 되면 즉각 Scale-out 수행.

## 2. 현상 파악 (Investigate)
알람이 울리면 즉시 아래 명령어를 통해 현재 메모리 상태와 범인(가장 큰 키)을 찾습니다.

```bash
# 1. Redis 서버 접속 후 메모리 상태 확인
redis-cli -h cache.mywebsite.internal info memory | grep -E "used_memory_human|maxmemory_human"

# 2. 실시간으로 메모리를 잡아먹는 큰 키(Big Key) 상위 10개 스캔 (주의: 운영 환경 영향 최소화를 위해 --bigkeys 사용)
redis-cli -h cache.mywebsite.internal --bigkeys

조치 방법도 적어야한다 위예시에 이어서 불필요한 혹은 만료된 키를 정리하는 마이그레이션 스크립트가 필요한데 아래에 적어주자

저 예시면 특정 이벤트 배치가 꼬여서 event:ranking:* 이런 키가 무한정 쌓이고 있다는 문제상황을 또 예시로 추가해봤을때 아래와 같이 마이그레이션 스크립트를 제공할 수 있다.

# 비동기로(UNLINK) 특정 패턴의 키를 안전하게 삭제하여 메모리 반환
redis-cli -h cache.mywebsite.internal --scan --pattern "event:ranking:*" | xargs redis-cli -h cache.mywebsite.internal UNLINK

step 2 step1로 안되면 redis node scale out을 하세요같은 2안들도 더 잇으면 좋다. 메모리 90돌파시 주저하지말고 aws cli를 통해 복제본 노드를 추가하여 분산시키자!

aws elasticache increase-replica-count \
    --replication-group-id my-redis-cluster \
    --new-replica-count 3 \
    --apply-immediately

마지막으로 에스컬레이션 010-xxxx-xxxx 혹은 @누구누구 태그하기 같은것들에 대한 정보도 두자

이처럼 잘 만들어진 런북은 소수의 시니어에게 집중된 장애 대응 지식을 팀 전체로 분산시키는 최고의 무기가 될 수 있다.

SRE/question/q_46.md