그래프
사례6건
6건 중 1~5번째
- 증상
2026-05-28 16:18 UTC 부터 us-southcarolina 리전에서 Lucidworks AI 가 호스팅하는 LLM 인 llama-3-8b-instruct, llama-3v2-3b-instruct, phi-4-multimodal-instruct 에 보낸 질의가 500 이나 429 오류로 실패했다. 검색, 임베딩 모델, Lucidworks Platform UI, passthrough LLM 호출은 정상이었다.
- 촉발
us-southcarolina 리전 클러스터의 정기 쿠버네티스 패치 업그레이드가 노드 풀을 차례로 교체했다. surge 방식의 노드 풀 업그레이드는 파드가 옛 노드에서 쫓겨나기만 하면 다음 노드로 넘어갔다. 그래서 Ray Serve 의 head 파드와 worker 파드가 새 노드에서 뜨기 전에 모두 쫓겨났다.
- 원인
- 구성 요소
- 기여 요인
- 조치
- 상태가 나빠 컨테이너 이미지를 받지 못하던 교체 head 노드를 손으로 지웠다.
- 교체 노드에서 LLM 이미지 받기가 끝나기를 기다렸고, 모든 호스팅 모델이 질의에 응답하는 것을 확인했다.
- 필요한 LLM 이미지가 든 새 노드를 띄우고 Lucidworks AI 트래픽을 그 노드로 돌렸다. 예측 엔드포인트의 200 응답으로 안정을 확인했다.
- 후속 조치
- LLM 워크로드를 돌리는 클러스터의 쿠버네티스 업그레이드를 순서대로 진행해, 한 노드 풀이 완전히 정상이 된 뒤에 다음 노드 풀을 올리게 한다.
- 큰 ML 모델 이미지를 받는 데 오래 걸리지 않도록 이미지를 노드에 미리 올려 두는 방법을 조사한다. 후보는 디스크 이미지에 컨테이너 이미지를 미리 넣어 두는 방법과 이미지 스트리밍이다.
- 비정상적으로 느린 Docker 이미지 받기를 조사하도록 클라우드 사업자에게 지원 티켓을 연다.
- 진행 중인 배포와 겹치지 않도록 쿠버네티스 유지 보수 시간을 LLM 서비스 담당자와 맞추는 알림 절차를 만든다.
- Ray 가 새 배포와 옛 배포를 스스로 정리하기를 기다리지 않고 Lucidworks Engineering 이 blue 나 green 으로 강제 전환할 수 있도록 Ray 클러스터 도구를 개선한다.
- 증상
2025년 1월 21일 23시 UTC쯤, 보관 데이터를 담는 데이터베이스 인스턴스의 남은 저장 공간이 거의 없다는 자동 알림이 울렸다. 23시 26분부터 워크플로 대기열이 늘면서 워크플로와 잡의 시작과 취소가 느려지고 UI에서 워크플로를 보기 어려워졌다.
- 촉발
1월 16일에 보관 데이터베이스의 함수 하나를 고친 코드 변경이 의도치 않게 로그 메시지를 지나치게 많이 만들어 냈다.
- 원인
- 구성 요소
- 기여 요인
- 감지
23시쯤 보관 데이터베이스의 남은 저장 공간이 거의 없다는 자동 알림이 울렸다. 같은 시각에 요청량 알림이 따로 울려 팀은 워크플로 지연을 곧바로 이 문제와 연결하지 못했다. 그 알림이 해결된 뒤에도 대기열이 늘자 다른 팀이 조사에 나섰다.
- 조치
- 23시 44분에 워크플로 대기열을 처리하는 이벤트 소비자를 증설했다.
- 23시 55분에 문제가 난 보관 데이터베이스의 읽기 복제본을 독립된 주 인스턴스로 승격했다.
- 후속 조치
- 로그 메시지를 지나치게 많이 만들던 데이터베이스 함수를 고쳤다.
- 워크플로 보관 호출의 재시도 정책에 최대 지속 시간을 두어 기본 타임아웃보다 일찍 실패하게 하고, 보관 서비스에 문제가 생겨도 워크플로 서비스가 받는 영향을 줄인다.
- 장기적으로 워크플로 보관 과정을 이벤트 기반 방식으로 바꿔 두 서비스를 떼어 놓는다.
- 데이터베이스에 예측 모니터링과 이상 탐지 모니터링을 더해, 이상한 움직임이 위험 수준에 닿기 전에 알림을 받는다.
- 교훈
보관 데이터베이스의 문제를 알리는 알림은 울렸지만, 데이터베이스가 예측보다 훨씬 빨리 차서 고객 영향이 나기 전에 대응할 시간이 거의 없었다. 워크플로 서비스가 보관 서비스를 동기로 호출하기 때문에 보관 쪽 문제가 워크플로 전체의 지연으로 번졌다.
- 증상
2023년 9월 7일 TANF-app 의 sprint 80 운영 배포가 실패했고, 9월 20일 sprint 82 배포는 디스크 공간 오류로 실패했다. 그 뒤 11월 9일까지 운영에 배포하지 못했다.
- 촉발
2023년 9월 7일 sprint 80 배포에서 이미 배포된 마이그레이션 search_indexes 0016 을 지웠고, 9월 20일 sprint 82 배포가 이 마이그레이션을 다시 만들어 큰 마이그레이션 0017 과 함께 운영 데이터베이스에서 돌렸다.
- 원인
- 구성 요소
- 기여 요인
- 감지
운영 배포가 실패하면서 드러났다. 9월 7일 sprint 80 배포와 9월 20일 sprint 82 배포가 차례로 실패했고, 9월 20일 배포에서 디스크 공간 오류가 났다.
- 조치
- 11월 8일 운영 데이터베이스 인스턴스 크기를 키우고 마이그레이션을 다시 돌렸다. 이번에는 빈 문자열을 정수로 바꾸는 오류로 마이그레이션이 실패했다.
- 운영 데이터베이스의 백업을 만들었다.
- `search_indexes` 테이블을 모두 비웠다. 팀은 여기서 운영 데이터를 잃는 것을 걱정하지 않았다.
- sprint 82 릴리스를 다시 배포해 운영을 sprint 82 로 되살렸고, 배포가 다시 가능해졌다.
- 빈 문자열 버그를 고쳤다.
- 후속 조치
- 데이터베이스 문제 해결 절차를 기술 문서에 더한다.
- 위키 페이지와 운영 플레이북에 흔한 문제와 대응을 정리한다.
- Failed-Deployment-Troubleshooting 문서에 데이터베이스 문제 절을 만들고 cf revisions 명령을 적는다.
- 운영에 직접 한 변경을 모은 GitHub 레포를 만들어, 비슷한 문제가 다시 날 때 길잡이로 쓴다.
- 운영 디버깅 세션의 터미널 출력을 저장한다.
- 코드 리뷰에서 지킬 Django 마이그레이션 모범 사례를 만든다.
- develop 에 머지된 마이그레이션은 고치지 않고, 그 시점부터 모델을 바꾸는 새 마이그레이션을 쓴다.
- 자동 생성된 마이그레이션 이름을 알아보기 쉬운 이름으로 바꾼다. 이름만 보고 내용을 알 수 없으면 조사하기 어렵다.
- 자동 생성 마이그레이션은 모델 변경 하나에 하나만 두고, PR 하나에서 모델을 여러 번 바꾸면 마이그레이션을 다시 생성한다.
- 시험에 쓸 데이터베이스 시딩과 백업을 어떻게 할지 논의 자리를 만든다.
- 교훈
계획에 없던 일이라 많은 개발자가 손을 보태야 했고, 팀이 작아 분야마다 모든 사람이 필요했다. 팀은 문제와 대응을 일찍 문서로 남겨 더 적은 사람으로 대응할 수 있게 하자고 했다. 작업 중인 코드를 raft, qasp, sandbox 환경에 배포한 뒤 마이그레이션을 바꾸면 그 환경에서 충돌이 난다. 대용량 데이터와 공백 채움이 없는 레코드 같은 예외 상황은 시험하지 않았고, 개인정보를 지운 운영 데이터베이스 사본이 있으면 실제 데이터로 더 많이 시험할 수 있다.
- 증상
2022년 4월 11일 13:17 UTC 에 고객과 Gitpod 직원들이 워크스페이스가 간헐적으로 응답하지 않는다고 알렸다. 4월 8일과 9일에 새 세대 워크스페이스 클러스터 ws39 를 모든 리전에 배포한 직후였다.
- 촉발
2022년 4월 8일과 9일에 새 세대 워크스페이스 클러스터 ws39 를 모든 리전에 배포한 것이 시작이었다.
- 원인
- 구성 요소
- 기여 요인
- 감지
2022년 4월 11일 13:17 UTC 에 고객과 Gitpod 직원들의 신고로 알았고, incident.io 연동으로 Slack 에 장애를 열었다. 4월 12일에도 고객과 직원의 신고로 알았고, 4월 17일에는 엔지니어들이 워크스페이스 노드의 CPU 부하가 오른 것을 보고 내부 장애를 열었다.
- 조치
- IO 제한 기능이 없어 워크스페이스 시작 트래픽을 이전 세대 클러스터 ws38 로 돌렸고, 4월 11일 15:37 UTC 에 마쳤다.
- t2d 대신 더 빠른 c2d 머신 유형과 로컬 SSD 를 쓰는 새 클러스터 ws39a 를 만들어 트래픽을 옮겼다.
- Let's Encrypt 속도 제한 문제를 풀고, Let's Encrypt 에 한도를 올려 달라고 요청했다.
- ws38 클러스터를 쓸 수 없어 EU XL 트래픽을 임시로 리전 EU 클러스터로 보내 워크스페이스를 다시 시작할 수 있게 했다. 그리고 망가진 ws-eu39xl 을 대신할 ws-eu39bxl 클러스터를 새로 만들었다.
- stopping 상태에 걸린 워크스페이스를 정리해 사용자가 다시 시작할 수 있게 했다.
- 4월 8일 배포 전처럼 1TB 부트 디스크를 단 노드로 ws40 을 만들어 디스크 IO 대역폭을 늘렸다.
- 모니터링으로 노드의 작업을 직접 살펴 과도한 CPU 시간을 쓰는 워크스페이스를 찾아 시스템에서 지웠다.
- 노드를 손으로 뒤지고 채굴 탐지 시스템을 함께 써서 부정 사용자를 찾아 Gitpod 사용을 막았다.
- ws38 세대에는 없던 ws-daemon 변경을 되돌려 CPU 제한을 다시 안정시켰고, 이 수정을 ws34 클러스터에 담아 배포했다.
- 새 ws34 배포에서 워크스페이스 포트로 가는 ACME HTTP 요청을 막아 Let's Encrypt 한도에 다시 걸리지 않게 했다.
- 워크스페이스 사이에 디스크 IO 를 공정하게 나누는 ws41xl 클러스터와 일반 리전용 ws41 클러스터를 만들어 트래픽을 단계적으로 옮겼다.
- 후속 조치
- 테스트 결과가 진행하면 안 되는 배포를 미리 걸러 내도록 테스트 자동화에 계속 투자한다.
- 새 클러스터로 트래픽 비율을 옮기는 간격을 배포마다 다르게 하고, 큰 배포일수록 단계 사이를 길게 둔다.
- 워크스페이스 클러스터 배포에 위험 평가 단계를 넣어 변경 묶음의 크기와 배포 속도를 정하고, 이 단계를 자동화하는 것을 목표로 한다.
- 팀 사이 의존이 롤백을 막지 않도록 팀끼리 주는 영향을 계속 줄인다.
- PR 을 머지하기 전에 하위 호환이 깨지는 변경을 찾는 리뷰 기준을 더하고, 그런 PR 은 나눠서 배포를 롤백하기 어려운 상황을 피한다.
- 장애 완화의 첫 수단으로 롤백을 권하도록 절차를 고쳤고, 이 과정을 자동화하는 방법을 논의한다.
- 상태 페이지의 워크스페이스 서비스가 장애를 주황이나 빨강으로 제대로 표시하도록 고쳤고, 플레이북도 그에 맞게 고쳤다.
- 장애 중 내부 소통을 Slack 채널 하나와 Google Meet 하나로 모으고, 장애 절차를 그에 맞게 고쳤다.
- 당번 체계를 다시 짜서 5월 9일부터 엔지니어링 인력의 10% 가 늘 당번을 맡고, 그 시간으로 관측성과 알림과 시스템 안정성을 개선한다.
- 교훈
4월 11일에 롤백을 결정했다면 가장 좋았다. 롤백하지 않고 수정을 계속 만들어 배포하면서 고객은 필요 이상으로 오래 성능 저하를 겪었고 일부는 데이터를 잃었다. 규모가 크고 바로 앞 배포와 가까운 변경을 너무 빨리 내보냈고, 테스트 결과가 배포를 막았어야 했다. 배포 묶음을 작게 하고 배포를 자주 한다는 원칙을 ws39 에서 지키지 못했고, 팀 사이 의존이 롤백을 어렵게 만들었다. 기여 요인 가운데 일부는 막을 수 있었다.
- 증상
2021년 3월 6일 11시 길드 업데이트 점검을 마친 뒤 데이터베이스 CPU 사용량이 예상보다 조금 높았다. 11시 30분쯤 24코어 머신인 데이터베이스 노드 하나가 24코어를 모두 쓰며 CPU 사용량이 최대치에 이르렀고, 같은 시각 서버 지표에서 상당한 양의 에러가 보이기 시작했다. 곧 다른 두 노드에서도 CPU 사용량 이상이 나타났다.
- 촉발
길드 업데이트 점검 뒤 서비스를 열자 모든 유저가 곧바로 새 기능을 썼고, 분석용 테이블에 guild-<uuid> 형식의 Primary Key가 매우 빠르게 쓰였다. 리팩토링으로 Primary Key 형식이 바뀐 테이블도 있었다.
- 원인
- 구성 요소
- 기여 요인
- 감지
모니터링 중 한 노드의 CPU 사용량이 최대치에 이르렀다는 소식과 함께 서버 지표에서 에러가 관측돼 알았다. 이후 노드 문제는 Host Status Check 실패 슬랙 알림과 이상 로그 감지 채널의 알림으로 알았다.
- 조치
- 기존 유저를 내보내지 않고 새 로그인만 막아 입장 인원을 0명으로 둔 대기열처럼 썼고, 지표를 보며 막고 풀기를 반복해 동시 접속자 수를 조절했다.
- 오후 2시 50분 노드 여러 대가 health check를 통과하지 못하자 아무도 게임을 할 수 없는 전체 긴급 점검에 들어갔다.
- 전체 데이터베이스 백업이 멈추자 테이블 단위로 백업했다. 부하가 몰린 것은 특정 테이블의 일부 Range였고 그 테이블은 다른 테이블로 복구할 수 있었기 때문이다.
- 서비스를 열기 전에 데이터베이스 부하를 최대한 줄이려고 플레이 기록 저장을 잠시 멈췄다.
- 오후 6시 반쯤 문제가 된 테이블들에 Split 작업을 시작해 부하가 모든 노드에 고르게 나뉘도록 했다.
- Host Status Check에 실패하고 filemap_fdatawait_range_keep_errors 로그가 나온 노드를 클러스터에서 빼기로 하고, Range 분리와 그 노드의 Decommission을 함께 진행했다. Decommission이 끝나자 복제되지 않은 Range가 0이 되고 지표가 안정됐다.
- 서비스를 다시 연 뒤 한 노드가 CPU를 100% 쓰자 다시 대기열 방식으로 접속을 조절해 CPU 사용량을 안정시켰다.
- 같은 노드가 거듭 CPU 100%에 이르러 노드 자체의 문제로 보고 그 노드를 종료해 문제를 끝냈다.
- 교훈
일반 RDBMS에서는 Primary Key prefix를 바꿔도 큰 문제가 되지 않지만, 분산 처리를 하는 CockroachDB의 프로덕션 클러스터에서는 이런 변경에 상당한 주의가 필요하다. 팀은 CockroachDB 스터디에서 문서와 자료를 읽어 이 내용을 알고 있었다. 그러나 직접 겪어 보니 글로 읽어 알던 것보다 훨씬 큰 일이었다.
이 6건에서 가장 많이 나오는 구성 요소: 데이터베이스, 인메모리 캐시. kubegap 은 Claude Code 나 Codex 에서 쿠버네티스 클러스터를 읽기만 하며 이런 틈을 점검합니다. 점검 항목의 근거는 이 라이브러리와 같은 공개 보고서입니다.
원인별1
배포 결함6건
- 구성 요소
- 기여 요인
IL-0237us-southcarolina 리전에서 Lucidworks AI 의 호스팅 LLM 이 약 1시간 반 동안 500 과 429 오류를 내며 멈췄다Lucidworks2026IL-0552보관 데이터베이스의 저장 공간이 차서 CircleCI 워크플로 시작이 늦어지고 UI에서 워크플로가 잘 보이지 않았다CircleCI2025IL-0523TANF-app 의 운영 배포가 PostgreSQL 마이그레이션 실패로 두 달 동안 막힘IL-0591Gitpod 워크스페이스가 새 클러스터 세대 배포 뒤 열흘 넘게 모든 리전에서 느려지고 시작 실패와 데이터 유실이 났다Gitpod2022IL-0566쿠키런: 킹덤 길드 업데이트 직후 CockroachDB 노드 몇 대에 부하가 몰려 CPU가 100%에 이르고 게임에 에러가 났다Devsisters2021IL-0278주간 소프트웨어 업데이트 뒤 GCP 의 Redis Cloud 클러스터 노드 대부분이 동시에 응답하지 않아 그 클러스터의 데이터베이스가 내려갔다Redis2016