Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[BE] 프록시서버 네임서버 CI/CD, Blue-Green 배포 #72

Merged
merged 48 commits into from
Nov 14, 2024
Merged
Show file tree
Hide file tree
Changes from 47 commits
Commits
Show all changes
48 commits
Select commit Hold shift + click to select a range
5027481
feat: blue, green 서버 다른 포트 사용
sjy2335 Nov 13, 2024
44f26f6
chore: 설정 파일 경로 input.source에서 넘겨주기
sjy2335 Nov 13, 2024
d574b4f
chore: 설정 파일 경로 input.source에서 넘겨주기
sjy2335 Nov 13, 2024
c0199c5
chore: 설정 파일 경로 input.source에서 넘겨주기
sjy2335 Nov 13, 2024
5d4a96d
fix: typeorm synchronize false
sjy2335 Nov 13, 2024
2cbb53d
chore: 포트 수정
sjy2335 Nov 13, 2024
09e4763
fix: 캐시 설정 수정
sjy2335 Nov 13, 2024
fb5b177
fix: 캐시 설정 수정
sjy2335 Nov 13, 2024
5b31adb
fix: 빌드 설정 수정
sjy2335 Nov 13, 2024
5d115ca
fix: 포트 수정
sjy2335 Nov 13, 2024
708057e
feat: 도커 이미지 헬스체크 옵션
sjy2335 Nov 13, 2024
88dee34
feat: 도커 이미지 헬스체크 옵션
sjy2335 Nov 13, 2024
1daf577
feat: 도커 이미지 헬스체크 옵션
sjy2335 Nov 13, 2024
208f5f0
feat: 도커 이미지 헬스체크 옵션 수정
sjy2335 Nov 13, 2024
3594b86
fix: 이미지 이름 수정
sjy2335 Nov 13, 2024
bb99b9b
fix: nginx 헬스체크 제거
sjy2335 Nov 13, 2024
4d48436
feat: 빌드 스크립트 작성
sjy2335 Nov 13, 2024
59a6777
feat: 프록시 서버 CI/CD yml 등 작성
sjy2335 Nov 13, 2024
3bc65be
fix: 설정 오류 수정
sjy2335 Nov 13, 2024
8575e3b
fix: PAT 사용
sjy2335 Nov 13, 2024
507335f
fix: 토큰 넘겨주는 방식
sjy2335 Nov 13, 2024
4846a22
chore: ghcr login action 버전 높임
sjy2335 Nov 13, 2024
8eeeadc
fix: 권한 위치 수정
sjy2335 Nov 13, 2024
8ce1fb8
fix: Dockerfile 수정
sjy2335 Nov 13, 2024
0a814eb
fix: Dockerfile 수정
sjy2335 Nov 13, 2024
b8eeeb5
chore: 헬스체크 시간 연장
sjy2335 Nov 13, 2024
d114b6b
chore: 도커 컨테이너 지연 주기
sjy2335 Nov 13, 2024
4f0f794
chore: 테스트 중
sjy2335 Nov 13, 2024
1dce373
chore: 프록시 서버만 테스트
sjy2335 Nov 13, 2024
0588584
fix: 최초 ghcr 로그인
sjy2335 Nov 13, 2024
26897d9
chore: 컨테이너 이름 직접 명시
sjy2335 Nov 13, 2024
8cfc61d
fix: 에코시스템 cjs로 변경
sjy2335 Nov 13, 2024
f214453
chore: 도커 컨테이너 지연 주기
sjy2335 Nov 13, 2024
0e34d10
feat: 빌드 설정 변경
sjy2335 Nov 13, 2024
daff699
feat: 네임서버 CI/CD 작성
sjy2335 Nov 13, 2024
2d0420d
fix: 에코시스템 cjs로 수정
sjy2335 Nov 13, 2024
5f4be37
fix: nginx 설정 수정
sjy2335 Nov 13, 2024
5edef53
fix: 응답 기대 제거
sjy2335 Nov 13, 2024
dd9e3cc
fix: 네트워크 설정 추가
sjy2335 Nov 13, 2024
e721cec
fix: 헬스체크 옵션 변경
sjy2335 Nov 13, 2024
4f33986
fix: 헬스체크 옵션 변경
sjy2335 Nov 13, 2024
e427131
fix: 헬스체크 옵션 변경
sjy2335 Nov 13, 2024
fb917d1
fix: udp 패킷 보존 설정
sjy2335 Nov 13, 2024
3b0a7ab
fix: udp 패킷 설정 수정
sjy2335 Nov 13, 2024
9e0af58
chore: 서버 3개 동시 배포
sjy2335 Nov 13, 2024
a9f3efe
chore: 콘솔 서버 헬스체크 시간 증가
sjy2335 Nov 13, 2024
af6cda5
fix: 헬스체크 반복 스크립트 추가
sjy2335 Nov 13, 2024
a5953f3
Merge branch 'dev-back' into be-feat#46
sjy2335 Nov 14, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
64 changes: 36 additions & 28 deletions .github/workflows/ci-cd.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ on:
- be-feat#46

