Skip to content

배포를 main push 자동 + blue-green 무중단 전환으로 개편 - #27

Merged
m-a-king merged 2 commits into
mainfrom
infra/bluegreen-auto-deploy
Aug 10, 2026
Merged

배포를 main push 자동 + blue-green 무중단 전환으로 개편#27
m-a-king merged 2 commits into
mainfrom
infra/bluegreen-auto-deploy

Conversation

@m-a-king

@m-a-king m-a-king commented Aug 9, 2026

Copy link
Copy Markdown
Collaborator

Situation

  • renderer 에서 카카오 톡딜 실패를 고친 PR 테스트 규약을 원칙(infra 설치본)/바인딩(extractor)으로 분리 #15 가 머지 후 이틀간 배포되지 않은 채 방치됐다. deploy 가 수동 트리거(workflow_dispatch) 전용이라 "머지됐는데 아무도 버튼을 안 누른" 갭이 조용히 생기는 구조였고, extractor 도 같은 구조다.
  • extractor 의 기존 배포는 교체식 단일 컨테이너라 전환 사이 수초 다운타임이 있다. "소비자가 core 워커뿐이라 재시도가 흡수한다"는 초기 결정이었지만, 머지 즉시 자동 배포로 바꾸면 배포 빈도가 올라가므로 무중단이 함께 필요해졌다.

Task

  • 머지가 곧 배포가 되게 한다: main push 트리거 추가.
  • 배포를 blue-green 무중단 전환으로 바꾼다: 소비자가 바라보는 :8090 을 고정한 채 슬롯을 갈아끼운다.

Action

트리거

  • on: push: branches: [main] 추가, workflow_dispatch 는 유지. concurrency 그룹(deploy, cancel 없음)이 연속 머지를 직렬화한다.
  • 롤백 경로 변경: "이전 커밋 workflow_dispatch 재배포"에서 "main 에 revert 머지(자동 재배포)"로. 새 슬롯 헬스 실패는 전환 없이 중단되므로 그 자체가 자동 롤백이다.

blue-green 구성

  • 박스 로컬 nginx 를 고정 프론트(:8090)로 신설한다 (배포 스크립트가 멱등 설치·conf 반영). 슬롯 컨테이너는 blue=18090 / green=18091 로 127.0.0.1 에만 바인딩되고, /etc/nginx/piki-extractor-upstream.conf 상태 파일이 서빙 슬롯의 source of truth 다. 전환 = 상태 파일 갱신 + nginx reload (core deploy 와 같은 패턴).
  • 사이트 conf 는 이 repo infra/nginx/extractor.conf 가 정본이고 매 배포 박스로 복사된다. proxy read 타임아웃은 호출자(core) read 예산보다 크게 둬 nginx 가 먼저 끊는 층이 되지 않게 했다.
단계 실패 시
새 슬롯 기동 + 직접 헬스체크 (180초 상한) 전환 없이 중단, 기존 슬롯이 계속 서빙 (자동 롤백)
upstream 갱신 + nginx -t 이전 upstream 원복 후 중단 (상태 파일과 실제 서빙의 괴리 차단 - 리뷰 반영)
nginx reload/restart 이전 upstream 원복 후 중단
:8090 경유 최종 헬스체크 이전 upstream 원복 + 새 슬롯 정리 후 실패 보고
구 슬롯 종료 최종 헬스 통과 뒤에만 수행, best-effort (timeout 상한, 성공한 전환을 못 막음)

메모리 캡

  • 슬롯당 --memory 640m --memory-swap 640m. 박스(t4g.small 1.8G)는 swap 0 이라 blue+green overlap 이 RAM 안에 들어야 한다 (2x640m + Alloy 약 100m + nginx·시스템 < 1.8G, 현 컨테이너 실사용 실측 356Mi). 기존 무제한(호스트 70%) 대비 좁아진 값이라 파싱 스파이크 OOM 이 관측되면 실측으로 재조정한다. cgroup-OOM 은 슬롯 하나로 격리되고 restart 정책이 재기동한다.

이행 (1회차 배포)

  • 레거시 단일 컨테이너(piki-extractor)가 :8090 을 점유 중이라, 1회차만 "새 슬롯 헬스 통과 → 레거시 제거 → nginx 기동" 순서로 처리한다. 제거와 기동 사이 수초 공백이 한 번 있고 core 워커 재시도가 흡수한다. 이후 배포는 reload 전환이라 무중단이다.

