Nginx Docker 환경, 서비스 중단으로 이어진 인증서 갱신
Docker 환경에서 SSL 인증서 자동 갱신으로 인한 서비스 중단
문제 상황: 많은 사용자 문의로 시작된 장애 대응
평소와 다름없이 서비스를 운영하던 중 사용자 문의 요청이 평소보다 비정상적으로 많이 들어왔습니다.
내용은 모두 다음과 같았습니다.
"앱에 접속이 안돼요." "데이터가 유실된거 같아요. 이전에 작성한 일기들이 보이지 않아요." "로그인이 안돼요."
초기 대응: 운영 서버 점검
즉시 운영 서버 상태를 점검했지만 애플리케이션 서버 자체는 정상이었습니다.
CPU, 메모리 등 시스템 자원은 모두 이상이 없었지만, 시스템 로그에 아무것도 나타나지 않은 것이 수상해서 네트워크 혹은 프록시 레벨에서의 문제일 가능성이 높다고 판단하고, 먼저 가동 중인 컨테이너를 확인했습니다.
문제는 프록시 역할을 하던 nginx 컨테이너가 중단되었기 때문에 모든 요청이 애플리케이션 서버로 들어가지 못했습니다.
운영 서버 장애를 확인 후, 동일한 상황을 재현하고 원인을 파악하기 위해 개발 서버를 활용하여 원인 추적을 시작했습니다. 개발 서버에서도 비슷한 시간대에 nginx가 중단되어 있었습니다.
문제 발생 원인을 고민하면서 이상한 점은, "개발자가 직접 배포나 서버 작업을 전혀 수행하지 않았다."라는 것이였습니다.
따라서 “무엇이 Nginx 컨테이너를 종료시켰는가?”로 원인을 좁혀갔습니다.
1차 조사: 도커 이벤트 로그 확인
우선 nginx 컨테이너가 언제, 어떤 이유로 중단되었는지 확인했습니다.
결과:
signal=3 (SIGOUT) -> 정상 종료 신호
exitCode=0 -> 에러가 아닌 정상 종료
즉, 비정상 종료가 아닌 무엇에 의해 의도적으로 컨테이너를 종료시킨 것이었습니다.
또한 로그에 com.docker.compose.service=nginx 라벨이 찍혀 있었고, 이는 Docker Compose가 직접 Nginx를 종료시켰다는 것을 의미했습니다.
그렇다면 누가 Docker Compose를 실행했는가? 가 다음 의문이었습니다.
2차 조사: 시스템 로그 분석
다음으로 시스템 로그를 확인했습니다.
발견된 내용:
즉, Certbot 자동 갱신이 시작되자마자 Nginx가 종료된 것을 확인했습니다.
이제 원인이 Certbot 관련 작업임을 확신할 수 있었습니다.
3차 조사: Cerbot 설정 및 로그 확인
Renewal 설정 확인
즉, cerbot이 인증서 갱신 전에 nginx를 중단시키도록 설정되어 있었습니다.
cerbot의 로그를 확인해보면,
cerbot standalone 모드가 80 포트를 점유한 상태에서 Nginx 재시작을 시도하고 포트 충돌이 발생하여 nginx가 재기동에 실패한 것이 원인이었습니다.
문제 원인 정리
문제는 다음과 같은 순서로 발생했습니다.
certbot 자동 실행
pre_hook 실행 →
docker compose stop nginxcertbot standalone 모드 실행 (포트 80 점유)
인증서 갱신 완료 후 deploy_cert.sh 실행
nginx 재시작 시도 → 포트 80 충돌로 실패
nginx 기동 실패 → 서비스 중단
즉, 자동화된 certbot 갱신 로직이 오히려 다운타임을 만 것이었습니다.
인증서 갱신 시기를 인지하고 미리 수동으로 갱신하는 방법도 있겠지만 이는 근본적인 해결책이 되지 못한다고 생각했습니다.
인증서 갱신 자동화로 인해 발생하는 문제를 어떻게 해결할 수 있을지 다음과 같은 대안을 분석해 봤습니다.
해결책 후보 분석
Blue/Green 배포 환경 구성
장점: 다운타임 없이 완전 무중단 가능
단점: 인프라 비용 및 복잡성 증가
현재 시스템 리소스만으로도 피크 타임에 사용자들의 요청을 처리하는 데 문제는 없었습니다. 인증서 갱신 자동화를 위해 시스템 리소스를 2배로 확장한다는 것은 좋은 선택이 아니라고 생각했습니다.
다른 CA 사용 (ZeroSSL, Google Trust Services)
장점: 갱신 주기나 일부 환경에서는 개선 가능
단점: 다른 CA로 변경해도 근본적인 갱신 방식은 크게 변경되지 않음
클라우드 관리형 인증서 (AWS ACM, Cloudflare)
장점: 자동화 안정성이 높음
단점: 추가 비용 발생 및 아키텍처 변경
ACM은 ALB/Cloud와 연동이 가능하기 때문에 직접 EC2 설치가 불가능합니다.
따라서 아키텍처 변경이 필요한데, 인증서 갱신을 위해 시스템 아키텍처를 변경하는 것은 지금 당장으로 봤을 때 비용을 높이고 운영 단순성을 해치는 선택이라고 판단했습니다.
시간차를 둔 재시작 (지연 재시작)
장점: 간단함
단점: 설정한 sleep 시간만큼의 다운타임 발생
post_hook 설정을 위와 같이 설정한다면 인증서 갱신에서 발생하는 문제를 해결할 수 있습니다.
하지만 의도적으로 시스템이 중단되는 시간을 설정해야 하고 이는 서비스 품질에 아주 큰 영향을 줄 수 있기 때문에 좋은 해결책이 아닙니다.
Webroot 방식 (✅ 최종 선택)
장점:
nginx 다운타임 불필요, 완전 무중단 갱신 가능
기존 인프라 유지 가능
단점으로는 단순히 nginx 설정만 수정해 주면 되기 때문에 큰 단점으로 느껴지지는 않았습니다.
최종적으로 Webroot 방식을 선택한 이유는 다음과 같습니다.
서비스 품질 저하 X
다운타임이 없기 때문에 ~
비용 효율성
추가 리소스나 서비스 변경이 불필요합니다.
기술적 단순성
문제를 해결하기 위해 아키텍처를 변경하거나 기술 변경이 필요없습니다.
운영 안정성
이미 검증된 표준 방식이므로 사용하는 데~
Webroot 방식이란
Standalone 방식 (기존 방식)
Certbot이 일시적으로 자체 웹 서버를 실행
80 또는 443 포트를 점유해야 함
따라서 기존 웹 서버(nginx)를 중단해야 함
갱신 중 서비스 중단 발생
Webroot 방식 (개선된 방식)
Certbot이 기존 웹 서버를 그대로 활용
특정 경로에 인증 파일만 생성
웹 서버는 계속 실행되며, 해당 경로만 접근 허용
무중단 갱신 가능
결과
개선된 지표
다운타임: 완전 제거 (0초)
포트 충돌: 해결
자동 갱신 안정성: 보장
운영 복잡도: 증가하지 않음
이번 이슈는 Let’s Encrypt 환경에서 흔히 발생하는 문제였습니다. Webroot 방식을 통해 다운타임 없는 SSL 인증서 자동 갱신을 구축할 수 있었고, 결과적으로 서비스 안정성을 높이면서 비용도 추가로 발생하지 않는 최적의 방법이었습니다.
고민 포인트
자동화의 양면성
이번에 발생한 문제를 통해 편리한 자동화가 예상하지 못한 서비스 장애를 일으킬 수 있다는 점입니다.
운영 안정성을 높이기 위해 인증서 갱신 자동화를 도입한 것이지만, 실제로 서비스 전체를 중단 시키는 리스크로 작용했습니다. 자동화는 사람의 개입 없이 반복 작업을 안정적으로 처리한다는 장점이 있지만, 도입 전 충분히 검증이 부족하면 더 큰 사고로 이어질 수 있었습니다.
따라서 운영 환경에서 자동화를 도입할 때는 단순히 "편리하다." 그래서 "바로 적용한다."가 아니라, 실패하는 경우 어떤 영향이 있을지, 빠른 복구 대응이 가능한지 검토해야 합니다.
로그의 중요성
이번 문제 해결 과정에서 로그 분석이 결정적인 역할을 했습니다.
Docker 이벤트 로그 → 컨테이너 종료 원인 파악
시스템 로그 → Certbot 실행 시점 확인
Certbot 로그 → 포트 충돌로 인한 재시작 실패 확인
이처럼 발생 시간을 기준으로 로그를 추적할 수 있었기 때문에 원인을 명확히 규명할 수 있었습니다. 만약 로그 체계가 부실했다면 원인을 찾는 데 훨씬 더 오랜 시간이 걸렸을 것입니다.
물론 이번 문제는 단순했기 때문에 단순히 컨테이너를 재기동해도 복구할 수 있었을 것입니다. 하지만 그 경우 당장은 해결하지만 원인은 모른 채 넘어가는 상황이 되었을 것입니다. 복잡하거나 재현이 어려운 장애라면, 로그 없이는 원인을 파악하기조차 불가능하고, 그만큼 서비스 중단이 길어지고 같은 문제가 반복될 가능성이 커질 수 있다고 생각합니다.
로그는 단순히 기록을 남기는 것을 넘어서, 장애 대응의 핵심입니다.
해결책의 선택 기준
문제를 해결하는 방법은 분명 여러 가지가 있습니다.
이번 경험을 통해 깨달은 것은, 현재 시스템과 잘 맞아떨어지고 장기간 안정적으로 유지할 수 있는 방법을 선택하는 기준이 명확해야 한다는 것입니다. 그러기 위해서는 다음과 같은 고려 사항들이 존재할 수 있습니다.
사용자 경험을 저해하는가?
향후 확장이나 유지보수가 용이한가?
추가로 발생하는 비용이 합리적인가?
등 여러 가지 존재할 수 있겠지만, 중요한 것은 가장 실용적이고 합당한 솔루션을 선택해야 한다는 것입니다.
Last updated