NGINX Canary 배포 를 NGINX Plus Ingress Controller에서 구현
NGINX Plus Ingress Controller를 활용한 NGINX Canary 배포 방식은 새로운 애플리케이션 버전을 안전하게 배포하는 전략입니다. 이 포스트에서는 NGINX의 기능을 통해 트래픽을 점진적으로 새로운 버전과 전환하여 안정성과 성능을 유지하는 방법을 설명합니다.
해당 포스트에서 사용한 전제 조건은 다음과 같습니다.
- Ubuntu 22.04 LTS
- Kubernetes v1.30.1
- NGINX Plus Ingress Controller 3.6.1
목차
1. Canary 배포란?
2. 애플리케이션 배포
2-1. 기존 서비스 배포
2-2. 신규 서비스 배포
2-3. NGINX Canary 배포를 위한 서비스
3. NGINX Canary 배포
3-1. NGINX Canary 배포를 위한 VirtualServer 리소스 배포
4. NGINX Canary 배포 테스트
5. 결론
1. Canary 배포란?
이 포스트에서 설명하는 Canary 배포란 소프트웨어 배포 전략 중 하나로, 새로운 버전의 애플리케이션을 전체 사용자에게 배포하기 전에 일부 사용자에게 먼저 배포하여 성능 및 안정성을 검증하는 방법입니다.
이 과정에서 소규모의 사용자 그룹(일명 canary users)이 새로운 버전을 사용하게 되며, 이들의 피드백과 시스템 모니터링을 통해 잠재적인 문제를 조기에 발견할 수 있습니다. 문제가 발생하지 않으면 점진적으로 더 많은 사용자에게 배포를 확대하게 되며, 문제가 발생할 경우 즉시 이전 버전으로 롤백할 수 있는 장점이 있습니다.
NGINX Canary 배포 에 관한 다른 포스트는 아래를 참조하세요.
2. 애플리케이션 배포
Canary 배포를 위해선 현재 기존 서비스와, 새로운 버전의 서비스가 있어야 합니다. 이번 포스트에서는 두 개의 서비스를 사용하여 NGINX Canary 배포 를 테스트합니다.
2-1. 기존 서비스 배포
기존 서비스는 다음과 같습니다.
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deploy1
namespace: devops
spec:
selector:
matchLabels:
app: nginx-deploy1
template:
metadata:
labels:
app: nginx-deploy1
spec:
containers:
- name: nginx-container1
image: nginx
ports:
- containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
name: nginx-svc1
namespace: devops
spec:
ports:
- name: http-ho-svc-port1
port: 80
targetPort: 80
selector:
app: nginx-deploy1
위에서 작성한 서비스는 일반 NGINX 이미지 입니다. 기존 서비스와 신규 서비스 구분을 위해 아래 명령을 사용하여 생성된 파드에 접속합니다:
# kubectl exec -it {생성된 기존 서비스 파드 명} -n devops
/usr/share/nginx/html/index.html 파일을 수정하여 response body를 수정합니다:
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
<h1>Old Version(v1)</h1>
</body>
</html>
2-2. 신규 서비스 배포
신규 서비스는 다음과 같습니다:
metadata:
name: nginx-deploy2
namespace: devops
spec:
selector:
matchLabels:
app: nginx-deploy2
template:
metadata:
labels:
app: nginx-deploy2
spec:
containers:
- name: nginx-container2
image: nginx
ports:
- containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
name: nginx-svc2
namespace: devops
spec:
ports:
- name: http-ho-svc-port2
port: 80
targetPort: 80
selector:
app: nginx-deploy2
위에서 작성한 서비스는 기존 서비스와 같은 NGINX 이미지 입니다. 기존 서비스와 신규 서비스 구분을 위해 아래 명령을 사용하여 생성된 파드에 접속합니다:
# kubectl exec -it {생성된 신규 서비스 파드 명} -n devops
마찬가지로, /usr/share/nginx/html/index.html 파일을 수정하여 response body를 수정합니다:
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
<h1>New Version(v2)</h1>
</body>
</html>
2-3. NGINX Canary 배포를 위한 서비스
위에서 생성한 서비스의 각각 응답은 다음과 같습니다.
기존 서비스:
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
<h1>Old Version(v1)</h1>
</body>
</html>
신규 서비스:
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
<h1>New Version(v2)</h1>
</body>
</html>
3. NGINX Canary 배포
NGINX Plus Ingress Controller 환경에서 NGINX Canary 배포를 진행하는 방법은 총 두 가지가 있습니다. Ingress 리소스를 사용한 방법과 NGINX Ingress Controller의 VirualServer 리소스를 사용하는 방법이 있습니다. 이번 포스트에서는 NGINX Ingress Controller의 VirtualServer 리소스를 사용하여 NGINX Canary 배포를 진행합니다.
(※ Ingress 리소스를 사용한 방법은 여기를 클릭하여 확인하세요.)
3-1. NGINX Canary 배포를 위한 VirtualServer 리소스 배포
apiVersion: k8s.nginx.org/v1
kind: VirtualServer
metadata:
name: hodevops
namespace: devops
spec:
host: ho.example.com # 도메인
ingressClassName: nginx
upstreams:
- name: v1 # 기존 서비스의 upstream 명
service: nginx-svc1 # 기존 서비스
port: 80
- name: v2 # 신규 서비스의 upstream 명
service: nginx-svc2 # 신규 서비스
port: 80
routes:
- path: /
splits:
- weight: 90 # v1 upstream으로 전체 트래픽량의 90%를 보냅니다.
action:
pass: v1
- weight: 10 # v2 usptream으로 전체 트래픽량의 10%를 보냅니다.
action:
pass: v2
NGINX Canary 배포를 구성하기 위해서는 spec.routes.splits.weight 에서 가중치를 조절하여 사용할 수 있습니다.
- weight – weight의 가중치는 0~100 범위에 속해야 합니다. 또한 모든 가중치 합은 100과 같아야 합니다.
이 포스트에서는 전체 트래픽의 90%를 기존 서비스(v1)으로 전달하고 전체 트래픽의 10%를 신규 서비스(v2)로 전달합니다.
4. NGINX Canary 배포 테스트
Postman을 사용하여 100개의 요청을 보내고, 요청을 받은 비율을 확인합니다.

