157df05292
## 개선 사항 ### 1. CLAUDE.md 문서 분해 (토큰 효율) - 원본: 6000+ 줄 → 축약: 239줄 (96% 감소) - 호출루시네이션 위험 제거 - 토큰 사용량 ~15% 감소 ### 2. 하네스 문서 작성 (명확성) - DEPLOYMENT_HARNESS.md: 배포 정책 + 검증 규칙 - NGINX_HARNESS.md: Nginx 상대경로 설정 - 각 하네스: 단일 책임 원칙 ### 3. 배포 스크립트 강화 (안정성) - deploy_gb.sh: 6단계 헬스 체크 + API 검증 - validate-deploy.sh: 사전 검증 프로세스 - 배포 버전 문제 시 자동 중단 + 롤백 ### 4. 문서 링크 정리 (가시성) - CLAUDE.md에서 모든 하네스 참조 - 우선 기준 명확화 - 배포 절차 체계화 ## 검증 완료 - ✅ 배포 스크립트 문법 정상 - ✅ E2E 테스트 1/1 통과 (프로덕션 환경) - ✅ 문서 링크 모두 유효 - ✅ 배포 체계 안정화 Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
285 lines
5.7 KiB
Markdown
285 lines
5.7 KiB
Markdown
# 배포 하네스 (Deployment Harness)
|
|
|
|
## 📋 개요
|
|
|
|
Green-Blue 배포 정책에서 **배포 버전의 안정성을 보장**하는 사전 검증 프로세스.
|
|
|
|
---
|
|
|
|
## 🎯 핵심 원칙
|
|
|
|
```
|
|
배포 버전에 문제 있음 → 배포 중단 + 자동 롤백
|
|
모든 검증 통과 → 배포 진행 + 포트 전환
|
|
```
|
|
|
|
---
|
|
|
|
## 🔍 사전 검증 (Pre-Deployment Validation)
|
|
|
|
### 1단계: 빌드 아티팩트 검증
|
|
|
|
**파일 존재 확인:**
|
|
```bash
|
|
✓ appsettings.Production.json
|
|
✓ TaxBaik.Web.dll
|
|
✓ TaxBaik.Proxy.dll
|
|
✓ wwwroot/version.json
|
|
✓ css/admin.css
|
|
```
|
|
|
|
**실행 권한:**
|
|
```bash
|
|
chmod +x deploy_gb.sh
|
|
```
|
|
|
|
### 2단계: 배포 환경 검증
|
|
|
|
**필수 환경 변수:**
|
|
```bash
|
|
ASPNETCORE_ENVIRONMENT=Production
|
|
ASPNETCORE_URLS=http://127.0.0.1:${TARGET_PORT}
|
|
ConnectionStrings__Default=Host=localhost;Database=taxbaikdb;...
|
|
ApiClient__BaseUrl=http://127.0.0.1:${TARGET_PORT}/api/
|
|
```
|
|
|
|
**데이터베이스 연결:**
|
|
```bash
|
|
✓ 호스트 접근 가능 (localhost:5432)
|
|
✓ 사용자 권한 확인 (taxbaik)
|
|
✓ 데이터베이스 존재 (taxbaikdb)
|
|
✓ 마이그레이션 최신 상태
|
|
```
|
|
|
|
### 3단계: 포트 상태 확인
|
|
|
|
**포트 사용 여부:**
|
|
```bash
|
|
Active Port: 5003 또는 5004 (이미 점유)
|
|
Target Port: 5004 또는 5003 (배포 대상, 비어있어야 함)
|
|
|
|
# 검증
|
|
netstat -tlnp | grep :${TARGET_PORT}
|
|
# 결과: (없음) → ✓ 통과
|
|
```
|
|
|
|
---
|
|
|
|
## 📈 배포 중 헬스 체크
|
|
|
|
### 단계별 검증
|
|
|
|
**1. 프로세스 시작**
|
|
```bash
|
|
nohup dotnet TaxBaik.Web.dll &
|
|
sleep 2
|
|
ps -p ${NEW_PID} # 확인
|
|
```
|
|
|
|
**2. 기본 헬스 체크** (최대 20회, 2초 간격)
|
|
```bash
|
|
curl http://127.0.0.1:${TARGET_PORT}/healthz
|
|
# 예상: HTTP 200 + "Healthy"
|
|
```
|
|
|
|
**3. API 엔드포인트 검증**
|
|
```bash
|
|
curl http://127.0.0.1:${TARGET_PORT}/api/blog?limit=1
|
|
# 예상: HTTP 200
|
|
# 의미: 데이터베이스 연결 확인
|
|
```
|
|
|
|
**4. 로그 오류 확인**
|
|
```bash
|
|
grep -i "fatal\|unhandled exception" web_${TARGET_PORT}.log
|
|
# 결과: (없음) → ✓ 통과
|
|
```
|
|
|
|
---
|
|
|
|
## 🚀 포트 전환 (Traffic Switch)
|
|
|
|
### 전환 전 최종 검증
|
|
|
|
**Nginx 설정 검증:**
|
|
```bash
|
|
sudo nginx -t
|
|
# 예상: "syntax is ok" + "test is successful"
|
|
```
|
|
|
|
**프록시 상태:**
|
|
```bash
|
|
ss -tlnp | grep :5001
|
|
# 예상: TaxBaik.Proxy.dll 실행 중
|
|
```
|
|
|
|
**포트 파일 업데이트:**
|
|
```bash
|
|
echo "${TARGET_PORT}" > /home/kjh2064/taxbaik_port
|
|
# 프록시가 이 파일을 읽어 트래픽 전환
|
|
```
|
|
|
|
**Nginx 재로드:**
|
|
```bash
|
|
sudo systemctl reload nginx
|
|
```
|
|
|
|
---
|
|
|
|
## ❌ 배포 실패 기준
|
|
|
|
### 배포 자동 중단 조건
|
|
|
|
| 조건 | 행동 | 복구 |
|
|
|------|------|------|
|
|
| **프로세스 시작 실패** | 즉시 종료 | 롤백 |
|
|
| **헬스 체크 20회 실패** | 즉시 종료 | 롤백 |
|
|
| **API 엔드포인트 오류** | 즉시 종료 | 롤백 |
|
|
| **로그에 FATAL 오류** | 즉시 종료 | 롤백 |
|
|
| **Nginx 설정 무효** | 포트 전환 중단 | 이전 포트 유지 |
|
|
| **포트 전환 후 서비스 불가** | 즉시 롤백 | 이전 포트로 복구 |
|
|
|
|
### 자동 롤백 프로세스
|
|
|
|
```bash
|
|
# 1. 새 프로세스 종료
|
|
kill -9 ${NEW_PID}
|
|
|
|
# 2. 이전 포트 파일 복구
|
|
echo "${ACTIVE_PORT}" > /home/kjh2064/taxbaik_port
|
|
|
|
# 3. Nginx 재로드
|
|
sudo systemctl reload nginx
|
|
|
|
# 4. 실패 알림
|
|
send_telegram "❌ 배포 실패: ${REASON}"
|
|
|
|
# 5. 종료 코드 1
|
|
exit 1
|
|
```
|
|
|
|
---
|
|
|
|
## 📊 배포 검증 체크리스트
|
|
|
|
**배포 전:**
|
|
- [ ] 빌드 성공 (0 오류)
|
|
- [ ] 테스트 성공 (모든 테스트 통과)
|
|
- [ ] 아티팩트 완전성 (파일 모두 존재)
|
|
- [ ] 환경 변수 설정 (필수 변수 모두 정의)
|
|
- [ ] DB 연결 가능
|
|
|
|
**배포 중:**
|
|
- [ ] 프로세스 시작 성공
|
|
- [ ] 헬스 체크 통과 (20회 이내)
|
|
- [ ] API 엔드포인트 응답
|
|
- [ ] 로그 오류 없음 (FATAL/Exception 없음)
|
|
- [ ] Nginx 설정 유효
|
|
|
|
**포트 전환:**
|
|
- [ ] 이전 Nginx 상태 정상
|
|
- [ ] 프록시 정상 실행
|
|
- [ ] 포트 파일 업데이트
|
|
- [ ] Nginx 재로드 성공
|
|
- [ ] 트래픽 정상 전환
|
|
|
|
**배포 후:**
|
|
- [ ] 공개 URL 접근 가능 (HTTP 200)
|
|
- [ ] 관리자 페이지 로드 (HTTP 200)
|
|
- [ ] E2E 테스트 통과 (1/1 성공)
|
|
- [ ] 배포 완료 알림 (Telegram)
|
|
|
|
---
|
|
|
|
## 🔄 롤백 절차
|
|
|
|
### 수동 롤백
|
|
|
|
**상황: 배포 후 심각한 오류 발생**
|
|
|
|
```bash
|
|
# 1. 이전 포트 확인
|
|
cat /home/kjh2064/taxbaik_port
|
|
# 결과: 5004 (새 포트)
|
|
|
|
# 2. 이전 포트로 복구
|
|
echo "5003" > /home/kjh2064/taxbaik_port
|
|
|
|
# 3. Nginx 재로드
|
|
sudo systemctl reload nginx
|
|
|
|
# 4. 확인
|
|
curl https://www.taxbaik.com/
|
|
# 예상: 이전 버전의 응답
|
|
```
|
|
|
|
### 배포 디렉토리 복구
|
|
|
|
**상황: 배포 파일 손상**
|
|
|
|
```bash
|
|
# 1. 최근 배포 목록
|
|
ls -ldt /home/kjh2064/deployments/taxbaik_*
|
|
|
|
# 2. 이전 배포 선택
|
|
PREVIOUS_DEPLOY="/home/kjh2064/deployments/taxbaik_20260708_170000"
|
|
|
|
# 3. 수동 배포 (deploy_gb.sh 다시 실행)
|
|
bash deploy_gb.sh $PREVIOUS_DEPLOY
|
|
```
|
|
|
|
---
|
|
|
|
## 📞 배포 실패 진단
|
|
|
|
### 로그 확인 순서
|
|
|
|
**1단계: 앱 로그**
|
|
```bash
|
|
tail -100 /home/kjh2064/deployments/taxbaik_*/web_500*.log
|
|
# 찾기: ERROR, FATAL, Exception, connection refused
|
|
```
|
|
|
|
**2단계: 프록시 로그**
|
|
```bash
|
|
tail -100 /home/kjh2064/taxbaik_proxy.log
|
|
# 찾기: 5001 포트 문제, 포트 파일 읽기 실패
|
|
```
|
|
|
|
**3단계: Nginx 로그**
|
|
```bash
|
|
sudo tail -100 /var/log/nginx/error.log
|
|
# 찾기: upstream connect failed, configuration error
|
|
```
|
|
|
|
**4단계: 시스템 로그**
|
|
```bash
|
|
sudo journalctl -u nginx -n 50
|
|
sudo dmesg | tail -20
|
|
```
|
|
|
|
---
|
|
|
|
## ✅ 성공 기준
|
|
|
|
```
|
|
모든 헬스 체크 통과
|
|
↓
|
|
포트 전환 성공
|
|
↓
|
|
E2E 테스트 1/1 통과
|
|
↓
|
|
배포 완료 알림 발송
|
|
↓
|
|
✅ 배포 성공
|
|
```
|
|
|
|
---
|
|
|
|
## 참고
|
|
|
|
- **배포 스크립트**: `/deploy_gb.sh`
|
|
- **검증 스크립트**: `/scripts/validate-deploy.sh`
|
|
- **Nginx 설정**: `/docs/NGINX_HARNESS.md`
|
|
- **CI/CD**: `.gitea/workflows/deploy.yml`
|