Kubernetes 프로브 오탐으로 재시작 루프가 날 때 복구 플레이북
💡 Key Takeaways
- 프로브는 빠를수록 좋은 설정이 아니라, 서비스 기동 특성과 트래픽 패턴에 맞는 지연 설계가 핵심입니다.
- 재시작 루프 대응은 코드 수정보다 원인 분류와 롤백 기준을 먼저 고정해야 MTTR이 줄어듭니다.
- 배포 파이프라인에서 프로브 변경을 별도 위험 항목으로 취급하면 동일 사고 재발을 크게 줄일 수 있습니다.
Kubernetes 프로브 오탐으로 재시작 루프가 날 때 복구 플레이북
1. 문제 정의: 앱은 살아 있는데 파드만 계속 죽는 상황
지난주 월요일 아침, 로그인 API 지연 알림이 연속으로 올라왔는데 APM 그래프를 보면 CPU와 메모리는 여유가 있었습니다. 이상했던 건 에러율보다 파드 재시작 횟수가 먼저 튀었다는 점이었습니다. 온콜이 처음에는 DB 커넥션 풀 고갈을 의심했지만, 실제로는 신규 배포에서 readinessProbe 타임아웃을 1초로 줄인 것이 원인이었습니다. 앱은 기동 직후 캐시 워밍을 2~3초 수행하는데 그 시간 동안 준비 신호가 반복 실패하면서 엔드포인트에서 빠졌다가 다시 붙는 플래핑이 생겼습니다. 여기에 HPA가 이 상태를 트래픽 급증으로 오해해 스케일 아웃을 시도하면서 노드 스케줄링 지연까지 겹쳤습니다. 겉으로는 “서버가 불안정하다”로 보이지만 본질은 프로브가 애플리케이션 생애주기를 잘못 모델링한 것입니다. 이런 사건에서는 코드 배포 중단보다 먼저, 어떤 프로브가 어떤 조건에서 오탐을 냈는지 타임라인을 10분 단위로 다시 그려야 합니다.
2. 판단 기준과 원인 분리: liveness, readiness, startup을 섞지 않는다
실무에서 자주 보는 실수는 세 종류의 프로브를 같은 기준으로 조정하는 것입니다. livenessProbe는 프로세스가 멈췄는지 확인하고, readinessProbe는 트래픽 수신 준비 상태를 판단하며, startupProbe는 느린 기동 시간을 보호합니다. 그런데 팀이 급하면 이 경계를 생략하고 “실패하면 빨리 재시작” 한 줄로 통일해 버립니다. 저희도 예전에 그랬고, 실제 장애가 아닌 순간 지연까지 치명 장애처럼 처리해 재시작 폭탄을 만들었습니다. 이후 기준을 바꿨습니다. 첫째, 기동 경로에 외부 의존성이 하나라도 있으면 startupProbe를 둡니다. 둘째, readinessProbe 실패는 자동 재시작과 연결하지 않고 엔드포인트 제외만 수행합니다. 셋째, livenessProbe 임계값은 GC 피크와 I/O 스파이크를 포함한 최악 구간 로그로 산정합니다. 이 세 가지를 분리하면 알림이 늘어도 원인 분류가 선명해져 복구 결정이 빨라집니다. 장애 회고에서도 “왜 재시작했는가”가 아니라 “왜 준비 상태 판단이 틀렸는가”로 질문이 바뀌면서 책임 공방이 줄고 설정 개선으로 대화가 이동했습니다.
3. 실행 절차: 30분 안에 루프를 끊고, 당일 안에 재발 방지선 세우기
복구 절차는 순서가 핵심입니다. 1단계는 배포 중지와 함께 문제 리비전을 고정하고 최근 프로브 변경 diff를 확인합니다. 2단계는 재시작 루프를 끊기 위해 livenessProbe 임계값만 임시 완화하고, readinessProbe는 유지해 트래픽 유입을 보수적으로 통제합니다. 여기서 두 값을 동시에 느슨하게 열면 장애 파드가 트래픽을 다시 받아 오류 전파가 커질 수 있습니다. 3단계는 노드 이벤트와 컨테이너 종료 사유를 묶어 “앱 실패”와 “스케줄링 실패”를 분리 집계하는 것입니다. 저희 팀은 이때 kubectl describe pod 결과를 슬랙 스레드에 붙여 팀 전체가 동일 증거를 보게 했고, 추측성 의견을 줄였습니다. 4단계는 임시 복구 후 2시간 안에 프로브 설계 PR을 열어 영구 조치를 커밋합니다. PR에는 변경 이유, 예상 부작용, 롤백 조건을 필수 템플릿으로 넣었습니다. 마지막으로 배포 전 리허설에서 워밍 지연을 인위적으로 주고 프로브 판정이 의도대로 동작하는지 재현 테스트를 실행했습니다. 이 과정을 문서화해 두면 다음 온콜은 같은 사고에서 훨씬 빠르게 루프를 끊을 수 있습니다.
4. 운영 체크리스트와 주의사항: 프로브 변경은 기능 배포보다 위험하다
프로브 설정은 YAML 몇 줄이라 가볍게 보이지만, 운영 안정성에 미치는 영향은 코드 변경보다 클 때가 많습니다. 그래서 저희는 프로브 변경을 “저위험 설정 수정”이 아니라 “트래픽 게이트 정책 변경”으로 분류합니다. 체크리스트도 별도로 둡니다. 배포 전에는 최근 7일 p95 응답시간과 기동 시간 분포를 기준값으로 기록하고, 배포 중에는 재시작 횟수와 엔드포인트 제외 시간을 5분 단위로 확인하며, 배포 후에는 최소 1시간 동안 자동 스케일 이벤트와 함께 교차 검증합니다. 특히 주의할 점은 환경별 복사 설정입니다. 스테이징에서 잘 동작한 값이 운영에서는 초기 캐시량과 외부 호출 수 차이 때문에 그대로 깨질 수 있습니다. 실제로 한 번은 운영만 Redis warm-up이 길어 startupProbe 유예 시간이 모자랐고, 그날은 기능 자체보다 설정 차이 때문에 더 오래 장애를 겪었습니다. 그 이후로는 프로브 수치 변경 시 “운영 전용 워밍 시나리오”를 테스트 항목에 넣었습니다. 결론적으로 프로브 안정화의 핵심은 마법 같은 숫자를 찾는 것이 아니라, 서비스 생애주기와 트래픽 현실을 반영한 기준을 계속 갱신하는 운영 습관입니다.