사례3건
3건 중 1~3번째
- 증상
2026-06-03 오후 3시 38분 EDT 에 xPRO 운영 CMS 와 xPRO 본 애플리케이션이 503 을 낸다는 알림이 함께 울렸다. 공개 사이트 https://xpro.mit.edu 에 고객이 제대로 접속하지 못했다.
- 촉발
cert-manager 가 2026-05-04 에 xpro-web.odl.mit.edu 인증서의 갱신 구간에 들어가 DNS-01 검증을 시작했다. 이 검증이 Fastly 가 만든 _acme-challenge.xpro-web.odl.mit.edu CNAME 과 부딪혀 끝나지 못했고, 기존 오리진 인증서가 2026-06-03 오후 3시 29분 EDT 에 만료됐다.
- 원인
- 구성 요소
- 기여 요인
- 감지
오후 3시 38분 EDT 에 xPRO 운영 CMS 와 xPRO 본 사이트가 503 을 낸다는 알림이 울렸다. 인증서가 만료된 지 9분 뒤였다.
- 조치
- 오래된 cert-manager 자원을 지우고 다시 만들어 cert-manager 가 백엔드 오리진의 새 인증서를 발급하게 했다. 이것으로 서비스가 돌아왔다.
- 후속 조치
- OpenEdX 가 아닌 xPRO 의 Fastly TLS 구독에서 백엔드 오리진 도메인을 뺐다.
- src/ol_infrastructure/applications/xpro 의 Production 스택에 Pulumi 변경을 배포했다.
- Fastly 의 검증 CNAME 을 뺀 뒤, xpro 네임스페이스에 있는 OpenEdX 가 아닌 xPRO 인증서를 cert-manager 로 직접 갱신하거나 cert-manager 가 저절로 갱신하게 했다.
- cert-manager 가 관리하는 오리진 도메인이 Fastly TLS 구독에 들어가지 못하게 막는 테스트나 정책 검사를 넣는 방안을 검토한다.
- cert-manager 의 CertificateRequest 와 Order 가 실패하면 더 일찍 알림을 보내, 인증서가 만료되기 전에 오래된 ACME 실패를 찾는 방안을 검토한다.
- 교훈
이 장애는 처음에 cert-manager 의 ACME 갱신 실패로 이해됐다. 그 이해는 맞았지만 모자랐고, 빠진 진단은 Fastly 가 cert-manager 의 몫인 백엔드 오리진 도메인의 검증까지 관리하도록 설정돼 있었다는 점이었다. 갱신 실패를 일찍 잡지 못한 것은 cert-manager 가 관리하는 백엔드 오리진 도메인이 Fastly TLS 구독에 들어가면 안 된다는 것을 검사하는 장치나 테스트가 없었기 때문이다. 팀은 TLS 인증서와 DNS 검증 레코드를 누가 맡는지 경계를 분명히 정하고 그 경계를 지키는 장치를 둬야 한다고 정리했다. 특히 TLS 자동화를 설정할 때 Fastly 의 공개 프런트엔드 도메인과 쿠버네티스 APISIX 백엔드 오리진 도메인을 바꿔 써도 되는 같은 서비스 도메인으로 다루면 안 된다.
- 증상
learn.mit.edu 가 멈췄다는 보고가 Sentry 이슈 링크와 함께 올라왔다. MIT Learn 의 운영 데이터베이스인 RDS PostgreSQL 인스턴스가 쓸 수 있는 저장 공간을 모두 써 버린 상태였고, 사이트는 503 과 504 오류를 냈다.
- 촉발
정기 릴리스 절차로 배포한 변경이 페이지 응답의 메인 쿼리 안에 집계를 넣었다. DRF 는 페이지 응답의 count 칸을 SELECT COUNT * ($QUERY) 로 계산하므로, 운영의 데이터 규모에서 이 쿼리가 임시 파일을 대량으로 만들었다.
- 원인
- 구성 요소
- 기여 요인
- 감지
엔지니어가 장애를 보고하며 Sentry 이슈를 연결했다. 이어 다른 엔지니어가 운영 데이터베이스의 저장 공간이 바닥난 것을 확인했고, FreeStorageSpace 지표와 Sentry 에 쌓인 504 도 같은 상황을 보여 줬다.
- 조치
- 쿼리 패턴 변경을 쓴 엔지니어가 그 변경이 원인임을 확인하고 릴리스를 롤백했다.
- 데이터베이스가 버퍼에 쌓인 WAL 파일을 따라잡아 비울 여유를 주려고 읽기 복제본을 삭제했다.
- AWS 지원의 도움을 받아 백업이 끝난 뒤 오래 돌던 쿼리를 안전하게 종료했다. pg_stat_activity 에서 state = 'active' 이고 시작한 지 10분이 넘은 쿼리를 pg_terminate_backend(pid) 로 끝내자 저장 공간과 처리 여유가 돌아왔다.
- 후속 조치
- 운영 learn 데이터베이스에 enhanced analytics 를 켜는 방안을 검토한다.
- 플랫폼 엔지니어링 문서 사이트에 롤백 절차를 적는다.
- 장기적으로는 새로 만드는 릴리스 관리 체계에서 롤백을 쉽게 할 수 있게 한다.
- 운영 데이터베이스의 DiskQueueDepth 에 알림을 걸되 너무 자주 울리지 않게 한다.
- API 와 사이트의 응답 시간이 평소보다 30% 넘게 높아지면 알림을 보낸다.
- 운영 데이터베이스 장애를 예제로 삼아 게임데이 훈련을 한다.
- 장애 관리 도구 Rootly 를 써서 장애 때 소통을 한 채널에 자동으로 모으고 장애 기록을 자동으로 남긴다.
- 장애 대응 런북을 가볍게 만든다. 장애가 나면 Zoom 통화를 열고, 당번 엔지니어가 지표가 평소 수준으로 돌아오는지 지켜보며, 소통 담당을 따로 두어 이해관계자의 문의가 핵심 대응자를 방해하지 않게 한다.
- 오래 도는 쿼리를 종료하는 SQL 과, 이 SQL 을 고쳐 아주 오래 도는 쿼리만 골라 종료하는 SQL 을 운영 Postgres 런북에 넣는다.
- Learn Resource View Event 모델이 지금은 건수를 세는 데만 쓰이므로 다시 설계해야 한다는 이슈를 쓴다.
- 익명화한 운영 데이터 생성 도구로 RC 환경의 데이터 양을 운영 수준까지 늘린다. 운영 데이터를 익명화해 담은 운영 규모의 부하 시험 환경을 만들고, 이해관계자도 시험에 쓰는 RC 에 영향이 없도록 인프라를 분리한다.
- 조회 수를 미리 계산해 둔 열에서 읽도록 고쳐 배포했다. 영향을 받던 API 의 운영 응답 시간이 약 13~15초에서 150~200ms 로 줄었다.
- 교훈
이 변경은 가장 시니어인 엔지니어 두 명이 꼼꼼히 리뷰했지만 로컬과 RC 환경에서는 아무 문제도 드러나지 않았다. 운영의 데이터 규모와 시스템 부하가 크게 달랐고, 효율적이라고 여긴 COUNT 집계가 디스크 사용량을 폭증시킬 것이라는 점은 당시 시스템 상태만 보고는 알기 어려웠다. 그래서 운영과 같은 규모의 데이터로 부하를 시험할 환경이 필요하다고 팀은 결론지었다. AWS 지원은 ORM 쿼리 변경을 운영 수준의 데이터를 담은 스테이징에서 시험하고, EXPLAIN ANALYZE 로 실행 계획과 예상 자원 사용을 보며, 시험 중 log_temp_files 로 임시 파일 생성을 지켜보라고 권했다. 폭주하는 쿼리를 막도록 temp_file_limit 를 설정하고, 실행 계획에 따라 work_mem 이나 shared_buffers 를 조정하되 메모리를 너무 쓰면 out of memory 로 장애 조치가 일어날 수 있다는 점도 짚었다. 임시 파일을 많이 쓰는 작업에는 임시 파일을 EBS 대신 로컬 NVMe 에 두는 RDS Optimized Reads 를 고려하라고 했다.
- 증상
설정 배포 6분 뒤 Pingdom 이 DevOps 당번 엔지니어에게 알림을 보냈고, xPro 운영 사이트는 응답하지 않았다. Heroku 로그에는 데이터베이스 로그인 실패가 찍혀 있었다.
- 촉발
오후 3시 45분에 Salt 로 xPro 운영 Heroku 스택에 설정 변경을 배포했다. 이때 Salt 가 본 Vault 리스가 곧 만료되고 갱신할 수 없는 상태여서 Vault 가 새 데이터베이스 자격 증명을 만들었고, 새 자격 증명은 RDS 의 새 기본값인 SCRAM 방식으로 만들어졌다.
- 원인
- 구성 요소
- 기여 요인
- 감지
설정 배포 6분 뒤인 오후 3시 51분에 Pingdom 이 DevOps 당번 엔지니어에게 알림을 보냈다. 당번 엔지니어가 알림을 받고 사이트가 응답하지 않는 것을 확인했다.
- 조치
- 새 데이터베이스 파라미터 그룹을 만들어 운영 중인 데이터베이스에 적용했다. 파라미터 그룹은 xPro RDS 가 쓰던 AWS 기본 파라미터 그룹을 복제한 뒤 필요한 값을 고친 것이었다.
- 데이터베이스가 RDS 콘솔에서 Available 로 보인 뒤 캐시된 자격 증명을 다시 지우고 Salt 로 Heroku 설정을 다시 적용했다. 그러자 사이트와 데이터베이스 로그인이 돌아왔다.
- 후속 조치
- xPro 의 자원 관리를 Pulumi 로 옮긴다. 특히 RDS 인스턴스와 그에 딸린 자원을 코드로 관리하고, AWS 가 주는 기본 파라미터 그룹을 쓰지 않는다.
- 교훈
복구를 늦춘 핵심 요인은 이 스택의 설정이 거의 코드로 관리되지 않았다는 점이었다. RDS 인스턴스가 수정할 수 없는 AWS 기본 파라미터 그룹을 쓰고 있어서, 기본 정의를 복제해 고치고 인스턴스에 새로 연결해야 했다. 이 일은 이미 연결된 파라미터 그룹의 값을 바꾸는 것보다 오래 걸렸다. 팀은 자원을 Pulumi 로 관리했다면 기본 파라미터 그룹을 쓰지 않으므로 이 지연이 없었을 것이라고 정리했다.
이 3건에서 가장 많이 나오는 구성 요소: 데이터베이스, CDN 과 엣지 네트워크. kubegap 은 Claude Code 나 Codex 에서 쿠버네티스 클러스터를 읽기만 하며 이런 틈을 점검합니다. 점검 항목의 근거는 이 라이브러리와 같은 공개 보고서입니다.