트래픽을 확인할 수 있는 도구를 사용하여 요청 받은 트래픽의 비율을 확인합니다.(이 포스트에서는 Prometheus를 사용하여 확인합니다.)
Prometheus를 확인 해보면, 위에서 구성한 NGINX Canary 설정대로 아래와 같이 총 100개의 요청 중 90개는 nginx-svc1, 10개는 nginx-svc2로 간 것을 확인할 수 있습니다.

Grafana로 시각화하여 확인해보면 기존 서비스(노란색 바)는 90%, 신규 서비스(초록색 바)는 10%인 것을 확인할 수 있습니다.

5. 결론
NGINX Canary 배포 방식을 NGINX Plus Ingress Controller에서도 동일하게 사용할 수 있습니다. 서버에 가중치를 부여하여 트래픽을 분배하는 방식으로, 이를 통해 신규 버전의 서버에 제한된 트래픽을 보내면서 안정성을 검증할 수 있습니다.
신규 버전을 일부 사용자에게 배포함으로 문제점과 사용자의 반응을 확인할 수 있고, 점진적으로 트래픽 량을 조절할 수 있습니다.
Kubernetes 환경에서의 Canary 배포 방식에 대한 자세한 내용은 아래 포스트를 참조하세요.
NGINX Plus를 사용하여 Canary 배포를 진행해보고 싶으시다면, 30일 무료 평가판을 신청하거나 NGINX STORE에 연락하여 논의하십시오.
댓글을 달려면 로그인해야 합니다.