검토 중 잡은 함정

  • upstream 포트 추출을 core 패턴(grep -oE '[0-9]+' | head -1) 그대로 가져오면 안 됐다. core 라인은 localhost:8080 이지만 여기는 127.0.0.1:18090 이라 첫 숫자가 127 로 잡힌다. 콜론 뒤 숫자만 뽑도록 바꿨고, 슬롯 판정 3케이스(부트스트랩·18090·18091)를 로컬 실행으로 검증했다.
  • 전환 실패 시 상태 파일 원복이 처음엔 없었다 (CodeRabbit 지적 수용). 원복 없이는 nginx -t·최종 헬스 실패 때 상태 파일만 새 슬롯을 가리킨 채 남아, 다음 배포가 실제 서빙 중인 슬롯을 비활성으로 오판해 제거한다. upstream 에 keepalive 도 함께 반영.

Result

  • 머지 즉시 배포가 돌므로 "머지됐는데 미배포" 갭이 구조적으로 사라진다. 이 PR 자체의 머지가 이행 1회차 배포가 된다.
  • 검증: YAML 파싱, 배포 스크립트 bash -n + shellcheck(warning 레벨) 클린, 슬롯 판정 로직 3케이스 실행 확인. 실제 무중단 전환은 머지 후 첫 두 배포(이행 + 정상 전환)에서 박스 로그·헬스로 실측 확인이 필요하다.
  • 박스 한 대가 전 환경을 서빙하므로 이 자동화로 prod 도 머지 즉시 배포된다. 배포 게이트는 PR 머지(리뷰 + CI green)로 옮겨진 것이다.

연관 이슈

Summary by CodeRabbit

  • 배포

    • 코드 변경 시 자동 배포와 수동 배포를 모두 지원합니다.
    • 무중단 블루-그린 방식으로 새 버전을 점검한 후 트래픽을 전환합니다.
    • 점검 실패 시 기존 서비스는 유지되고 새 버전은 자동으로 정리됩니다.
    • 배포 후 서비스 경로를 최종 검증합니다.
  • 서비스 안정성

    • 배포 중 연결 유지와 요청 시간 제한을 개선했습니다.
    • 새 버전 전환 시 트래픽 중단을 최소화합니다.

- 트리거에 push(main)를 더해 머지가 곧 배포가 되게 한다. renderer #15 가 머지 후 수동 트리거 누락으로 이틀 미배포된 사고가 계기 - "교체식 단일 컨테이너 + 수초 다운타임 허용" 초기 결정을 "머지 = 무조건 배포 + 무중단"으로 대체
- 박스 로컬 nginx 를 고정 프론트(:8090)로 두고 슬롯 컨테이너(blue=18090/green=18091, 127.0.0.1 바인딩)를 upstream 상태 파일 갱신 + reload 로 전환한다 (core deploy 와 같은 패턴, 상태 파일이 서빙 슬롯의 source of truth)
- 슬롯에 --memory 640m 를 건다: 박스(t4g.small 1.8G)가 swap 0 이라 blue+green overlap 이 RAM 안에 들어야 한다. 파싱 스파이크 OOM 이 관측되면 실측 재조정
- 레거시 단일 컨테이너(piki-extractor)가 :8090 을 점유한 이행 1회차는 새 슬롯 헬스 통과 후 레거시 제거 - nginx 기동 순서로 처리한다 (수초 공백 1회, 소비자 재시도가 흡수). 이후 배포는 reload 전환이라 무중단
- 새 슬롯 헬스 실패 시 전환 없이 중단해 기존 슬롯이 계속 서빙한다 (자동 롤백)
- upstream 포트 추출은 콜론 뒤 숫자만 문다 - 라인에 127.0.0.1 이 있어 무차별 숫자 grep 은 127 을 먼저 문다
@m-a-king m-a-king added the infra 운영 환경 (IaC·클라우드 리소스·secret·배포 workflow) label Aug 9, 2026
@m-a-king m-a-king self-assigned this Aug 9, 2026
@coderabbitai

coderabbitai Bot commented Aug 9, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

배포 워크플로가 main push와 수동 실행을 지원한다. 새 이미지를 비활성 blue-green 슬롯에 배포하고 헬스체크한다. 검증이 성공하면 Nginx upstream을 전환하고 이전 슬롯을 정리한다.

Changes

Blue-green 배포

