Blue-Green 무중단 배포 – NGINX Ingress Controller로 구현

이 포스트에서는 가장 많이 알려진 무중단 배포 전략 중 하나인 Blue-Green 무중단 배포를 Kubernetes 클러스터의 NGINX Ingress Controller를 통해서 구현하는 방법에 관해 설명합니다.

Kubernetes의 pod와 service를 통해 간단한 웹 서버를 구버전과 신버전으로 구성하고, VirtualServer 리소스를 통해 NGINX Ingress Controller가 요청을 전달할 service를 구버전에서 신버전으로 전환하는 과정을, 예제를 통해 알아보도록 하겠습니다.

이 포스트의 배포 전략 예제는 NGINX Ingress Controller, NGINX Plus Ingress Controller 모두 적용 가능합니다.

목차

1. Blue-Green 무중단 배포 전략이란?
2. 사전 구성 사항
3. Blue-Green 무중단 배포 구현
 3-1. 구버전(Blue) 배포
 3-2. 신버전(Green) 배포, 트래픽 전환
4. 결론

1. Blue-Green 무중단 배포 전략이란?

Blue-Green deployment

해당 배포 전략은 가장 많이 알려진 3가지 무중단 배포 전략인 Rolling 배포, Canary 배포, Blue-Green 배포 전략 중 하나입니다. 무중단 배포 전략은 사용자가 서비스를 이용할 수 없는 다운 타임이 존재하는 중단 배포 방식과 다르게, 서비스가 새로운 버전으로 배포되는 중에도 사용자가 다운 타임 없이 지속적으로 서비스를 이용할 수 있도록 합니다.

운영 환경의 구버전(Blue)과 동일한 환경으로 신버전(Green)을 구성한 후, 기존 구버전으로 전달되던 트래픽을 신버전으로 전환함으로써 다운 타임 없이 새로운 버전을 배포할 수 있는 전략입니다. Rolling 배포, Canary 배포와 다르게 구버전과 신버전이 공존하며 전환되는 것이 아닌, 구버전에서 신버전으로 즉시 전환되는 것이 특징입니다.

해당 전략의 장점으로는, 전환이 완료되고 문제가 발생하더라도 이전 버전으로 트래픽을 다시 전환하여 빠르게 롤백이 가능합니다. 또한 신버전이 구버전과 동일한 운영 환경에서 구성되어, 실제 환경에서 미리 테스트가 가능합니다.
반면에, 두 버전이 동시에 구성되어야 하므로 시스템 자원이 두 배로 필요한 단점이 있습니다.

2. 사전 구성 사항

  • Kubernetes 버전 : 1.28.8
  • NGINX Ingress Controller 버전 : 3.5

Blue-Green 무중단 배포에 사용될 NGINX Ingress Controller는 nginx-ingress 네임스페이스에 배포했습니다. Kubernetes 클러스터에 NGINX Ingress Controller를 배포하는 방법은
NGINX Ingress Controller Documentation을 참고하세요.

$ kubectl get all -n nginx-ingress


NAME                                READY   STATUS    RESTARTS      AGE
pod/nginx-ingress-98ff4d588-cc65d   1/1     Running   2 (29s ago)   57s

NAME                    TYPE       CLUSTER-IP    EXTERNAL-IP   PORT(S)                      AGE
service/nginx-ingress   NodePort   10.111.26.1   <none>        80:30348/TCP,443:30588/TCP   50d

NAME                            READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/nginx-ingress   1/1     1            1           57s

NAME                                      DESIRED   CURRENT   READY   AGE
replicaset.apps/nginx-ingress-98ff4d588   1         1         1       57s

NGINX Ingress Controller는 예제를 위해 NodePort 타입의 서비스를 통해 클러스터 외부로 노출했습니다. 실제 프로덕션 환경에서는 LoadBalancer 타입을 사용하세요.

3. Blue-Green 무중단 배포 구현

Blue-Green 무중단 배포 구현을 위해, 구버전 웹 서버인 web-blue를 Kubernetes 클러스터에 먼저 배포하고, 신버전 웹 서버인 web-green을 클러스터에 배포한 후 트래픽을 전환하여 무중단 배포를 구현하겠습니다.

3-1. 구버전(Blue) 배포

1. 구버전 web-blue deployment를 배포하고 확인합니다.

# app-v1.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: web-blue
  labels:
    app: web-blue
    version: v1
spec:
  replicas: 3
  selector:
    matchLabels:
      app: web-blue
      version: v1
  template:
    metadata:
      labels:
        app: web-blue
        version: v1
    spec:
      containers:
      - image: nginxstore/blue-green:webapp-blue
        name: web-app-blue
        ports:
        - containerPort: 80
$ kubectl apply -f app-v1.yaml

deployment.apps/web-blue created

$ kubectl get pod

NAME                        READY   STATUS    RESTARTS   AGE
web-blue-77b7dc9657-8pvsb   1/1     Running   0          34s
web-blue-77b7dc9657-mm662   1/1     Running   0          34s
web-blue-77b7dc9657-xdccg   1/1     Running   0          34s

2. web-blue service를 배포하고 확인합니다.

# app-v1-service.yaml

apiVersion: v1
kind: Service
metadata:
  name: web-blue-svc
  labels:
    app: web-blue
    version: v1
spec:
  ports:
  - port: 80
    targetPort: 80
    protocol: TCP
    name: http
  selector:
    app: web-blue
    version: v1
$ kubeclt apply -f app-v1-service.yaml 

