Incident Library

IL-0523 U.S. Department of Health and Human Services · 2023-09-07database

TANF-app 의 운영 배포가 PostgreSQL 마이그레이션 실패로 두 달 동안 막힘

미국 보건복지부의 TANF-app 은 2023년 9월 7일부터 11월 9일까지 운영에 배포하지 못했다. 팀은 여러 사고가 하나로 겹쳤다고 밝혔다. 9월 7일 sprint 80 배포가 실패했고, 이때 이미 배포된 마이그레이션 search_indexes 0016 을 지우고 배포 환경의 자동 마이그레이션을 주석 처리했다. 9월 20일 sprint 82 배포는 자동 마이그레이션을 되살리고 0016 을 다시 만들었지만 디스크 공간 오류로 실패했고, 큰 마이그레이션 search indexes 0017 이 드러났다. 9월 7일과 9월 20일 사이에는 develop 파이프라인이 막혀 있었고, 9월 20일 뒤에는 staging 문제가 운영 배포를 막았다.

11월 1일 raft 환경에서 대량 데이터로 재현해 보았지만 마이그레이션이 성공했다. 데이터베이스 크기는 마이그레이션 중 최대 8배로 늘었다 돌아왔고 `temp_files` 는 약 4gb 늘었다. 11월 3일 팀은 큰 마이그레이션을 작게 나누기, PostgreSQL 의 `tmp_file_limit` 올리기, cloud.gov 의 데이터베이스 인스턴스 저장 공간 늘리기, 백업에서 새 인스턴스를 만들어 임시 테이블 공간 비우기를 해결 방안으로 꼽았다. 11월 6일 raft 환경의 저장 공간을 20gb 로 낮추자 임시 공간이 인스턴스 크기를 넘어 문제가 재현됐다.

11월 8일 운영 데이터베이스 인스턴스를 키우고 마이그레이션을 다시 돌리자, 빈 문자열을 정수로 바꾸는 오류가 새로 났다. 원인은 T3 레코드에 있었다. T3 레코드가 사례 파일 하나만 담고 둘째 사례 자리를 공백으로 채우지 않은 채 제출됐다. 파이썬의 부분 문자열 동작 때문에 이 값은 파싱 중 `value_is_empty` 검사를 빠져나갔고, 빈 문자열로 저장됐다. 모델의 필드 타입이 처음부터 맞았다면 마이그레이션이 실패하지 않았을 것이라고 팀은 밝혔다. 11월 9일 팀은 새 데이터베이스를 만드는 대신 운영 데이터베이스를 백업하고 `search_indexes` 테이블을 모두 비운 뒤 sprint 82 릴리스를 다시 배포했고, 운영 배포가 다시 가능해졌다. 빈 문자열 버그는 raft-tech/TANF-app PR 2748 로 고쳤다.

심각도
–
영향 범위
TANF-app production deployments were blocked from 7 September to 9 November 2023
영향 사용자
–
지역
–
감지까지
–
복구까지
63d

증상

2023년 9월 7일 TANF-app 의 sprint 80 운영 배포가 실패했고, 9월 20일 sprint 82 배포는 디스크 공간 오류로 실패했다. 그 뒤 11월 9일까지 운영에 배포하지 못했다.

9월 7일 배포에서 팀은 이미 배포된 마이그레이션 search_indexes 0016 을 지웠고, 배포 환경에서 `makemigrations` 와 `migrate` 를 주석 처리해 마이그레이션을 손으로 돌리게 했다. 9월 20일 배포는 이 주석을 풀고 망가진 0016 을 다시 만들었는데, 이때 디스크 공간 오류가 났고 큰 마이그레이션인 search indexes 0017 이 드러났다. 두 배포 사이에는 develop 파이프라인이 여러 이유로 막혀 있었고, 9월 20일 뒤에는 staging 문제가 운영 배포를 막았다.

11월 1일 팀은 raft 환경에 t1, t2, t3, t4, t5 를 각각 70만~100만 행 올리고, 로컬 환경에서 배포된 데이터베이스를 대상으로 마이그레이션을 돌려 문제를 재현해 보았다. 마이그레이션 중 데이터베이스 크기는 최대 8배까지 늘었다가 끝나면 처음 크기로 돌아왔고, `temp_files` 는 끝난 뒤 약 4gb 늘어 있었다. 레코드 수가 운영보다 훨씬 많은데도 마이그레이션은 성공했고, 팀은 데이터베이스 설정 차이 때문이라고 보았다.

11월 6일 raft 환경의 데이터베이스 인스턴스 저장 공간을 20gb 로 낮추자, 마이그레이션을 여러 번 돌린 끝에 임시 공간이 인스턴스 크기를 넘어 문제가 재현됐다.

11월 8일 운영 데이터베이스 인스턴스를 키우고 마이그레이션을 다시 돌리자, 빈 문자열을 정수로 바꾸다 실패하는 새 오류가 났다. 해당 마이그레이션에 의심 가는 곳이 많아 손으로는 빈 필드를 찾지 못했고, "Debugging commands" 의 "check for blank strings in CharFields" 함수로 T3 의 필드들을 짚어 냈다. T3 의 모든 문자 필드에 `None` 이 아니라 `''` 가 든 레코드가 있었다.

증상 배포 실패노드 디스크 가득 참

원인

촉발
2023년 9월 7일 sprint 80 배포에서 이미 배포된 마이그레이션 search_indexes 0016 을 지웠고, 9월 20일 sprint 82 배포가 이 마이그레이션을 다시 만들어 큰 마이그레이션 0017 과 함께 운영 데이터베이스에서 돌렸다.

감지

운영 배포가 실패하면서 드러났다. 9월 7일 sprint 80 배포와 9월 20일 sprint 82 배포가 차례로 실패했고, 9월 20일 배포에서 디스크 공간 오류가 났다.

조치

후속 조치

교훈

계획에 없던 일이라 많은 개발자가 손을 보태야 했고, 팀이 작아 분야마다 모든 사람이 필요했다. 팀은 문제와 대응을 일찍 문서로 남겨 더 적은 사람으로 대응할 수 있게 하자고 했다. 작업 중인 코드를 raft, qasp, sandbox 환경에 배포한 뒤 마이그레이션을 바꾸면 그 환경에서 충돌이 난다. 대용량 데이터와 공백 채움이 없는 레코드 같은 예외 상황은 시험하지 않았고, 개인정보를 지운 운영 데이터베이스 사본이 있으면 실제 데이터로 더 많이 시험할 수 있다.

출처

참고 문서

관련 사례

내 클러스터에도 있는지 확인하기

kubegap 은 Claude Code 나 Codex 에서 쿠버네티스 클러스터를 읽기만 하며 이 사례와 같은 상태를 점검합니다. 이 사례의 구성 요소: 데이터베이스, 스키마 마이그레이션. 점검 항목의 근거는 이 사례 같은 공개 보고서입니다.

AI 도구와 스크립트용

API 는 키가 필요 없습니다. MCP 서버는 search_incidents, get_incident, list_incidents, get_topic, vocab 도구를 내놓습니다. 사용법은 API 와 MCP.