Layer / File(s) Summary
배포 진입점과 Nginx 계약
.github/workflows/deploy.yml, infra/nginx/extractor.conf
main push 및 수동 배포를 지원한다. Nginx 설정을 업로드하고 :8090 요청을 런타임 upstream으로 전달한다.
비활성 슬롯 실행과 헬스체크
.github/workflows/deploy.yml
현재 upstream 상태로 비활성 슬롯을 선택한다. 컨테이너를 localhost 포트에 실행하고 슬롯별 헬스체크를 수행한다. 실패하면 트래픽을 전환하지 않고 슬롯을 삭제한다.
트래픽 전환과 이전 슬롯 정리
.github/workflows/deploy.yml
헬스체크가 성공하면 upstream을 갱신하고 Nginx를 reload 또는 restart한다. 최종 :8090 경로를 검증한 후 이전 슬롯을 정리한다.

Estimated code review effort: 4 (Complex) | ~45 minutes

Sequence Diagram(s)

sequenceDiagram
  participant GitHubActions
  participant Docker
  participant Nginx
  participant InactiveSlot
  participant PreviousSlot

  GitHubActions->>Docker: 새 이미지로 비활성 슬롯 실행
  GitHubActions->>InactiveSlot: 직접 헬스체크
  InactiveSlot-->>GitHubActions: 헬스체크 결과
  GitHubActions->>Nginx: upstream 갱신 및 reload/restart
  Nginx->>InactiveSlot: :8090 요청 전달
  GitHubActions->>Nginx: 최종 경로 검증
  GitHubActions->>PreviousSlot: 이전 슬롯 중지 및 삭제
Loading

Possibly related PRs

  • TeamPiKi/extractor#6: 동일한 배포 워크플로를 수정하지만, 이 변경은 단일 컨테이너 배포 대신 blue-green 및 Nginx 라우팅을 사용한다.
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed 제목은 main push 자동 배포와 blue-green 무중단 전환이라는 변경의 핵심을 정확하고 간결하게 설명합니다.

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
infra/nginx/extractor.conf (1)

10-12: 🚀 Performance & Scalability | 🔵 Trivial | ⚡ Quick win

upstream keepalive 캐시를 설정하십시오.

proxy_http_version 1.1Connection ""만으로는 upstream idle connection cache가 생성되지 않습니다. keepalive를 추가해야 주석의 연결 재사용 동작이 적용됩니다.

제안 변경
 upstream piki_extractor {
     include /etc/nginx/piki-extractor-upstream.conf;
+    keepalive 32;
 }

배포 대상 Nginx 버전과 실제 동시 요청 수에 맞는 keepalive 값을 확인하십시오.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@infra/nginx/extractor.conf` around lines 10 - 12, upstream piki_extractor 블록에
upstream idle connection 재사용을 위한 keepalive 설정을 추가하십시오. 배포 대상 Nginx 버전과 실제 동시 요청
수를 기준으로 적절한 keepalive 값을 정하고, 기존 include 설정은 유지하십시오.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.github/workflows/deploy.yml:
- Around line 206-221: Update the deployment transition around the upstream
state update, nginx validation/reload, and healthcheck to preserve the previous
state before writing the inactive slot. Make the state-file replacement atomic,
and on any validation, reload, or final :8090 healthcheck failure restore the
previous upstream atomically and reload nginx before failing. Move the
piki-extractor stop/remove cleanup until after the final healthcheck succeeds.

---

Nitpick comments:
In `@infra/nginx/extractor.conf`:
- Around line 10-12: upstream piki_extractor 블록에 upstream idle connection 재사용을
위한 keepalive 설정을 추가하십시오. 배포 대상 Nginx 버전과 실제 동시 요청 수를 기준으로 적절한 keepalive 값을 정하고,
기존 include 설정은 유지하십시오.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 6a08643e-da0d-4fdc-8c91-a9db7de3c31e

📥 Commits

Reviewing files that changed from the base of the PR and between 3fa9894 and 18a7922.

📒 Files selected for processing (2)
  • .github/workflows/deploy.yml
  • infra/nginx/extractor.conf

Comment thread .github/workflows/deploy.yml Outdated
- nginx -t·reload·최종 헬스체크 어느 단계가 실패해도 이전 upstream 을 원복한다. 원복이 없으면 상태 파일만 새 슬롯을 가리킨 채 남아, 다음 배포가 실제 서빙 슬롯을 비활성으로 오판해 제거한다 (CodeRabbit 리뷰 반영)
- 최종 헬스 실패 시 새 슬롯도 정리하고, 구 슬롯 제거는 최종 헬스 통과 뒤에만 수행
- upstream 에 keepalive 4 추가 (nitpick 반영 - location 의 1.1 + Connection 초기화 전제)
@m-a-king
m-a-king merged commit 59104db into main Aug 10, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

infra 운영 환경 (IaC·클라우드 리소스·secret·배포 workflow)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant