VirtualServer 를 사용한 다양한 라우팅을 구성하는 방법
이번 포스트에서는 쿠버네티스 환경에서 NGINX Plus Ingress Controller의 VirtualServer 리소스를 사용하여 다양한 라우팅을 구성하는 방법에 대해 간단하게 소개합니다.
VirtualServer 리소스는 NGINX Plus Ingress Controller에서 제공하는 Custom Resource Definitions(CRDs) 중 하나이며, 쿠버네티스에서 제공하는 Ingress 리소스의 대안으로 권장되는 로드 밸런싱 구성입니다. 따라서 이 리소스를 사용하면 더 세밀한 라우팅 규칙과 설정을 정의하여 애플리케이션의 트래픽 관리를 개선할 수 있습니다.
VirtualServer 리소스는 기본 쿠버네티스의 Ingress 리소스보다 더 유연하고 더 강력한 구성 옵션을 제공합니다.
목차
1. VirtualServer 리소스의 주요 특징
2. VirtualServer 리소스 기본 구성
2-1. VirtualServer를 사용한 기본 로드 밸런싱 구성
2-2. VirtualServer를 사용하여 Redirect
2-3. VirtualServer를 사용하여 지정 응답 반환
2-4. VirtualServer 리소스를 사용한 프록시
2-5. VirtualServer 리소스를 사용한 rewrite
1. VirtualServer 리소스의 주요 특징
앞서 말했듯이, VirtualServer 리소스를 사용하면 더욱 세밀한 라우팅 규칙과 설정을 정의하여 애플리케이션의 트래픽 관리를 개선할 수 있습니다.
이에 대한 주요 특징은 다음과 같습니다:
- 세분화된 라우팅 규칙 – URI, Header, Method 등 다양한 요청 속성에 따라 트래픽을 라우팅할 수 있습니다.
- 향상된 로드 밸런싱 – NGINX Plus에서 사용할 수 있는 Round-Robin, Least Connection, IP Hash 등 여러 로드 밸런싱 알고리즘을 지원합니다.
- TLS/SSL 지원 – SSL/TLS Termination 및 인증서 관리를 위한 설정을 포함합니다.
- 세션 지속성 – 사용자 정의 가능한 세션 지속성 설정을 통해 사용자 세션을 특정 백엔드 서버에 고정할 수 있습니다.
- Health Check – 백엔드 서비스의 가용성을 모니터링하기 위한 상세한 Health Check 설정을 제공합니다.
구성에 대한 자세한 지시문은 이 가이드를 참조하세요.
2. VirtualServer 리소스 기본 구성
VirtualServer 리소스의 기본 구성은 다음과 같습니다:
apiVersion: k8s.nginx.org/v1
kind: VirtualServer
metadata:
name: my-app
spec:
host: myapp.example.com
tls:
secret: myapp-tls
upstreams:
- name: myapp-backend
service: myapp-svc
port: 80
routes:
- path: /
action:
pass: myapp-backend
위 예시에서는 myapp.example.com 도메인으로 들어오는 트래픽을 myapp-svc 서비스로 라우팅합니다. 또한 spec.tls.secret 으로 SSL/TLS 인증서 설정을 포함하여 HTTPS 트래픽을 처리합니다.
2-1. VirtualServer를 사용한 기본 로드 밸런싱 구성
아래와 같은 일반적인 Deployment 리소스와 Service 리소스를 배포합니다.
여기서 replicas를 2로 설정하여 두 개의 파드를 작성합니다.
apiVersion: apps/v1
kind: Deployment
metadata:
name: ho-deploy1
namespace: nginx-ingress
spec:
replicas: 2
selector:
matchLabels:
app: hodeploy1
template:
metadata:
labels:
app: hodeploy1
spec:
containers:
- name: hotainer1
image: nginx
ports:
- containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
namespace: nginx-ingress
name: ho-svc1
spec:
ports:
- name: http-ho-svc-port1
port: 80
targetPort: 80
selector:
app: hodeploy1
작성한 Service 및 Deployment 리소스 배포 및 확인
$ k apply -f service.yaml
deployment.apps/ho-deploy1 created
service/ho-svc1 created
$ k get pods -n nginx-ingress
NAME READY STATUS RESTARTS AGE
ho-deploy1-55bc496d86-dphp7 1/1 Running 0 29s
ho-deploy1-55bc496d86-j6w95 1/1 Running 0 29s
nginx-ingress-74d4b4f674-86dnn 1/1 Running 0 23h
두 개의 ho-deploy1-*** 파드가 생긴 것을 확인할 수 있습니다.
이후 해당 파드로 트래픽을 보내줄 VirtualServer 리소스를 작성합니다.
apiVersion: k8s.nginx.org/v1
kind: VirtualServer
metadata:
name: hodevops
namespace: nginx-ingress
spec:
host: hodevops.nginxstore.kr
ingressClassName: nginx
upstreams:
- name: root # upstream 이름을 root로 정의
service: ho-svc1 # 서비스 정의
port: 80
routes:
- path: / # 경로가 / 일 때
action:
pass: root # upstream의 root로 요청 전달
작성한 VirtuialServer 리소스 배포 및 확인
$ k apply -f virtualserver.yaml
virtualserver.k8s.nginx.org/hodevops created
$ k get vs -n nginx-ingress
$ k get virtualserver -n nginx-ingress
NAME STATE HOST IP PORTS AGE
hodevops Valid hodevops.nginxstore.kr 17s
VirtualServer 배포 시 STATE 상태가 Valid 이어야 정상적으로 배포된 것입니다.
현재 두 파드의 구성은 모두 아래와 같습니다.
ho-deploy1-55bc496d86-dphp7:
server {
listen 80;
server_name ho-deploy1-55bc496d86-dphp7;
location / {
default_type application/json;
return 200 '"server_name": "${server_name}"';
}
}
ho-deploy1-55bc496d86-j6w95:
server {
listen 80;
server_name ho-deploy1-55bc496d86-j6w95;
location / {
default_type application/json;
return 200 '"server_name": "${server_name}"';
}
}
이제 curl 요청으로 서비스로 프록시 되는지을 확인합니다.
$ curl hodevops.nginxstore.kr
"server_name": "ho-deploy1-55bc496d86-dphp7"
$ curl hodevops.nginxstore.kr
"server_name": "ho-deploy1-55bc496d86-j6w95"
$ curl hodevops.nginxstore.kr
"server_name": "ho-deploy1-55bc496d86-dphp7"
$ curl hodevops.nginxstore.kr
"server_name": "ho-deploy1-55bc496d86-j6w95"
2-2. VirtualServer를 사용하여 Redirect
VirtualServer를 사용하여 redirect를 하는 방법은 간단합니다.
아래와 같이 VirtualServer 리소스를 작성합니다(Service 및 Deployment 리소스는 위의 예시와 동일합니다):
apiVersion: k8s.nginx.org/v1
kind: VirtualServer
metadata:
name: hodevops
namespace: nginx-ingress
spec:
host: hodevops.nginxstore.kr
ingressClassName: nginx
upstreams:
- name: root
service: ho-svc1
port: 80
routes:
- path: /google # /google 로 요청시
action:
redirect:
url: https://google.com/ # https://google.com/으로 redirect
code: 301
작성한 리소스 배포 및 확인:
$ k apply -f virtualserver.yaml
virtualserver.k8s.nginx.org/hodevops created
$ k get vs -n nginx-ingress
$ k get virtualserver -n nginx-ingress
NAMESPACE NAME STATE HOST IP PORTS AGE
nginx-ingress hodevops Valid hodevops.nginxstore.kr 17s
curl 명령을 통해 redirect가 되는지 확인합니다:
$ curl -I hodevops.nginxstore.kr
HTTP/1.1 301 Moved Permanently
Server: nginx/1.25.3
Date: Thu, 04 Apr 2024 05:25:03 GMT
Content-Type: text/html
Content-Length: 169
Connection: keep-alive
Location: https://google.com/
2-3. VirtualServer를 사용하여 지정 응답 반환
반환 작업은 요청에 대한 미리 구성된 응답을 정의합니다. 이번 예시에서는 간단한 텍스트를 응답하도록 하겠습니다.
아래와 같이 VirtualServer 리소스를 작성합니다.
apiVersion: k8s.nginx.org/v1
kind: VirtualServer
metadata:
name: hodevops
namespace: nginx-ingress
spec:
host: hodevops.nginxstore.kr
ingressClassName: nginx
upstreams:
- name: root
service: ho-svc1
port: 80
routes:
- path: /text
action:
return:
code: 200
type: text/plain # MIME Type
body: " This is return Page\n
${request_uri}\n ${request_method}\n ${request_body}\n ${scheme}\n${args}\n${host}\n ${request_time}\n ${request_length}\n ${nginx_version}\n ${pid}\n ${connection}\n ${remote_addr}\n ${remote_port}\n ${time_iso8601}\n ${time_local}\n ${server_addr}\n ${server_port}\n ${server_name}\n ${server_protocol}\n ${connections_active}\n ${connections_reading}\n ${connections_writing} and ${connections_waiting}"
위 구성 내용은 /text로 요청할 시 지정된 body에 있는 내용을 반환하며 NGINX의 variable도 사용할 수 있습니다.
작성한 VirtualServer 리소스 배포 및 확인
$ k apply -f virtualserver.yaml
virtualserver.k8s.nginx.org/hodevops created
$ k get vs -n nginx-ingress
$ k get virtualserver -n nginx-ingress
NAME STATE HOST IP PORTS AGE
hodevops Valid hodevops.nginxstore.kr 10s
curl 명령을 사용하여 /text 경로에 요청합니다.
$ curl hodevops.nginxstore.kr/text
This is return Page
/text
GET
http
hodevops.nginxstore.kr
0.000
96
1.25.3
523
1237
10.244.0.0
1346
2024-04-04T06:30:07+00:00
04/Apr/2024:06:30:07 +0000
10.244.2.70
80
hodevops.nginxstore.kr
HTTP/1.1
2
0
1 and 1
2-4. VirtualServer 리소스를 사용한 프록시
VirtualServer 리소스에서 proxy 기능을 사용하면 요청을 특정 서비스로 전달하고, 필요에 따라 요청과 응답을 조작할 수 있습니다. Proxy 기능을 통해 rewrite, 헤더 조작 등 다양한 사용 사례에 적용될 수 있습니다.
Proxy에서는 크게 4가지 기능을 구현할 수 있습니다.
- upstream – 요청을 프록시할 업스트림의 이름을 지정합니다.
- requestHeaders – 요청 헤더를 수정합니다.
- responseHeaders – 응답 헤더를 수정합니다.
- rewritePath – 경로가 ~로 시작하는 정규식인 경우 rewritePath는 $1-9의 캡처 그룹을 포함할 수 있습니다. 자세한 내용은 rewrite 예시를 참조하세요.
아래는 proxy 기능을 사용한 간단한 예시입니다:
apiVersion: k8s.nginx.org/v1
kind: VirtualServer
metadata:
name: hodevops
namespace: nginx-ingress
spec:
host: hodevops.nginxstore.kr
ingressClassName: nginx
upstreams:
- name: proxy # 업스트림 이름
service: ho-svc1
port: 80
routes:
- path: /proxy # 해당 경로의 요청이 들어오면 프록시
action:
proxy:
upstream: proxy # 위에 정의한 업스트림 이름으로 프록시
responseHeaders: # response header 수정
add: # response header 추가
- name: My-Response-Header # header 이름: "My-Response-Header"
value: Value # header 값: "Value"
현재 ho-svc1에 대한 파드 구성은 아래와 같습니다.
ho-deploy1-55bc496d86-dphp7:
server {
listen 80;
server_name ho-deploy1-55bc496d86-dphp7;
location / {
default_type application/json;
return 200 '"server_name": "${server_name}"\n';
}
location /proxy {
default_type application/json;
return 200 '"server_name": "${server_name}"\n Proxy_success\n';
}
}
ho-deploy1-55bc496d86-j6w95:
server {
listen 80;
server_name ho-deploy1-55bc496d86-j6w95;
location / {
default_type applcation/json;
return 200 '"server_name": "${server_name}"\n';
}
location /proxy {
default_type application/json;
return 200 '"server_name": "${server_name}"\n Proxy_success\n';
}
}
이제 curl 명령을 통해 response header가 추가되었는지 확인합니다:
$ curl -i hodevops.nginxstore.kr/proxy
HTTP/1.1 200 OK
Server: nginx/1.25.3
Date: Fri, 05 Apr 2024 01:16:15 GMT
Content-Type: application/json
Content-Length: 60
Connection: keep-alive
My-Response-Header: Value # 추가한 response header
"server_name": "ho-deploy1-55bc496d86-j6w95"
Proxy_success
2-5. VirtualServer 리소스를 사용한 rewrite
VirtualServer 리소스에서 rewrite는 rewritePath라는 지시문을 통해 사용할 수 있습니다.
rewritePath 지시문을 사용하여 요청된 경로(URL)을 수정하여 내부적으로 다른 경로로 전달할 수 있게 해줍니다. 이 기능은 클라이언트가 요청한 원래 URL을 서버의 특정 경로로 재지정하고자 할 때 유용하게 사용됩니다.
이에 대한 예시는 다음과 같습니다:
apiVersion: k8s.nginx.org/v1
kind: VirtualServer
metadata:
name: hodevops
namespace: nginx-ingress
spec:
host: hodevops.nginxstore.kr
ingressClassName: nginx
upstreams:
- name: proxy
service: ho-svc1
port: 80
routes:
- path: /proxy
action:
proxy:
upstream: proxy
responseHeaders:
add:
- name: My-Response-Header
value: Value
rewritePath: / # /proxy에 대한 요청을 / 경로로 rewrite하여 프록시
작성한 구성을 배포하고 curl 명령어를 통해 확인합니다.
$ kubectl apply -f virtualserver.yaml
virtualserver.k8s.nginx.org/hodevops created
$ curl hodevops.nginxstore.kr/proxy
# service pod log
10.244.x.148 - - [05/Apr/2024:04:07:20 +0000] "GET / HTTP/1.1"
10.244.1.148 - - [05/Apr/2024:04:07:20 +0000] "GET / HTTP/1.1"
10.244.1.148 - - [05/Apr/2024:04:07:20 +0000] "GET / HTTP/1.1"
10.244.1.148 - - [05/Apr/2024:04:07:21 +0000] "GET / HTTP/1.1"
service pod의 로그를 확인해보면 / 경로로 요청을 받은 것을 확인할 수 있습니다.
VirtualServer와 관련된 자세한 정보를 확인하려면 이 가이드를 확인하세요.
NGINX Plus를 직접 사용해 보시려면 30일 무료 평가판을 신청하거나 NGINX STORE에 연락하여 논의하십시오.
NGINX에 대한 최신 정보들을 빠르게 전달받고 싶으시다면, 아래의 뉴스레터를 구독하세요.