jobs:
# 먼저 sparse checkout으로 레포지토리 체크아웃
# 먼저 레포지토리 체크아웃
setup:
runs-on: ubuntu-latest
steps:
Expand All @@ -18,44 +18,52 @@ jobs:
permissions:
packages: read

# # 네임서버 배포
# deploy-name-server:
# needs: setup
# uses: ./.github/workflows/deploy-service.yml
# with:
# service: name-server
# path: backend/name-server
# key_secret: SSH_KEY
# port_secret: SSH_PORT
# host_secret: NAME_SERVER_HOST
# user_secret: NAME_SERVER_USER
# env_secret: NAME_SERVER_ENV

# 콘솔 서버 배포
deploy-console-server:
needs: setup
uses: ./.github/workflows/deploy-service.yml
with:
service: web35-watchducks
path: backend/console-server
source: "./web35-watchducks/backend/console-server/*.yml, ./web35-watchducks/backend/console-server/*.conf"
secrets:
host: ${{ secrets.CONSOLE_SERVER_HOST }}
user: ${{ secrets.SSH_USER }}
key: ${{ secrets.SSH_KEY }}
port: ${{ secrets.SSH_PORT }}
key: ${{ secrets.SSH_KEY }}
host: ${{ secrets.CONSOLE_SERVER_HOST }}
env: ${{ secrets.CONSOLE_SERVER_ENV }}
tok: ${{secrets.GHCR_TOKEN}}

# 프록시 서버 배포
deploy-proxy-server:
needs: setup
uses: ./.github/workflows/deploy-service.yml
with:
service: web35-watchducks
path: backend/proxy-server
source: "./web35-watchducks/backend/proxy-server/*.yml"
use_host_nginx: true
secrets:
user: ${{ secrets.SSH_USER }}
port: ${{ secrets.SSH_PORT }}
key: ${{ secrets.SSH_KEY }}
host: ${{ secrets.PROXY_SERVER_HOST }}
env: ${{ secrets.PROXY_SERVER_ENV }}
tok: ${{secrets.GHCR_TOKEN}}

# # 프록시 서버 배포
# deploy-proxy-server:
# needs: setup
# uses: ./.github/workflows/deploy-service.yml
# with:
# service: proxy-server
# path: backend/proxy-server
# key_secret: SSH_KEY
# port_secret: SSH_PORT
# host_secret: PROXY_SERVER_HOST
# user_secret: PROXY_SERVER_USER
# env_secret: PROXY_SERVER_ENV

# 네임서버 배포
deploy-name-server:
needs: setup
uses: ./.github/workflows/deploy-service.yml
with:
service: web35-watchducks
path: backend/name-server
source: "./web35-watchducks/backend/name-server/*.yml, ./web35-watchducks/backend/name-server/*.conf"
secrets:
user: ${{ secrets.SSH_USER }}
port: ${{ secrets.SSH_PORT }}
key: ${{ secrets.SSH_KEY }}
host: ${{ secrets.NAME_SERVER_HOST }}
env: ${{ secrets.NAME_SERVER_ENV }}
tok: ${{secrets.GHCR_TOKEN}}
113 changes: 76 additions & 37 deletions .github/workflows/deploy-service.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
name: Deploy Service

