장애 대응 런북
실제 운영에서 발생할 가능성이 높은 장애 시나리오별 대응 절차입니다. 각 항목은 증상 → 확인 → 원인 분류 → 조치 → 재발 방지 순으로 정리되어 있습니다.
장애 대응 공통 전제:
-
모든 서비스는 Kubernetes(NHN NKS) 위에서 돌아갑니다. 로그는
kubectl logs <POD>로 확인합니다. -
네임스페이스 맵 (gitops 기준):
-
파드 라벨: 애플리케이션 파드는
app.kubernetes.io/component=<api|worker|scheduler|admin|dashboard>로 셀렉트합니다 (레거시app=<name>라벨은 붙어있지 않음). -
파드 이름은
prd-cone-watcher-api-*,prd-cone-watcher-worker-*,prd-cone-watcher-scheduler-*패턴입니다. (prefix는 basecone-watcher-+ overlayprd-가 합쳐진 결과) -
시간대는 컨테이너 기본인 UTC 기준입니다. 한국 시각은 +9시간.
-
Dramatiq 워커는 자동 재시도가 0회로 설정되어 있습니다 (
common/worker/brokers.py:17Retries(max_retries=0)).config.DRAMATIQ_MAX_RETRIES=3은 미사용 상수이니 혼동 주의. 실패는 곧바로 워커 파드 stdout 로그에 스택트레이스를 남기고 끝납니다. 재실행은 수동입니다. -
worker_task컬렉션은 현재 미사용 레거시입니다. AWS 시절 포크 유산이며WorkerTaskController가 어디서도 호출되지 않아 문서가 쌓이지 않습니다. 태스크 실행 여부는kubectl logs+error_log+ 결과물(nhn_invoice등) 확인 조합으로 판단합니다.
A. 청구서 생성 실패
관련 작업: 스케줄러 nhn_invoice_task (매월 5일 00:00 KST)
A.1 증상
- 매월 5~6일에 "청구서가 안 보인다"는 고객사 제보.
- 대시보드에서 특정 조직만 청구서가 누락됨.
Unissued상태로 넘어가지 않고Origin만 쌓임.
A.2 확인
A.3 원인 분류
A.4 조치
특정 조직만 재실행
- 해당 조직의 월별 청구서를 삭제(DB 접근 가이드 §5.2 참조).
nhn_invoice_task.send(company_id='...', organization_id='...', month='YYYY-MM')로 재생성.
전체 회사 재실행
nhn_invoice에서 해당 월 상태 분포 확인(§A.2 의 aggregate 쿼리).Origin만 있고Unissued복사가 실패한 경우: 다음 호출로 복사 단계부터 다시 실행됩니다.- 고객에게 이미 발행된 청구서가 있다면 섣불리 재실행하지 말고 단건 씩 처리.
워커 파드 재기동
A.5 재발 방지
- 매월 5~6일 배치 성공 확인 을 체크리스트로 운영합니다.
worker_task가 비어있으므로 결과물 + 로그 두 가지로 검증: - 특정 고객사에서 반복 실패한다면 해당
nhn_account자격증명을 우선 점검합니다(§B).
B. NHN API 연동 오류
관련 모듈: common/client/nhn/reseller.py
B.1 증상
- 특정 NHN 계정 하나만 사용량이 수집되지 않음.
- 프로젝트 목록 동기화가 계속 실패.
- 청구서
Origin생성이 안 됨.
B.2 확인
워커 로그에서 호출 경로와 응답 코드를 직접 확인할 수도 있습니다.
B.3 원인 분류
B.4 조치
- 자격증명 문제:
prd-env시크릿 값 교체 후 워커·스케줄러·API 파드 재기동. - 일시적 장애: 수동 재실행.
- 공공 환경 계정:
nhn_account.cloud_type == 'GOV'이면NHN_GOV__*키로 호출합니다. 키 쌍이 섞이지 않았는지 확인.
B.5 재발 방지
- NHN API 키에 만료일이 있으면 만료 30일 전 알람 을 별도 캘린더에 등록.
- 주요 실패 URL은
error_log.context에 남으므로, 주 1회 상위 에러 패턴을 확인하는 운영 루틴을 둡니다.
C. 워커 / 스케줄러 정체
관련 컴포넌트: Dramatiq (Worker), APScheduler (Scheduler), Redis(Valkey) 브로커
C.1 증상
- 스케줄 시각이 지났는데 작업이 실행되지 않음.
- 작업을 enqueue 했는데 워커 파드 로그에 아무 실행 흔적이 없음 (소비되지 않은 것).
Origin청구서는 생성됐는데Unissued로 넘어가지 않고 멈춤.
C.2 확인
큐에 쌓인 메시지를 확인하려면 Valkey에 직접 붙어서:
참고: 여기서
hk-prd는 K8s 네임스페이스가 아니라 Redis key prefix 입니다. 애플리케이션은APP_ENV값으로hk-{env}를 만들어 모든 dramatiq 관련 키 앞에 붙입니다(config/__init__.py:redis_namespace). K8s 네임스페이스는 항상valkey입니다. 큐 이름은HK-COMMON상수(config.COMMON_QUEUE_NAME).
C.3 원인 분류
C.4 조치
큐가 계속 쌓일 때 (워커가 느린 경우)
- 워커 파드 수 증설.
- 긴 작업(예: 청구서 배치)은
company_id단위로 쪼개 수동 enqueue.
스케줄러가 발사하지 않을 때
- 스케줄러 파드 로그에서 예외 스택 확인.
.env.scheduler의 cron 표현식이 UTC 기준임을 확인 (한국시각 09:00 → UTC 00:00).- 파드 재기동.
워커가 멈춘 것처럼 보일 때
AgeLimit초과로 조용히 드롭됐을 가능성 — 워커 로그에 실행 시작 라인이 전혀 없으면 이 케이스.- 수동 재enqueue. 큐가 비어있는지 먼저 확인(
LLEN hk-prd:HK-COMMON).
C.5 재발 방지
- 스케줄 시각 전후 15분 내 워커 파드 로그에 해당 태스크 실행 라인이 찍히는지 정기 점검 (
kubectl logs -l app.kubernetes.io/component=worker --since=30m). - 워커 파드 메모리 상한이 충분한지 확인 (청구서 배치는 데이터 양에 따라 순간 메모리가 큽니다).
- Redis가 영속(persistence) 설정인지 확인 — 재기동 시 큐가 날아가면 스케줄 손실로 이어집니다.
D. DB / 서버 이상
대상: MongoDB (PSMDB), 애플리케이션 파드
D.1 증상
- API 응답이 전면적으로 느려지거나 500 에러.
- 특정 API만 타임아웃 (주로 통계/목록 조회).
- 디스크 사용량 알람.
D.2 확인
MongoDB에 직접 붙어서:
D.3 원인 분류
D.4 조치
연결 고갈
- API 파드 재기동으로 풀을 리셋. 임시 조치이며 근본 원인은 쿼리 튜닝.
- 연결 풀 크기는 클라이언트 설정: minPoolSize=10, maxPoolSize=100 (
common/client/database/mongo.py).
인덱스 이슈
common/database/<collection>_db.py의additional_indexes에 필요한 인덱스가 있는지 확인.- 애플리케이션 시작 시 자동으로 인덱스를 생성하므로, 신규 인덱스를 넣은 코드 배포 후에는 최초 기동 시 생성 시간이 길 수 있습니다.
디스크 관리
error_log는 TTL 90일,invoice_deliveries는 365일로 자동 정리.activity_log는 TTL이 없으므로 장기적으로 가장 빨리 자람. 필요 시 기간 잘라deleteMany또는 아카이브.
디스크가 Full이면
- 쓰기 중단을 먼저 확인: API/워커가 쓰기 실패로 에러를 뱉고 있다면 우선 긴급 공간 확보.
- PVC 확장이 가능하면 StorageClass의
allowVolumeExpansion=true를 이용해 확장. - 임시로 오래된 로그 컬렉션 정리:
- 여유를 확보한 뒤, 근본적인 아카이브 전략 수립 (§D.5).
OOM
- 워커 파드의
resources.limits.memory확인. - 대용량 조직/월은 청구서 배치를 조직 단위로 쪼개 호출.
D.5 재발 방지
- 주간 점검:
db.stats(), 컬렉션별stats(), 노드 디스크 사용률. - 월간 점검: 쿼리 프로파일링을 짧게 켰다가 끄고,
COLLSCAN이 잡히는 API를 정리. - 분기 점검:
activity_log등 TTL이 없는 컬렉션 증가 추이. 필요 시 아카이브 / 삭제 정책 수립.
공통: 수동 태스크 실행 방법
권장 — scripts/enqueue_task.py
scripts/enqueue_task.py 가 dry-run, 인자 검증, 중복 실행 경고를 포함한 래퍼입니다. 자세한 사전 전제(Valkey 포트포워딩 · APP_ENV · REDIS_*)는 scripts/README.md 참조.
워커 파드 내부에서 실행하면 포트포워딩·환경변수 세팅이 불필요합니다.
대안 — 워커 쉘 직접 접속
스크립트가 다루지 않는 태스크이거나 복잡한 조합이 필요할 때만 사용.
주의: 같은 월·회사에 이미 작업이 돌고 있다면 중복 실행이 됩니다. 재실행 전 워커 파드 로그에서 해당 태스크가 아직 진행 중인지(
kubectl logs -n cone-watcher -l app.kubernetes.io/component=worker --since=1h | grep <TASK_NAME>) 반드시 확인하세요.enqueue_task.py는 dry-run 단계에서 이 확인 커맨드를 안내합니다.
에스컬레이션 순서
- 운영 담당자 1차 대응 (이 문서 범위).
- 30분 내 해결되지 않으면 백엔드 개발 담당자 호출.
- NHN Cloud 측 문제(키 만료, API 장애)로 확정되면 NHN 리셀러 창구로 이관.
- 데이터 손상·유실 가능성이 있으면 즉시 쓰기 작업 중단 후 백업 및 복구 의 복구 절차로.