일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
- 1차원 DP
- 2차원 dp
- 99클럽
- @GeneratedValue
- @GenericGenerator
- @Transactional
- Actions
- Amazon EFS
- amazon fsx
- Android Studio
- ANSI SQL
- ApplicationEvent
- async/await
- AVG
- AWS
- Azure
- bind
- builder
- button
- c++
- c++ builder
- c03
- Callback
- case when
- CCW
- chat GPT
- CICD
- Collections
- Combination
- combinations
- Today
- Total
기록
CICD 파이프라인 구축기(4) - 블루그린 배포를 활용한 무중단 배포 구축 본문
1. 개요
블루그린 배포(Blue-Green Deployment)는 애플리케이션 배포 중에도 사용자 경험을 유지할 수 있는 무중단 배포 방식입니다. 이를 통해 새 애플리케이션 버전을 테스트하고, 안정적으로 운영 환경에 반영할 수 있습니다.
본 가이드는 GitHub Actions, Docker, Nginx, Spring Boot, AWS를 활용하여 블루그린 배포를 구현하는 방법을 다룹니다. 주요 내용은 다음과 같습니다:
- 블루그린 배포 아키텍처
- CI/CD 파이프라인 구성
- 배포 스크립트와 관련 설정
- Blue와 Green 환경 간 트래픽 전환
2. 블루그린 배포 아키텍처
2.1. 주요 개념
- Blue 환경: 현재 사용자 요청을 처리 중인 운영 환경.
- Green 환경: 새로운 버전의 애플리케이션을 배포하고 테스트하는 대기 환경.
- 트래픽 전환: Nginx를 통해 요청을 Blue에서 Green으로, 또는 그 반대로 전환.
2.2. 구성 요소
Nginx
Nginx는 클라이언트 요청을 받아 Blue 또는 Green 컨테이너로 전달합니다. 설정 파일을 동적으로 변경하여 트래픽을 제어합니다.
- 개발 환경 (dev):
- 8880 포트 → Blue(8810) 또는 Green(8811) 컨테이너
- 운영 환경 (prd):
- 8881 포트 → Blue(8820) 또는 Green(8821) 컨테이너
Docker
Docker는 애플리케이션 실행 환경을 제공합니다. 각각의 Blue와 Green 환경은 독립된 컨테이너에서 실행됩니다.
Spring Boot
Spring Boot는 컨테이너 내부에서 애플리케이션의 API 요청을 처리하며, /healthCheck
API를 통해 상태를 확인합니다.
3. 배포 프로세스
- 배포 모드 설정
- 개발(
dev
) 또는 운영(prd
) 모드를 선택하여 배포를 시작합니다.
- 개발(
- 이전 환경 정리
- 실행 중인 컨테이너와 이미지를 정리합니다.
- 새로운 환경 배포
- 기존 Blue 환경이 실행 중이라면 Green 환경을 배포합니다(또는 그 반대).
- 헬스 체크 수행
- 새 환경의
/healthCheck
API를 호출하여 상태를 확인합니다.
- 새 환경의
- Nginx 설정 업데이트
- 설정 파일의
proxy_pass
를 업데이트하여 새 환경으로 트래픽을 전환합니다.
- 설정 파일의
- 이전 환경 종료
- 트래픽 전환이 완료되면 이전 환경의 컨테이너와 이미지를 종료 및 삭제합니다.
4. 배포 환경과 포트 매핑
환경 | 서버 구분 | 내부 포트 | 외부 포트 | 컨테이너 이름 | 설명 |
---|---|---|---|---|---|
개발(dev) | Blue | 9090 | 8810 | blue-dev | 개발 환경의 Blue 컨테이너 |
개발(dev) | Green | 9090 | 8811 | green-dev | 개발 환경의 Green 컨테이너 |
운영(prd) | Blue | 9091 | 8820 | blue-prd | 운영 환경의 Blue 컨테이너 |
운영(prd) | Green | 9091 | 8821 | green-prd | 운영 환경의 Green 컨테이너 |
5. 주요 구성 파일
5.1. deploy.sh
배포 스크립트는 Blue와 Green 환경 간 전환 및 Nginx 설정 업데이트를 자동으로 처리합니다.
#!/bin/bash
MODE=${1:-dev}
PORT1=8810
PORT2=8811
if [ "$MODE" == "prd" ]; then
PORT1=8820
PORT2=8821
fi
EXIST_BLUE=$(docker ps --filter "name=blue-${MODE}" -q)
if [ -n "$EXIST_BLUE" ]; then
NEW_COLOR="green"
NEW_PORT=$PORT2
OLD_COLOR="blue"
OLD_PORT=$PORT1
else
NEW_COLOR="blue"
NEW_PORT=$PORT1
OLD_COLOR="green"
OLD_PORT=$PORT2
fi
docker compose -f docker-compose.${MODE}.${NEW_COLOR}.yaml up -d
for i in {1..10}; do
if curl -s http://localhost:${NEW_PORT}/health | grep -q "OK"; then
echo "New environment is healthy"
break
fi
sleep 10
done
sudo sed -i "s|http://127.0.0.1:${OLD_PORT}|http://127.0.0.1:${NEW_PORT}|" /path/to/nginx.${MODE}.conf
sudo nginx -s reload
docker compose -f docker-compose.${MODE}.${OLD_COLOR}.yaml down
5.2. Docker Compose 파일
docker-compose.dev.blue.yaml
services:
app:
container_name: blue-dev
build:
context: .
dockerfile: Dockerfile
ports:
- '8810:9090'
environment:
- SPRING_PROFILES_ACTIVE=dev
networks:
default:
external: true
docker-compose.dev.green.yaml
services:
app:
container_name: green-dev
build:
context: .
dockerfile: Dockerfile
ports:
- '8811:9090'
environment:
- SPRING_PROFILES_ACTIVE=dev
networks:
default:
external: true
docker-compose.prd.blue.yaml
services:
app:
container_name: blue-prd
build:
context: .
dockerfile: Dockerfile
ports:
- '8820:9091'
environment:
- SPRING_PROFILES_ACTIVE=prd
networks:
default:
external: true
docker-compose.prd.green.yaml
services:
app:
container_name: green-prd
build:
context: .
dockerfile: Dockerfile
ports:
- '8821:9091'
environment:
- SPRING_PROFILES_ACTIVE=prd
networks:
default:
external: true
5.3. Nginx 설정 파일
nginx.dev.conf
server {
listen 8880;
server_name localhost;
location / {
proxy_pass http://127.0.0.1:8810; # Blue 컨테이너 기본 설정
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
nginx.prd.conf
server {
listen 8881;
server_name localhost;
location / {
proxy_pass http://127.0.0.1:8820; # 운영 Blue 컨테이너 기본 설정
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
6. CI/CD 파이프라인 구성
GitHub Actions를 사용하여 코드를 빌드하고, AWS S3와 EC2를 통해 애플리케이션을 배포합니다.
CICD.yml
name: CI/CD Pipeline
on:
push:
branches:
- dev
- prd
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- name: Checkout Code
uses: actions/checkout@v2
- name: Configure AWS Credentials
run: |
aws configure set aws_access_key_id ${{ secrets.AWS_ACCESS_KEY_ID }}
aws configure set aws_secret_access_key ${{ secrets.AWS_SECRET_ACCESS_KEY }}
aws configure set default.region ap-northeast-2
- name: Build JAR File
run: |
chmod +x gradlew
./gradlew clean build
cp build/libs/*.jar apiProject.jar
- name: Deploy via SSH
uses: appleboy/ssh-action@master
with:
host: ${{ secrets.EC2_HOST }}
username: ${{ secrets.EC2_USERNAME }}
key: ${{ secrets.EC2_SSH_KEY }}
script: |
aws s3 cp s3://${{ secrets.S3_BUCKETNAME }}/jars/apiProject.jar bin/apiProject.jar
bash bin/deploy.sh ${{ github.ref == 'refs/heads/prd' && 'prd' || 'dev' }}
7. 장단점
장점
- 서비스 지속성 유지: 배포 과정에서 애플리케이션 중단이 없어, 사용자 경험에 영향을 주지 않고 새로운 버전을 배포할 수 있습니다.
- 빠른 복구 및 안정성: 문제가 발생할 경우, Nginx 설정만 복원하면 이전 환경으로 즉시 롤백할 수 있어 안정성을 보장합니다.
- 안전한 테스트 환경 제공: Green 환경에서 새 버전을 테스트한 후 안정성이 확인되면 운영 환경으로 전환 가능하므로 리스크를 최소화합니다.
- 유연한 확장성: Blue와 Green 환경을 분리하여 개발, 테스트, 배포 과정을 독립적으로 운영할 수 있습니다.
단점
- 높은 리소스 요구: Blue와 Green 두 환경을 동시에 유지해야 하므로, 서버와 리소스 사용량이 증가해 운영 비용이 상승합니다.
- 구성 및 유지보수의 복잡성: 여러 설정 파일(Nginx, Docker Compose, 배포 스크립트 등)을 관리해야 하며, 각 구성 요소의 동작을 세심하게 조율해야 합니다.
- 추가적인 초기 작업: 배포 환경을 구성하고 이를 자동화하기 위한 초기 설정 작업이 복잡하고 시간이 소요됩니다.
결론
블루그린 배포는 무중단 배포를 가능하게 하여 서비스 안정성과 가용성을 높이는 강력한 전략입니다. 특히, 애플리케이션 배포의 리스크를 최소화하고 빠른 롤백을 지원하며, 테스트와 운영을 분리해 안전한 배포를 보장합니다. 다만, 추가 리소스와 구성 복잡성 등 초기 비용이 요구되므로, 이를 관리할 충분한 계획과 프로세스를 수립하는 것이 중요합니다.
그러나 현재 구성에서는 GitHub Actions를 통해 JAR 파일을 빌드하고 S3에 업로드한 뒤, 배포 스크립트를 실행하여 컨테이너를 관리하는 과정을 설명하고 있습니다. 이 프로세스를 더욱 간소화할 수 있는 개선 방안을 다음과 같이 생각했습니다. 추후에 아래를 고려한 배포 프로세스를 다시 마련해보겠습니다.
- S3 업로드 프로세스 단순화:
S3에 JAR 파일을 업로드하는 과정을 GitHub Actions에서 완전히 관리하되, S3의 푸시 이벤트를 활용하여 배포를 자동화합니다. 이는 JAR 파일 업로드 이후 서버 배포 프로세스를 AWS Lambda나 EventBridge 등으로 연결해 추가적인 작업을 자동화하는 방식입니다.
- Docker 이미지 기반 배포:
JAR 파일 대신 GitHub Actions에서 Docker 이미지를 빌드하고 이를 Docker Hub 또는 ECR에 푸시합니다.
배포 서버는 S3가 아닌 Docker Hub에서 이미지를 직접 다운로드하여 컨테이너를 실행하도록 변경합니다. 이를 통해 전체 배포 프로세스가 단순화되며, 컨테이너 환경에서 더 일관된 실행 환경을 보장할 수 있습니다.
'DevOps' 카테고리의 다른 글
AWS/EC2 인스턴스를 SSM(Session Manager)으로 안전하게 연결 (0) | 2024.12.09 |
---|---|
청구서와 Cost Explorer : AWS 비용 모니터링 (0) | 2024.11.22 |
AWS EC2 사용자 데이터를 이용한 도커 설치 및 실행 가이드 (0) | 2024.11.12 |
작성중 - [AWS/SAA-C03] Route 53: Routting Policies (0) | 2024.10.17 |
[AWS] Elasticache 생성과 연결 확인 (0) | 2024.10.14 |