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 무중단 배포 전략이란?

해당 배포 전략은 가장 많이 알려진 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번 포트로 접속했습니다.

구버전 웹 앱인 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으로 접속되는 것을 확인합니다.

VirtualServer 리소스를 수정하여 간단하게 트래픽을 전환하고, 무중단 배포를 구현했습니다.
4. 결론
이번 포스트에서는 Blue-Green 무중단 배포를 Kubernetes 클러스터의 NGINX Ingress Controller와 VirtualServer 리소스를 통해서 구현하는 방법에 대해 알아봤습니다.
Kubernetes 클러스터에 구버전 웹 앱인 web-blue를 먼저 배포하고, VirtualServer 리소스를 구성하고, 접속하여 확인했습니다. 이후 신버전 웹 앱인 web-green을 배포하여, 구버전과 신버전이 동시에 배포된 환경에서, VirtualServer 리소스를 수정하여 트래픽을 구버전 웹 앱에서 신버전 웹 앱으로 전환했습니다.
이처럼 NGINX Ingress Controller의 VirtualServer 리소스를 통해서 간단하게 트래픽을 전환하고, 신버전에서 문제가 생길 경우 이전의 VirtualServer 리소스를 다시 배포하여 빠르게 구버전으로 트래픽을 전환하여 롤백할 수 있습니다.
댓글을 달려면 로그인해야 합니다.