Nginx + GitHub Utterances 장애 복구기

어느 날 갑자기 블로그가 죽었다#

2026년 1월 29일 아침.

평소처럼 plzrun.com에 접속했는데 아예 사이트가 열리지 않았다.
404도 아니고, 일부 기능 고장도 아니고, 그냥 접속 자체가 안 되는 상태였다.

처음엔 “EC2가 죽었나?”, “디스크 찼나?” 같은 생각부터 들었다.

하지만 서버에 직접 접속해보니 EC2 자체는 살아 있었고, 문제는 Nginx였다.


1단계: 블로그 전체 장애 (Nginx 기동 실패)#

증상#

  • plzrun.com 접속 불가
  • Nginx 서비스가 계속 내려가 있음
  • 수동 재시작도 실패

원인 로그#

journalctl -u nginx
[emerg] host not found in upstream "api.github.com"
nginx: configuration file test failed

👉 문제는 GitHub API를 upstream으로 지정한 설정이었다.

Nginx 설정 안에 아래와 같은 코드가 있었는데,

proxy_pass https://api.github.com/...

이 설정은 Nginx 시작 시점에 DNS 해석이 안 되면, 서버 자체가 부팅 실패로 간주된다.

마침 그 시점에:

  • unattended-upgrade가 실행 중이었고
  • systemd-resolved / network 서비스가 재시작되는 타이밍과 겹치면서
  • api.github.com DNS 해석이 실패

👉 그 결과 Nginx 전체가 기동 불가 → 블로그 전체 다운


1단계 조치: Nginx를 다시 살리기#

여기서 가장 중요했던 조치 두 가지:

1) resolver 명시#

resolver 1.1.1.1 8.8.8.8 valid=300s ipv6=off;

→ Nginx가 런타임에 DNS를 다시 해석할 수 있도록 변경

2) upstream을 변수 기반으로 변경#

set $github_api api.github.com;
proxy_pass https://$github_api;

이렇게 바꾸자:

  • DNS가 순간적으로 실패해도
  • Nginx는 부팅 자체는 성공
  • 블로그 메인 페이지 정상 복구

🎉 여기까지가 1차 복구.
👉 이제 블로그는 다시 열렸다.


그런데… 최신 댓글만 안 나온다?#

블로그는 열리는데, 좌측 사이드바에 있는 Utterances 기반 최신 댓글 위젯만 비어 있음을 발견했다.

  • 본문 댓글은 정상
  • 댓글 작성도 정상
  • 최신 댓글 목록만 실패

이때부터는 전체 장애가 아니라 기능 장애였다.


2단계: 최신 댓글 위젯 장애#

구조 정리#

브라우저 → /api/github-comments/... → Nginx → GitHub API

문제의 JS 코드:

const issuesApi = "/api/github-comments/issues";
const commentsApi = "/api/github-comments/issues/{id}/comments";

하지만 Nginx 설정을 보니…

proxy_pass https://api.github.com/repos/.../issues/comments;

👉 경로를 고정해버린 상태

그래서:

  • /issues 요청 ❌
  • /issues/{id}/comments 요청 ❌
  • 일부 curl 테스트만 우연히 성공

즉, JS가 기대하는 REST 구조와 Nginx가 프록시하는 구조가 불일치했다.


2단계 조치: GitHub API 그대로 프록시#

해결 방법은 아래와 같았다.

Nginx는 가공하지 말고 ‘관문’처럼만 두자. GitHub API는 그대로 통과시키는 게 제일 안전하다.

location /api/github-comments/ {
    set $github_api api.github.com;

    resolver 1.1.1.1 8.8.8.8 valid=300s ipv6=off;
    proxy_ssl_server_name on;
    proxy_set_header Host $github_api;

    include /etc/nginx/conf.d/github-token.conf;

    proxy_set_header Accept "application/vnd.github+json";
    proxy_set_header User-Agent "plzrun-blog";

    proxy_pass https://$github_api/repos/sency90/plzrun-blog-comments/;

    proxy_connect_timeout 5s;
    proxy_read_timeout 15s;
    proxy_send_timeout 15s;
}

결과:

  • /issues 정상
  • /issues/{id}/comments 정상
  • 최신 댓글 위젯 즉시 복구

🎉 2차 복구 완료


진짜 원흉: Jenkins Agent 폭주#

추가로 로그를 보다가 소름 돋는 걸 발견했다.

jenkins-agent.service: restart counter is at 2082xxx
  • Jenkins agent가 무한 재시작
  • systemd에 엄청난 부하
  • unattended-upgrade + 네트워크 재시작과 겹침

👉 Jenkins agent 즉시 disable

sudo systemctl disable jenkins-agent
sudo systemctl stop jenkins-agent

이후 서버 안정화.


정리#

장애 흐름 요약#

  1. unattended-upgrade + 네트워크 재시작
  2. DNS 해석 실패
  3. Nginx upstream 해석 실패 → 블로그 전체 다운
  4. resolver + 변수 기반 proxy_pass로 1차 복구
  5. 최신 댓글 위젯은 API 경로 불일치로 여전히 실패
  6. proxy_pass 구조 수정 → 기능 완전 복구
  7. Jenkins agent 폭주 발견 및 차단

교훈#

  • ❌ Nginx에 외부 DNS upstream을 하드코딩하지 말 것
  • ❌ systemd 서비스 무한 재시작 방치 금물
  • ✅ reverse proxy는 “중계자”로만 두는 게 가장 안전
  • ✅ 기능 장애와 전체 장애를 반드시 분리해서 생각할 것