service/web-blue-svc created

$ kubectl get svc

NAME           TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)   AGE
kubernetes     ClusterIP   10.96.0.1      <none>        443/TCP   101d
web-blue-svc   ClusterIP   10.102.119.7   <none>        80/TCP    5s

3. 배포한 web-blue pod에 접근할 수 있도록 VirtualServer 리소스를 배포합니다.

# web-app-vs-v1.yaml

apiVersion: k8s.nginx.org/v1
kind: VirtualServer
metadata:
  name: web-app
spec:
  host: webapp.example.com
  upstreams:
  - name: webapp
    service: web-blue-svc
    port: 80
  routes:
  - path: /
    action:
      pass: webapp
$ kubectl apply -f web-app-vs-v1.yaml 

virtualserver.k8s.nginx.org/web-app created

$ kubectl get vs

NAME      STATE   HOST                 IP    PORTS   AGE
web-app   Valid   webapp.example.com                 21s

4. VirtualServer 리소스에 작성한 webapp.example.com에 접속해 확인합니다.

예제를 위해 hosts 파일을 수정하여 webapp.example.com으로 접속하고, NodePort service를 통해 NGINX Ingress Controller가 노출된 30348번 포트로 접속했습니다.

Blue-Green deployment : blue app

구버전 웹 앱인 web-blue 배포가 완료되었고, 신버전 웹 앱인 web-green 을 이어서 배포하겠습니다.

3-2. 신버전(Green) 배포, 트래픽 전환

1. 신버전 web-green deployment를 배포하고 확인합니다.

# app-v2.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: web-green
  labels:
    app: web-green
    version: v2
spec:
  replicas: 3
  selector:
    matchLabels:
      app: web-green
      version: v2
  template:
    metadata:
      labels:
        app: web-green
        version: v2
    spec:
      containers:
      - image: nginxstore/blue-green:webapp-green
        name: web-app-green
        ports:
        - containerPort: 80
$ kubeclt apply -f app-v2.yaml

deployment.apps/web-green created

$ kubectl get pod
NAME                         READY   STATUS    RESTARTS   AGE
web-blue-77b7dc9657-8pvsb    1/1     Running   0          25m
web-blue-77b7dc9657-mm662    1/1     Running   0          25m
web-blue-77b7dc9657-xdccg    1/1     Running   0          25m
web-green-5575d48bf9-9z9rw   1/1     Running   0          41s
web-green-5575d48bf9-bpllm   1/1     Running   0          41s
web-green-5575d48bf9-s7htt   1/1     Running   0          41s

이제 Kubernetes 클러스터에는 구버전 web-blue와 신버전 web-green이 동시에 배포되어 있습니다.

2. web-green service를 배포하고 확인합니다.

# app-v2-service.yaml

apiVersion: v1
kind: Service
metadata:
  name: web-green-svc
  labels:
    app: web-green
    version: v2
spec:
  ports:
  - port: 80
    targetPort: 80
    protocol: TCP
    name: http
  selector:
    app: web-green
    version: v2
$ kubectl apply -f app-v2-service.yaml 

service/web-green-svc created

$  kubectl get svc

NAME            TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)   AGE
kubernetes      ClusterIP   10.96.0.1        <none>        443/TCP   101d
web-blue-svc    ClusterIP   10.102.119.7     <none>        80/TCP    13m
web-green-svc   ClusterIP   10.108.145.113   <none>        80/TCP    16s

3. 트래픽을 전환하기 위해, 기존의 VirtualServer 리소스를 수정하여 배포합니다.

# web-app-vs-v2.yaml

apiVersion: k8s.nginx.org/v1
kind: VirtualServer
metadata:
  name: web-app
spec:
  host: webapp.example.com
  upstreams:
  - name: webapp
    service: web-green-svc
    port: 80
  routes:
  - path: /
    action:
      pass: webapp

기존의 VirtualServer 리소스에서 트래픽이 전달될 service 이름을 신버전인 web-green-svc로 수정합니다.

$ kubectl apply -f web-app-vs-v2.yaml 

virtualserver.k8s.nginx.org/web-app configured

4. webapp.example.com에 다시 접속해, 새로운 web-green으로 접속되는 것을 확인합니다.

Blue-Green deployment : green app

VirtualServer 리소스를 수정하여 간단하게 트래픽을 전환하고, 무중단 배포를 구현했습니다.

4. 결론

이번 포스트에서는 Blue-Green 무중단 배포를 Kubernetes 클러스터의 NGINX Ingress Controller와 VirtualServer 리소스를 통해서 구현하는 방법에 대해 알아봤습니다.

Kubernetes 클러스터에 구버전 웹 앱인 web-blue를 먼저 배포하고, VirtualServer 리소스를 구성하고, 접속하여 확인했습니다. 이후 신버전 웹 앱인 web-green을 배포하여, 구버전과 신버전이 동시에 배포된 환경에서, VirtualServer 리소스를 수정하여 트래픽을 구버전 웹 앱에서 신버전 웹 앱으로 전환했습니다.

이처럼 NGINX Ingress Controller의 VirtualServer 리소스를 통해서 간단하게 트래픽을 전환하고, 신버전에서 문제가 생길 경우 이전의 VirtualServer 리소스를 다시 배포하여 빠르게 구버전으로 트래픽을 전환하여 롤백할 수 있습니다.

NGINX STORE를 통한 솔루션 도입 및 기술지원 무료 상담 신청

* indicates required