permissions:
contents: read


on:
workflow_call:
inputs:
Expand All @@ -9,6 +13,12 @@ on:
path:
required: true
type: string
source:
type: string
use_host_nginx:
required: false
type: boolean
default: false
secrets:
host:
required: true
Expand All @@ -20,11 +30,14 @@ on:
required: true
env:
required: true
tok:
required: true

jobs:
deploy:
runs-on: ubuntu-latest

permissions:
packages: write
steps:
# Sparse checkout으로 하위 디렉토리만 체크아웃
- name: Checkout repository with sparse checkout
Expand All @@ -38,32 +51,24 @@ jobs:
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3

- name: Cache Docker images
uses: actions/cache@v3
with:
path: /tmp/.buildx-cache
key: docker-compose-cache-${{ github.sha }}
restore-keys: |
docker-compose-cache-

- name: Transfer YAML files using SCP
uses: appleboy/scp-action@master
with:
host: ${{ secrets.host }}
username: ${{ secrets.user }}
key: ${{ secrets.key }}
port: ${{ secrets.port }}
source: "./${{ inputs.service }}/${{ inputs.path }}/*.yml, ./${{ inputs.service }}/${{ inputs.path }}/*.conf"
source: ${{ inputs.source }}
target: "/home/watchducks/app"
strip_components: 3

# GHCR 로그인
- name: Log in to GHCR
uses: docker/login-action@v2
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
password: ${{ secrets.tok }}

# 도커 이미지 빌드 & 푸시
- name: Build and push Docker image for ${{ inputs.service }}
Expand All @@ -76,6 +81,7 @@ jobs:
ghcr.io/${{ github.repository_owner }}/${{ inputs.service }}/${{ inputs.path }}:latest
cache-from: type=gha
cache-to: type=gha,mode=max
push: true

# 각 서비스 서버에 배포
- name: Deploy ${{ inputs.service }} to server
Expand All @@ -90,37 +96,70 @@ jobs:
touch .env
echo "${{ secrets.env }}" > .env

echo "${{ secrets.tok }}" | docker login ghcr.io -u ${{ github.actor }} --password-stdin

# 최신 이미지 가져오기
docker-compose pull
# Nginx 시작 (재시작 포함)
docker-compose up -d --no-deps nginx

# Nginx가 실행 중인지 확인
for i in {1..10}; do
if docker-compose ps | grep nginx | grep "Up"; then
echo "Nginx is running"
break
# 호스트에 설치된 Nginx를 사용할지 확인
if [ "${{ inputs.use_host_nginx }}" == "true" ]; then
# Dockerized Nginx 없이 Blue 컨테이너만 시작
docker-compose up -d --no-deps server-blue

# Blue 인스턴스 헬스 체크 - 최대 5번 시도
echo "Blue 컨테이너 헬스 상태 확인 중..."
for i in {1..5}; do
health_status=$(docker inspect --format='{{json .State.Health.Status}}' app-server-blue-1 | tr -d '"')
if [ "$health_status" == "healthy" ]; then
echo "Blue 컨테이너가 정상 상태입니다."
break
else
echo "Blue 컨테이너가 정상 상태로 전환되지 않았습니다. 시도 $i/5..."
sleep 10
fi
done

# 최종 헬스 상태 확인
if [ "$health_status" != "healthy" ]; then
echo "Blue 컨테이너가 정상 상태로 전환되지 않았습니다."
exit 1
fi
echo "Waiting for Nginx to be ready..."
sleep 2
done

# Blue 인스턴스를 새 버전으로 준비
docker-compose up -d --no-deps server-blue

# Blue 인스턴스 헬스 체크
for i in {1..30}; do
if curl -s http://localhost/api | grep -q "Hello World!"; then
echo "Blue container is ready"
break
# Nginx 재로드
sudo nginx -s reload
echo "호스트 Nginx 리로드 완료로 트래픽 전환 완료"

