본문 바로가기
한화시스템 Beyond SW Camp/데브옵스

[Jenkins] Kubernetes 환경에 무중단 배포(Blue-Green)

by taeh00n 2025. 3. 20.

Blue-Green 방식 배포

두 개의 독립적인 환경(Blue와 Green)을 사용 업데이트를 수행하는 방식

 

Blue 환경 (현재 운영 중인 환경)

 

  • 현재 사용자들이 접속하는 기존의 배포된 환경

Green 환경 (새로운 버전의 환경)

  • 새로운 버전의 애플리케이션을 배포하는 환경

 

배포 과정

1단계 : Blue 환경에서 현재 운영 중인 버전이 실행되고 있을 때 Green 환경새로운 버전의 애플리케이션을 배포

2단계 : 새로운 버전(새로운 코드)이 Green 환경에서 정상적으로 작동하는지 확인

3단계 : Green 환경에서의 배포가 성공적으로 끝나면 로드 밸런서나 DNS 등의 트래픽 라우팅 방법을 통해 사용자 트래픽을 Blue 환경에서 Green 환경으로 전환

4단계 : 모든 트래픽이 Green 환경으로 전환되면 Blue 환경은 대기 상태로 전환됩니다. 이 상태에서 문제가 발생하면 빠르게 Blue 환경으로 롤백 가능

 

장점

무중단 배포 : 트래픽 전환이 거의 즉시 이루어져 애플리케이션의 다운타임 없이 배포

롤백 용이 : 문제가 발생할 경우 Blue 환경으로 트래픽을 돌려보내는 것만으로 빠르게 이전 버전으로 롤백 가능

안정성 : 새로운 버전의 애플리케이션이 Green 환경에서 충분히 검증되기 때문에 안정적으로 배포


디플로이먼트 2개 생성 (Blue, Green)

 

apiVersion: apps/v1
kind: Deployment
metadata:
  name: backend-deployment-green
  namespace: cth
spec:
  selector:
    matchLabels:
      type: green
  replicas: 1
  template:
    metadata:
      labels:
        type: green
    spec:
      containers:
      - name: green
        image: xogns0518/jenkins_test:27
apiVersion: apps/v1
kind: Deployment
metadata:
  name: backend-deployment-blue
  namespace: cth
spec:
  selector:
    matchLabels:
      type: blue
  replicas: 1
  template:
    metadata:
      labels:
        type: blue
    spec:
      containers:
      - name: blue
        image: xogns0518/jenkins_test:28

 

서비스 생성

apiVersion: v1
kind: Service
metadata:
  name: blue-green-svc
spec:
  selector:
    type: green
  ports:
  - port: 8080
    name: "p8080"  
    targetPort: 8080
  type: LoadBalancer

 

Blue 서버 전환 (새 버전으로 업데이트된 서버)

Blue 서버에서 새로운 버전의 배포가 끝났다는 가정하에 Blue로 모든 트래픽을 전환해보겠다

 

서버가 중단됐다는 말 없이 바로 전환된 것을 볼 수 있다. 즉, 무중단 배포가 된 것이다.

 


Jenkins Script

echo "Add Permission"
chmod +x /var/lib/jenkins/workspace/webhook_test/demo/gradlew

echo "Gradle Build"
cd /var/lib/jenkins/workspace/webhook_test/demo  
./gradlew bootJar

echo "Docker Build"
docker build --tag xogns0518/jenkins_test:$BUILD_ID  /var/lib/jenkins/workspace/webhook_test/demo

echo "Docker Login"
docker login -u [DockerID] -p [DockerPW]

echo "Docker Push"
docker push xogns0518/jenkins_test:$BUILD_ID


even_or_odd=$((BUILD_ID % 2))
echo $even_or_odd

echo "Deployment"
if [ "$even_or_odd" -eq 0 ]; then
ssh test@192.0.3.10 kubectl apply -f - <<EOF
apiVersion: apps/v1
kind: Deployment
metadata:
  namespace: cth
  name: backend-deployment-green
spec:
  selector:
    matchLabels:
      type: backend
      deployment: green
  replicas: 2
  strategy:
    type: RollingUpdate
  minReadySeconds: 10
  template:
    metadata:
      labels:
        type: backend
        deployment: green
    spec:
      containers:
        - name: backend-green
          image: xogns0518/jenkins_test:$BUILD_ID
      terminationGracePeriodSeconds: 0
EOF

echo "Green 배포 완료 대기 중..."
ssh test@192.0.3.10 kubectl rollout status deployment/backend-deployment-green -n cth
ssh test@192.0.3.10 kubectl wait --for=condition=available deployment/backend-deployment-green --timeout=120s -n cth

ssh test@192.0.3.10 kubectl apply -f - <<EOF
apiVersion: v1
kind: Service
metadata:
  namespace: cth
  name: backend-svc
spec:
  selector:
    type: backend
    deployment: green
  ports:
  - port: 8080
    targetPort: 8080
  type: LoadBalancer
EOF

ssh test@192.0.3.10 kubectl scale deployment backend-deployment-blue --replicas=0 -n cth

else
ssh test@192.0.3.10 kubectl apply -f - <<EOF
apiVersion: apps/v1
kind: Deployment
metadata:
  namespace: cth
  name: backend-deployment-blue
spec:
  selector:
    matchLabels:
      type: backend
      deployment: blue
  replicas: 2
  strategy:
    type: RollingUpdate
  minReadySeconds: 10
  template:
    metadata:
      labels:
        type: backend
        deployment: blue
    spec:
      containers:
        - name: backend-blue
          image: xogns0518/jenkins_test:$BUILD_ID
      terminationGracePeriodSeconds: 0
EOF

echo "Blue 배포 완료 대기 중..."

ssh test@192.0.3.10 kubectl rollout status deployment/backend-deployment-blue -n cth
ssh test@192.0.3.10 kubectl wait --for=condition=available deployment/backend-deployment-blue --timeout=120s -n cth

ssh test@192.0.3.10 kubectl apply -f - <<EOF
apiVersion: v1
kind: Service
metadata:
  namespace: cth
  name: backend-svc
spec:
  selector:
    type: backend
    deployment: blue
  ports:
  - port: 8080
    targetPort: 8080
  type: LoadBalancer
EOF
ssh test@192.0.3.10 kubectl scale deployment backend-deployment-green --replicas=0 -n cth
Fi