Skip to content

Commit

Permalink
Merge pull request #72 from boostcampwm-2024/be-feat#46
Browse files Browse the repository at this point in the history
[BE] 프록시서버 네임서버 CI/CD, Blue-Green 배포
  • Loading branch information
sjy2335 authored Nov 14, 2024
2 parents 30ccd4d + a5953f3 commit 27ebfe6
Show file tree
Hide file tree
Showing 18 changed files with 759 additions and 119 deletions.
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 "배포가 성공적으로 완료되었습니다."
74 changes: 36 additions & 38 deletions backend/console-server/docker-compose.yml
Original file line number Diff line number Diff line change
@@ -1,43 +1,41 @@
version: '3.8'
services:
clickhouse:
image: clickhouse/clickhouse-server:latest
container_name: clickhouse
restart: always
environment:
CLICKHOUSE_DB: ${LOCAL_CH_DB}
CLICKHOUSE_USER: ${LOCAL_CH_USER}
CLICKHOUSE_PASSWORD: ${LOCAL_CH_PASSWORD}
CLICKHOUSE_DEFAULT_ACCESS_MANAGEMENT: 1
TZ: Asia/Seoul
nginx:
image: nginx:latest
ports:
- "8123:8123" # HTTP 인터페이스
- "9000:9000" # Native 인터페이스
- "80:80"
volumes:
- clickhouse_data:/var/lib/clickhouse
networks:
- app_network
ulimits:
nofile:
soft: 262144
hard: 262144
memlock:
soft: -1
hard: -1
nproc:
soft: 131072
hard: 131072
cap_add:
- SYS_NICE
- NET_ADMIN
- IPC_LOCK
security_opt:
- seccomp:unconfined
volumes:
clickhouse_data:
driver: local
- ./nginx.conf:/etc/nginx/nginx.conf
depends_on:
- server-blue
- server-green

networks:
app_network:
name: app_network
driver: bridge
server-blue:
image: ghcr.io/boostcampwm-2024/web35-watchducks/backend/console-server:latest
container_name: app-server-blue-1
environment:
- NODE_ENV=production
- 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=3002
restart: always
volumes:
- ./.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;
});
Loading

0 comments on commit 27ebfe6

Please sign in to comment.