else
# 콘솔 서버의 Dockerized Nginx 설정
docker-compose up -d --no-deps nginx

# Dockerized Nginx와 함께 Blue 컨테이너 시작
docker-compose up -d --no-deps server-blue

# Blue 인스턴스 헬스 체크 - 최대 5번 시도
echo "Blue 컨테이너 헬스 상태 확인 중..."
for i in {1..5}; do
health_status=$(docker inspect --format='{{json .State.Health.Status}}' app-server-blue-1 | tr -d '"')
if [ "$health_status" == "healthy" ]; then
echo "Blue 컨테이너가 정상 상태입니다."
break
else
echo "Blue 컨테이너가 정상 상태로 전환되지 않았습니다. 시도 $i/5..."
sleep 10
fi
done

# 최종 헬스 상태 확인
if [ "$health_status" != "healthy" ]; then
echo "Blue 컨테이너가 정상 상태로 전환되지 않았습니다."
exit 1
fi
echo "Waiting for Blue container to be ready..."
sleep 1
done

# Nginx 리로드로 트래픽 전환
docker-compose exec nginx nginx -s reload
# Dockerized Nginx 리로드로 트래픽 전환
docker-compose exec nginx nginx -s reload
echo "Dockerized Nginx 리로드 완료로 트래픽 전환 완료"
fi

# 기존 Green 인스턴스 종료
# Green 컨테이너 시작 (두 설정 모두에서 수행)
docker-compose up -d --no-deps server-green
echo "Deployment completed successfully"
echo "배포가 성공적으로 완료되었습니다."
18 changes: 15 additions & 3 deletions backend/console-server/docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,18 +12,30 @@ services:

server-blue:
image: ghcr.io/boostcampwm-2024/web35-watchducks/backend/console-server:latest
container_name: app-server-blue-1
environment:
- NODE_ENV=production
- PORT=3000
- PORT=3001
restart: always
volumes:
- ./.env:/usr/src/app/.env
healthcheck:
test: ["CMD", "nc", "-z", "localhost", "3001"]
interval: 10s
timeout: 2s
retries: 5

server-green:
image: ghcr.io/boostcampwm-2024/web35-watchducks/backend/console-server:latest
container_name: app-server-green-1
environment:
- NODE_ENV=production
- PORT=3000
- PORT=3002
restart: always
volumes:
- ./.env:/usr/src/app/.env
- ./.env:/usr/src/app/.env
healthcheck:
test: ["CMD", "nc", "-z", "localhost", "3002"]
interval: 10s
timeout: 2s
retries: 5
4 changes: 2 additions & 2 deletions backend/console-server/nginx.conf
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
http {
upstream console_server {
server server-blue:3000 weight=1;
server server-green:3000 backup;
server server-blue:3001 weight=1;
server server-green:3002 backup;
}

server {
Expand Down
2 changes: 1 addition & 1 deletion backend/console-server/src/config/typeorm.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ export default registerAs('typeOrmConfig', () => {
password: process.env.DB_PASSWORD,
database: process.env.DB_NAME,
autoLoadEntities: true,
synchronize: true,
synchronize: false,
}
) as TypeOrmModuleOptions;
});
33 changes: 33 additions & 0 deletions backend/name-server/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# 빌드 스테이지
FROM node:22-alpine AS build

WORKDIR /usr/src/app

# 패키지 파일 복사 및 의존성 설치
COPY package*.json ./
RUN npm install

# 소스 코드 복사 및 빌드
COPY . .
RUN npm run build

# 런타임 스테이지
FROM node:22-alpine

WORKDIR /usr/src/app

# 프로덕션 의존성 설치
COPY package*.json ./
RUN npm install --production

# 빌드 결과물 복사
COPY --from=build /usr/src/app/dist ./dist

# PM2 설치 (옵션)
RUN npm install pm2 -g

# PM2 설정 파일 복사 (옵션)
COPY ecosystem.config.cjs ./

# 애플리케이션 실행
CMD ["pm2-runtime", "ecosystem.config.cjs"]
Loading
Loading